Осваиваем Composer
Ну что, на прошлом уроке мы фактически закончили писать ядро нашего сайта, и с этого момента я предлагаю завязать с велосипедостроением и припасть к достижениям мирового сообщества.
А именно - начать использовать менеджер зависимостей для PHP - Composer. Он позволит нам легко устанавливать разные полезные вещи на сайт, обновлять их и даже удалять. Если вы уже работали с менеджером пакетов GNU/Linux - то вам всё это будет очень знакомо.
В качестве разминки, удалим Fenom из директории core и установим через Composer. Для этого нужно в корне сайта создать файл composer.json и прописать в нём требуемые пакеты (подробнее можно прочитать на Хабре):
{
"require": {
"php":">=5.3.0",
"fenom/fenom": "2.*"
}
}
Теперь нужно только скачать composer.phar и запустить его в корне сайта:
php composer.phar install
На https://modhost.pro и качать ничего не нужно - просто запускаем composer в директории:
composer install
И волшебным образом у нас появляется директория /vendor/ с установленным Fenom. Что же с ним делать дальше?
Принцип работы
Давайте немного остановимся, и я объясню, как именно функционирует Composer, если вы еще не знаете.
Composer - это менеджер пакетов, который работает с ними согласно правил в composer.json. То, что мы там напишем, и будет устанавливаться.
При установке пакетов Composer пробегается по их правилам и генерирует самый важный файл - /vendor/autoload.php, который загружает все скачанные классы. Нам, выходит, нужно только подключить этот файл в своём проекте, и с этих пор мы можем запускать свои классы без require:
$Fenom = new Fenom::factory($tplDir, $compileDir);
То есть, система уже знает, где физически находится Fenom и нам не нужно делать reuire_once('путь к fenom'). Также нам не нужно держать сам Fenom в своём проекте, достаточно хранить там наш composer.json.
Еще раз, для закрепления: 1. Пишем composer.json
- Устанавливаем пакеты через composer.phar
- Подключаем в проект /vendor/autoload.php
- Используем любые установленные классы через new Class()
Лишних файлов в проекте нет, лишних require нет, установленные пакеты обновляются через тот же composer:
php composer.phar update
Всё очень просто и удобно. Стоит только раз использовать такую схему работы и велосипедить дальше уже просто невозможно!
Подключаем Fenom
Для работы с установленными пакетами нам нужно просто добавить autoload.php в наш класс Core:
function __construct(array $config = array()) {
$this->config = array_merge(
array(
'controllersPath' => dirname(__FILE__) . '/Controllers/',
'templatesPath' => dirname(__FILE__) . '/Templates/',
'cachePath' => dirname(__FILE__) . '/Cache/',
'fenomOptions' => array(
'auto_reload' => true,
'force_verify' => true,
),
),
$config
);
// Например, вот тут
require_once dirname(dirname(__FILE__)) . '/vendor/autoload.php';
}
Из метода getFenom() теперь можно выбросить проверку и подключение файлов, а также загрузку его классов. Итоговый метод выглядит так:
public function getFenom() {
if (!$this->fenom) {
try {
if (!file_exists($this->config['cachePath'])) {
mkdir($this->config['cachePath']);
}
$this->fenom = Fenom::factory($this->config['templatesPath'], $this->config['cachePath'], $this->config['fenomOptions']);
}
catch (Exception $e) {
$this->log($e->getMessage());
return false;
}
}
return $this->fenom;
}
Просто вызываем Fenom::factrory - и он сам загрузится. Вот коммит с изменениями - смотрите, сколько кода мы убрали сразу из своего проекта!
Зачем нам таскать с собой Fenom и обновлять его вручную, если давно придуман Composer, который об этом позаботится гораздо лучше? Всё, что нам нужно - положить в корень проекта composer.json.
Давайте теперь отрефакторим и наш собственный проект, чтобы он также подключался в autoload.php.
Рефакторинг проекта
Вся эта замечательная автозагрузка работает при помощи пространств имён - namespaces. Это такая фишка для гарантированного отделения имён классов друг от друга. Все классы, как бы, лежат в своих виртуальных директориях, и чтобы их использовать, нужно указывать полное имя или задавать псевдоним. Подробнее можно снова прочитать на Хабре.
При этом, физически файлы должны быть разложены в таких же директориях, чтобы загрузчик знал где их искать. Как именно это работает расписано в официальных стандартах, но я вам советую проглядеть вот эту статью.
Отсюда следует два вывода: Composer можно использовать только в PHP 5.3+, и наш проект нужно переписать так, чтобы он использовал пространства имён.
Первым делом, нужно определить имя для нашего проекта. Пусть будет Brevis - от латинского "короткий". Теперь наша директория /core/ - это пространство имён Brevis. Значит: - Класс Core становится \Brevis\Core и находится в core\Core.php
- Класс Controller становится \Brevis\Controller и находится в core\Controller.php
- Класс Controlles_Home становится \Brevis\Controllers\Home и находится в core\Controllers\Home.php
- Класс Controlles_Test становится \Brevis\Controllers\Test и находится в core\Controllers\Test.php
Обратите внимание, что физическое расположение файлов совпадает с пространством имён. Это потому, что мы уже следуем стандарту PSR-4.
Теперь в начале каждого класса пишем используемое пространство имён. У основных классов это:
<?php
namespace Brevis;
А у контроллеров:
<?php
namespace Brevis\Controllers;
PhpStorm сразу начинает подсвечивать нам все использования Exception и Fenom как неправильные, потому что они вызываются внутри пространства имён, но без указания полного имени. Тут 2 варианта исправления: 1. Пробежаться по всему коду и добавить к именам этих классов \, чтобы было \Exception и \Fenom
- Не страдать фигнёй, а использовать псевдонимы - возможность указать короткое имя для класса
Конечно, выбираем второй вариант:
<?php
namespace Brevis;
use \Fenom as Fenom;
use \Exception as Exception;
И ничего в коде менять не нужно - все вызовы Fenom теперь автоматически будут разрешены в \Fenom на этапе работы.
Теперь переименовываем контроллеры и указываем в них псевдонимы:
<?php
namespace Brevis\Controllers;
use Brevis\Controller as Controller;
class Home extends Controller {
Как видите, изменения кода совсем минимальные. У нас уже была верная структура для работы автозагрузчика, поэтому осталось всего несколько штрихов.
Перемещаем autoload.php из класса \Brevis\Core в index.php, потому что пространство имён Brevis у нас скоро и само будет работать через автозагрузку и лишние require ему не нужны.
Index.php теперь выглядит вот так:
require_once dirname(__FILE__) . '/vendor/autoload.php';
$Core = new \Brevis\Core();
$req = !empty($_REQUEST['q'])
? trim($_REQUEST['q'])
: '';
$Core->handleRequest($req);
Метод \Brevis\Core::handleRequest() переписываем, убирая всякие проверки файлов. Нам нужно проверять только наличие класса, используя get_class():
public function handleRequest($uri) {
$request = explode('/', $uri);
$className = '\Brevis\Controllers\\' . ucfirst(array_shift($request));
/** @var Controller $controller */
if (!class_exists($className)) {
$controller = new Controllers\Home($this);
}
else {
$controller = new $className($this);
}
$initialize = $controller->initialize($request);
if ($initialize === true) {
$response = $controller->run();
}
elseif (is_string($initialize)) {
$response = $initialize;
}
else {
$response = 'Возникла неведомая ошибка при загрузке страницы';
}
echo $response;
}
Как видите, мы определяем полное имя загружаемого контроллера, проверяем его наличие, а если такого контроллера нет - загружаем \Brevis\Controllers\Home.
В общем, вся логика осталась прежней, а количество кода сократилось. Нет ручной работы с файлами, нет никаких require, вся работа по подключению классов лежит на autoload.php. Соотвественно, и параметр controllersPath из системного конфига пропадает.
Осталось добавить и наш собственный проект в автозагрузку. Для этого меняем composer.json вот так:
{
"name": "Brevis",
"autoload": {
"psr-4": {
"Brevis\\": "core/"
}
},
"require": {
"php": ">=5.3.0",
"fenom/fenom": "2.*"
}
}
Блок autoload указывает, что загружать дополнительно, кроме установленных пакетов. Ключ psr-4 указывает, как именно загружать наш проект, и указывает директорию core/ как основную для пространства имён Brevis.
Запускаем
php composer.phar update
и наши классы попадают в автозагрузку. Всё должно работать, смотрим изменения на GitHub.
Заключение
Вот мы и переписали наш проект в соотвествии с последними стандартами в мире программирования на PHP. Согласитесь, было не так уж и страшно?
Зато теперь наш код чистенький, опрятненький, соотвествует стандартам и отлично работает!
На следующем занятии мы установим через Composer xPDO 3.0 (да-да, он уже переписан и поддерживает namespaces, хоть пока и только в dev-ветке) и подключим его к нашей БД.
Напишем схему, сгенерируем по ней модель и создадим пару таблиц.
0
👍
👎
❤️
🔥
😮
😢
😀
😡
22 989
07.06.2015, 09:01:00
16 комментариев
Семён Лобачевский
07.06.2015, 21:19:45
Спасибо за урок! Понял, что со стандартизацией и автоматизацией в разработке гораздо проще и удобней.
07.06.2015, 21:33:11
Согласен! Причём, чем больше используешь готовых пакетов, тем лучше это выглядит. Вот, вчера так за день переписал один проект - аж на душе полегчало!
Семён Лобачевский
07.06.2015, 21:32:41
Вопрос по алгоритму работы приложения, как вы запоминаете что и с чем взаимодействует? Какие классы и методы нужны в том или ином случае? Я так подозреваю, что для создания даже такого мини фреймворка, всё равно требуется сначала составить логику работы этого фреймворка или всё проще?
07.06.2015, 21:36:36
А не нужно ничего запоминать - всё подскажет PhpStorm. Для того мы и пишем ему комментарии у методов и переменных, чтобы быстро переходить по ним. Вся работа разбивается на отдельные мелкие методы, помещается в контроллеры и запутаться сложно.
Ну а в целом, всегда есть любимые решения: - Fenom для шаблонизации - xPDO для работы с БД - PhpMailer для почты - Parsedown для работы с Markdown.
Если понадобится что-то еще, просто гуглю, смотрю документацию и устанавливаю через Composer. Не понравилось - удаляю и ищу что-то новое.
Сергей
22.09.2015, 23:30:00
Вот тут непонятно...каким образом запустить?
23.09.2015, 06:10:17
Зайти в консоль сервера, перейти в директорию с проектом и набрать
Сергей
23.09.2015, 12:09:42
Василий, видимо я совсем новичок)) А как можно попасть в консоль сервера? - гуглил, выдает только консоль контрстрайка...У меня как раз modhost.pro.
23.09.2015, 12:21:31
Вторая ссылка в Яндексе по запросу как можно попасть в консоль сервера.
Имя пользователя, сервер и пароль для SSH показываются в окне информации сайта на modhost.
Сергей
23.09.2015, 18:08:15
Спасибо, буду разбираться!)
05.01.2016, 14:08:32
Василий, А если у меня типовой виртуальный хостинг без доступа к консоли и ssh не будет работать? Есть ли альтернативные способы запустить установку Composer? Если нет, сильно ли мне это затруднит изучение дальнейших материалов курса?
05.01.2016, 14:18:19
Честно говоря, виртуальный хостинг без консоли - это сегодня не совсем типовое. Бывает, что SSH отключен по умолчанию, но можно включить из панели управления.
В принципе, можно скачать всё нужное из репозиториев на GitHub и залить на сервер, но через Composer, конечно, было бы в разы удобнее.
Есть еще вариант запускать composer из php скрипта через браузер. Ну и можно, конечно, купить сайт для разработки на https://modhost.pro за 75 руб - там всё есть.
05.01.2016, 15:17:32
Вот нашел скрипт NoConsoleComposer, который все устанавливает через бразузер. Может кому пригодится. Теперь осталось разобраться, что он мне там поустанавливал.
05.01.2016, 16:47:23
В общем в итоге купил хостинг на modstore. Все установил, код переписал, с GitHub сверился, все нормально. Но почему то сайт не работает, и вот эта строка в конце урока
выдает ошибку Could not open file: composer.Видимо что то не туда положил, но в итоге застрял и что делать не знаю. Нужна подсказка.
05.01.2016, 17:01:19
У нас там всё проще:
И еще обрати внимание, что ты положил composer.json выше директории core (рядом с www), а не внутри. Так тоже можно, но нужно будет поменять путь к autoload.php.
05.01.2016, 17:04:09
А вот этот файл .gitignore зачем нужен? Про него речи в уроке не было но в GitHub он есть.
05.01.2016, 17:04:56
http://habrahabr.ru/post/202696/
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так.
А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен.
Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500
Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи.
...
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо!
Извини, тупанул.