THE BELL

Есть те, кто прочитали эту новость раньше вас.
Подпишитесь, чтобы получать статьи свежими.
Email
Имя
Фамилия
Как вы хотите читать The Bell
Без спама

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

А именно - начать использовать менеджер зависимостей для 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 .

Еще раз, для закрепления:

  1. Пишем composer.json
  2. Устанавливаем пакеты через composer.phar
  3. Подключаем в проект /vendor/autoload.php
  4. Используем любые установленные классы через 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.

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

Отсюда следует два вывода: 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 .

Теперь в начале каждого класса пишем используемое пространство имён. У основных классов это:
PhpStorm сразу начинает подсвечивать нам все использования Exception и Fenom как неправильные, потому что они вызываются внутри пространства имён, но без указания полного имени. Тут 2 варианта исправления:

  1. Пробежаться по всему коду и добавить к именам этих классов \, чтобы было \Exception и \Fenom
  2. Не страдать фигнёй, а использовать псевдонимы - возможность указать короткое имя для класса
Конечно, выбираем второй вариант:
Теперь переименовываем контроллеры и указываем в них псевдонимы:

Перемещаем 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-ветке) и подключим его к нашей БД.

Напишем схему, сгенерируем по ней модель и создадим пару таблиц.

В этом посте я расскажу о личных впечатлениях от использования такой интересной штуки, как . Если кто не в курсе, это менеджер зависимостей для PHP библиотек, который облегчает установку, обновление и поддержку различных библиотек в вашем проекте.Программисту для комфортной работы нужна инфраструктура (это я вам точно говорю:-). Это и удобное кресло, мощная машина с двумя мониторами, и совеременная IDE, средства работы с базами данных, инструменты отладки. Но кроме того важна инфраструктура разработки самого проекта.

Возьмём к примеру Ruby. Этот язык, блин, ну просто законодатель мод в сфере веб-дева. Там и удобные инструменты скаффолдинга (ну в ZF это тоже есть), и такие штуки, как rake для выполнения задач. Я уж не говорю про миграции, юнит-тесты со всяческими mock-объектами. Когда я кодил на Ruby ощущение было сродни тому, что сидишь в комфортабельном кресле в бизнес-классе в самолете и единственной твоей проблемой является выбор напитка под настроение.

Шучу-шучу. Не всё так радужно в Ruby Есть куча кривых гемов, разработчики иногда выпускают такооое чудо, что мама не горюй. Я уж молчу про низкоуровневое шаманство, когда надо сделать что-то типа распределённой или многопоточной системы. Но речь в посте будет не об этом. А о том, что в Ruby есть такая штук, как RubyGems.

RubyGems это система для управления зависимостями в Ruby проекте. В частности есть такая штука как Bundler, который одним движением устанавливает нужные пакеты или обновляет их. Именно с него наглым образом был списан он послужил вдохновением для Composer.

Что умеет Composer

Итак, краткий обзор фич. Их всего две: управление пакетами и автозагрузка классов. Надо сказать, что без composer обе эти задачи отнимали достаточно много времени. Интернет до сих пор пестрит статьями в стиле «как связать ZF 1.x и Doctrine 2» или «как установить Doctrine 2 ODM и Doctrine 1 ORM». Извращение, скажет вы. Я спеуиально утрировал, но согласитесь, приходится довольно сильно заморачиваться чтобы скрестить некоторые фреймворки или библиотеки. С выходом Composer ситуация поменялась.

Отдельное спасибо надо сказать за человеческую автозагрузку. Ух сколько времени я когда-то потратил на интеграцию Zend_Loader_Autoloader и Doctrine/ClassLoader. Теперь это в прошлом. Садимся в кресло

Пример composer.json

Вот пример файла с описанием зависимостей из одного проекта.

{ "require": { "doctrine/common": "2.3.0", "doctrine/migrations": "dev-master", "doctrine/dbal": "2.3.0", "doctrine/orm": "2.3.0", "doctrine/mongodb": "1.0.x-dev", "doctrine/mongodb-odm": "1.0.x-dev", "simukti/zf1": "1.12.0", "zendframework/zendframework": "2.0.3" }, "autoload": { "psr-0": { "ZendExtra": "vendor/netandreus/zend-extra/lib/", "DoctrineExtra" : "vendor/netandreus/doctrine-extra/lib/", "MyProject": "vendor/myvendor/myproject/lib/", "Hydrators": "misc/cache/", "": "app/default/models/" } }

Итак, давайте пройдёмся построчно. В блоке require мы описываем название пакетов в виде vendorName/packageName и минимально необходимые версии для нашего проекта. Потом они будут сами скачиваться и устанавливаться в папку vendor. Как видите Доктрина например раскукожилась сразу в несколько пакетов. Кстати миграции в отдельный пакет выделились совсем недавно, так что следите за новостями проекта. Товарищу simukti выражаю огромную благодарность, за то что он портировал все последние версии ZF 1.x в composer. Когда мне в своё время он понадобился, я начал это делать… да так и не успел в связи с другими задачами. Сейчас же в рамках одного проекта у нас есть возможность использовать компоненты Doctrine 2 ODM + ORM + ZF 1.x + ZF 2.x. Сумасшедший винигрет, но нам он нужен. Т.к. мы потихоньку мигрируем с MySQL (да простит меня Michail Widenius) на MongoDB. Основной костяк — на ZF1, ну а ZF2 — тоже не из праздного любопытсята /* интрига */ .

Теперь вторая часть конфига — require. Тут мы задаём классы (вернее их неймспейсы) и места их хранения, т.е. разрешаем пути для соответствующих неймспейсов. Обратите внимание на несколько моментов. Для гидраторов доктрины (если вы не знаете что это, то можете пропустить) указываем пути, т.к. при отсутствующем автозагрузчике доктрины она не может их найти. Последняя строка — местоположение помойки, где могут лежать классы с любыми неймспейсами. Основная особенность Composer в том, что такая помойка (к счастью) может быть только одна. А вот в нашем проекте классы require’ились откуда попало, поэтому пришлось провести так сказать garbage collection и свалить всё в одну кучу. Придётся конечно когда-нибудь и её разобрать, но теперь по крайней месте весь мусор в одном месте. Ну а ZendExtra и DoctrineExtra — этомои расширения, котоыре я частично описывал в своих постах.

Баги Composer

Ну куда же без багов. Самый пожалуй замечатенльный баг . Когда вы, уверенные, что у вас всё ок, делаете php composer.phar update, вас ждёт … разочарование. Пробелема в том, что composer не выкачивает исходники (вернее не обновляет их) если указана dev ветка, и исходники старше 6 месяцев. К сожалению в моём composer.json такими оказались пакеты с доктриной. Решение простое, перед тем, как делать update удаляем пакеты с доктриной.

Второй баг был в том, что в репозитарийх некоторых пакетов лежит файл.gitignore, который выкачивается при update/install. А если потом исходники проекта (вместе с этим пакетом) закоммитить, то они не дойдёт. Например в assembla, с которйо я работаю появляется некий пустой файл вместо папки с сорцами. При этом коммит и пуш проходит нормально, а траварищи жалуются, что к ним ничего не прилетает. Решение простое, после Update стираем наифг файлы.gitignore из изходников с пакетами.

Использовать или нет Composer?

Да! Как сказал кто-то, ваша библиотека — отстой, если в её корне не лежит файл composer.json Не ну серьезно, прошли времена php 4, phpclasses, кучи автозагрузчиков в стеке. Давайте перестанем плодить говнокод, будем соблюдать стандарты (ну хотя бы psr-0) и писать так сказать код с человеческим лицом. Я всецело за унификацию и стандартизацию! Enjoy!

Спасибо!

Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:

Что это и зачем оно мне надо?

Если у тебя возник этот вопрос, тогда не читай дальше статью и сперва спроси у google “что такое dependency injection?” и зачем тебе нужен dependency manager (в частности ).

Лично у меня уже не существует приложений без composer-а. Особенно при разработке под фреймворк. Вот лишь коренные преимущества использования менеджера зависимостей в проектах:

  • Удобная установка и обновление сторонних пакетов и библиотек
  • Правильный деплоймент
  • Чужой код от сторонних пакетов не коммитится в свой репозиторий, и не мусорит код и статистику
  • Гибкое управление версиями зависимостей

Установка

Тут все максимально просто, но сперва надо определиться с методом использования: один composer для всего localhost-а или каждому проекту свой composer? (можно конечно и комбинировать)

Первый вариант удобен разработчикам которые одновременно трудятся над множеством приложений и все держат в чистоте и свежести. Второй вариант используется при требовании от приложения иметь точную и единую версию composer-а у всех разработчиков, и тут он коммитится в репозиторий.

Держим Composer вместе с приложением

Команды Composer

install

Установив и собрав свой composer.json можно приступить к установке тех самых пакетов которые мы указали в своем json-файле в блоке “require” и “require-dev”. Для этого мы используем команду install .

Composer install ./composer.phar install php composer.phar install

* Первая команда (строка 1) для тех кто выбрал метод установки единого для всей операционной системы. Вторая и третья нужны всем остальным и отличаются лишь тем, дали вы права на запуск phar-файла либо нет.

При первом запуске команды install мы получим последнюю либо точную версию всех пакетов которые мы указали в json-файле (в зависимости от того как мы указали версию для каждого отдельного пакета). Повторный запуск команды install ни к чему не приведет – и это важный момент!

Во время исполнения install скачает все библиотеки в папку vendor нашего проекта (ниже опишу как сменить этот путь), а рядом с json -файлом будет создан новый файл composer.lock (это снепшот – слепок установленных пакетов с указанием их точных версий). Папку vendor стоит сразу же поместить в .gitignore , дабы случайно не смешать все со своим кодом. А вот lock -файл наоборот, нужно закомитить и отправить в репозиторий. Если удалить папку vendor или некоторые пакеты из него а потом опять вызвать команду install , то все пакеты будут восстановлены с точно теми же версиями которые были установлены при первом вызове install . Так происходит, потому что проверяет наличие lock -файла, и при его наличии игнорирует версии пакетов указанные в json-файле (только если те не были спущены!), и устанавливает версии указанные в lock -файле.

Таким образом, передавая единый lock -файл между всеми разработчиками, команда будет гарантировано иметь одинаковые версии пакетов (думаю не стоит пояснять зачем).

update

При необходимости же обновить версии пакетов до актуальных – вызываем команду update .

Composer update ./composer.phar update php composer.phar update

После чего все пакеты будут обновлены. Так же будет обновлен и lock -файл.

Тут стоит помнить что обновляться пакеты будут в соответствии с форматом версии указанным для каждого из них отдельно в json -файле. Синтаксис указания версий для пакетов хорошо описан в официальной документации .

self-update

Еще одна полезная команда, которая обновит сам .

Composer self-update ./composer.phar self-update php composer.phar self-update

show

./composer.phar show -s -t ./composer.phar show -i -t

Эта команда отображает список установленных пакетов.

Первый пример (с ключом -s ) отобразит дерево пакетов которые мы сами руками указали в json -файле.

Второй пример (с ключом -i ) отобразит абсолютно все установленные пакеты, рекурсивно включая зависимости всех наших первоначальных пакетов.

Ключ -t меняет отображение ответа в стиль дерева зависимостей.

vendor path или как сменить путь установки библиотек

Для изменения пути установки пакетов, необходимо использовать директиву vendor-dir в json -файле. Вот пример:

{ "name": "My Project", "description": "Project description", "homepage": "http://my-project.com/", "config": { "vendor-dir": "/vendor/custom/path" }, "require": { "php": ">=5.3.3", "zendframework/zendframework": "2.*" }, "require-dev": { "zendframework/zftool": "v0.1.0", "zendframework/zend-developer-tools": "dev-master" } }

Заключение

Я постарался описать все основное что может понадобится для знакомства с Composer-ом. Более глубокие фичи лучше изучать по документации . Например: как подключить загрузку собственной библиотеки с github .

А для удобного поиска необходимых пакетов советую пользоваться проектом packagist.org

Если же возникнут вопросы, смело пишите в комментарии.

Мир PHP-разработки с давних времён славится хаотической практикой создания зависимых самописных неуниверсальных систем. И приверженцы остальных языков над ним смеялись. В последние годы, что действительно хорошо, он всё более масштабно переходит к другому, более осознанному будущему. Интересная для многих практика социального программирования с использованием публичных репозиториев привнесла идею обобщении полученных знаний.

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

Реализация структуры нового Yii2 переработана для работы с компонентами через Composer. По этому поводу мы его и рассмотрим. Но вначале немного удалимся в философию и психологию открытого программного обеспечения.

Новое программирование

Эпоха социальных сетей и интернет-мессенджеров раздвинула границы общения. Наличие публичных репозиториев и систем контроля версий расширило возможности разработки. Теперь создавать и улучшать любую библиотеку могут любые разработчики со всего мира.

Что же нужно для более широкого внедрения практики свободно распространяемых компонентов? Во многом это движение подкрепляется развитием цивилизованной публикации личных наработок в публичные репозитории, а также внедрением общих стандартов PSR.

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

Неужели нужно хранить принципиальный, граничащий с разумностью консерватизм и быть против заимствований в языках программирования? Гораздо полезнее собрать положительные черты изо всех языков друг в в друга, и этим сделать удобными и максимально эффективными все языки мира!

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

Раньше каждый фреймворк всё делал по-своему. Имел свои расширения для авторизации, почты, шаблонизации. Тысячи часов программисты тратили на написание своих компонентов и «обёрток» для адаптации готовой библиотеки под стандарты своей системы. Каждый фреймворк на своём официальном сайте имел список расширений, порой несовместимых с другими фреймворками. Но теперь, за счёт всеобщей договорённости об избавлении от лишних зависимостей и за счёт перехода всех крупных разработчиков на единые способы проектирования и написания кода, время неуместной самостоятельности проходит.

Если раньше не было никакой удобной преемственности, никакого обмена готовыми компонентами (кроме выкладки в личные блоги, и лишь некоторые, особо продвинутые, даже добавляли свой код в репозиторий PEAR), то сейчас всё больше и больше готовых и отлаженных пакетов выставлены на обозрение широкой публике.

Миллионы репозиториев на GitHub и прочих подобных сервисах позволяют легко собрать нужный набор «запчастей» и использовать для написания своих приложений.

You don’t need a framework

Из чего состоит веб-приложение? А из чего фреймворк? Это, например, сборка из системы маршрутизации для «разруливания» адресов, ORM для работы с базой данных, контейнера для хранения компонентов, шаблонизатора, логгера и... подборки классов для работы с API разных систем, отправки электронной почты и дополнительных служебные компонентов.

Совсем недавно это приходилось либо программировать самому, либо не очень успешно искать в глубине блогов. Сейчас это уже другое время. Вам нужен ORM? Возьмите Doctrine или Propel. Нужен шаблонизатор? Возьмите Twig. Аналогично Monolog для ведения логов и SwiftMailer для почты. Нужен поиск? Загрузите себе компонент LuceneSearch от Zend Framework или найдите драйвер для Sphinx. А в качестве маршрутизатора можно взять тот-же компонент, который используется в Symfony Framework. И прочее, и прочее для работы с авторизациями социальных сетей, платёжными шлюзами...

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

Революция фреймворков

Набирающий сейчас популярность Laravel Framework уже один за одним обгоняет другие фреймворки. Сам он содержит мало кода, очень лёгкий внутри за счёт использования в своей работе пары десятков чужих публичных компонентов. Некоторые из них, кстати, мы уже перечислили. Похожая система компонентов издавна используется и в Symfony.

Если Yii1 это не использовал (в отличие от Symfony, Laravel и некоторых других), так как на момент его создания это было ещё не модно и многие вещи не поддерживались теми версиями языка PHP, то в новой версии Yii2 теперь встроены принципы работы с различными пакетами и соблюдены международные стандарты написания кода. А это значит, что прямо на наших глазах совершается переход, необходимый для любого серьёзного фреймворка. Совершился вход в новый объединённый союз. И на момент написания этих строк он уже совершён! Это важно. И скептицизм, разгорающийся в сети в момент каждой микрореволюции внутри любого фреймворка, здесь просто неуместен.

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

Что такое Composer

Развёртывание и разработка приложения происходит чаще всего так:

    На реальном или виртуальном компьютере-сервере мы устанавливаем язык PHP. Но на «голом» интерпретаторе приложение требует дополнительных компонентов. Мы устанавливаем скомпилированные библиотеки, расширения через PEAR и Pecl, потом скачиваем из репозитория наш фреймворк. И после этого наш сайт начнёт работать. При этом мы, естественно, не включаем установленные библиотеки к файлам проекта в нашу систему контроля кода.

    Теперь нам нужно найти и загрузить готовые компоненты. Мы заходим на GitHub или другие системы и клонируем оттуда эти библиотеки. Но при этом нужно быть аккуратным, так как они могут аналогично зависеть от других библиотек. Так что нам нужно изучить все компоненты и загрузить в нашу папку для расширений их полный комплект. Хорошим тоном было бы авторам компонентов указывать список зависимостей в файле Readme.

    Все эти дополнительные компоненты для экономии места можно не хранить в системе контроля версий, так как для крупного проекта их размер может составить сотни мегабайт. Достаточно составить вручную и приложить их полный список. С указанием источника и рабочей версии. Для автоматизации процесса скачивания можно добавить bash-скрипт, который будет клонировать репозитории по этому списку.

    В проекте теперь имеются несколько десятков сторонних расширений. Вместо ручного вызова include каждого класса можно сделать общий для всех автозагрузчик. Особенно если в классах используются пространства имён.

    Со временем каждый компонент желательно обновлять. Если их десятки, то вручную это делать будет утомительно. Это тоже можно автоматизировать консольным скриптом. Также должна быть возможность указывать в списке конкретные ограничения по версиям, чтобы обновлять только минорные версии и не перескочить случайно «слишком сильно». Своеобразная настраиваемая и запускаемая вручную система автоматического обновления.

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

Именно этим (управлением зависимостями, централизованной загрузкой и обновлением компонентов) и занимаются пакетные менеджеры.

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

Так что мы теперь можем сформировать и дополнить некое понимание о его назначении. И даже можем теперь настроить список зависимостей для нашего проекта:

А по практическому применению можно ещё прочесть несколько материалов, включая упомянутую выше статью:

  • UPD: Наш практикум по Git и Composer .

На этом пока всё. Пакетные менеджеры, надёюсь, стали понятнее. Если что-то не очень понятно или если есть чем дополнить, то напишите об этом в комментариях. Ну и не забывайте подписываться на рассылку, чтобы следить за сайтом. Это легко и полезно. Заранее спасибо!

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

Кратко, как это работает:

  1. У вас есть проект, который зависит от нескольких библиотек.
  2. Некоторые из этих библиотек зависят от других библиотек.
  3. Вы описываете в своём проекте те библиотеки, от которых непосредственно зависит ваш код.
  4. Composer находит нужные версии требуемых библиотек для всего проекта, скачивает их и устанавливает в папку вашего проекта.
При создании Composer авторы черпали идеи и вдохновение из аналогичных проектов: npm для Node.js и Bundler для Ruby.

Изначально он был спроектирован и разработан двумя людьми Nils Adermann и Jordi Boggiano , сейчас в проекте участвует более двадцати контрибьюторов, Проект написан на PHP 5.3, распространяется под лицензией MIT и доступен на github .

Первые коммиты были сделаны апреле 2011 года и на сегодняшний день Composer находится в стадии «alpha3». Однако, он уже достаточно стабилен и используется многими популярными PHP проектами (например, Symfony 2 ). Список проектов использующих Composer можно посмотреть на сайте packagist.org - это официальный репозиторий Composer пакетов. Кстати, на недавней конференции Devconf 2012 разработчик фреймворка Yii в своём докладе упомянул, что Yii2 скорее всего тоже будет использовать Composer.

В этой статье я кратко опишу основные возможности Composer и мы попробуем создать демонстрационный проект использующий Composer для загрузки необходимых библиотек. Все примеры будут доступны на github.com и bitbucket.org.

Что умеет Composer?

  • Скачивать пакеты и их зависимости;
  • по умолчанию, пакеты скачиваются из официального репозитория packagist.org. Любой человек может свободно добавить туда свой пакет, чтобы сделать его установку максимально лёгкой и удобной для всего мира;
  • пакеты можно скачивать не только с packagist.org, но и из любого git, mercurial или svn репозитория;
  • при скачивании пакетов с github.com или bitbucket.org не требуется установленной системы контроля версий (git или hg), Composer работает через API этих сайтов;
  • git/hg/svn репозиторий с пакетом может находиться не только на одном из перечисленных выше сайтов, но в любом другом месте, например, в локальной сети предприятия или вообще на локальном жестком диске;
  • кроме того, устанавливаемая библиотека не обязательно должна быть оформлена в виде Composer-пакета, вы можете сделать установку из любого git/hg/svn репозитория произвольной структуры;
  • наконец, устанавливаемый пакет не обязательно должен быть git/hg/svn репозиторием, это может быть произвольный zip файл доступный по любому uri!
  • все пакеты устанавливаются в текущую директорию (откуда была выполнена команда install), это позволяет иметь несколько различных версий библиотек при работе над разными проектами параллельно;
  • команда update обновляет все установленные (или установит заново случайно удалённые) пакеты до свежих версий. А может и не обновлять версии до самых свежих, если создать специальный composer.lock файл - это позволяет зафиксировать комбинацию из стабильных версий всех используемых в проекте библиотек;
  • после установки пакетов автоматически генерируется autoload.php, с помощью которого можно подключить установленные библиотеки в коде вашего проекта. При подготовке Composer-пакета рекомендуется использовать PSR-0 - стандарт расположения и именования php файлов, чтобы autoload смог их легко найти. В любом случае, автор пакета может описать правила, по которым autoload будет искать файлы тех или иных классов или неймспейсов. Если вы устанавливаете библиотеку, которая не оформлена как Composer-пакет (например, произвольный git репозиторий с github), то задача описания правил autoload ложится на ваши плечи. Так что никакой магии с генерируемым autoload.php нет - он умеет загружать всё (даже библиотеки с набором функций вне классов), главное, чтобы были описаны правила (автором библиотеки или вами).

Рабочий пример: используем Composer в своём проекте

Чтобы разобраться, как пользоваться Composer"ом, напишем маленький проектик на PHP: «Super Hello World». Поскольку мы не хотим изобретать велосипед и писать код «с нуля», возьмём готовые библиотеки и фреймворки.

Мы будем использовать cледующие библиотеки:

  1. микрофреймворк Silex
  2. шаблонизатор Twig (доступен в виде Composer пакета на packagist.org),
  3. наш собственный логер посещений SuperLogger , который я оформил в виде Composer-пакета и опубликовал на github
  4. нашу старую, но любимую легаси-библиотеку superlib , которая состоит из мешанины классов без неймспейсов и функций без классов; библиотека опубликована на github, но не является оформленным Composer-пакетом
Как мы это делали раньше: скачивали нужные нам фреймворки и библиотеки, думали куда их распаковать, писали в проекте кучу require (или require_once для надёжности).

Как мы это сделаем теперь: используем Composer - он сам скачает все библиотеки и сгенерирует для нас autoload.php. Кроме того, если мы захотим показать «Super Hello World» коллегам, достаточно будет опубликовать код нашего проекта на github (или ещё где-нибудь), не включая всех требуемых библиотек в репозиторий и не готовя длинной инструкции по их установке. Нашим коллегам достаточно будет скачать (склонировать) «Super Hello World» и выполнить команду
php composer.phar install
Composer распространяется в виде одного файла composer.phar (phar - это php-архив) - по сути это PHP скприт, который может принимать несколько команд (install, update, ...) и умеет скачивать и распаковывать библиотеки.

Кстати, немного о синтаксисе запуска.
Если вы работаете под Windows, то скорее всего вы будете писать что-то вроде
php C:\path\to\composer.phar install
Можно упростить себе жизнь, создав composer.bat и положив его в %PATH%.

В Linux и OS X можно настроить на исполнение команду типа
composer install

composer.json
Итак, мы готовы написать наш Super Hello World проект. И я его только что написал: http://github.com/pqr/superhelloworld . Код состоит из одного index.php файла в директории web и шаблона layout.twig в директории views.

Голова всему - это файл composer.json . Он должен быть в корне проекта, в нашем случае рядом с директориями web и view. В этом файле необходимо указать от каких библиотек зависит наш проект. Кроме того, если эти библиотеки не являются оформленными Composer-пакетами, то нужно указать некоторую дополнительную информацию об устанавливаемой библиотеке (например, описать правила автозагрузки классов и функций для autoload.php).

Composer.json, как вы догадались, имеет формат данных JSON. На вопрос "почему именно JSON? " разработчики Composer отвечают "Потому что. Просто примите это. ".

Нам нужно описать один js-объект, в котором будут находиться все инструкции. Первая и самая главная инструкция: require .

Подключаем пакеты с сайта packagist.org
{ "require": { "php":">=5.3.0", "silex/silex":"dev-master", "twig/twig":">=1.8,<2.0-dev" } }
Здесь я описал зависимость проекта от PHP версии 5.3.0 и выше, от silex (микрофреймворк) и от twig (шаблонизатор). Silex и Twig доступны в виде Composer-пакетов на сайте packagist.org, поэтому дополнительных настроек не требуют. Замечу, что Silex в свою очередь зависит ещё от нескольких пакетов - все они будут скачены и установлены автоматически.

Имя пакета состоит из двух частей разделёных косой чертой: названия поставщика (vendor name) и названия библиотеки . Названием поставщика зачастую является ник автора или имя компании. Иногда, название поставщика совпадает с именем самой библиотеки или фреймворка.

Для каждого пакета обязательно нужно указать номер версии. Это может быть бранч в репозитории, например, «dev-master» - приставка dev сигнализирует, что это имя бранча, а сам бранч соответсвенно называется «master». Для mercurial репозитория аналогичная запись будет выглядеть как «dev-default». В качестве номера версии можно указать и более сложные правила, используя операторы сравнения. Кстати, если вы скачиваете код из удалённого репозитория, то Composer сканирует теги и имена веток в этом репозитории на предмет чего-то похожего на номера версий, например тег «v1.2.3» будет использован как указатель на версию 1.2.3.

Подключаем на собственный Compsoer-пакет
Далее, подключим наш собственный пакет SuperLogger, который правильно оформлен, но опубликован не на packagist.org, а на github:
{ "require": { "php":">=5.3.0", "silex/silex":"dev-master", "twig/twig":">=1.8,<2.0-dev", "mycompany/superlogger":"dev-master" }, "repositories":[ { "type":"git", "url":"http://github.com/pqr/superlogger" } ] }
Чтобы Composer знал где искать пакет «mycompany/superlogger», мы добавили массив repositories со ссылкой на соотвествующий github репозиторий. Обратим внимание, что записи в массиве repositories напрямую никак не связаны с блоком require - между пакетами и репозиториями не указано соответствие. На сколько я понял, Composer ищет все требуемые пакеты во всех указанных репозиториях (в т.ч. на сайте packagist.org) и скачивает найденные совпадения по каким-то внутренним приоритетам. Более глубоко я в этом моменте ещё не разбирался, поправьте меня, если кто-то знает детали.
Подключаем произвольный git репозиторий
Теперь подключим нашу легаси-библиотеку superlib, которая лежит на github, но не является оформленным Composer-пакетом, т.к. она очень старая.
{ "require":{ "php":">=5.3.0", "silex/silex":"dev-master", "twig/twig":">=1.8,<2.0-dev", "mycompany/superlogger":"dev-master", "pqr/superlib":"1.2.3" }, "repositories":[ { "type":"git", "url":"http://github.com/pqr/superlogger" }, { "type":"package", "package":{ "name":"pqr/superlib", "version":"1.2.3", "source":{ "type":"git", "url":"http://github.com/pqr/superlib", "reference":"master" }, "autoload":{ "classmap":["timer.php"], "files":["lib_functions.php"] } } } ] }
В массив repositories добавился объект, который целиком описывает пакет pqr/superlib. По сути, это то описание, которое должен был бы сделать автор библиотеки и положить его внутри своего репозитория. Но по условиям задачи, superlib не является оформленным Composer-пакетом, поэтому нам пришлось создать его описание в рамках Super Hello World проекта. Аналогичным образом можно подключить любую другую библиотеку, в т.ч. простой zip файл.
Подключаем простой zip файл
Например, вот как могло бы выглядеть описание зависимости от шаблонизатора Smarty, распространяемого в виде zip файла с исходниками в svn:
{ "repositories":[ { "type":"package", "package":{ "name":"smarty/smarty", "version":"3.1.7", "dist":{ "url":"http://www.smarty.net/files/Smarty-3.1.7.zip", "type":"zip" }, "source":{ "url":"http://smarty-php.googlecode.com/svn/", "type":"svn", "reference":"tags/Smarty_3_1_7/distribution/" } } } ], "require":{ "smarty/smarty":"3.1.*" } }
Инстукция autoload
Вернёмся к нашему проекту.
Описывая «pqr/superlib», мы добавили инструкцию autoload . В ней указан файл timer.php, в котором будущий автозагрузчик будет искать классы и указали файл с функциями lib_functions.php - он будет принудительно подключаться в начале autoload.php.

Итак, наш проект состоит из:

  • в корне лежит файл composer.json;
  • в корне находятся директории web и views;
  • внутри директории web лежит файл с «бизнес-логикой» нашего приложения: index.php;
  • внутри директории views лежит файл шаблона layout.twig;
  • дополнительно, в папку web я положил.htaccess (для apache) и web.config (для IIS 7.5) с правилами mod_rewrite/url rewriter - непосредсвенно к настройке Composer они отношения не имеют.
Всё готово к запуску.
Запускаем composer install
php composer.phar install
Composer клонирует репозитории и распаковывает их на нужной версии в директорию vendor , которую он сам создаёт в корне проекта. После распаковки, в директории vendor мы найдём:
  • файл autoload.php
  • служебные директории.composer и composer
  • pimple - пакет, который подтянулся вместе с микрофреймворком Silex
  • silex - сам микрофреймворк, его мы явным образом затребовали при описании зависимостей
  • symfony - некоторые компоненты из Symfony 2, которые требуются для работы Silex
  • twig - шаблонизатор, который мы также явно запросили
  • mycompany - внутри этой директории будет находиться репозиторий superlogger скаченный с github
  • pqr - внутри этой директории будет находиться репозиторий superlib, также скаченный с github
Остаётся только подключить autoload.php в начале файла web/index.php (require "../vendor/autoload.php") и все библиотеки и функции будут доступны!
Как создать собственный Composer пакет?
В этом проекте мы использовали Composer с точки зрения потребителя библиотек. А как самому создать Composer пакет, чтобы любой другой человек смог им воспользоваться?

На самом деле, один из таких пакетов я создал, когда подготавливал примеры для этой статьи. В корне репозитория superlogger лежит файл composer.json похожей структуры, который описывает сам пакет и его зависимости (в случае с superlogger зависимостей нет). Другие примеры: репозитории silex и twig, которые скачались в папку vendor - все они имеют файл composer.json в корне - смотрите, изучайте!

И, конечно, не забывайте про документацию на официальном сайте getcomposer.org/doc/ .
Эту тему я оставлю вам для самостоятельной проработки.

Подведём итоги

В этой статье я рассказал, что такое Composer, его историю и описал основные возможности. Мы с вами попробовали создать проект, который использует Composer для установки пакетов с сайта packagist.org и из наших собственных репозиториев.

Самое время попробовать!

  1. Скачате Composer (getcomposer.org/download/)
  2. Скачате superhelloworld (git clone git://github.com/pqr/superhelloworld.git)
  3. Установите зависимости (cd superhelloworld && php composer.phar install)
  4. Изучите появившуюся папку vendor и сгенерированный autoload.php
  5. Используте Composer в своих проектах
  6. PROFIT!!!

На добавку пара ссылок

THE BELL

Есть те, кто прочитали эту новость раньше вас.
Подпишитесь, чтобы получать статьи свежими.
Email
Имя
Фамилия
Как вы хотите читать The Bell
Без спама