2013-12-05 3 views
0

Я использую Yii в своем проекте и хочу реализовать модель события с обратными вызовами. Я сделал модель «Event» в MySQL и хочу хранить анонимные функции во многих областях, например,Вызов анонимной функции из db

**Event model in Yii** 
id - int 
name - varchar(255) 
beforeEvent - text 

В «afterEvent» поле сохраненной функции:

function(){echo 'afterEvent #1';} 

Тогда Принести все события и попробовать вызов функция «afterEvent»:

$events  = Event::model()->findAll(); 
foreach ($events as $event) 
{ 
    $event->beforeEvent();        
} 

Как я не этот метод в модели Event, я сделал метод прокси

public function beforeEvent() { call_user_func($this->beforeEvent); } 

Проблема в ошибке:

call_user_func() expects parameter 1 to be a valid callback, function 'function(){ echo 'afterEvent of event #1 done'; }' not found or invalid function name


Найдено 1 Раствор: в прокси-метода BeforeEvent() использовать create_function функцию следующим образом:

public function beforeEvent(array $params){ 
$callback = create_function('$params', $this->beforeEvent); 
$callback($params); 
} 

, но в руководстве сказано:

This function internally performs an eval() and as such has the same security issues as eval(). Additionally it has bad performance and memory usage characteristics. If you are using PHP 5.3.0 or newer a native anonymous function should be used instead.

и мы знаем, что eval - это зло. Как я могу использовать анонимную функцию в этой ситуации?

+0

Это зло, если вы не можете управлять входом.Проблема здесь в том, что если кто-то получает доступ к вашей базе данных, они могут выполнять произвольный код на веб-сервере. Поэтому, независимо от способа выполнения этого кода, проблема все равно будет существовать. –

ответ

1

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

Это также много здравомыслящих относительно возможности реорганизации вашего кода. Представьте, что вам нужно переписать что-то, что сломает миллион функций обратного вызова, хранящихся в вашей базе данных ... не забавная ситуация. Данные - ваш актив, код - вот что делает этот актив доступным. Как правило, всегда держитесь в затылке. «Что, если я удалю золото с помощью этого проекта, внезапно нужно масштабировать до 100x размера, и я нанял агентство, чтобы переписать все в more scalable platform X за ночь, могу ли я просто продолжить используя те же данные? " Следовательно, данные должны быть несовместимыми с платформой. Хранение исполняемого кода в базе данных - нет.

+0

спасибо, идея - «идентификатор того, что вы хотите совершить в определенном событии (например, sendEmail)», отлично. – 6yt9Bka

0

Вы правы, вам следует избегать eval.

Я бы использовал другие типы PHP callables и сериализовал их в столбце beforeEvent, используя serialize.

Тогда вы будете в состоянии назвать их, как вы предложили:

public function beforeEvent() { call_user_func($this->beforeEvent); } 

Анонимные функции не могут быть сериализованы (пока).

Смежные вопросы