Intereting Posts
PHP escape пользовательский ввод для имени файла Отображение таблицы в PHP с повторяющимися столбцами css исчезает при попытке создать чистый URL-адрес Переменная конкатенированная строка запроса mysql отлично работает в phpMyAdmin, но не PHP в скрипте Как функция автоматического вызова в php для вызова любой другой функции Преобразование html в word / excel / powerPoint с помощью PHP Google App Engine getImageServingUrl с именем файла загрузки Проверка совместимости версий PHP Загрузка изображения на facebook Несколько запросов PHP-запросов на сбои Ближайшая дата SQL Некоторые значения с плавающей запятой должны суммироваться до нуля в PHP, но не Считать конкретные значения в многомерном массиве Создание интерфейса в PHP, который может указать тип, чтобы определить, какой класс использовать Можно ли защитить каталог / файл на сервере от внешнего мира, но сделать его доступным для PHP?

Получение этой внутренней функции

У меня есть функция вне моего класса, и я call_user_func ее изнутри с помощью call_user_func , моя проблема в том, что я не могу использовать класс доступа внутри функции. Мне нужен способ доступа к моему классу, не передавая его в аргументы, если бы был способ сделать $this работу внутри функции, которая была бы замечательной.

Любые советы, кроме передачи класса с аргументом в функцию, будут оценены;

 function test($arg1) { $this->code = 10; // i know $this won't work here, // but i need a way to change $code // property from this function without // passing class into this function by using arguments } class MyClass { public $code; public function call() { call_user_func("test", "argument1"); } } 

Если вы можете переместить функцию внутри своего класса, вы можете вызвать ее так:

 call_user_func(array($this, 'the_function')); 

Если у вас есть PHP5.3, вы можете использовать закрытие:

 $that = $this; $function = function() use ($that) { // use $that instead of $this }; call_user_func($function); 

Если вы можете добавить аргумент, вы можете сделать следующее:

 call_user_func('the_function', "argument1", $this); 

Передайте $this как первый параметр, если функция запрашивает его:

(Если функция имеет параметр с именем $__this , передайте $this как параметр)

 function the_function($__this, $foo, $bar) { } $arguments = array('argument1'); $function = new ReflectionFunction('the_function'); $params = $function->getParameters(); if (count($params) > 0 && $params[0]->name == '__this') { array_unshift($arguments, $this); } $function->invokeArgs($arguments); 

Вы можете сделать то же самое с комментариями doc:

 /** * @IWantThis */ function the_function($__this) { } $function = new ReflectionFunction('the_function'); if (preg_match('/@IWantThis/', $function->getDocComment()) { ... 

Непосредственно у вас есть два варианта: либо передача объекта в функцию, либо значение для объекта . Я понятия не имею, если это единственное задание, которое выполняет функция, поэтому это может не решить вашу проблему, просто показывая альтернативу, поскольку вы написали, что передача объекта функции не является вариантом:

 function test($arg1) { return 10; } class MyClass { public $code; public function call() { $this->code = call_user_func("test", "argument1"); } } 

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

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

 function test($arg1) { global $object; $object->code = 10; } class MyClass { public $code; public function call() { global $object; $object = $this; call_user_func("test", "argument1"); unset($object); } } с function test($arg1) { global $object; $object->code = 10; } class MyClass { public $code; public function call() { global $object; $object = $this; call_user_func("test", "argument1"); unset($object); } } 

Чтобы создать более динамический контекст, вы инкапсулируете все в какой-то контекст:

 class contextCallback { private $object; public function __construct($object) { $this->object = $object; } public function test() { $this->object = 10; } } class MyClass { public $code; public function call() { $callback = new contextCallback($this); call_user_func(array($callback, 'test'), "argument1"); # or: $callback->test("argument1"); } } 

Однако я думаю, что передача $this в качестве аргумента намного проще и почти то же самое с гораздо меньшим количеством кода. Я понятия не имею, почему вам нужен call_user_func поэтому он остается абстрактным.

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

 function test($arg1) { $object->code = 10; return array($value, $object); } class MyClass { public $code; public function call() { list($value, $object) = call_user_func("test", "argument1"); foreach($object as $var => $value) $this->$var = $value; } } 

У вас есть два варианта. Сделайте метод методом объекта MyClass или сделайте объект параметром функции.

Если у вас есть функция, вы хотите, чтобы она делала то же самое, каждый раз. Это означает, что если функция зависит от некоторого состояния (например, значение $this ), вам нужно найти способ либо 1. сделать его глобальным (не здесь), либо 2. передать его в качестве параметра.

Вы все равно не нуждаетесь в $this в этой функции, вам нужен какой-то объект, который имеет атрибут, названный любым содержимым $code (я думаю, что это опечатка на самом деле. Я думаю, вы имеете в виду $this->code не $this->$code ).

Вы можете использовать закрытие (php 5.3+), чтобы «передать» ссылку на объект тем функциям, которые в ней нуждаются.
Но вам нужно будет сделать разницу между «старыми» функциями и «новыми» функциями расширения. И новые функции по-прежнему имеют доступ к общедоступным свойствам / методам объекта.

 <?php class MyClass { public $code = 0; protected $functions=array(); public function call($fn) { if ( is_string($fn) && isset($this->functions[$fn]) ) { $fn = $this->functions[$fn]; } if ( !is_callable($fn) ) { die('add error handler here'); } $rv = call_user_func($fn, 'argument1'); } public function loadFunctions($file) { $fnInit = require $file; $fns = $fnInit($this); $this->functions = array_merge($this->functions, $fns); } } $m = new MyClass; $m->loadFunctions('ext.php'); $m->call('oldFn'); $m->call('foo'); $m->call('bar'); echo 'and now $m->code is: ', $m->code; 

и как ext.php:

 <?php function oldFn($arg) { // that's probably all you have to do atm to have a new "extension function" for your class echo "oldFn($arg)\n"; } return function($obj) { // and that's more or less how the new functions would have to be declared/defined return array( 'foo'=>function($arg1) use($obj) { echo "foo($arg1) + code: $obj->code\n"; $obj->code = 1; }, 'bar'=>function($arg1) use($obj) { echo "bar($arg1) + code: $obj->code\n"; $obj->code = 2; } ); }; 

печать

 oldFn(argument1) foo(argument1) + code: 0 bar(argument1) + code: 1 and now $m->code is: 2 

(если это кажется вам чем-то возможным, я могу написать немного больше текста … но не сейчас ;-))

 call_user_func("test", array($this,"argument1")); 

Я не 100%, но вы должны иметь доступ к нему с помощью

 function test($arg1) { $arg1[0]->code = 10; } 

Будет ли runkit соответствовать вашим потребностям, в частности runkit_function_redefine ?