call back function with $this - php

I am trying to use an instance method as a callback for PHP 5.2.1. I am aware that as of PHP 5.4 you can use $this inside a closure, and in PHP 5.3 you can rename $this to $self and pass that to the closure. However, neither of these methods will suffice since I need this to work for PHP 5.2.1. The two commented lines was my last attempt. That results in Fatal error: Call to a member function hello() on a non-object - is there anyway I can have a callback to an instance method in PHP 5.2.1?
<?php
class Test {
public function __construct() {
$self = &$this;
$cb = function() use ( $self ) {
$self->hello();
};
call_user_func( $cb );
// $cb = create_function( '$self', '$self->hello();' );
// call_user_func( $cb );
}
public function hello() {
echo "Hello, World!\n";
}
}
$t = new Test();

Pass an array to include the object:
call_user_func( array( $this, 'hello' ) );
http://us3.php.net/manual/en/language.types.callable.php

$cb = create_function('$self', '$self->hello();');
This is just making a function that can take a parameter called $self. It's the same as this:
function test($self){
$self->hello();
}
You can try passing $self (or $this) to the function when you call it:
call_user_func($cb, $this);
You can also try to make $self a global variable, so that the anonymous function made by create_function can read it.
$GLOBALS['mySelf'] = $self;
$cb = create_function('', 'global $mySelf; $mySelf->hello();');
call_user_func($cb);
// You may want to unset this when done
unset($GLOBALS['mySelf']);

How about SIMPLICITY?
class Test {
public function __construct() {
$this -> funcName($this);
}
public function funcName($obj) {
$obj->hello();
}
public function hello() {
echo "Hello, World!\n";
}
}
Update: Just tested the codes. They are working fine using this.
call_user_func_array(array($self, "hello"), array());

Related

Pass Method form different class for later execution to a second class

I have to classes and I want to pass a method fro classA to classB constructor and store it on a classB instance variable so as to execute it later.
class A
{
public function execute()
{
$ClassB = new ElgEmpAnalyticsImporterControllerImporterEmporioOrder(ConMW::getDB(), $this -> lPointFile, [$this, 'getLastPoints'] );
$ClassB -> import();
}
public function getLastPoints(Array $keys)
{
$res = [];
forEach ( json_decode( file_get_contents($this -> lastPointFile) ) as $key => $value ):
if ( in_array($key, $keys) ):
$res[$key] = $value;
else:
$res[$key] = '';
endif;
endforeach;
unset($key);
unset($value);
return $res;
}
}
classB
{
public $getLastPoints = null;
public function __construct(callable $getLastPoints)
{
$this -> getLastPoints = $getLastPoints;
}
public function import()
{
$lastPoints = $this -> getLastPoints(['idOrder', 'orderLastExport']);
}
}
Trying to execute it like that I get the error "Call to undefined method getLastPoints()"
I think the problem is on storing the function on the instance variable $getLastPoints of classB. I can conclude this because If I execute the function on the constructor it works. That means if I change the constructor of classB like this
classB
{
public $getLastPoints = null;
public function __construct(callable $getLastPoints)
{
$getLastPoints(['idOrder', 'orderLastExport']);
}
}
it works.
But what i need is to execute the external function inside the import function.
Can someone please help me?
thanks for your time,
Edit for clarification: My question is why I can execute the function inside the contructor like this :
$lastPoint(a,b)
but when I assign the callable into an instance variable like this:
$this -> lastPoint(a,b)
it does not work.
I read that php uses different storage for variables and function. PHP probably sees the callable $lastPoints as a variable. So can the callable $lastPoints, be added as dynamic function to my instance of classB?
Christoforos
PHP Callable Object as Object Member
$getlastpoints is a property with an array value stored in it, not a function.
call_user_func_array($this->getlastpoints, ['idOrder', 'orderLastExport']);
public function import()
{
$my_func = $this->getLastPoints;
$lastPoints = $my_func(['idOrder', 'orderLastExport']);
}
In a nutshell, the reason you will have to do this is because you can define properties and methods in a PHP class having the same name. e.g.
class foo {
public $bar
public function bar() {}
}
so in this instance, if allowed to directly access a stored callable on the $bar property... What would the call below reference?
$my_foo_obj->bar()
To avoid the situation, you cannot call it directly.

Call static function from variable

I have the following setup:
class test {
public static function something() {
$somethingElseFunction = "somethingElse";
// How can I call the method with the name saved in variable?
}
public static function somethingElse($a) {
echo 'bla';
}
}
How can I call the function using the variable? (the function name is in variable).
Also I need to do a function_exists() for it.
Tried this:
if (function_exists(self::$somethingElseFunction ())) {
if (!call_user_func(self::$somethingElseFunction , $a)) {
}
}
Didn't work.
In PHP>=5.4 you can use just self:: de-reference:
self::$somethingElseFunction();
-but in earlier versions that will cause error (because it wasn't allowed to use dynamic static methods de-reference). So then you can always use such things as call_user_func_array() :
class test {
public static function something() {
$somethingElseFunction = "somethingElse";
call_user_func_array(array(__CLASS__, $somethingElseFunction), array("bla"));
}
public static function somethingElse($a) {
var_dump($a);
}
}
test::something();
-this will work for PHP>=5.0
About function_exists() call - it expects string as parameter, thus I recommend to use method_exists() - because that function is intended to do the stuff:
public static function something() {
$somethingElseFunction = "somethingElse";
if(method_exists(__CLASS__, $somethingElseFunction))
{
call_user_func_array(array(__CLASS__, $somethingElseFunction), array("bla"));
}
}
You should be able to use the following:
test::$somethingElseFunction();
Use this function:
$classname = 'somethingElse';
call_user_func('test::' . $classname, $params);

PHP Redefine a closure with bind() and its scope [duplicate]

When using anonymous functions in PHP, you can easily use variables from right outside of its scope by using the use() keyword.
In my case the anonymous functions are already defined somewhere, but called later on (somewhere else) in a class.
The following piece of code is to illustrate the idea:
<?php
$bla = function ( $var1 ) use ($arg)
{
echo $var1;
};
class MyClass
{
private $func;
public function __construct ( $func )
{
$this->func = $func;
}
public function test ( $arg )
{
$closure = $this->func;
$closure ( 'anon func' );
}
}
$c = new MyClass($bla);
$c->test ( 'anon func' );
What i'm doing is i create an anonymous function and store that in a variable. I pass that variable to the method of a class and that is where i want to run the anonymous function.
But i can't use the use() keyword to get the $arg parameter from the method this way. Because the anonymous function was declared outside of the method.
But i really need a way to get the variables from the method where the anonymous function is run from. Is there a way to do that, when the anonymous function is declared somewhere else..?
The point of the use keyword is to inherit/close over a particular environment state from the parent scope into the Closure when it's defined, e.g.
$foo = 1;
$fn = function() use ($foo) {
return $foo;
};
$foo = 2;
echo $fn(); // gives 1
If you want $foo to be closed over at a later point, either define the closure later or, if you want $foo to be always the current value (2), pass $foo as a regular parameter.
FWIW, you can do it if you use a use reference (php.net ex 3.3) and a global, ugly since it uses globals, but just to put it out there:
<?php
$bla = function ( $var1 ) use (&$arg)
{
return "var1:$var1, arg:$arg";
};
class MyClass
{
private $func;
public function __construct ( $func )
{
$this->func = $func;
}
public function test ( $param )
{
global $arg;
$arg=$param;
$closure = $this->func;
return $closure ( 'anon func' );
}
}
$c = new MyClass($bla);
echo $c->test ( 'bla bla' ); //var1:anon func, arg:bla bla

How to create runtime function which uses object context?

I am having a class and I have a dynamically created function (created via "create_function") but I cannot find a way to tell PHP that I want this function to be created for this class only (class function) and because of that the new function cannot access the object properties. Take a look at the following code:
class Test {
private $var=1;
function __construct() {
call_user_func(create_function('', 'echo $this->var;'));
}
}
new Test;
This throws error "Fatal error: Using $this when not in object context in D:\WWW\index.php(7) : runtime-created function on line 1"
You probably want runkit_method_add, not create_function.
As of php 5.4 anonymus function also have $this in their context. With a little help from the magic _call method it is possible to add a closure as a method to a class, without additional code:
class Test
{
private $var = 1;
function __construct()
{
$this->sayVar = function() { echo $this->var; };
}
public function __call( $method, $args )
{
if ( property_exists( $this, $method ) ) {
if ( is_callable( $this->$method ) ) {
return call_user_func_array( $this->$method, $args );
}
}
}
}
$test = new Test();
$test->sayVar(); // echos 1

simple "plugin" system using __call

so far, I have this:
class Foo{
private $plugin_methods = array();
public function registerPlugin($caller, $method){
list($object, $caller) = explode('.', $caller);
$this->plugin_methods[$object][$caller] = $method;
}
public function _doPluginMethod($object, $name, $args){
if(isset($this->plugin_methods[$object][$name]))
return call_user_func_array($this->plugin_methods[$object][$name], $args);
throw new Exception("Method '{$name}' not defined for '{$object}'.");
}
public function __call($name, $args){
return $this->_doPluginMethod('foo', $name, $args);
}
}
and now I can do this:
$foo = new Foo();
$foo->registerPlugin('foo.my_plugin', function($something){
return $something * 1000;
});
$foo->my_plugin(3453245);
But how can I get to the $this object inside my "plugin" function?
Depends on the version of PHP you are using. As of PHP 5.4, the use of $this in anonymous functions (also called closures) is possible. Prior to that, it wasn't.
Check the changelog here: http://php.net/manual/en/functions.anonymous.php

Categories