А именно — начать использовать менеджер зависимостей для PHP — Composer. Он позволит нам легко устанавливать разные полезные вещи на сайт, обновлять их и даже удалять. Если вы уже работали с менеджером пакетов GNU/Linux — то вам всё это будет очень знакомо.
В качестве разминки, удалим Fenom из директории core и установим через Composer. Для этого нужно в корне сайта создать файл composer.json и прописать в нём требуемые пакеты (подробнее можно прочитать на Хабре):
{ "require": { "php":">=5.3.0", "fenom/fenom": "2.*" } }Теперь нужно только скачать composer.phar и запустить его в корне сайта:
php composer.phar installНа 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.
Еще раз, для закрепления:
- Пишем composer.json
- Устанавливаем пакеты через composer.phar
- Подключаем в проект /vendor/autoload.php
- Используем любые установленные классы через new Class()
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
Теперь в начале каждого класса пишем используемое пространство имён. У основных классов это:
<?php namespace Brevis;А у контроллеров:
<?php namespace Brevis\Controllers;
PhpStorm сразу начинает подсвечивать нам все использования Exception и Fenom как неправильные, потому что они вызываются внутри пространства имён, но без указания полного имени. Тут 2 варианта исправления:
- Пробежаться по всему коду и добавить к именам этих классов \, чтобы было \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-ветке) и подключим его к нашей БД.
Напишем схему, сгенерируем по ней модель и создадим пару таблиц.
← Следующая заметка
Подключаем xPDO
Подключаем xPDO
Предыдущая заметка →
Расширение и наследование шаблонов Fenom
Расширение и наследование шаблонов Fenom
Понял, что со стандартизацией и автоматизацией в разработке гораздо проще и удобней.
Я так подозреваю, что для создания даже такого мини фреймворка, всё равно требуется сначала составить логику работы этого фреймворка или всё проще?
Ну а в целом, всегда есть любимые решения:
— Fenom для шаблонизации
— xPDO для работы с БД
— PhpMailer для почты
— Parsedown для работы с Markdown.
Если понадобится что-то еще, просто гуглю, смотрю документацию и устанавливаю через Composer. Не понравилось — удаляю и ищу что-то новое.
Имя пользователя, сервер и пароль для SSH показываются в окне информации сайта на modhost.
Если нет, сильно ли мне это затруднит изучение дальнейших материалов курса?
В принципе, можно скачать всё нужное из репозиториев на GitHub и залить на сервер, но через Composer, конечно, было бы в разы удобнее.
Есть еще вариант запускать composer из php скрипта через браузер. Ну и можно, конечно, купить сайт для разработки на modhost.pro за 75 руб — там всё есть.
Теперь осталось разобраться, что он мне там поустанавливал.
Но почему то сайт не работает, и вот эта строка в конце урока
выдает ошибку Could not open file: composer.
Видимо что то не туда положил, но в итоге застрял и что делать не знаю. Нужна подсказка.
И еще обрати внимание, что ты положил composer.json выше директории core (рядом с www), а не внутри. Так тоже можно, но нужно будет поменять путь к autoload.php.