- Глобальная установка: генерация ссылок и запуск исполняемых файлов
- Что происходит при локальной установке
- Выводы
Многие пакеты — это приложения командной строки, еще их называют cli-утилитами. Пользователи по-разному взаимодействуют с ними: запускают команды, передают аргументы и опции, выводят результат. Все взаимодействие происходит интерактивным образом через терминал. Для запуска файлов из командной строки в Composer существует секция bin
конфигурационного файла composer.json
. Рассмотрим на примере:
"bin": ["bin/php-package"]
Эта запись означает, что при установке пакета в операционной системе будет создан файл с именем php-package
. Это не просто файл, а символическая ссылка. Запуск этого файла-ссылки приведет к запуску файла вашего проекта по адресу bin/php-package
.
Как можно заметить, имя ссылки задается именем файла и совпадает с ним. Также обратите внимание, что ссылок может быть множество — столько, сколько вы сами укажете в секции bin
.
Месторасположение символической ссылки и способ ее запуска из командной строки различаются в зависимости от способа установки пакета:
- Локального
- Глобального с командой
global
— например,composer global vendor/package
Рассмотрим каждый случай отдельно.
Глобальная установка: генерация ссылок и запуск исполняемых файлов
При глобальной установке пакета Composer создает символические ссылки в каталоге $HOME/.composer/vendor/bin
. Другими словами, при создании ссылок в домашнюю директорию пользователя, от имени которого запускалась установка пакета, будет добавлен каталог .composer/vendor/bin
со ссылками. Это каталог по умолчанию, но путь к нему нам надо самостоятельно прописать в переменной окружения PATH
. После этого мы можем запускать приложение по имени символической ссылки из командной строки, находясь в любой точке файловой системы. Так происходит, потому что при поиске исполняемых файлов командная оболочка ищет их последовательно по всем путям, прописанным в переменной окружения PATH
.
В зависимости от версии Composer директория по умолчанию может различаться. Кроме того, это значение можно конфигурировать. Чтобы посмотреть, в какую конкретно директорию composer складывает ссылки на исполняемые файлы, можно воспользоваться командой composer global config bin-dir --absolute
:
composer global config bin-dir --absolute
Changed current directory to /home/hex/.composer
/home/hex/.composer/vendor/bin
Посмотреть содержание переменной окружения PATH
в вашей системе можно с помощью команды echo
:
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/hex/.composer/vendor/bin/
Пример
Давайте создадим и опубликуем пакет, который для краткости и наглядности будет очень простым. Этот пакет будет состоять всего из двух исполняемых файлов, запуск которых выведет приветствие и прощание с Хекслетом.
Структура проекта:
ls -al
drwxrwxr-x 2 hex hex 4096 Jul 1 04:32 .
drwxrwxr-x 3 hex hex 4096 Jul 1 04:21 ..
-rw-rw-r-- 1 hex hex 225 Jul 1 04:31 composer.json
-rw-rw-r-- 1 hex hex 0 Jul 1 04:32 sayBye
-rw-rw-r-- 1 hex hex 0 Jul 1 04:32 sayHi
Содержимое исполняемого файла sayHi
:
#!/usr/bin/env php
<?php
print_r("Hello, Hexlet!\n");
Содержимое исполняемого файла sayBye
:
#!/usr/bin/env php
<?php
print_r("Bye-bye! See you later, Hexlet!\n");
Содержимое конфигурационного файла composer.json
:
cat composer.json
{
"name": "hex/small-talk-with-hexlet",
"description": "Small talk with Hexlet",
"keywords": ["hexlet", "php", "composer"],
"license": "MIT",
"bin": [
"./sayHi",
"./sayBye"
]
}
Обсудим исполняемые файлы немного подробнее:
- Чтобы запускать файлы из командной строки, пользователь должен иметь право на выполнение этого файла (атрибут
x
) - Если исполняемый файл содержит код, то надо указать интерпретатор, который будет исполнять этот код при запуске исполняемого файла. Это делается с помощью шебанга. В примере выше мы указали php в качестве интерпретатора, а путь к нему задали с помощью специальной утилиты env. Мы решили не указывать абсолютный путь, потому что в разных системах php может находиться по совершенно разным путям
В итоге, мы подготовили пакет. После публикации он становится доступен для установки под именем hex/small-talk-with-hexlet
.
Теперь установим этот пакет в систему глобально. Но сначала убедимся, что никаких символических ссылок в директории не существует:
composer global config bin-dir --absolute
Changed current directory to /home/hex/.composer
/home/hex/.composer/vendor/bin
ls -al /home/hex/.composer/vendor/bin | grep say
Здесь с помощью фильтра grep
мы попытались найти файлы, содержащие в своем имени строчку "say"
(как наши ссылки в секции bin
). Поиск не дал результатов, потому что до установки пакета таких файлов нет.
Далее глобально устанавливаем пакет в систему:
Теперь воспользуемся grep
и снова проверим директорию установки исполняемых файлов:
ls -al /home/hex/.composer/vendor/bin | grep say
lrwxrwxrwx 1 hex hex 36 Jul 1 07:45 sayBye -> ../hex/small-talk-with-hexlet/sayBye
lrwxrwxrwx 1 hex hex 35 Jul 1 07:45 sayHi -> ../hex/small-talk-with-hexlet/sayHi
Как и ожидалось, в этом каталоге находятся символические ссылки — об этом свидетельствует первый символ l
, определяющий тип файла в строке атрибутов файла lrwxrwxrwx
. Эти ссылки можно запускать из любой точки файловой системы:
sayHi
Hello, Hexlet!
sayBye
Bye-bye! See you later, Hexlet!
cd /media/ # Перейдем в другой каталог
sayHi # Выполняем команду
Hello, Hexlet!
sayBye # Выполняем команду
Bye-bye! See you later, Hexlet!
Из примера видно, что мы можем успешно запускать одни и те же команды из разных директорий. Причины, по которым это происходит, мы подробно обсуждали выше.
Что происходит при локальной установке
В подавляющем большинстве случаев разработчики устанавливают пакеты не глобально, а локально. При такой установке пакеты привязываются к конкретному проекту и размещаются внутри его каталога по пути ./vendor/
. При этом ссылки на исполняемые файлы устанавливаемых пакетов Composer размещает в каталоге ./vendor/bin
.
Ссылки на исполняемые файлы локально установленных пакетов заточены под использование в скриптах, в секции scripts
конфигурационного файла composer.json
. Для этого существует особенный синтаксис. Эту тему мы проходили в уроке, посвященном скриптам.
Естественно, к символическим ссылкам можно также обратиться напрямую, указав нужный путь. Давайте рассмотрим это на примере, подключив к нашему разрабатываемому проекту small-talk-with-hexlet
пакет PHP_CodeSniffer:
composer require --dev "squizlabs/php_codesniffer=*"
Для примера возьмем команду composer require --dev some_package
. Если установить пакет с флагом --dev
в корневом каталоге проекта, он автоматически добавится в зависимости проекта, то есть в секцию require-dev
файла composer.json
. Этой возможностью мы и воспользовались.
Посмотрим, какие новые файлы появились в директории проекта:
ls -al
drwxrwxr-x 4 hex hex 4096 Jul 1 08:11 .
drwxrwxr-x 3 hex hex 4096 Jul 1 04:21 ..
drwxrwxr-x 8 hex hex 4096 Jul 1 07:06 .git
-rw-rw-r-- 1 hex hex 286 Jul 1 08:10 composer.json
-rw-rw-r-- 1 hex hex 3388 Jul 1 08:11 composer.lock
-rwxrwxr-x 1 hex hex 73 Jul 1 04:46 sayBye
-rwxrwxr-x 1 hex hex 56 Jul 1 04:45 sayHi
drwxrwxr-x 5 hex hex 4096 Jul 1 08:11 vendor
Как и ожидалось, появился каталог ./vendor
, в котором лежит код подключенного пакета и других пакетов, от которых он зависит.
Как узнать место, где Composer хранит ссылки на исполняемые файлы локально подключаемых пакетов? Это можно сделать с помощью команды composer config bin-dir
.
Обратите внимание, что здесь нет команды global
. В нашем случае это каталог ./vendor/bin
. Заглянем в него:
ls -al vendor/bin/
drwxrwxr-x 2 hex hex 4096 Jul 1 08:11 .
drwxrwxr-x 5 hex hex 4096 Jul 1 08:11 ..
lrwxrwxrwx 1 hex hex 43 Jul 1 08:11 phpcbf -> ../squizlabs/php_codesniffer/scripts/phpcbf
lrwxrwxrwx 1 hex hex 42 Jul 1 08:11 phpcs -> ../squizlabs/php_codesniffer/scripts/phpcs
В коде выше видно, что при установке PHP_CodeSniffer
добавилось два исполняемых файла для запуска разных программ. Давайте запустим phpcs
. Это линтер — утилита, которая проверяет код на соответствие стандартам:
./vendor/bin/phpcs --standard=PSR12 sayHi sayBye
Программа отработала корректно и завершилась молча — без дополнительного вывода отчета об ошибках. Так произошло, потому что в наших файлах не было никаких нарушений оформления кода.
Затем была попытка запустить исполняемый файл из командной строки только по имени, но она привела к неудаче — bash: phpcs: command not found
. Командная оболочка просто не нашла файл — при глобальной установке все было бы по-другому.
Выводы
В этом уроке мы рассмотрели общие принципы и отдельные нюансы работы Composer с исполняемыми файлами проекта. Важно отметить, что эти принципы характерны для большинства других пакетных менеджеров из разных языков — например, менеджера пакетов Node.js в JavaScript. Если в будущем вам придется столкнуться с чем-то подобным, вам будет намного проще.
Пример глобальной установки пакета:
Самостоятельная работа
- Установите утилиту phploc глобально
- В проекте php-package запустите анализ количества строк
- В проекте hexlet-php также запустите phploc и сравните результаты анализа обоих проектов
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.