Динамически создать подкласс - PullRequest
1 голос
/ 08 января 2009

Я использую Kohana и только что нашел этот кусок кода в их методе автозагрузки

        // Class extension to be evaluated
        $extension = 'class '.$class.' extends '.$class.'_Core { }';

        // Start class analysis
        $core = new ReflectionClass($class.'_Core');

        if ($core->isAbstract())
        {
            // Make the extension abstract
            $extension = 'abstract '.$extension;
        }

        // Transparent class extensions are handled using eval. This is
        // a disgusting hack, but it gets the job done.
        eval($extension);

В основном это происходит, когда я имею в виду класс, который не существует (посредством создания объекта, вызова class_exists () и т. Д.), Кохана создаст класс (например, Foo), который расширяет класс библиотеки, который следует определенное соглашение об именах (например, Foo_Core). просто будучи любопытным, есть ли способ сделать что-то подобное, но без использования eval?

Ответы [ 3 ]

2 голосов
/ 08 января 2009

Если вы хотите создать динамический класс, тогда eval() - это функция goto ( каламбур предназначен. ) Как бы это ни было связано, я обнаружил, что вы можете поместить объявление класса в if-then заявление. Таким образом, вы можете сделать следующее:

if(true)
{
    class foo
    {
       // methods
    }
}

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

1 голос
/ 08 января 2009

Я думаю, что вы застряли с eval() для этого.

Это помечено как "отвратительный взлом", так что все в порядке:)

Мне было бы интересно узнать, что вы делаете с таким пустым классом ...

0 голосов
/ 08 января 2009

Если вы хотите иметь возможность кэшировать ваши динамически созданные классы, вы можете записать в файл и потребовать его вместо этого. Это можно считать одинаково хакерским, но это вариант. Для классов, которые создаются один раз и используются часто, это может быть хорошим решением. Для классов, которые должны быть динамическими каждый раз, придерживаться eval, вероятно, лучшее решение.

$proxyClassOnDisk = '/path/to/proxyCodeCache/' . $clazz .'.cachedProxyClass';
if ( ! file_exists($proxyClassOnDisk) ) {
    // Generate the proxy and put it into the proxy class on disk.
    file_put_contents($proxyClassOnDisk, $this->generateProxy($object));
}
require_once($proxyClassOnDisk);

В этом примере идея заключается в том, что вы создаете динамические прокси для класса $object. $this->generateProxy($object) вернет строку, которая более или менее похожа на то, как $extension выглядит в исходном вопросе.

Это ни в коем случае не полная реализация, просто некоторый псевдокод, чтобы показать то, что я описываю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...