В продолжение моей предыдущей статьи на эту тему, решил пересмотреть и переосмыслить то, с чем приходилось работать в течение полугода. В целом, модель годная, но при использовании вскрываются некоторые мелкие недостатки, которые удобнее было бы организовать по другому. Итак

Классы и библиотеки

В 21 веке без автозагрузки уже никуда. Сейчас активно использую на всех своих проектах автозагрузку по стандарту psr-4. Кто до сих пор не знаком со стандартами, разрабатываемыми PHP-FIG - то бегом знакомиться.
В директории /local у меня теперь существует папочка /classes, которая и содержит в себе все необходимые классы. Единственный мой класс, который подключается вручную в init.php - \Mx\Psr4Autoloader. Там же я регистрирую соответствие пространства имен и директории на сервере, а после этого класс уже делает все за меня - мне остается лишь соблюдать структуру директорий и правила именования файлов.

require_once(__DIR__ . '/../local/classes/Mx/Psr4Autoloader.php');
$psr4 = new \Mx\Psr4Autoloader();
$psr4->addNamespace('Mx', __DIR__ . '/../local/classes/Mx/');
$psr4->register();

Большинство современных библиотек поддерживает стандарты автозагрузки (psr-4 или его предка psr-0), не стесняйтесь добавлять реализацию для этих автозагрузчиков и использовать их, подключая сторонние библиотеки. Это справедливо только для тех библиотек, которые еще по каким-то причинам не опубликованы в packagist или на гитхабе. С остальными же все сильно проще, они легко подключаются с помощью composer.

Для хранения проектного кода я сейчас в большей степени использую классы, а значит все правила, описанные выше, применяются и к обычному коду для битрикса. Я принял для себя следующую структуру (Mx - это краткое имя вендора, компании в которой я работаю ):
/local/classes/Mx/Main - все, что относится к главному модулю, а именно
/local/classes/Mx/Main/Component/ - дополнения функционала компонентов. Пока-что тут только базовый класс, который я использую для создания всех своих компонент
/local/classes/Mx/Main/EventHandler - обработчики событий, для них я использую свой автозагрузчик, о котором чуть ниже
/local/classes/Mx/Main/Agent/ - различные агенты, которые тоже можно дробить по принадлежности к функционалу
и так далее .. Можно придумать очень много, и будет все разложено «по полочкам». Мне - удобно. А вам?

Обработчики событий

Для обработчиков я использую нечто подобное psr-4 автозагрузчику, только переписанному на свой лад. Принцип тот же - есть класс, который задает соответствие директории и пространства имен. В этом классе есть метод, который регистрирует все эти соответствия и автоматически вызывает addEventHandler для всех найденных обработчиков.

$el = new \Mx\Main\EventListener();
$el->addNamespace('\\Mx\\Main\\EventHandler', __DIR__ . '/../local/classes/Mx/Main/EventHandler');
$el->register();

А в реализации метода register как раз и содержится вся «магия». Помимо этого есть также и базовый класс для всех обработчиков событий, который позволяет обмениваться данными между обработчиками, управлять порядком вызова обработчиков, да и все что душе угодно можно к нему прикрутить. Мне оч. нравится

Зависимости

Про Composer я уже писал, и там тоже нужно статью несколько дополнить, чем займусь в ближайшее время. А сейчас хочу лишь напомнить, что есть такая замечательная штука, и нет ни одной причины, чтобы не использовать ее.
Кстати говоря - есть возможность подключать не только обычные классы-библиотеки, но и компоненты Symfony. Есть возможность нативно подключать даже битриксовые библиотеки/компоненты/шаблоны (в этом нам поможет composer/installers). В общем - дерзайте, вещь нужная и полезная.

На доработку

Пока остается еще неразрешенная проблема с фронтенд-библиотеками. Не нравится мне моя текущая система. Хочу подцепить к битриксу BowerPHP, организовав хранение и управление зависимостями. А там может получится и грамотный автозагрузчик сделать на основании конфигов Bower.
Также в планах обернуть все описанное выше в небольшой модуль, чтобы цеплять его к проекту через composer. Работу уже начал, скоро будет, тогда и опубликую.

UPD. А вот и модуль UPD2. Продолжение статьи