Как сделать свой composer пакет

Обновлено: 31.07.2024

А именно — начать использовать менеджер зависимостей для PHP — Composer. Он позволит нам легко устанавливать разные полезные вещи на сайт, обновлять их и даже удалять. Если вы уже работали с менеджером пакетов GNU/Linux — то вам всё это будет очень знакомо.

В качестве разминки, удалим Fenom из директории core и установим через Composer. Для этого нужно в корне сайта создать файл composer.json и прописать в нём требуемые пакеты (подробнее можно прочитать на Хабре):
Теперь нужно только скачать composer.phar и запустить его в корне сайта:
На modhost.pro и качать ничего не нужно — просто запускаем composer в директории:
И волшебным образом у нас появляется директория /vendor/ с установленным Fenom. Что же с ним делать дальше?

Принцип работы

Давайте немного остановимся, и я объясню, как именно функционирует Composer, если вы еще не знаете.

Composer — это менеджер пакетов, который работает с ними согласно правил в composer.json. То, что мы там напишем, и будет устанавливаться.

  1. Пишем composer.json
  2. Устанавливаем пакеты через composer.phar
  3. Подключаем в проект /vendor/autoload.php
  4. Используем любые установленные классы через new Class()

Подключаем Fenom

Зачем нам таскать с собой Fenom и обновлять его вручную, если давно придуман Composer, который об этом позаботится гораздо лучше? Всё, что нам нужно — положить в корень проекта composer.json.

Давайте теперь отрефакторим и наш собственный проект, чтобы он также подключался в autoload.php.

Рефакторинг проекта

Вся эта замечательная автозагрузка работает при помощи пространств имён — namespaces. Это такая фишка для гарантированного отделения имён классов друг от друга. Все классы, как бы, лежат в своих виртуальных директориях, и чтобы их использовать, нужно указывать полное имя или задавать псевдоним. Подробнее можно снова прочитать на Хабре.

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

Отсюда следует два вывода: Composer можно использовать только в PHP 5.3+, и наш проект нужно переписать так, чтобы он использовал пространства имён.

  • Класс 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

Теперь в начале каждого класса пишем используемое пространство имён. У основных классов это:
А у контроллеров:

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

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

Перемещаем autoload.php из класса \Brevis\Core в index.php, потому что пространство имён Brevis у нас скоро и само будет работать через автозагрузку и лишние require ему не нужны.

Index.php теперь выглядит вот так:

В общем, вся логика осталась прежней, а количество кода сократилось. Нет ручной работы с файлами, нет никаких require, вся работа по подключению классов лежит на autoload.php. Соотвественно, и параметр controllersPath из системного конфига пропадает.

Осталось добавить и наш собственный проект в автозагрузку. Для этого меняем composer.json вот так:
Блок autoload указывает, что загружать дополнительно, кроме установленных пакетов. Ключ psr-4 указывает, как именно загружать наш проект, и указывает директорию core/ как основную для пространства имён Brevis.

Запускаем
и наши классы попадают в автозагрузку. Всё должно работать, смотрим изменения на GitHub.

Заключение

Вот мы и переписали наш проект в соотвествии с последними стандартами в мире программирования на PHP. Согласитесь, было не так уж и страшно?

Зато теперь наш код чистенький, опрятненький, соотвествует стандартам и отлично работает!

На следующем занятии мы установим через Composer xPDO 3.0 (да-да, он уже переписан и поддерживает namespaces, хоть пока и только в dev-ветке) и подключим его к нашей БД.

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

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

Использование пакетов способствует соблюдению современных принципов разработки программного обеспечения, например, DRY: “Don’t Repeat Yourself”, значительно уменьшая количество дублирующейся информации всех видов.

В большинстве случаев, у пакетов есть зависимости. Когда для работы “Пакета A” требуется “Пакет B”, мы говорим, что “Пакет A” зависит от “Пакета B”. Довольно часто для пакета формируется цепь таких зависимостей (“Пакет A” зависит от “Пакета B”, “Пакет B” зависит от “Пакета C”, список можно продолжить).

Представьте, что пакетных менеджеров не существует. Какие действия необходимо осуществить, для того чтобы обеспечить работоспособность “Пакета A”, зависящего от “Пакета B”? Для начала мы скачаем исходный код “Пакета A”, после чего обнаружим, что его функциональность зависит от “Пакета B”. Поэтому мы приложим максимум усилий, для того чтобы найти исходный код “Пакета B”. Но такой алгоритм может и не сработать, потому что мы не уверены, что в результате скачивания получим нужную версию “Пакета B”. Эту историю можно продолжить, а она касается только одной зависимости. Представляете, каким кошмаром обернется наличие у необходимого пакета множественных зависимостей или их цепочки.

Composer vs. PEAR

Кое-что с названием PEAR было еще до появляения Composer. Разработчики PHP с многолетним стажем наверняка знакомы с PEAR. Этот продукт сущестует с 1999 года. PEAR, как и Composer, был создан с целью развития инфраструктуры повторного использования пакетов. Тем не менее, по ряду причин он был отвергнут сообществом разработчиков:

  1. в отличии от Composer, PEAR - системный пакетный менеджер. В таком случае, имея несколько проектов с пакетами различных версий, использующими одинаковые зависимости, разработчики получали множество проблем,
  2. для того, чтобы пакет был размещен в репозитарии PEAR, требовалось собрать определенное количество голосов. Это условие воспринималось негативно и не способствовало росту репозитария. В конце концов, программист должен писать код, а не заниматься его популяризацией.

Composer

Composer - это пакетный менеджер уровня приложений для PHP. Его создатель вдохновился примерами NodeJS NPM и Ruby’s Bundler. В настоящее время этот пакетный менеджер признан всем сообществом PHP-разработчиков.

Экосистема Composer содержит две части:

  1. собственно Composer, который является утилитой командной строки для установки пакетов,
  2. Packagist - репозитарий пакетов.

Пакетный менеджер уровня приложений управляет зависимостями только в пределах проекта. Это значительно облегчает управление проектами и предохраняет рабочее место от хранения большого количества ненужных файлов. Все необходимые пакеты хранятся в директории конкретного проекта.

Каждый разработчик может выкладывать свои пакеты в Packagist. В отличие от PEAR, нет необходимости набирать какие-то голоса. Тем не менее, популярность вашего проекта определяется собранными звездами.

Packagist

Как было написано выше, Packagist - дефолтный репозитарий пакетов для Composer. На момент написания этот статьи (ноябрь 2019) 244385 пакетов доступны для установки из этого репозитария. Каждый раз, перед тем как приступить к созданию с нуля какого-либо функционала на PHP, рекомендуется заглянуть в Packagist - скорее всего необходимая задача уже решена и пакет присутствует в репозитарии. Можно с уверенность сказать, что PHP-разработчики, использующие в своей работе Composer и Packagist, экономят кучу сил и времени.

Установка Composer

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

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

MacOS/Linux/Unix

Для установки Composer требуется PHP версии 5.3.2+. Так же необходимо привести в соответствие некоторые настройки PHP, но нет смысла останавливаться на этом - установщик продукта предупредит о всех несовместимых параметрах. После успешной проверки настроек установщик скачает файл composer.phar в рабочую директорию.

PHAR - бинарный файл, формат архива для PHP, запускаемого из командной строки

Для глобальной установки composer.phar должен находиться в PATH . Поэтому сразу после удачного завершения работы установщика, необходимо выполнить следующую команду:

Теперь для запуска пакетного менеджера достаточно набрать в консоли composer вместо php composer.phar .

Windows

Достаточно скачать и запустить установщик для Windows.

Актуальную информацию о глобальном и локальном вариантах установке Composer в различных операционных системах можно узнать здесь.

Проверка установки

Для того чтобы убедиться в том, что Composer установлен корректно, достаточно выполнить следующую команду (из директории установки - в случае локальной установки, из любой директории - в случае глобальной установки):

Если результат будет подобен этому, установка выполнена верно:

Работа с Composer

Теперь Composer готов к работе. Рассмотрим небольшой пример:

Допустим, мы завершили работу над проектом, но для демонстрации его возможностей клиенту нужно сгенерировать пул даных: имена и адреса пользователей. Конечно, есть желание, чтобы такие данные выбирались случайным образом и, вообще, были максимально похожи на реальные. Одно из решений: самостоятельно создать массив имен и адресов, а затем случайным образом выбирать из него значения с помощью функции array_rand(). Надеюсь, Вы понимаете, что это непрактичное и скучное решение. А что делать, если нам понадобятся сотни пользовательских данных? Нужно найти альтернативное решение.

На помощь приходит Packagist - здесь есть пакет, который справится с поставленной задачей на сто процентов. Он даже называется Faker.

Давайте установим Faker с помощью Composer.

Из корневой директории проекта выполним команду:

Для установки пакета потребуется всего лишь несколько секунд. За это время Composer скачает zip-архив Faker с GitHub и создаст несколько внутренних файлов и папок.

После установки пакета в директории проекта можно обнаружить новые папки и файлы:

  1. composer.json
  2. composer.lock
  3. vendor

composer.json

Этот файл описывает зависимости в проекте. Это просто JSON-файл, демонстрирующий установленные для данного проекта пакеты.

Когда Вы запускаете из консоли команду composer require , файлы composer.json и composer.lock автоматически обновляются в соответствии с изменениями в составе пакетов. И наоборот, если пакеты добавлены в файл composer.json , достаточно из директории проекта выполнить команду composer install , для того, чтобы скачать необходимые пакеты. Если нужно обновить версии всех пакетов в проекте до последних, соответствующих установленным ограничениям, необходимо выполнить команду composer update .

Рассмотрим три основные команды Composer:

composer require

Команда добавляет к зависимостям строго определенный пакет. Когда к проекту нужно добавить один пакет, достаточно аыполнить команду composer require . Это очень удобно, так как нет необходимости лишний раз модифицировать файл composer.json .

Другое предназначение этой команды - обновление версий уже установленных пакетов. Например, в проекте установлена последняя версия пакета Faker (1.8.0) с помощью команды:

В случае, когда при выполнении команды composer require не указана необходимая версия пакета, происходит скачивание последней доступной версии.

Допустим, тестируемое приложение несовместимо с пакетом версии 1.8.0, но отлично работает с более ранней версией - 1.4.0. Для того, чтобы решить возникшую проблему достаточно выполнить команду:

В этом случае произойдет не только скачивание пакета установленной версии, но и корректное обновление соответствующих файлов Composer.

composer install

Эта команда в первую очередь обращается к файлу composer.lock . Если данный файл присутствует, для указанных в нем пакетов будут установлены версии в строгом соответствии с версиями определенными в composer.lock , следует заметить, что для этих пакетов содержимое файла composer.json будет проигнорировано. Если файл composer.lock отсутствует, команда обратится к composer.json и установит последние версии пакетов в соответствии с ограничениями определенными в этом файле.

Возникает вопрос: в чем различия?

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

Эта команда обычно используется в 3 случаях:

  1. при старте нового проекта, когда в файле определены все зависимости и нужно скачать необходимые пакеты,
  2. когда идет размещение проекта из внешего репозитария (например, с GitHub), пакеты не хранятся в проекте, команда запускается, чтобы установить необходимые пакеты, в соответствии с настройками файлов Composer,
  3. в некоторых стратегиях переноса проекта из разработки в “боевую” среду.

composer update

Эта команда отличается от composer install тем, что обращается только к файлу composer.json . Таким образом, команда обновляет только пакеты, определенные в этом файле до последних версий в соответствии с установленными в composer.json ограничениями. Так же composer update устанавливает все новые пакеты, добавленные в composer.json .

Таким образом, composer update , как и composer require можно использовать для того, чтобы актуализировать версии пакетов. Но composer require не трубует внесения предварительных изменений в composer.json .

Команда composer update обращается только к информации в файле composer.json - это создает логическую ловушку при переносе проекта в “боевую” среду.

composer update никогда нельзя использовать на продакшене

Ваше приложение успешно работает с пакетом Faker 1.4.0 в тестовой среде. Вы переносите проект в “боевые” условия и для установки пакетов запускаете composer update . Допустим, в файле composer.json определено нестрогое соответствие версии пакета Faker и имеет вид fzaninotto/faker: 1.* . Как результ, на продакшене окажется пакет Faker 1.8.0, несовместимый с данным приложением. То есть пакеты, в тестовой и боевой средах не будут идентичными. А это не тот результат, к которому мы стремимся.

Как избежать такой ситуации? Рекомендации просты:

  1. переносите composer.lock вместе с composer.json ,
  2. в “боевой” среде используйте только composer install

Соблюдение этих нехитрых условий позволит вам быть уверенными в полном соответствии переносимых пакетов.

composer.lock

В то время, как composer.json определяет состав пакетов, необходимых для проекта, и накладывает ограничения на используемые версии пакетов, composer.lock определяет точные версии пакетов, установленных в проекте. Иными словами composer.lock сохраняет текущее состояние проекта. Это очень важный момент, который необходимо знать.

Тот факт, что composer install сначала обращается к composer.lock , делает эту команду безопасной и приоритетной для использования. И вот почему:

Рассмотрим следующую ситуацию. Случайно из проекта удалили папку vendor со всеми установленными пакетами. Что делать? Достаточно запустить команду composer install и будут установлены все необходимые версии пакетов, используемых в проекте.

Но есть и другой вопрос. Если мы используем систему контроля версий (например, git), нужно ли хранить в репозитарии файл composer.lock ?

Это зависит от весьма простых условий:

  1. Обычно работа над проектом ведется в команде, и хочется быть уверенным в постоянной полной идентичности исходного кода в определенных ветках репозитария. Это означает, что composer.lock нужно коммитить и хранить в репозитарии.
  2. Когда идет работа над собственным пакетом или библиотекой, редко возникает необходимость в использовании команды composer install , в таком случае нет никакой необходимости в хранении в репозитарии файла composer lock .

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

  1. Зависимости определены в файле composer.json - используйте composer install .
  2. Есть необходимость в определенном пакете - используйте composer require some/package .
  3. Нужно установить несколько пакетов - определите их в composer.json и запустите composer update .
  4. Хотите протестировать новую версию определенного пакета - используйте composer rerquire some/package:new-version .
  5. Хотите протетсировать все новые версии установленных пакетов - используйте composer update .

Автозагрузка

Скорее всего Вы часто используете выражения include и require . Проблема в том, что такой подход делает код перегруженным. В наихудшем случае, изменение структуры проекта, влечет большой объем работы, связанной с поиском и заменой.

Решение - автозагрузка. Это решение позволяет определить пути для поиска классов и избавить разработчика от рутинной работы, связанной с подключением файлов через include и require . Конечно, мы должны помнить, что на самом деле автозагрузка использует все те же управляющие конструкции include и require .

Но, давайте еще раз вернемся к нашему вымышленному проекту. Остался еще один вопрос, которого мы не коснулись. А именно, директория vendor , которую создает Composer. По умолчанию Composer сохраняет все пакеты именно в этой директории.

Кроме того Composer создает файл vendor/autoload.php , который обеспечивает автозагрузку кода установленных пакетов.

В нашем случае, для использования возможностей пакета Fake, достаточно просто подключить автозагрузчик:

после этого Faker готов к работе:

Сообщество

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

Спасибо за внимание.

Photo by CHUTTERSNAP on Unsplash

Linux Twitter Интернет Windows Synaptic wine Asus A7u Ubuntu Asus virtualbox wordpress домен хостинг LAMP mySQL phpmyadmin Google Facebook Firefox 3G usb skype восстановление samba безопасность android Apple Ebay iPhone Samsung модем SQL

МЫ ВКОНТАКТЕ

Локальная разработка пакетов с composer

Локальная разработка пакетов с composer

В этой статье мы рассмотрим как установить локальную библиотеку через менеджер зависимостей Composer. Предположим, это может быть полезно если вы работаете над библиотекой, которую в дальнейшем хотите опубликовать в сети и предоставить возможность ее установки для других разработчиков через composer/packagist. Но при этом в ходе разработки и отладки пакета - конечно же хочется, чтобы пакет можно было развернуть на "реальном" приложении и проверить всю его логику еще раз перед публикацией.

Недостаток подхода состоит в том, что в приложении, куда мы будем подключать нашу библиотеку, в composer.json нужно выставить параметр "minimum-stability" на "dev". Что означает, что в проет притянутся другие зависимые либы в development версиях.

Итак, внутри composer.json файла Вашего приложения прописываем дефиницию для тесриуемого локального пакета, добавляя repositories объект:

Аргумент "type": "path" позволяет Composer понять, что вы ссылаете на локальный репозиторий, а "url" определяет абсолютный или относительный путь к вашей библиотеке.

Этих двух параметров будет достаточно, но при таком подходе Composer будет копировать содержимое из локального пути к билиотеке внутрь проекта. А чтобы иметь возможность проверить следующие правки, нужно будет выполнять команду composer update.

Чтобы предотвратить такое поведение менеджера зависимостей - добавляем дополнительную опцию "symlink": true. Теперь вместо полного копирования в папку vendor, будет лишь создан симлинк на локальный путь к библиотеке.

Для установки локального пакета через Composer выполняем:

После этого Ваша библиотека будет связана с приложением по средствам symlink и вы можете приступать к испытаниям. Удачи!

Все мы любим Composer. Он существенно изменил способ построения PHP приложений, основанных на небольших и повторно используемых компонентах, но это создает новые проблемы, особенно, когда у нас есть единая точка отказа. С помощью Satis, мы можем сделать процесс выкладки более устойчивым, добавив резервирование для всех потенциальных точек отказа (Packagist и GitHub). Давайте посмотрим, как это работает.

Как работает Composer?

Нижеприведённая диаграмма показывает, как работает Composer при использовании Packagist в качестве центрального хранилища:


Если мы указываем, что хотим использовать различные репозитории, то Composer использует хранилище по умолчанию: Packagist. Composer запросит у Packagist информацию о всех пакетах, требуемых в файле composer.json , а также зависимостей, необходимых для этих пакетов.

Когда Composer получает всю информацию, он разрешает граф зависимостей, используя SAT solver и генерирует файл composer.lock с конкретными пакетами, которые должны быть установлены для того, чтобы выполнить требования, запрашиваемые в файле composer.json . Наконец, Composer загружает эти пакеты из различных источников: GitHub, Bitbucket, PEAR или любого GIT/SVN/Mercurial репозитория.

Данная архитектура имеет несколько проблем: что произойдет, если Packagist упадет? Это не будет работать. Composer не сможет разрешить граф зависимостей. В дополнение к этой проблеме, что произойдет, если необходимые пакеты размещаются в GitHub’е, и он в настоящее время не работает? Это не будет работать. Пакеты не будут загружены, что повлияет на вашу разработку и выкладку.

Как мы можем минимизировать все эти проблемы? Добавлением резервирования. Мы можем создать наш собственный репозиторий с помощью Satis, используя это хранилище вместо (или в дополнение к) Packagist. Следующая диаграмма показывает ту же схему, но с использованием специального хранилища:


Теперь, Composer запрашивает информацию о необходимых пакетах в нашем индивидуальном хранилище и будет обращаться к Packagist только том случае, если наш репозиторий не имеет этой информации. Мы даже можем отключить Packagist и настроить наш репозиторий, чтобы все зависимости пакетов загружались в него. Кроме того, наше хранилище может загрузить пакеты и действовать в качестве reverse proxy сервера. Таким образом, мы больше не зависим от GitHub’а для загрузки пакетов.

Установка

Мы можем установить Satis с помощью Composer:

Файл конфигурации репозитория

Формат файла довольно прост, но давайте посмотрим, что каждое из полей значит:

  • "name" : имя хранилища.
  • "homepage" : URL репозитория.
  • "repositories" : содержит список репозиториев, которые мы хотим отразить.
  • "require-all" : скачать все пакеты, а не только те, что с тегом.
  • "require-dependencies" : если значение "true", Satis автоматически разрешает и добавляет все зависимости, поэтому Composer’у не нужно будет использовать Packagist.
  • "archive" : "tar" файлы будут храниться в "dist" каталоге и нам не нужно будет загружать "dev" пакеты.

Затем, мы говорим Satis создать хранилище:

После этого, у нас есть новый каталог с названием servergrove-satis , который содержит два файла: packages.json и index.html . Первый является файлом конфигурации хранилища, который будет прочитан Composer’ом, чтобы определить, какие пакеты предлагает репозиторий. Файл index.html - просто статический HTML файл с информацией о хранилище. Он также содержит каталог dist со всеми пакетами, поэтому они не будут больше загружеаться с GitHub’а.

И, наконец, мы публикуем наш репозиторий с помощью PHP-шного встроенного сервера (для реальных хранилищ рекомендуется использовать Apache или Nginx):


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

После того как репозиторий заработал, последним шагом нужно будет сообщить Composer’у, что мы хотим использовать его. Это может быть сделано путем добавления следующих строк в файл composer.json вашего проекта.

После этого, при запуске composer install будет использоваться наше хранилище:

Читайте также: