Сегодня я делаю что-то немного сложное в PHP 5.3.29. Я нахожусь в сценарии, где я должен цепи func_get_args
, call_user_func_array
и передать немного аргументов по ссылке.
Попытка упрощенного сценария выглядит следующим образом:
caller.php
//* Caller Setup *//
// Define which Modules call which Hooks
global $hooks = array(
'hookA' => array('moduleA', 'moduleB'),
'hookB' => array('moduleA')
);
// Generically calls any Hook for all Modules
function caller_call_hook($hook, $by_reference = array())
{
// Use Hooks Array
global $hooks;
// Initialize Return Array
$values = array();
// Determine the Arguments for the Function Call
$args = func_get_args();
// Remove $hook and $by_reference from the Arguments
unset($args[0], $args[1]);
$args = array_values($args); // Collapse Array
// Map specified Arguments by Reference
foreach($by_reference as $index)
$args[$index] =& $args[$index];
// Call each Embedded Hook
foreach($hooks[$hook] as $module)
$values[$module] = call_user_func_array($module . '_' . $hook, $args);
// Return all Values
return $values;
}
//* Caller Triggers *//
function caller_hook_A($paramA, $paramB)
{
caller_call_hook('hook_A', array(), $paramA, $paramB);
}
function caller_hook_B(&$paramA)
{
caller_call_hook('hook_B', array(0), $paramA);
}
moduleA.php
function moduleA_hook_A($paramA, $paramB) { ... }
function moduleA_hook_B(&$paramA) { ... }
moduleB.php
function moduleB_hook_A($paramA, $paramB) { ... }
Выполнение всего этого выдает предупреждение:
Warning: Parameter 1 to moduleA_hook_B() expected to be a reference, value given in caller_call_hook()
Как я могу сделать эту работу, как задумано?
Просто, чтобы дать некоторое представление о том, что на самом деле происходит здесь:
Я работаю в рамках, где caller_hook_*
называется рамкой. Я по сути использую гость как временный «Code Hub», где различные функции в моем коде обрабатываются отдельно.
И нет, я не могу разделить этот проект на несколько проектов. Это ограничение наложено на меня. Обычно, я бы выбрал этот маршрут.
module*
функции — это в основном внутренние функции, которые я хочу иметь возможность легко включать и выключать. Это намеренно отдельные файлы, так как сами модули не имеют кроссовера, за исключением того, что они иногда используют одни и те же хуки.
Все конфигурации для самих крючков обрабатываются в $hooks
переменная (Это упрощенная версия. Обычно есть также атрибуты функций для каждого модуля, атрибуты модуля и т. Д., Но это не требуется для этой конкретной проблемы.).
Я стараюсь максимально обобщить это. Я знаю, что я мог бы засунуть все в соответствующие caller_hook_*
функций, но по мере роста этого проекта эти хуки станут громоздкими для обслуживания, если независимые функции будут объединены.
Некоторые из крючков используют Pass-By-Reference на некоторых из их аргументов, поэтому я должен иметь возможность указать, какие из них. Все, что я сделал до сих пор, работает для всех Pass-By-Value только функции.
Я тоже не хочу использовать время вызова по ссылке.
Я закончил тем, что заставил это работать, хотя странное решение.
Я был на правильном пути, просто немного не в себе.
Я изменил это:
// Map specified Arguments by Reference
foreach($by_reference as $index)
$args[$index] =& $args[$index];
к этому:
// Map specified Arguments by Reference
$refs = array();
foreach($args as $key => &$value)
$refs[$key] =& $value;
и это:
// Call each Embedded Hook
foreach($hooks[$hook] as $module)
$values[$module] = call_user_func_array($module . '_' . $hook, $args);
к этому:
// Call each Embedded Hook
foreach($hooks[$hook] as $module)
$values[$module] = call_user_func_array($module . '_' . $hook, $refs);
Это немного странно, но это делает работу. Оказывается, мне не нужно $by_reference
переменная.
Других решений пока нет …