Динамически загружать функции в класс из внешнего файла - PullRequest
2 голосов
/ 08 апреля 2009

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

$registry->helper->load('external_helper_function_file');

после этого он сможет вызывать функцию в файле следующим образом:

$registry->helper->function();

Спасибо за любую помощь

Ответы [ 3 ]

7 голосов
/ 08 апреля 2009

Если оставить в стороне мнения, это хороший ООП дизайн. Это возможно даже с текущей версией PHP, хотя и не так чисто, как с PHP5.3.

class Helper {
    /* ... */
    function load($file) {
      include_once($file);
    }
    function __call($functionName, $args) {
       if(function_exists($functionName))  
         return call_user_func_array($functionName, $args);
    }

}
2 голосов
/ 08 апреля 2009

хорошо, во-первых, я согласен, что это плохие манеры. также в 5.3 вы можете использовать новый синтаксис замыкания с магическим словом __call для использования операторов в качестве функций (стиль JS).

Теперь, если мы хотим предоставить способ сделать это по-вашему, я могу подумать об использовании create_fnuction, смешанного с магией __call.

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

хорошо, вот класс. Я получил вдохновение от класса, который видел несколько недель назад и использовал замыкания для реализации объектов в стиле JS:

/**
 * supplies an interface with which you can load external functions into an existing object
 * 
 * the functions supplied to this class will recive the classes referance as a first argument, and as 
 * a second argument they will recive an array of supplied arguments.
 * 
 * @author arieh glazer <arieh.glazer@gmail.com>
 * @license MIT like 
 */
class Function_Loader{
    /**
     * @param array holder of genarated functions
     * @access protected
     */
    protected $_funcs = array();

    /**
     * loads functions for an external file into the object
     * 
     * a note- the file must not contain php tags.
     * 
     * @param string $source a file's loaction
     * 
     * @access public
     */
    public function load($source){
        $ptrn = '/function[\s]+([a-zA-Z0-9_-]*)[\s]*\((.*)\)[\s]*{([\w\s\D]+)}[\s]*/iU';
        $source = file_get_contents($source);
        preg_match_all($ptrn,$source,$matches);
        $names = $matches[1];
        $vars = $matches[2];
        $funcs = $matches[3];
        for ($i=0,$l=count($names);$i<$l;$i++){
            $this->_funcs[$names[$i]] = create_function($vars[$i],$funcs[$i]);
        }
    }

    public function __call($name,$args){
        if (isset($this->_funcs[$name])) $this->_funcs[$name]($this,$args);
        else throw new Exception("No Such Method $name");
    }
}

ограничения - во-первых, источник не может иметь никаких тегов php. Во-вторых, функции всегда будут публичными. В-третьих, мы можем только подражать этому. я передал в качестве 1-го аргумента $ this, а второй - массив аргументов (это 4-е ограничение). Кроме того, вы не сможете получить доступ к закрытым членам и методам из класса. пример для исходного файла:

function a($self,$arr=array()){
    //assuming the object has a member called str
    echo $self->str;
}

это было забавное упражнение для меня, но в целом плохая практика

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

То есть вы хотите не просто include файл, а include его в области объекта?

...

Я думаю, вы поступили неправильно. Это имеет больше смысла, если у объекта registry есть ряд вспомогательных членов, которые имеют свои собственные функции. Чистый результат может выглядеть примерно так:

$registry->aHelper->aFunction();
$registry->aDifferentHelper->aDifferentFunction();

При осторожном использовании синтаксиса {} вы сможете динамически добавлять объекты-члены к вашему объекту бога.

На данный момент стоит отметить, что объект бога почти неизменен анти-паттерн . Если вы нуждаетесь в этих функциях глобально, используйте технику начальной загрузки и поместите их в глобальную область видимости. Если вам нужно передать эти данные, то либо передать их нужным функциям, либо сохранить в базе данных и получить их в другом месте.

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

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