Зарегистрируйтесь, чтобы продолжить обучение

Исполняемые файлы в пакетах PHP: Настройка окружения

Многие пакеты — это приложения командной строки, еще их называют 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"
    ]
}

Обсудим исполняемые файлы немного подробнее:

  1. Чтобы запускать файлы из командной строки, пользователь должен иметь право на выполнение этого файла (атрибут x)
  2. Если исполняемый файл содержит код, то надо указать интерпретатор, который будет исполнять этот код при запуске исполняемого файла. Это делается с помощью шебанга. В примере выше мы указали 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. Если в будущем вам придется столкнуться с чем-то подобным, вам будет намного проще.

Пример глобальной установки пакета:


Самостоятельная работа

  1. Установите утилиту phploc глобально
  2. В проекте php-package запустите анализ количества строк
  3. В проекте hexlet-php также запустите phploc и сравните результаты анализа обоих проектов

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Занимайтесь созданием сайтов, веб-приложений, сервисов и их интеграцией с внутренними бизнес-системами на бекенд-языке PHP
10 месяцев
с нуля
Старт 12 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»