SilenceOfWinter
@SilenceOfWinter
та еще зажигалка...

Расширение/наследование автозагрузчика Composer'а?

Встала задача: после загрузки классов наследующих определенный интерфейс вызывать метод для инициализации их статических свойств.
Проблема в том, что:
  1. загрузчик Composer не реализует механизм событий
  2. имя класса авто генерируется при установке пакета (что-то вроде ComposerAutoloaderInitb1b2e8b29b5f68f94ccccac75d036f38) и соответственно непонятно как лучше организовать наследование

В голову пришли варианты:
  1. Decorator обертка: вначале загружать загрузчик Composer, потом передавать его в фасад и перерегистрировать автозагрузку на фасад
  2. генерировать класс наследующий загрузчик Composer: добавить событие в composer.json
    "scripts": {"post-root-package-install": "Vendor\CodeGenerator\Autoloader::generate"}
    и в этом методе генерировать код

Как лучше реализовать? Рассматриваю любые варианты (:
  • Вопрос задан
  • 193 просмотра
Решения вопроса 1
SilenceOfWinter
@SilenceOfWinter Автор вопроса, куратор тега PHP
та еще зажигалка...
в итоге разобрав все подводные камни пришел в выводу что единственный жизнеспособный вариант это добавить свой загрузчик после композиторского и наследующий Composer\Autoload\ClassLoader.
Внимание: В 7.4 OPCache обзавелся предзагрузкой классов которая минует автозагрузку.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@genteelknight
Fullstack web developer
В комментах к самому вопросу напихали тебе по самое не хочу и местами даже по делу. Но возможно в твоем случае по другому никак не сделать. Лично я за первый вариант. Самому приходилось патчить загрузчик композера на ряде проектов, примерно так это выглядит:

<?php

use Composer\Autoload\ClassLoader;
use function Composer\Autoload\includeFile;

if (file_exists($composerAutoloaderPath = __DIR__ . '/../../../autoload.php')) {
    $patchedLoader = new class(require $composerAutoloaderPath) {
        private $loader;

        public function __construct(ClassLoader $loader)
        {
            $loader->unregister();
            $this->loader = $loader;
        }

        public function register($prepend = false): void
        {
            spl_autoload_register([$this, 'loadClass'], true, $prepend);
        }

        public function unregister(): void
        {
            spl_autoload_unregister([$this, 'loadClass']);
        }

        /**
         * Loads the given class or interface.
         * @param string $class The name of the class
         * @return bool True if loaded, null otherwise
         */
        public function loadClass($class): bool
        {
            if ($file = $this->loader->findFile($class)) {
                includeFile($file);

                // дополнительные патчи здесь

                return true;
            }

            return false;
        }
    };

    $patchedLoader->register(true);
}


Вместо vendor/autoload.php подключаешь файл со своим лоадером.

Этот вопрос ты можешь адресовать разработчикам пакетов которые я подключаю в своем проекте.


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

если надо выполнить какую то операцию при загрузке вешейте на события композера
если надо что то дополнительно заггрузить так и пропишите это в composer.json
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы