Автозагрузка классов

ksnk

прохожий
Чтобы предложить админу включить или выключить имеющиеся плагины ?
 

fixxxer

К.О.
Партнер клуба
Если предположить, что это действительно надо (в чем я сомневаюсь).

1) перечислить явно (поскольку далеко не все модели - это aggregate roots)

$models = [
ModelA::class,
ModelB::class,
..
];

2) просканировать файловую систему, найти по паттерну нужные php-файлы, преобразовать имя файла в имя класса, подгрузить автолоадером (class_exists), отфильтровать по необходимости reflection-ом
 

StalkerClasses

Новичок
А зачем в админке список моделей вообще
какое дело админу до внутреннего устройства исходного кода?
Зачем мне это понадобилось покажу позже.
Список моделей ищется glob по файловой маске. В характерном месте/местах сайта. Обычно эти места прописываются в конфиге, или система сама их знает... В друпал, к примеру, все модели имеют расширение не .php, а .model, так как в нормальной модельке может быть значительно более одного файла. Дальше, когда файл нашелся, его можно попробовать отзеркалить - reflectionClass. так можно получить информацию об общем предке (бывает полезно), проверить параметры ключевых методов, если нет интерфейсов, или настроить автоматом вызов, если так и надо.
Вы как раз описали ту задачу которую я пытаюсь решить.
Я не смог получить информацию о файлах которые загружаются через композер. Мне пришлось сделать Include нескольких нужных папок.

1) перечислить явно (поскольку далеко не все модели - это aggregate roots)
Я не могу перечислять явно в этом нет смысла
2) просканировать файловую систему, найти по паттерну нужные php-файлы, преобразовать имя файла в имя класса, подгрузить автолоадером (class_exists), отфильтровать по необходимости reflection-ом
Слишком сложно ради того что бы получить инфу о класее.
.
 

ksnk

прохожий
Слишком сложно ради того что бы получить инфу о класее.
? Проще инклудить неизвестный файл и непонятным классом? иногда нарываясь на синтаксические ошибки ...

Я как-то сочинял для таскания с места на место, простой и настраиваемый инструментарий. Вот, примерно, на каком виде остановился.
Для всех файлов, которые подходят под маску **/*_scenario.php рефлексируется класс, совпадающий с именем файла, парсится блок phpDoc с описанием класса и по нему строится менюшка приложения с возможностью выбрать тот или иной сценарий.

В классе пробегаюсь по всем методам do_* . К таким методам парсим блок phpDoc описания функции
PHP:
<?php
namespace scenario;
/**
 *  анализатор логов
 */

/**
 * Читалка длинных логов. Греп по IP.
 * Class grep_logs_scenario
 * @property scaner $scaner
 * @tags scanlog
 */
class grep_logs_scenario extends scenario
{

    /**
     * Сканирование логов по IP
     * @param string $log :select[:все|~dir(*.{gz,log})] лог для поиска
     * @param string $pattern :text IP для поиска
     * @param string $text :text текст для поиска
     */

    function do_scanlog($log,$pattern,$text=''){
        $this->scaner->newhandle($log);$reg1='';
        if(!empty($text)) $reg1=$text;
        if(!empty($pattern)) $reg='~'.preg_quote($pattern).'[^\n]+~';
        else {
            $reg=$reg1;
        }
        $reg1='~\.(jpe?g|gif|js|ico|css|png)(\?\d+?|)\s+HTTP/1~';
        $reg2='~YandexBot/3\.0|AhrefsBot/5\.0~';
        do {
            $this->scaner->scan($reg,0);
            if($this->scaner->found){
                $result=$this->scaner->getresult();
                $result=$result[0];
                if(preg_match($reg1,$result) || preg_match($reg2,$result)) continue;
                echo $result. PHP_EOL;
            } else
                break;
        } while (true);
    }
Автоматически строится вот такая формочка
1415
По заполнении формы и нажатии на кнопку - вызывался метод класса.
 

atainex

некромант
Когда-то баловался этой темой. Писал самописный микродвижок для самых маленьких различных решений. Сделал так, чтобы можно было использовать composer (с его автозагрузчиком), но в то же время, если composer не подтянут, чтобы всё работало по-прежнему так же. Для этого даже название метода addPsr4() повторил (чтобы конфликтов не было, в случае наличия или отсутствия composer-автозагрузчика). Эта штука, можно смело утверждать, копирует поведение композиторного автозагрузчика. Обратите внимание, что скрипт в конце возвращает экземпляр (удалите, если не нужно).

На пальцах принцип такой: метод addPsr4() добавляет в репозиторий пространство имён и путь к физической директории с классами соответствующего пространства. В репозиторий также попадает первый символ пространства (для дальнейшего удобного поиска нужного пространства у вызываемого класса). При вызове класса, тут уже описано поведение для spl_autoload_register(), оно заключается в поиске соответствующего пространства имён по первой букве вызываемого класса, дальше идёт конвертация пути согласно физической директории + самой структуры пространства имени, где уже происходит require_once() конкретного файла.

PHP:
namespace Lampa;

class LampaLoader
{
    function __construct() {
        /*
        * Здесь можно перечислить те пространства имён и директорию к классам этого пространства,
        * которые должны грузиться в первую очередь (например системные)
        */
        // $this->addPsr4('Lampa\\', 'system/classes');
    }
    protected $namespaceMap = array();
    protected $prefixMap = array();

    public function addPsr4($namespace, $path, $prepend = false)
    {
        $length = strlen($namespace);
        if ('\\' !== $namespace[$length - 1]) {
            die('Не пустой PSR-4 префикс должен быть со слешем (\) в конце');
        }
        $fixPath = static::fixPath(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . $path);
        if (is_dir($fixPath)){
            $this->namespaceMap[$namespace] = $fixPath;
            $this->prefixMap[$namespace[0]][$namespace] = $length;
            $this->register();
            return true;
        }
        return false;
    }

    public function register()
    {
        spl_autoload_register(array($this, 'autoload'));
    }

    protected function autoload($class)
    {
        if (!empty($this->prefixMap[$class[0]])) {
            $sortPrefixes = uksort($this->prefixMap[$class[0]], function ($a, $b) {
                return strlen($b) - strlen($a);
            });
            foreach ($this->prefixMap[$class[0]] as $kPref => $vPref) {
                if(stristr($class, $kPref)) {
                    $sPref = $kPref;
                    break;
                }
            }
            $pathParts = explode('\\', str_replace($sPref, '', $class));
            if (is_array($pathParts)){
                if (!empty($this->namespaceMap[$sPref])) {
                    $filePath = $this->namespaceMap[$sPref]. DIRECTORY_SEPARATOR .implode(DIRECTORY_SEPARATOR, $pathParts).'.php';
                    if (file_exists($filePath)) {
                        require_once $filePath;
                        return true;
                    } else {
                        return false;
                    }
                }
            }
        } else {
            die('Класс «'.$class.'» не найден в системе');
        }
        return false;
    }
   
    public static function fixPath($path)
    {
        return str_replace('/', DIRECTORY_SEPARATOR, str_replace('\\', '/', $path));
    }

}

return new LampaLoader();
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
чувак, открой для себя wordpress, на нем не случайно более трети всех сайтов мира работает
 

AnrDaemon

Продвинутый новичок
А мне вот режет глаза eval. Что теперь? Сидеть и выпиливать его из фреймворка?
 
Сверху