2013-12-09 4 views
1

Справочная информация:

Я использую Symfony Console Component, чтобы написать консольное приложение, которое завернуто в объект Shell. Я написал команду с именем console:reload, которая опустошает массив команд из объекта Application и повторно добавляет классы команд, перечисленные в определенном каталоге.php - Является ли php кешированием классов перед созданием?

Эта команда запускается при запуске оболочки, поэтому Application загружается доступными командами. Классы загружаемой расположены в специальном каталоге и должны следовать простому правилу имя: <CommandName>Command.php:

// Inside ReloadCommand->execute() method... 
$pamperoApp = $this->getApplication(); 
$pamperoApp->clearCommands(); 
$namespace = "pampero\\cli\\modules"; 
foreach(glob(MODULES_DIR . "/*/*Command.php") as $command) { 
    $class = str_replace(".php", "", $namespace . "\\" . basename(dirname($command)) . "\\" . basename($command)); 
    $this->getApplication()->add(new $class); 
} 

автозагрузку обеспечивается Symfony ClassLoader используется (композитор):

// Main entry point... 
loader = require_once __DIR__ . '/../vendor/autoload.php'; 
$loader->set('pampero', __DIR__ . '/../..'); 

Я прочитал код от ClassLoader класс, и то, что он делает, - это сохранить путь к имени файла, поэтому нет кэширования объекта.

Вот проблема:

я запустить приложение: php packages.php. Оболочка появляется после выполнения команды ReloadCommand. Список доступных и загруженных команд готов к использованию.

Если я создаю новый файл, скажем: ExampleCommand.php, а затем я набираю: console:reload, новая команда действительно будет добавлена. Теперь, если я изменил код внутри ExampleCommand.php и снова запустил console:reload, изменения, внесенные в класс, не вступят в силу.

Но это еще не все. Если я удалю файл примера, вызовите console:reload, создайте файл снова и запустите: console:reload команда будет добавлена.

Чтение:

Я прочитал APC связанные вещи, и, прежде чем создавать новые классы я делал такие вещи, как:

// Prior adding commands in ReloadCommand 
apc_clear_cache(); 
apc_clear_cache('user'); 
apc_clear_cache('opcode'); 

Без везения. Я также запустил apc.php и включил/отключил apc.enable_cli. Ни одна из этих вещей не создает объект, представленный модифицированным файлом.

Так что мои подсказки и подсказки о проблемах превращаются в кеширование классов при обнаружении файла/класса. Но как этого избежать? Я не хочу перезапускать оболочку, если через классы добавлена ​​дополнительная функциональность.

Любые идеи?

+0

Я думаю, что проблема заключается, что, когда файл включен, изменения в файл не будет отражаться. – Sebastian

ответ

0

Я отвечу на свой вопрос, поскольку нашел решение.

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

Итак, мне нужна была какая-то интроспекция. После чтения/поиска/поиска в течение всей ночи, наконец, я нашел Runkit.

Runkit documentation можно найти здесь. Я знаю, что это не лучшее, что вы можете сделать с вашим дизайном кода.Но для моих потребностей проекта, правда в том, что Reflection был необходим.

Вот модифицированный код с помощью Runkit:

protected function execute(InputInterface $input, OutputInterface $output) 
{ 
    // Gets a reference to the console application and removes all commands 
    $pamperoApp = $this->getApplication(); 
    $pamperoApp->clearCommands(); 
    // Adds default commands and add this command 
    $pamperoApp->addCommands($pamperoApp->getDefaultCommands()); 
    $pamperoApp->add($this); 

    $namespace = "pampero\\cli\\modules"; 

    foreach(glob(MODULES_DIR . "/*/*Command.php") as $filename) { 
      $className = str_replace(".php", "", $namespace . "\\" . basename(dirname($filename)) . "\\" . basename($filename)); 
      // Do not add this command again. This command shouldn't be modified on-the-fly 
      if (get_class($this) !== $className) { 
        $class = new $className(); 
        // Redefines the class definition 
        runkit_import($filename, RUNKIT_IMPORT_CLASSES | RUNKIT_OVERRIDE_OBJECTS | RUNKIT_IMPORT_OVERRIDE); 
        $pamperoApp->add($class); 
      } 
    } 
} 
Смежные вопросы