Проблема.
Предположим такую ситуацию: Вам необходимо создать сервис, который будет основой для ряда последующих. Наследники этого сервиса, например, могут создаваться копированием папки родителя и установкой зависимостей внутри себя. И жить они все должны в моно-репозитории.
Какие пути решения сразу приходят на ум? Самое простое, наверное, создать подобный alias (если вы в *nix):
alias create-project="cp -r project/ new-project/ && cd new-project/ && composer install"
Конечно есть желание сделать все более элегантно и поэтому следующим по счету, но первым по разумности, в голову приходит решение использовать возможности Composer.
Официальные пути решения
Решения предлагаемые Composer:
- Платный Private Packagist;
- Бесплатный Satis;
- Собственный packages.json.
Первый вариант хорош, но не подойдет если у Вас нет желания платить, и Вы хотите обойтись по максимуму своими силами.
Второй вариант довольно таки грубый, особенно в случае если необходимо придумать решение для малого количества своих библиотек. Согласитесь, что поднимать сервис для
Третий вариант весьма скудно описан в официальной документации, и его описания нет в части про создание своих локальных библиотек.
С чем едят packages.json
В документации сказано, что composer использует файл packages.json для получения базовой мета-информации пакета:
{
"packages": {
"vendor/package-name": {
"dev-master": {
"name": "vendor/package-name",
"version": "1.1.3",
"dist": {
"url": "./path/to/package",
"type": "path"
}
},
}
}
}
Это готовый файл, который можно передавать в команду create-project, как аргумент repository:
composer create-project --repository=./path/to/packages.json vendor/package-name new-project-name
К сожалению без танцев с бубном, описанная выше конфигурация и команда не создают новую папку с проектом. После выполнения команды мы получаем symlink на папку оригинального проекта с названием нового проекта. Нас такое не устраивает, поэтому идем искать ответы в документацию.
Все описано в документации
К счастью так и есть. Очень многое описано в документации, но, к сожалению, у Composer там много белых пятен.
Вроде как в схеме packages.json должны быть свойства:
"options": {
"symlink": false
}
// или
"transport-options": {
"symlink": false
}
Но ни первое, ни второе не работают как ожидается, куда бы их не пристраивали. При этом ошибок при небольших нарушениях схемы не возникает.
Для установления истины мне пришлось создать issue в github репозитории composer. Пока нет официального ответа, что и послужило стимулом написать заметку. Надеюсь мне ответят и появится более интересное решение. О чем молчать конечно не буду.
Решение
В документации есть описание переменной окружения COMPOSER_MIRROR_PATH_REPOS. Она управляет необходимым нам поведением. С помощью команды ниже мы добавим ее в систему:
export COMPOSER_MIRROR_PATH_REPOS=1
Эту строку необходимо выполнить в командной строке и, желательно, добавить в .bashrc, чтобы она автоматически выполнялась при открытии новой сессии терминала. Сделать это можно, например, так:
echo "export COMPOSER_MIRROR_PATH_REPOS=1" >> ~/.bashrc
Теперь при выполнении команды на создание проекта, composer создаст копию локального пакета, а не symlink на папку-источник.
Автор: весёлый усач