- PVSM.RU - https://www.pvsm.ru -
Никто не будет отрицать что Composer довольно удобный инструмент, и что есть бесплатные или дешевые хостинги которые не предоставляют какую либо консольку или встроенного инструмента для работы с Composer. Вот как раз с таким стеком я и столкнулся. Ну и как завещали джедаи, vendor сразу же добавляется в .gitignore чтоб не засорять им репозиторий и не гонять туда/сюда библиотеки.
Первое что пришло в голову это сделать скрипт доступный из Web, который можно дёрнуть в нужный момент и он обновит зависимости или установит их.
Для этого нам нужно провести некоторые манипуляции.
1. Для установки композера локально нам необходимо скачать composer.phar [1].
2. Создать папку куда он распакуется (пусть будет var).
3. Создать composer.json (ну про этот я думаю вы уже и так знаете если работали с composer).
4. Ну и создать сам скрипт для работы с композером из Web (пусть будет composer.php).
Итак мы имеем такую структуру нашего будущего сайта:

Сам же composer.phar будет следующим:
<?php
use ComposerConsoleApplication;
use SymfonyComponentConsoleInputArrayInput;
use SymfonyComponentConsoleOutputStreamOutput;
//Уберём лимиты, чтоб скрипт не отвалился раньше времени
ini_set("memory_limit", -1);
ini_set("max_execution_time", 0);
//Корень проекта
$root = __DIR__ . "/../";
//Папка для разархивирования
$dir = "{$root}/var";
//Смотрим если Phar архив еще не распакован, то распакуем его
if (file_exists("{$dir}/vendor/autoload.php") === false) {
$composerPhar = new Phar("{$root}/composer.phar");
$composerPhar->extractTo($dir);
}
//Подключим автолоадер для использования классов композера
require_once("{$dir}/vendor/autoload.php" . '');
//Обьявим переменную окружения чтоб обозначить где хранится сам композер
putenv("COMPOSER_HOME={$dir}/bin/composer");
//Изменим папку на корень чтоб vendor хранился на том же уровне что и WebRoot
chdir($root);
//Подготавливаем комманду установки
$input = new ArrayInput(['command' => 'install']);
//Создаем вывод в стрим
$stream = fopen('php://temp', 'w+');
$output = new StreamOutput($stream);
//Запускаем "консольное" приложение
$application = new Application();
$application->setAutoExit(false);
$application->run($input, $output);
//А тут должен быть вывод
echo stream_get_contents($stream);
И если вы счатливчик. То после вызова скрипта, он развернёт папку vendor.
Но я таким не оказался) Первое что сломало мои планы это настройка phar.readonly = On в php.ini, и как вы уже догадались на бесплатных хостингах править его обычно нельзя. Тогда я начал искать пути обхода.
Первое что попробовал это создать user.ini который переопределит настройки в php.ini, на локальной машине сработало) А вот на этот функционал зарезан был.
Тогда я попробовал использовать еще один трюк. Переименовать composer.phar в просто composer, результат то же. На локалке сработало, на
Тогда пришлось всё таки вместо скрипта распаковать в var файлы локально и залить их на сервер.
Также стоит закрыть скрипт авторизацией, чтоб всякие персоны не вызывали его. Также в конечную версию скрипта я добавил выбор команды через параметры.
<?php
use ComposerConsoleApplication;
use SymfonyComponentConsoleInputArrayInput;
use SymfonyComponentConsoleOutputStreamOutput;
//Уберём лимиты, чтоб скрипт не отвалился раньше времени
ini_set("memory_limit", -1);
ini_set("max_execution_time", 0);
//Негоже в Web хранить скрипты не закрытые паролем, чтоб кто-то посторонний мог их вызвать
if (isset($_SERVER['HTTP_AUTHORIZATION']) AND !empty($_SERVER['HTTP_AUTHORIZATION'])) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)), 2);
} elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) AND !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['REDIRECT_HTTP_AUTHORIZATION'], 6)), 2);
}
//Детали для авторизации, не забудьте поменять на что-то более секьюрное
$config = [
'user' => 'admin',
'password' => 'admin',
];
//Пускаем или не пускаем пользователя дальше
if ((isset($_SERVER['PHP_AUTH_USER']) && $_SERVER['PHP_AUTH_USER'] == $config['user'] && isset($_SERVER['PHP_AUTH_PW']) && $_SERVER['PHP_AUTH_PW'] == $config['password'])) {
unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']);
} else {
$uniqueID = uniqid();
header("WWW-Authenticate: Basic realm='{$uniqueID}'");
header('HTTP/1.0 401 Unauthorized');
exit();
}
//Корень проекта
$root = __DIR__ . "/../";
//Папка для разархивирования
$dir = "{$root}/var";
//Смотрим если Phar архив еще не распакован, то распакуем его
if (file_exists("{$dir}/vendor/autoload.php") === false) {
$composerPhar = new Phar("{$root}/composer.phar");
$composerPhar->extractTo($dir);
}
//Подключим автолоадер для использования классов композера
require_once("{$dir}/vendor/autoload.php" . '');
//Обьявим переменную окружения чтоб обозначить где хранится сам композер
putenv("COMPOSER_HOME={$dir}/bin/composer");
//Изменим папку на корень чтоб vendor хранился на том же уровне что и WebRoot
chdir($root);
//Не очень то хорошо, но будем надеятся что пароль знает только человек который знает что он делает, и делает это во имя добра)
//По умолчанию composer update, так как он используется чаще чем ?command=install
$params = !empty($_GET) ? $_GET : ['command' => 'update'];
//Подготавливаем комманду установки.
$input = new ArrayInput($params);
//Создаем вывод в стрим
$stream = fopen('php://temp', 'w+');
$output = new StreamOutput($stream);
//Запускаем "консольное" приложение
$application = new Application();
$application->setAutoExit(false);
$application->run($input, $output);
//А тут должен быть вывод
echo stream_get_contents($stream);
Также не помешает добавить в .htaccess правило для проброса заголовка авторизации (в случае с CGI) и редиректа на HTTPS, так как авторизация уходит в открытом виде.
RewriteEngine On
#Если у вас CGI, то заголовок авторизации потеряется, поэтому нужно его принудительно добавить
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#Переадресация на HTTPS, так как авторизация уходит в незашифрованном виде
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:SSL} !=1 [NC]
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
Автор: Ninazu
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/308091
Ссылки в тексте:
[1] необходимо скачать composer.phar: https://getcomposer.org/composer.phar
[2] хостинге: https://www.reg.ru/?rlink=reflink-717
[3] Источник: https://habr.com/ru/post/439424/?utm_campaign=439424
Нажмите здесь для печати.