web-development

Хостинг с которым я работаю. Так что это даже как-бы не реклама

Хостинг unihost.com плюс домен бесплатно
Пользовательский поиск

Понравилось? Поделитесь с знакомыми и друзьями!

Пропустил я их в свое время и многие методы освоил по кускам из разных материалов =) а тут все скопом. Берем и проходим. Каждое видео минуты 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

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

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

Валидация
Просто еще небольшая заметка на память, чтобы не копаться по всему интернету. HTML5+CSS3 сейчас сильно упрощает жизнь. Раньше столько сложностей было в том чтобы сделать резиновые формы, а сейчас достаточно использовать условные единицы измеряемые в %% от ширины(vw) или высоты(vh) viewport-а. Как многие знают, размер шрифта используемый единицы em, %% или другие, казалось бы динамические единицы измерения на самом деле берут всего-лишь значение базового шрифта, но сейчас можно использовать все те же vw и vh для задания пропорционального всем другим элементам размера шрифта. Замечу что в хроме и хромиуме, как возможно и во всем остальном на основе webkit, есть баг, при изменении размера окна, размер шрифтов автоматически не пересчитывается. Но этот баг вроде должны поправить к новым версиям.

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

Сама форма, к примеру

Страницы