- PVSM.RU - https://www.pvsm.ru -

Файловый менеджер (Silex + Kendo UI) — Tutorial

Внезапная история из прошлого! Дело было так. Несмотря на то, что я программист «немного другого толку», обратились ко мне со стандартной просьбой – сделать сайт. Обычно я не берусь за подобные дела, но в этот раз решил немного подзаработать, тем более что это был не сайт-визитка или интернет-магазин, а нормальный сайт с базой некоторых объектов, объекты добавляются-редактируются-удаляются (аля CRUD) и с ними необходимо выполнять некоторые операции. О! подумалось мне, да это идеальная задача для (название фреймворка скрыто) и после всяческой бухгалтерии я незамедлительно приступил к делу.

Собственно дальше ничего интересного и необычного так и не произошло. Спустя какое-то время заказчику был продемонстрирован сайт. И… он остался доволен. Очень неожиданное завершение истории.

Правда, появилась небольшая как бы просьба. Файловый менеджер, тот, с помощью которого на сайт в статью можно вставить картинку, ему не понравился. Вот хотелось ему чтобы всё как-то проще было. А тут и кнопок целых 20! Да и действий много. А нужно-то всего-навсего загрузить картинку на сервер и вставить на страничку. Ну ладно, подумал я, их же целый интернет, да и сам я много раз делал подобные решения. Но один страшен, как чёрт, другой по одному файлу загружает за раз, а вот третий ничё так вроде, но платен. В общем, история завершилась быстро, созданием простенького файлового менеджера с нуля. Но как-то сиделось мне, да и взгрустнулось. И выпил я (сока с мякотью, конечно). И открыл IDE и понеслось…

Файловый менеджер (Silex + Kendo UI) — Tutorial

Поправил я код, добавил туда кучу некоторых особенностей и написал эту статью, в которой попробую рассказать, в отличие от кучи мануалов, никак сделать блог, а как сделать файловый менеджер на Silex + Kendo UI. Без БД, без просмотрщика и редакторов и без прочей «шелухи».

Сперва начну с того, что попытаюсь объяснить, почему я выбрал именно эти инструменты (фреймворки).

Silex – микрофреймворк, про который я много раз слышал отзыв: “Так в нём же нету нихрена!”. А вот это неправда, Silex – вполне логичное решение, а заключалось оно в том, чтобы взять огромный такой Symfony2 и удалить папку vendors. Совсем. Придумали же ведь Composer – «инструмент», про который много уже писали, а умеет он, на основе содержимого файлика composer.json взять и скачать актуальные версии нужных библиотек (вендоров – vendors). Нужен нам ORM для доступа к БД, любим мы шаблонизатор TWIG, хотим в redis-ке хранить значения. Пропишем в composer.json нужное, выполним команду php composer.phar install и вот Silex не такой уж и никакой.
А вот для файлового менеджера он подходит куда как лучше, чем некоторые другие громоздкие решения.

Нужно определиться, что нам будет нужно от silex:
1) Конечно, решение на популярном фреймворке само по себе уже хорошо
2) Работа с сессиями
3) Работа с ответами (response и redirect)
4) Шаблонизатор twig
Немного дополню, почему я так люблю twig и всячески склоняю других его использовать. Я не верстальщик, но очень часто мне приходится работать в шаблонами (view) в привычном для php виде: т.е. использовать вставки из php. «php мощный, он сам себе шаблонизатор!» — повторяют ребята напротив. Так-то оно да, но он слишком мощный шаблонизатор. Я много раз ловил себя на мысли, что я пишу в шаблоне логику! А этого делать категорически нельзя! Так вот twig заставляет переосмыслить процесс создания шаблонов. Он достаточно мощный, чтобы уметь делать многое, и в то же время он оставляет идеи «попрограммить» в шаблоне.

Ну ладно, с php фреймворком решили — пускай будет. А почему kendo ui? Он же большой? Ну да, он действительно не маленький. Но, во первых-сайт который я делал уже использовал kendo, а во-вторых решение на этом JS фреймворке выглядит красиво. Из больших (известных) решений есть ещё ExtJS, но к нему я испытываю стойкую нелюбовь. Пахнет он плохо, и не красивый, имхо.
Что нам нужно от kendo:
1) window [1]
2) splitter [2]
3) uploader [3]
4) menubar [4]
5) treeview [5]
Кстати, если взять сторонние js либы для таких целей, то получится уже не слишком маленькой решение.

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

Response

У Symfony2 и конечно же у Silex есть очень удобная для работы особенность – они позволяют управлять исходящими (response) запросами. Данное приложение активно использует javascript, а js (в частности jquery ajax), может по-разному реагировать на ответ от приложения. Другими словами, если ajax функция получит нормальный ответ с кодом 200 – она отреагирует так-то, а если ошибку – по-другому. Например, jquery функция ajax может обрабатывать методы onSuccess (ответ 200 OK) и onError(не 200, а например, 500) (onSuccess и онError с недавних пор — done и fail). А с помощью вендора HttpFoundationResponse можно, как раз, отправить ответ с нужным кодом.

Где это используется – пытаемся сохранить файл (загрузить) в файловой системе. Но системный администратор, что-то там намудрил, и вместо пользователя www-data папка стала принадлежать пользователю root. Значит, сохранить файл мы не сможем – не хватает прав. Запишем полученную ошибку в переменную $this->error. А в функции-обработчике действия (сохранений картинки) сделаем так:

if ($save->handleUpload($sPath, $_thumbPath)) {
        return new Response('', 200);
} else {
        return new Response($save->getError(), 200);
}

Где, handleUpload – функция которая сохраняет файл, если операция удалась – вернёт TRUE, в противном случае FALSE.

Namespaces

Silex старается использовать все новшевства php, и в частности активно использует namespaces.
В принципе, можно использовать и обычный include, но это как-то не кашерно. Воспользуемся способом, который предлагает Silex, а тот в свою очередь с недавнего времени переложил функцию «регистрации адресного пространства» на composer.

И так. В нашем файловом менеджере можно выделить две логические части:
1) работа с файловой системой;
2) сохранение файлов и генерация превьюшек для изображений.
Создадим два класса: class Files {} и class Save {}. Каждый класс будет находиться в одноимённом файле в папке: /src/Fm/Components. Чтобы наше приложение понимало откуда нужно загружать эти файлы, пропишем в composer.json:

"autoload":{
        "psr-0":{
            "Fm" : "src/"
        }
    }

А теперь выполним команду:
php composer.phar update

Теперь можно использовать наши классы, но перед этим не забываем объявить их

use FmComponentSave
use FmComponentFiles

Оценить прелесть использования namespaces можно только в большом приложении, но тем не менее, нужно стараться использовать «правильные» методы. Ведь очень часто бывает, что если пренебречь такой, казалось бы малостью, позже может получиться так, что приложение разрослось и уже поздно думать о рефакторинге, и дешевле его переписать с нуля.

Depency Injecting

Следующая особенность фремворка Silex – вездесущий Depency Injecting. Если вы слышали об оном из Symfony2 может показаться, что это какая-то страшнейшая и мутнейшая хня, которая нужна только в Entrprise. И вот снова это мнение не верное.
1) Все тексты о DI – сплошь корявый промтовский перевод с английской документации, которая генерировалась в phpDocumentaror-е
2) Люди, которые работают в этом самом Entrprise, говорить простыми словами не могут или же не хотят, потому что что-то знают. IT буддисты.

Вернусь к DI. Класс Files() много где используется в коде. Если работать по старинке, то в каждом действии, придётся создавать новый объект new Files(). DI позволяет создать объект только один раз:

$app['files'] = function() {
    return new Files();
};

И позже уже иметь его копию обращаясь к $app['files']. Но, важно помнить, что:


$app['files']->getFiles($dir); //получаем список файлов в private $_files;
$app['files']->getFolderFiles(); //геттер, возвращает массив $_files;

Не сработает! Потому что, нужно делать так:

$class = $app['files'];
$class->getFiles($dir); //получаем список файлов в private $_files;
$class->getFolderFiles(); //геттер, возвращает массив $_files;

Другими словами, при каждом обращении к $app['files'] будет создана новая копия «сервиса». Новый «сервис» можно создать и так:

$app['some_service'] = $app->share(function () {
    return new Service();
});

Тогда в процессе выполнения приложения всегда будет одна его копия.

Файловый менеджер выложен на Github [6].

В этой статье не рассмотрена библиотека kendo ui. В принципе, если будет желание — можно сделать беглый её осмотр, с особенностями, которые затрагивают тему файлового менеджера.

Автор: Zazza

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/27282

Ссылки в тексте:

[1] window: http://demos.kendoui.com/web/window/index.html

[2] splitter: http://demos.kendoui.com/web/splitter/index.html

[3] uploader: http://demos.kendoui.com/web/upload/index.html

[4] menubar: http://demos.kendoui.com/web/menu/index.html

[5] treeview: http://demos.kendoui.com/web/treeview/index.html

[6] Github: https://github.com/Zazza/fm-silex-kendo

[7] Источник: http://habrahabr.ru/post/168829/