web-development

Расширяем Chrome/Chromium

Часто по работе приходиться вкручивать всякого разного. В данном случае понадобилось делать расширение для хрома и собирать информацию по кусочкам.
Не могу не упомянуть хороший блог посвященный расширениям для хрома.
В этом материале я расскажу об основах но чуть больше чем многие введения.
Если вы попали на мой материал то скорее всего уже видели что само расширение состоит из нескольких базовых файлов:
  1. icon.png - иконка расширения
Пропустил я их в свое время и многие методы освоил по кускам из разных материалов =) а тут все скопом. Берем и проходим. Каждое видео минуты 2-3 длиться, потом простенькая задачка. Все удобно. Но на английском, если кто не понимает английский - печаль.

Ссыль на туториал: http://discover-devtools.codeschool.com/
Лаборатория хакера Книга дает практический упор на взлом и поиск уже существующих для софта уязвимостей, применения эксплоитов и нескольких методов взлома. Не сказал бы что ожидал от книги чего-то сверхестественного, ведь там где крутятся большие деньги никто не будет светить рецептами на миллион. В общем, для введения в хакинг книга очень практична. Книга понравилась, но теперь хочется чего-то более углубленного.
Вот как все просто:
postresql=> \o /путь/к/файлу.txt
postresql=> postgresql query ( запрос к базе )
postresql=> \o ( возвращаем стандартный вывод )
Все.
Публикую скорее как памятку самому себе и всем кому может помочь.
Задача тривиальная, импортировать файл-дамп базы данных PostgreSQL в Windows.
1) Запускаем pgAdmin III
2) Plugins->PSQL Console
3) Создаем базу данных командой create database mydbname;
4) Создаем пользователя. Так как это Windows, в котором я занимаюсь лишь разработкой то пользователь будет иметь все права на публичную схему.
create user myuser with password 'somepassword';
grant all privileges on all tables in schema public to myuser;
5) Загружаем дамп базы данных командой из консоли Windows:
"C:\Program Files\PostgreSQL\9.5\bin\psql.exe" mydbname myuser < E:\somedump.sql


После этого в консоли будет вывод импорта базы данных. На этом все.
PHP обьекты, шаблоны и методики программирования.  Мэтт Зандстра Сложно взять и оценить то все что дает такая книга веб-разработчику... Методологию разработки, схемы, подсказки, инструменты. Сейчас достаточно много книг которые помогу подняться на уровень junior, их не тяжело узнать, все они называются подобно "как создать сайт с помощью PHP+MySQL" и т.д. Эта же книга уровнем выше. Рассмотрение ООП, шаблоны проектирования, систем контроля версий, юнит-тестов(то что я для себя считал тратой времени), развертывания приложения, сервер непрерывной интеграции(НИ). Все это значительно выше уровнем чем просто создать сайтик. Для тех кто создает или собирается создавать проекты средней и высокой сложности, такую книгу стоит взять на вооружение. Периодами книга была достаточно тяжелой, и начинающим явно не подойдет, но столько информации для уровня middle и senior... Must Have.
Моя личная оценка книге 5+. Автору огромное спасибо за труд. P.S. Пошел настраивать сервер НИ...
Наверное все веб-разработчики знают как PageSpeed Insights относиться к подгрузке CSS и JS файлов в верху страницы. Не становятся исключением в этом плане и шрифты самого Google: Google Fonts. А используются они достаточно часто. Но и на этот случай у гугла есть решение. Нужно всего-лишь подключить специальный лоадер для шрифтов. Подключаем таким образом:
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.16/webfont.js"></script>
    <script>
        WebFont.load({
            google: {
                families: ['Open+Sans:400,300,600,700,800:latin,cyrillic,cyrillic-ext']
            }
        });
    </script>
В families как не трудно догадаться мы и прописываем шрифт и его настройки. Все. Более подробно можно ознакомиться тут. Разработчики заявляют о поддержке разными браузерами и подгрузке шрифтов с Google Fonts, Typekit, Fonts.com и Fontdeck. А соразработчиками выступают Google и Typekit.
nofollow link Небольшая функция, прогнав через которую текст на выходе получаем закрытыми атрибутом rel="nofollow" все ссылки кроме внутренних...
Как применять HTML5 теги Вот такой перевод небольшой и вольный сделал. Ссылка
chrome расширения Стала небольшая задача выполнять по клику на кнопку определенную функцию на странице. Вроде все бы ничего, да вот общение между расширением и самой страницей происходит достаточно изолированно, с весьма ограниченными механизмами обмена. Так, чтобы выполнить свой скрипт на странице расширение должно вставить свой скрипт на страницу. В тоже время чтобы его выполнить придется использовать обмен сообщениями и события.

Теперь немного более приземленно.
Создаем папку с расширением, например myclickbtn
В ней создаем файл manifest.json, ...
После обновления Windows на 10 версию PHPStorm не смог запустить терминал. В решении помогает гугл давая ссылку.
Решение сводиться к запуску обычного терминала, клику по управляющей окном панели правой кнопкой мыши и выбора Properties(Свойства).
windows terminal
Внизу ставим галочку на "Use legacy console"(Использовать прежнюю версию консоли)
Использовать прежнюю версию консоли
ОК.
После переходим в PHPStorm и запускаем новый терминал. Все.
youtube image У нас есть текст фрейма поделиться, но нужно получить картинку превью.
Для этого нам нужно выпарсить ID видео и подставить в нужную ссылку:
Youtube генерирует несколько таких ссылок: http://img.youtube.com/vi/<insert-youtube-video-id-here>/0.jpg http://img.youtube.com/vi/<insert-youtube-video-id-here>/1.jpg http://img.youtube.com/vi/<insert-youtube-video-id-here>/2.jpg http://img.youtube.com/vi/<insert-youtube-video-id-here>/3.jpg Что соответствует размерам и аналогично ссылкам в том же порядке: По умолчанию: http://img.youtube.com/vi/<insert-youtube-video-id-here>/default.jpg Для картинок в высоком качестве: http://img.youtube.com/vi/<insert-youtube-video-id-here>/hqdefault.jpg Среднее качество: http://img.youtube.com/vi/<insert-youtube-video-id-here>/mqdefault.jpg Стандартный размер картинки: http://img.youtube.com/vi/<insert-youtube-video-id-here>/sddefault.jpg Максимальный размер картинки: http://img.youtube.com/vi/<insert-youtube-video-id-here>/maxresdefault.jpg Просто выбираем подходящую ссылку.
Я парсил из кода следующей регуляркой:
//кусок кода выбирающий превью для ютуба
preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $this->body, $matches);
            //preg_match("/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^\?&"'>]+)/", $this->body, $matches);
            if (!empty($matches[1])) $vid_id = $matches[1];
            if (!empty($vid_id)) return "http://img.youtube.com/vi/".$vid_id."/0.jpg";

Такой код вернет нам ссылку с подставленным айди видео, что нам и требовалось.
Может кому пригодиться. Код найден где-то на stackoverflow. Если у ссылки путь начинается с hash(#), то при клике код скролит страницу к нужному элементу на странице.
$(function() {
    $("a[href*='#']:not([href='#'])").click(
        function()
        {
        if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname)
        {
            var target = $(this.hash);
            target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
            if (target.length)
            {
                $('html,body').animate({
                    scrollTop: target.offset().top
                }, 1000);
                return false;
            }
        }});
    });
Нужна была возможность добавлять новый элемент в список если такого элемента у нас еще не было, благо select2 предусматривает подобную возможность. Загвоздка заключалась только в том что мы использовали список с числовыми id как значение и брался из базы данных. Имеем классическую конструкцию из трех таблиц:
материал(id, ..., ..., ...); теги(id,...,...,...); материал_тег(id_material, id_tag);
Так вот, сам select2 мы используем так:
<select id="multiple" class="form-control select2-multiple" multiple name="tags[]"  >
                                {foreach $labels as $label}
                                    <option value="{$label->id}" {if !empty($exists.{$label->id})}selected{/if} >{$label->title}</option>
                                {/foreach}
                            </select>
<script>

    $(document).ready(function () {

        $("#multiple").select2({
            placeholder: "Select or add tags",
            tags: true,
            tokenSeparators: [",", " "],
            createSearchChoice:function(term, data) {
                if ( $(data).filter( function() {
                            return this.text.localeCompare(term)===0;
                        }).length===0)
                {
                    return { id: term, text:term };
                }
            }
        });
</script>
На стороне сервера я использую фреймворк Laravel 5 и в контроллере использую такую часть кода:
//...
//материал
$record = Linkedin_GroupLabel::find($id);
//...
//Сбрасываем связи с тегами
                        $record->tags()->detach();
                        $rtags  = array();
                        foreach ($request->input('tags') as $tag){
//если значение элемента селекта число, значит это id
                            if (is_numeric($tag)){
                                $rtags[] = $tag;
                            }
                            else //в противном случае это новое значение
                            {
                                $new = Linkedin_Label::where('title','=',trim($tag))->first();
                                if (empty($new->id)){
                                    $new = new Linkedin_Label();
                                }
                                $new->title = trim($tag);
                                $new->save();
                                $rtags[] = $new->id;
                            }
                        }
//аттачим айдишники между записями
                        $record->tags()->attach($rtags);

Единственное НО при таком, записи тегов не должны быть только числом, иначе is_numeric подумает что добавлен айдишник, а не новый тег. Очень вероятно что у кого-то есть вариант получше, но данный случай для меня работает.
Пришлось все вот это чудо поднимать, так как нужно делать серверную и клиентскую часть под одну задачу. Искренне не понимаю тех веб-девелоперов которые работают веб-разработкой под Windows )) ну да ладно, это их личное дело.

Итак, проблема следующая:
Windows 7+Apache2.4+PostgreSQL+Laravel = PDO Exception: driver not found
При этом команда:
php -m
Показывает что как pgsql так и pdo_pgsql есть, но Laravel 5 уверенно доказывает обратное. При этом в php.ini:
extension=php_pdo_pgsql.dll
extension=php_pgsql.dll
раскомментированны.

Но вот команда:
php -a
Вызывающая интерактивную консоль php, так же сообщает:
Unable to load dynamic library `D:\WebServer\php\ext\php_pgsql.dll` - тут вместо сообщения какая-то каша, но явно что-то не в порядке.

Оказалось, не хватает dll для данных расширений.

Нужны библиотеки:


libpq.dll, libiconv-2.dll и libintl-8.dll Взять их можно в установленном PostgreSQL, в папке:
C:\Program Files\PostgreSQL\9.4\bin\
вместо 9.4 может быть ваша версия.
Копируем их в:
apache\bin\

Вместо libiconv-2.dll у меня лежала iconv.dll, на всякий случай скинул как есть, так и копию переименованную в libiconv-2.dll
Перезапускаем apache и видим что Laravel 5 на эту проблему больше не ругается.
В один прекрасный момент заметил что до этого работающий парсер начал вместо нормального текста показывать крокодилов. Недолгие поиски привели к решению:
<?php
$url = file_get_contents('your-xml-file.xml');
//именно эти строчки и выравнивают всю кривость кодировки
$url = mb_convert_encoding($url, 'utf-8', mb_detect_encoding($string));
$url = mb_convert_encoding($url, 'html-entities', 'utf-8');
$dom = new DOMDocument();
$dom->loadHTML($url);
$page_content = $dom->saveHTML();
Все.

Задача:

Выводить собственную страницу 404

Решение:

Открываем файл app/Exceptions/Handler.php и немного меняем код функции render:
//...
public function render($request, Exception $e)
{
//customize 404 page
if ($this->isHttpException($e)) {

$statusCode = $e->getStatusCode();

switch ($statusCode) {
case '404':
//путь к файлу с HTML разметкой
return response()->view('front/notfound');
}
}
return parent::render($request, $e);
}
//...
Вот собственно и все. Нашел как-то на страницах интернета, ссылку на источник не помню.

Задача создавать Sitemap.xml по крону.

Как и говорит нам документация по Laravel 5. В нем уже есть готовый планировщик, достаточно добавить его один раз в крон, а все нужные задачи подключать уже в него. Создаем задачи для планировщика
#php artisan make:console XMLSitemap
Console command created successfully.
Новый файл будет создан по пути...

Задача

Если в конце ссылки присутствует символ "/" делать редирект 301 на страницу без него самого.
Задача типичная, значит решение найти не сложно
Итак, создаем Middleware:
#php artisan make:middleware RedirectTrailingSlash
Middleware created successfully.
Заполняем наш файл (app/Middleware/RedirectTrailingSlash.php) соответствующим кодом:
<?php namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Str;

class RedirectTrailingSlash {

/**
* Handle an incoming request.
*
* @param  \Illuminate\Http\Request  $request
* @param  \Closure  $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (preg_match('/.+\/$/', $request->getRequestUri()))
{
//в исходном коде использовалась другая функция редиректа, выбивало ошибку
return redirect(rtrim($request->getRequestUri(), '/'), 301);
}
return $next($request);
}
}

Регистрируем наш Middleware в Http/Kernel.php:
'front.trailingslash'=>'App\Http\Middleware\RedirectTrailingSlash',

Используем. Я использовал его в конструкторе базового контроллера, чтобы все наследующие контроллеры его выполняли:
//...
class BaseController extends Controller {

//...
public function __construct()
{
$this->middleware('front.trailingslash');
//...
}
//...
}

Все. Теперь при переходе на ссылку вида /our/url/ нас перешлет на /our/url
CKEditor Нужно мне к очередному проекту прикрутить CKEditor + простой загрузчик файлов. Использовать внешний загрузчик не вижу смысла, а тот интерфейс который предоставляет нам CKEditor для загрузки файлов нам вполне годиться. Сам проект использует базовый фреймворк Laravel 5.
Создаем контроллер для загрузки файлов, выполнив команду из консоли:
Получил ошибку в MySQL/MariaDB:
Table 'sources_template_fields_value' doesn't exist in engine

До этого переносил базу файлами, просто скопировав /var/lib/mysql

Чтобы починить нужно для нужной таблицы выполнить следующие команды:
alter table sources_template_fields_value discard tablespace;
alter table sources_template_fields_value import tablespace;

После этого табличка снова в строю.
Там где обычная логика не действует, действует какая-то сказочная. Вот так и в этом случае, неожиданно, в сложном запросе с подзапросом нужно выбрать сумму товаров всех, и отнять сумму товаров с определенной категории.
select (sum(total_price)-(select sum(z_sum) from user_orders where user_id=4  and zennobox=1 and status=2)) as sum from user_orders where user_id=4;


И тут так получилось что все время на тестовый запрос я получал NULL. Начал проверять и оказалось что число-NULL = NULL. Печально, когда даже не догадываешься о таком. Но решение тут простое, добавляем функцию ifnull(value,default):
select (sum(total_price)-ifnull((select sum(z_sum) from user_orders where user_id=4  and zennobox=1 and status=2),0)) as sum from user_orders where user_id=4;


Получаем то что нужно. Очередная мелочь, которая привносит небольшие приключения в нашу жизнь.
Собственно для тех кто не знает что такое PhantomJS, вещает хабр:
PhantomJS это все плюшки WebKit из консоли с управлением на JS и поддержкой различных стандартов и технологий: DOM, CSS, JSON, Canvas и SVG.

Прикручивают его для разных целей, для тестирования, парсинга и для любой другой автоматизации связанной с загрузкой страниц, особенно с поддержкой JavaScript.

CasperJS - это надстройка над PhantomJS позволяющая более удобно его использовать. Добавляется сохранение скриншота части страниц, более удобная работа со страницей и другие плюшки.

Стала задача для сайта все-таки подключить свой домен и перенести комментарии на него. Решается все просто. В контакте, внизу страницы, переходим по ссылке "Разработчикам", переключаемся на "Мои приложения", напротив нужного нам нажимаем "Редактировать"->"Настройки".
Смотрим поле "Базовый домен" и добавляем новый.

Вот и вся проблема.
На любопытную страничку наткнулся на просторах интернета. А искал я сравнение производительности XMLHttpRequest с jQuery get и post. И в общем-то на страничке можно провести сразу тест для конкретной своего браузера и посмотреть результаты других.

И получилось у меня что xhr3 всех быстрее, ну и раза в два быстрее jQuery методов. Оно в принципе и не удивило бы ни кого, скорее удивило бы обратное. Но все же интереснее смотреть на цифры.

P.S. К сожалению время от времени сайт не доступен, хотел картинку сюда вставить, но увы. Пробуйте, время от времени он все же работает.
Функции SizeOf для JavaScript нету, но зная типы данных и их размер, можно такую написать самостоятельно. А так как мы люди ленивые, то просто посмотрим гугл и найдем подходящий:

function roughSizeOfObject( object ) {
    var objectList = [];
    var recurse = function( value ) {
        var bytes = 0;

        if ( typeof value === 'boolean' ) {
            bytes = 4;
        } else if ( typeof value === 'string' ) {
            bytes = value.length * 2;
        } else if ( typeof value === 'number' ) {
            bytes = 8;
        } else if (typeof value === 'object'
                 && objectList.indexOf( value ) === -1) {
            objectList[ objectList.length ] = value;
            for( i in value ) {
                bytes+= 8; // assumed existence overhead
                bytes+= recurse( value[i] )
            }
        }
        return bytes;
    }
    return recurse( object );
}


Проработавшая база данных, некоторый период времени, не исключая, а по некоторым данным и утверждая что InnoDB тем более, фрагментируется, и начинает работать медленно. Требуется оптимизация. Скрипт найденный на stackoverflow.com, проверен на личном опыте.
Делайте Backup, не надейтесь на то что повезет, 1 раз если не повезет, будет хуже чем если 100 раз повезет

Создаем файлик optimizedb.sql
set @a=null,@c=null,@b=concat("show tables where",ifnull(concat(" `Tables_in_",database(),"` like '",@c,"' and"),'')," (@a:=concat_ws(',',@a,`Tables_in_",database(),"`))");

Prepare `bd` from @b;
EXECUTE `bd`;
DEALLOCATE PREPARE `bd`;

set @a:=concat('optimize table ',@a);
PREPARE `sql` FROM @a;
EXECUTE `sql`;
DEALLOCATE PREPARE `sql`;

set @a=null,@b=null,@c=null;


Ну и скармливаем его нужной базе данных:
mysql -p mydb < ./optimizedb.sql


Дальше ждем результат. После окончания скрипт выведет результаты и завершиться.
Наверное на текущий момент, карты Yandex являются одними из самых удобных и функциональных. Прикрутить их не сложно, не хватает только нормальных материалов с примерами. Понятно что есть официальная документация, которая позволяет сделать почти все что хочешь и много того что не хочешь, но в кипе информации, для разных версий API найти то нужное понимание не легко. Иногда проще по примеру разбираться что и аз что отвечает.

Так вот, Яндекс.карты это не сложно. Есть два вида геокодирования, прямое и обратное. В одном случае мы получаем по текстовому адресу координаты на карте, во втором - по координатам получаем текстовый адрес. Вариантов размещения точек на карте API карт тоже имеет не один.

Небольшое отступление: Для себя я использую фреймворк Kohana 3, но в общем, это не вносит практически никаких корректив в код. Использую ORM, но не думаю что для кого-то будет сложность заменить $object->title на $row['title']. Главная же цель, показать что все не так сложно как кажется. Еще что следует учесть, что мы используем координаты заранее сохраненные в базе. Для этого в конце статьи есть ссылка к Yandex API, по которой можно получать координаты. Лучше всего один раз спросить API карт и сохранить результат у себя, чем лишними запросами дергать их API

Остальное внутри

После обновления перестали подключаться воркеры к Gearman. Долго не мог понять в чем причина, ведь и в логах чисто, и в настройках сервера все в порядке. Но в англоязычном сегменте интернета с этим уже сталкивались. Вся проблема заключалась в том что теперь нужно указывать хост и порт для подключения.
То есть было:
$client->addServer();
А стало:
$client->addServer('127.0.0.1',4730);


После этого воркеры снова стали подключатся. Вот такая небольшая заметка, может кому еще поможет.
Заметка в этот раз будет очень короткая.

Иногда стоит задача, как например замена и/или добавление заголовков в передаваемый запрос. К примеру стоит задача написать парсер, который парсит картинку, но картинка отдается сервером только после проверки заголовка Referer.

В этом классно помогает расширение для Chrome/Chromium: Modify Headers for Google Chrome

Работать очень просто, нажимаем плюсик справа вверху. Заполняем появившуюся строчку. Нажимаем стрелочку запуска слева вверху. И теперь во все открываемые страницы.

Вот собственно и все.
Может быть я плохо искал, а может действительно ее и нет, но я так и не нашел функцию которая от сервера возвращает текущее положение Gearman: какие очереди висят, количество воркеров на текущий момент в очереди, количество на текущий момент выполняемых задач. Но сам код для получения такой информации достаточно прост:

function action_index()
    {
        $info = shell_exec('gearadmin --status');
        $count = explode(chr(10),$info);
        $tasks = array();
        foreach ($count as $row){
            $record = explode("\t",$row);
            if (count($record)>3){
                $tasks[$record[0]] = array(
                    'name'=>$record[0],
                    'queue'=>$record[1],
                    'running'=>$record[2],
                    'workers'=>$record[3],
                );
            }

        }
        return $tasks;
    }
Вот и весь код.
ion.RangeSlider Слайдер Ion.RangeSlider мне очень нравиться, работать удобно, гибкость большая. Но есть в нем один неприятный баг(может и больше, но мне попался именно этот). А именно, если слайдер инициализируеться в не отображаемом блоке, то его ширина сбрасывается и значение каждого значения шкалы будет left:-1;

Исправляется это легко. Просто при отображении скрытого блока, в котором у нас и находиться один или несколько слайдеров, вызываем функцию update, даже без параметров. Выглядит это так:
$(".ionrange").ionRangeSlider("update");


Сам баг уже описан и там же отвечен.
Всем кто занимается версткой под андроид не хватает Developer Tools в Chrome на смартфонах и планшетах Android. Но не каждый знает что можно с компьютера использовать Developer Tools для подключенного к нему планшету/смартфону. А делается все очень просто.
  1. Подключаете через USB устройство
  2. Подключаемое устройство выведет меню и в нем мы разрешаем отладку (Отладка по USB | "Enable USB debugging on your Android device")
  3. На компьютере в Chrome/Chromium в строке для URL вводим chrome://inspect и жмем Enter.
  4. На вкладке Devices Включаем Discover USB devices
  5. В списке появятся подключенные к компьютеру устройство
  6. Под нужным устройством нажимаем inspect
После этой последовательности действий Chrome/Chromium создаст новое окно в Developer Tools отображаемом для выбранного устройства. Выглядит это так:


Более подробно можно глянуть здесь.
Бывает так что существующие темы уже попросту допекли. Хочется создать свою тему. А иногда просто хочется разгрузить мозги и сделать что-то простое и приятное. Чем и займемся. Сильно с темизацией конечно не разгонишься, но кое-что приятное сделать можно. Если что-то будет непонятным, есть официальный гайд по созданию темы для браузера хром. Немного анатомии тем для хромиума/хрома.

Картинки

Используется 5 картинок: 1) Фрейм темы – Картинка отображается как рамка для кнопок "Закрыть", "Развернуть", "Свернуть". Если вы решите их не использовать(не добавите в свою тему), браузер будет использовать картинки с дефолтной темы. Требование к картинкам: Минимальная высота: 30px. Нет ограничений по ширине. Панелька(toolbar) – Фоновая картинка для кнопок "Назад", "Вперед", "Обновить" и всего этого ряда кнопок. Требования: Минимальная высота: 120px. Нет ограничений по ширине. Бекграунд для вкладок(табов) – Картинка используется для неактивных вкладок, когда открыто несколько вкладок. Требования: Минимальная высота: 65px. Бекграунд для вкладки "Добавить новую" – Эта картинка отображается в основной части окна для вновь созданной вкладки. Минимальный рекомендуемый размер 800x600, но любая картинка будет масштабирована под разрешение. Атрибуты темы – Картинка отображаемая в правом нижнем углу любой темы для Хрома.
Gearman stack

Что такое Gearman?

Введение весьма неплохо описано тут
Если вкратце то Gearman это менеджер очередей состоящий из трех компонентов:
  • сервер задач — является центральной частью Gearman, именно сюда будут приходить задачи и результаты от клиентов и исполнителей, и именно отсюда будут высылаться задания и результаты, исполнителям и клиентам соответственно.
  • исполнитель — является основной частью, где необходима реализация какой-либо функциональности. Исполнитель принимает и пытается выполнить задание от сервера.
  • клиент — также имплементируется отдельно, создаёт и отсылает задачу на сервер и, в некоторых случаях (о них — позже), получает результат.
Картинка в топе поста показывает алгоритм работы с Gearman-ом.

Кратко от авторов Gearman

  • Open Source и BSD лицензия.
  • Мультиязычность - Большой список поддерживаемых языков.
  • Гибкость - Вы не ограничены какими-либо паттернами проектирования.
  • Скорость - Gearman работает на простом протоколе и с оптимизированным интерфейсом, потоками. Сервер написан на C/C++ для минимизации оверхедов.
  • Встраеваемый - быстры и легкий, удобен для любых масштабов приложений. Так же легко внедряется в существующие приложения с минимальным оверхедом.
  • Нет единой точки отказа - Gearman помогает не только в масштабировании систем, но и в повышении отказоустойчивости.
  • Нет ограничений на размер сообщения - Gearman поддерживает размер каждого сообщения до 4Гб в размере. Нужно больше? Не проблема, Gearman может делить сообщения на части.
  • Обеспокоены масштабированием? - Не стоит. Craig’s List, Tumblr, Yelp, Etsy,… откройте для себя то о чем они уже знают годами.
Пример, прекрасно иллюстрирующий для чего он нужен так же описан был на хабре весьма точно:
Пользователь закачал фотографию на сайт, и хочет показать её всем своим друзьям. Необходимо быстро подготовить различные размеры данной фотографии, для использования по всему сайту. Да, до определённого момента все работы по генерации графики можно проводить в основном коде системы, а потом придёт хабраэффект, и вся система рухнет под наплывом желающих. Теперь рассмотрим как эту задачу можно решить с использованием Gearman — при получении фотографии, мы создаём задачу для gearman сервера, в которую входит необходимая информация о фотографии (в принципе возможно включить в задачу даже саму фотографию, но, мне кажется, это будет накладно, лучше использовать адрес) и отправляем её на выполнение. Сервер задач выбирает (round robin) свободного исполнителя (как Вы наверное уже догадались, исполнителей может быть несколько) и отсылает задачу на выполнение. Исполнитель получает всю необходимую информацию, обрабатывает её как нам бы этого и хотелось — и отправляет ответ об успешно выполненной задаче и, если задача была синхронная, результат работы.
Врапперов к языкам для работы с Gearman достаточно много, так что все основные языки будут иметь возможность взаимодействовать с ним, среди них perl, php, python, java, C и другие. Сервер имеет возможность сохранять очередь задач в какое-либо хранилище, чтобы при рестарте была возможность восстановить весь процесс без потери данных. Хранилищем может выступать MySQL/drizzle, memcached, PostgreSQL или sqllite. Основной обьект над которым происходит вся работа в системе - Задача(Task), имеющая параметры. Идентифицируются задачи по ключу Название/Параметры. При полном совпадении ключей двух задач, будет выполнена только одна, остальные идентичные ей будут отброшены.

Установка

apt-get install gearman gearman-server gearman-job-server gearman-tools  php5-gearman

Celery Logo

Предисловие

Статья получилась относительной, отчасти удачной, отчасти нет. Сразу оговорюсь, использовать в PHP у меня его так и не получилось. После запуска сервера и ввиду того что я не нашел нормальной библиотеки для Celery под PHP я отказался от его использования. На момент написания статьи появились не исправленные пока Deprecated функции в библиотеках, а больше времени на эксперименты в глубине чужих библиотек у меня не было. Но, возможно кому-то она все-таки поможет.

Что такое Celery(Сельдерей)

Со слов статьи на хабре
Это распределенная асинхронная очередь заданий, которая обладает широким функционалом.

И так, что же умеет Celery:

  • Выполнять задания асинхронно или синхронно
  • Выполнять периодические задания(умная замена crond)
  • Выполнять отложенные задания
  • Распределенное выполнение (может быть запущен на N серверах)
  • В пределах одного worker'а возможно конкурентное выполнение нескольких задач(одновременно)
  • Выполнять задание повторно, если вылез exception
  • Ограничивать количество заданий в единицу времени(rate limit, для задания или глобально)
  • Routing заданий(какому worker'у что делать)
  • Несложно мониторить выполнение заданий
  • Выполнять подзадания
  • Присылать отчеты об exception'ах на email
  • Проверять выполнилось ли задание(удобно для построения Ajax приложений, где юзер ждет факта завершения)

Подготовка

Что такое Composer?

Composer (getcomposer.org) — это относительно новый и уже достаточно популярный менеджер зависимостей для PHP. Вы можете описать от каких библиотек зависит ваш проект и Composer установит нужные библиотеки за вас! Причём Composer — это не менеджер пакетов в классическом понимании. Да, он оперирует с сущностями, которые мы будем называть «пакетами» или библиотеками, но устанавливаются они внутрь каждого проекта отдельно, а не глобально (это одно из основных отличий от старого-доброго PEAR).

Кратко, как это работает:
У вас есть проект, который зависит от нескольких библиотек.
Некоторые из этих библиотек зависят от других библиотек.
Вы описываете в своём проекте те библиотеки, от которых непосредственно зависит ваш код.
Composer находит нужные версии требуемых библиотек для всего проекта, скачивает их и устанавливает в папку вашего проекта.

При создании Composer авторы черпали идеи и вдохновение из аналогичных проектов: npm для Node.js и Bundler для Ruby.
Так нам об этом говорит Хабр

Composer и Kohana 3

Composer включен в Kohana 3 по умолчанию, использовать его легко и просто.

Ищем нужный нам пакет в репозитории.
Нашли? Открыли? В описании мы видим графу require: "massivescale/celery-php": "dev-master"

Дальше в корне проекта выполняем:

php composer.phar require  massivescale/celery-php

После этого composer спросит версию репозитория с которого тянуть файлы, вписываем ему dev-master и жмем Ввод. Выглядит это так:

Please provide a version constraint for the massivescale/celery-php requirement: dev-master

Дожидаемся сообщения.

./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing videlalvaro/php-amqplib (v2.2.6)
    Downloading: 100%        

  - Installing massivescale/celery-php (dev-master df7be31)
    Cloning df7be316f47bf6f812f08e2142f40da5ef39a041

Writing lock file
Generating autoload files

Которое означает что пакет был добавлен в папку vendor. В ту же папку Composer скачает все пакеты от которых зависит скачиваемый вами пакет.

Так же может быть что Composer выдаст сообщение требующее обновление его самого:
This dev build of composer is outdated, please run "composer.phar self-update" to get the latest version.
Так и делаем:

php composer.phar self-update

Но это немного не все. Чтобы включить Autoloader в Kohana 3 и использовать библиотеки нужно добавить строку в bootstrap.php:

require(DOCROOT.'vendor/autoload.php');

Добавляем его до загрузки модулей.

Автоподгрузка классов Composer уже встроена в Kohana 3, по этому кроме добавления выше указанной строки других сложностей в использовании пакетов не возникает:

$c = new Celery('localhost', 'myuser', 'mypass', 'myvhost');
$result = $c->PostTask('tasks.add', array(2,2));

Все остальное по аналогии.

Хостинг unihost.com

Нет времени распыляться на описание данного хостера, как делают многие блогеры, я лучше еще кусок какого-либо из своих проектов за это время напишу(На блог внимание не обращать, реально руки не доходят его переписать).
Скажу основное:
Повесил собственноручно около десятка сайтов на данный шаред хостинг за этот год. Из них несколько самописных на фреймворке Kohana 3, несколько на Drupal. 1000+ в день держит спокойно. Саппорт вменяем. Обращался раз 6 за год. Пару раз просто уточнить некоторые детали. Все вопросы очень быстро решаются через онлайн-чат с саппортом. ISPmanager, FTP доступ, PhpMyAdmin, прочее. Так что, со спокойной совестью рекомендую.

Что должен делать IT-шник постоянно? Правильно, это знает наверное каждый - учиться. И вот расширяя кругозор и углубляясь все больше и больше в использование Баз данных я сделал очередной виток в поиске полезной информации по инструментарию который использую.

Responsivefilemanager

Действительно прикольный и удобный файлменеджер для загрузки файлов и картинок. Скачать можно на самом сайте плагина.

Удобный, красивый и просто подключается. Все плюшки можно увидеть прямо на самом сайте. К тому же он бесплатный, единственное что просит сам автор это возможной финансовой поддержки, по желанию использующих плагин.

Страницы