Внедрить код в закрытие PHP - PullRequest
2 голосов
/ 28 февраля 2011

У меня уже есть определенное замыкание, и я хочу вставить код внутрь при выполнении.Вот пример:

$predefined = "print 'my predefined injected code<br />';";
$closure = function () {
  print 'hello<br />';
};
call_user_func_array($closure, array());
// output : hello

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

$closure = function () {
  print 'my predefined injected code<br />';
  print 'hello<br />';
};

Можно ли вставить код в закрытие перед его выполнением?

Примечание: я не могу использовать "create_function", котораявзять код в виде строки, так что может быть легко изменено.Замыкания уже определены и определены определенным образом (через функцию, которая принимает аргумент обратного вызова, а не строковый аргумент).

Спасибо за вашу помощь.


РЕДАКТИРОВАТЬ:

Вот решение

function hackClosure($closure, $inject_code)
{
    $reflection = new ReflectionFunction($closure);
    $tmp = $reflection->getParameters();
    $args = array();
    foreach ($tmp as $a) array_push($args, '$'.$a->getName() . ($a->isDefaultValueAvailable() ? '=\''.$a->getDefaultValue().'\'' : ''));
    $file = new SplFileObject($reflection->getFileName());
    $file->seek($reflection->getStartLine()-1);
    $code = '';
    while ($file->key() < $reflection->getEndLine())
    {
        $code .= $file->current();
        $file->next();
    }
    $start = strpos($code, '{')+1;
    $end = strrpos($code, '}');
    return create_function(implode(', ', $args), substr($code, $start, $end - $start) . $inject_code);
}

$theClosure = function () { print 'something'; };

$inject_code = "print ' to say';";

$func = hackClosure($theClosure, $inject_code);
$func();

Он отображает

something to say

вместо

something

Ответы [ 3 ]

8 голосов
/ 28 февраля 2011

Вы не можете напрямую ввести его. Однако вы можете обернуть его.

$newClosure = function() use ($closure) {
    print 'my predefined injected code<br />';
    $closure();
};

Кроме того, нет необходимости использовать call_user_func_array, поскольку вы не передаете никаких аргументов. Просто позвоните $closure();

Кроме того, вы можете создать оболочку для нового замыкания:

$creator = function($closure) {
    return function() use ($closure) {
        print 'my predefined injected code<br />';
        $closure();
    };
};

$newClosure = $creator($closure);
$newClosure();
0 голосов
/ 28 февраля 2011

Разве это не то, что вы ищете?http://php.net/manual/en/function.eval.php

0 голосов
/ 28 февраля 2011

возможно что-то вроде этого:

$closure = function($optionalcode = null) {
    print('blah blah blah');
    if (!isnull($optionalcode)) { eval($optionalcode); }
    print('blah blah blah');
}

$closure("print('yoohoo!');");

Однако, eval() является злом и его следует избегать любой ценой.

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