can we alias(save to a variable) a class method in php - php

here is an example class:
public class example
{
private $foof;
public function __construct()
{
$this->foof = $this->foo;
}
public function foo($val=0)
{
// do something...
}
}
So basically, in the constructer of the sample code, is it possible to assign a class method to a variable?
Ultimately what i want is to have an associative array with all the class methods aliased in it...that possible in php?

In PHP5.3+ (which you should be using anyway!) you can simply create an anonymous function which calls your method:
$this->foof = function() {
$this->foo(1);
};
However, you cannot call it using $this->foof() - you have to assign it to a variable first: $foof = $this->foof; $foof();
In older PHP versions you cannot easily do this - create_function() does not create a closure so $this is not available there.

You don't need to use anonymous functions. Just use the Callable pseudo type.
$this->foof = array($this, 'foo');
...
call_user_func($this->foof);

Related

How to reference a method within class as a callback to a custom function in PHP? [duplicate]

I have a class with methods that I want to use as callbacks.
How can I pass them as arguments?
Class MyClass {
public function myMethod() {
// How should these be called?
$this->processSomething(this->myCallback);
$this->processSomething(self::myStaticCallback);
}
private function processSomething(callable $callback) {
// Process something...
$callback();
}
private function myCallback() {
// Do something...
}
private static function myStaticCallback() {
// Do something...
}
}
Check the callable manual to see all the different ways to pass a function as a callback. I copied that manual here and added some examples of each approach based on your scenario.
Callable
A PHP function is passed by its name as a string. Any built-in or user-defined function can be used, except language constructs such as: array(), echo, empty(), eval(), exit(), isset(), list(), print or unset().
// Not applicable in your scenario
$this->processSomething('some_global_php_function');
A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.
// Only from inside the same class
$this->processSomething([$this, 'myCallback']);
$this->processSomething([$this, 'myStaticCallback']);
// From either inside or outside the same class
$myObject->processSomething([new MyClass(), 'myCallback']);
$myObject->processSomething([new MyClass(), 'myStaticCallback']);
Static class methods can also be passed without instantiating an object of that class by passing the class name instead of an object at index 0.
// Only from inside the same class
$this->processSomething([__CLASS__, 'myStaticCallback']);
// From either inside or outside the same class
$myObject->processSomething(['\Namespace\MyClass', 'myStaticCallback']);
$myObject->processSomething(['\Namespace\MyClass::myStaticCallback']); // PHP 5.2.3+
$myObject->processSomething([MyClass::class, 'myStaticCallback']); // PHP 5.5.0+
Apart from common user-defined function, anonymous functions can also be passed to a callback parameter.
// Not applicable in your scenario unless you modify the structure
$this->processSomething(function() {
// process something directly here...
});
As of PHP 8.1, we now have first-class callables. They use the syntax $callable = functionName(...). The three dots are part of the syntax and not an omission.
You can use the new syntax to create callable class methods.
Class MyClass {
public function myMethod() {
// first-class callables
$this->processSomething($this->myCallback(...));
$this->processSomething(self::myStaticCallback(...));
}
private function processSomething(callable $callback) {
// Process something...
$callback();
}
private function myCallback() {
// Do something...
}
private static function myStaticCallback() {
// Do something...
}
}
The three dots are not an omission/placeholder for parameters. They are a special syntax for creating a callable. If the method accepts no parameters, the syntax remains the same.
Since 5.3 there is a more elegant way you can write it, I'm still trying to find out if it can be reduced more
$this->processSomething(function() {
$this->myCallback();
});
You can also to use call_user_func() to specify a callback:
public function myMethod() {
call_user_func(array($this, 'myCallback'));
}
private function myCallback() {
// do something...
}
You can set the method return type to callable. It works for PHP 7.1
protected function myMethod(): callable
{
return function (int $j) {
};
}
Then call it like this:
someFunction($this->myMethod());

How to use class methods as callbacks

I have a class with methods that I want to use as callbacks.
How can I pass them as arguments?
Class MyClass {
public function myMethod() {
// How should these be called?
$this->processSomething(this->myCallback);
$this->processSomething(self::myStaticCallback);
}
private function processSomething(callable $callback) {
// Process something...
$callback();
}
private function myCallback() {
// Do something...
}
private static function myStaticCallback() {
// Do something...
}
}
Check the callable manual to see all the different ways to pass a function as a callback. I copied that manual here and added some examples of each approach based on your scenario.
Callable
A PHP function is passed by its name as a string. Any built-in or user-defined function can be used, except language constructs such as: array(), echo, empty(), eval(), exit(), isset(), list(), print or unset().
// Not applicable in your scenario
$this->processSomething('some_global_php_function');
A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1.
// Only from inside the same class
$this->processSomething([$this, 'myCallback']);
$this->processSomething([$this, 'myStaticCallback']);
// From either inside or outside the same class
$myObject->processSomething([new MyClass(), 'myCallback']);
$myObject->processSomething([new MyClass(), 'myStaticCallback']);
Static class methods can also be passed without instantiating an object of that class by passing the class name instead of an object at index 0.
// Only from inside the same class
$this->processSomething([__CLASS__, 'myStaticCallback']);
// From either inside or outside the same class
$myObject->processSomething(['\Namespace\MyClass', 'myStaticCallback']);
$myObject->processSomething(['\Namespace\MyClass::myStaticCallback']); // PHP 5.2.3+
$myObject->processSomething([MyClass::class, 'myStaticCallback']); // PHP 5.5.0+
Apart from common user-defined function, anonymous functions can also be passed to a callback parameter.
// Not applicable in your scenario unless you modify the structure
$this->processSomething(function() {
// process something directly here...
});
As of PHP 8.1, we now have first-class callables. They use the syntax $callable = functionName(...). The three dots are part of the syntax and not an omission.
You can use the new syntax to create callable class methods.
Class MyClass {
public function myMethod() {
// first-class callables
$this->processSomething($this->myCallback(...));
$this->processSomething(self::myStaticCallback(...));
}
private function processSomething(callable $callback) {
// Process something...
$callback();
}
private function myCallback() {
// Do something...
}
private static function myStaticCallback() {
// Do something...
}
}
The three dots are not an omission/placeholder for parameters. They are a special syntax for creating a callable. If the method accepts no parameters, the syntax remains the same.
Since 5.3 there is a more elegant way you can write it, I'm still trying to find out if it can be reduced more
$this->processSomething(function() {
$this->myCallback();
});
You can also to use call_user_func() to specify a callback:
public function myMethod() {
call_user_func(array($this, 'myCallback'));
}
private function myCallback() {
// do something...
}
You can set the method return type to callable. It works for PHP 7.1
protected function myMethod(): callable
{
return function (int $j) {
};
}
Then call it like this:
someFunction($this->myMethod());

Storing a reference to a class function in a variable in PHP

Here is a hypothetical example (the parent class PageState, contains an instance of the class FooterState - the instance may not be created, depending on the conditions. The FooterState needs to call a function which is public and is created in the PageState class):
class PageState {
private $footer_state = null;
function PageState() {
$this->footer_state= new FooterState($this);
}
public function getExpectedPageDimensions() {
// do calculations based on existing body content
return $dimensions;
}
}
class FooterState {
private $get_dimensions_func = null;
function FooterState($page_state) {
// Here, we need to get the reference to the function from the $page_state class
$this->get_dimensions_func = $page_state->getExpectedPageDimensions;
}
public function addLogos($logo_data) {
$page_dimensions = $this->get_dimensions_func();
// use the page dimensions to decide on the size of the content
return Array('width' => $width, 'height' => $height);
}
I am aware of alternative solutions:
Instead of making a copy of the reference to the function, create a refference to the class $this->page_state = $page_state; and then functions in FooterState can call $this->page_state->getExpectedPageDimensions();
Use global $PageStateInstance; and then just call $PageStateInstance->getExpectedPageDimensions();
But I am wondering if it is at all possible to store a reference to a class function in a variable. If the functions were outside of the class, it would be possible to do stuff like $func = 'getExpectedPageDimensions'; $func();.
You can pass on an instance plus a function as a callable: An array with the instance and the function name. There is a similar system for calling static class methods.
# An example callback method
class MyClass {
function myCallbackMethod() {
echo 'Hello World!';
}
}
# create an instance
$obj = new MyClass();
# and later:
call_user_func(array($obj, 'myCallbackMethod'));
From the docs here: http://php.net/manual/en/language.types.callable.php
Instead of making a copy of the reference to the function, create a refference to the class $this->page_state = $page_state; and then functions in FooterState can call $this->page_state->getExpectedPageDimensions();
This is the best generic solution.
But I am wondering if it is at all possible to store a reference to a class function in a variable.
Yes it is, but it really only works for static functions unless you instantiate the class. Example:
class A {
public static function doSomethingStatic() {
// ...
}
public function doSomethingElse() {
// ...
}
}
$somevar = 'A::doSomethingStatic';
$result = call_user_func($somevar); // calls A::doSomethingStatic();
$myA = new A();
$myref = array($myA, 'doSomethingElse');
$result = call_user_func($myref); // calls $myref->doSomethingElse();
Note that in the second example you have to instantiate the class and pass an array as the first parameter to call_user_func().
References: http://php.net/manual/en/function.call-user-func.php and http://php.net/manual/en/language.types.callable.php
is at all possible to store a reference to a class function
I think you mean object instead of class, but yes you can, with closures.
I don't think you need to though. $this->page_state seems like it'll work just fine.
Don't use globals.

How do I assign a class instance method to a variable?

Say I'm here:
class Foo
{
public function test()
{
// I'm here!
}
private function pow() {}
}
I want to declare a local variable that references the method $this->pow. I try:
$pow = $this->pow;
This doesn't work:
Notice: Undefined property: Foo::$pow
How do I reference a class instance method in PHP?
I need this because I need to pass the function to an anonymous function inside test. I can't pass $this to the anonymous function because I'm using PHP 5.3, and that only became possible in PHP 5.4. Also, the function pow is not public, so I can't assign $this to an intermediary variable and pass that to the anonymous function.
If pow is public as it is in your example, then you can simply do this:
$self = $this;
$invokePow = function() use ($self) { $self->pow(); };
// ... some time later ...
$invokePow(); // calls pow()
You can also do the same by passing around array($this, 'pow') as a callable and invoking it with call_user_func.
If pow is not public, you are simply out of luck.
However, if you are able to upgrade to 5.4 then it all becomes much easier:
$invokePow = function() { $this->pow(); };
You don't need to capture $this explicitly, and you can invoke $invokePow from any context (even outside the class).

How to Pass a function to a class in php

I have a class that generates data based on a few things. I would like to format that data from the outside. So I am trying to pass a function into the class so that it would format that data. I have looked at many examples, but it seems this is unique.
Can anybody give an idea of how to do this? The following code gives an error.
<?php
class someClass {
var $outsideFunc; // placeholder for function to be defined from outside
var $somevar='Me'; // generated text
function echoarg($abc){
$outsideFunc=$this->outsideFunc; // bring the outside function in
call_user_func($outsideFunc,$abc); // execute outside function on text
echo $abc;
}
}
function outsidefunc($param){ // define custom function
$param='I am '.$param;
}
$someClass=new someClass();
$someClass -> outsideFunc = 'outsideFunc'; // send custom function into Class
$someClass -> echoarg($someClass->somevar);
$someClass -> outsidefunc = 'outsidefunc';
In PHP, function names are not case sensitive, yet object property names are. You need $someClass->outsideFunc, not $someClass->outsidefunc.
Note that good OOP design practice calls for the use of getter and setter methods rather than just accessing properties directly from outside code. Also note that PHP 5.3 introduced support for anonymous functions.
Yeah. You are right. Now there is no error. But it does not work either.
By default, PHP does not pass arguments by reference; outsidefunc() does not actually do anything useful. If you want it to set $param in the caller to something else, and do not want to just return the new value, you could change the function signature to look like this:
function outsidefunc(&$param) {
You would also need to change the way you call the function, as call_user_func() does not allow you to pass arguments by reference. Either of these ways should work:
$outsideFunc($abc);
call_user_func_array($outsideFunc, array(&$abc));
Why not pass your function as an argument?
<?php
class someClass {
public $somevar="Me";
public function echoarg($abc,$cb=null) {
if( $cb) $cb($abc);
echo $abc;
}
}
$someClass = new someClass();
$someClass->echoarg($someClass->somevar,function(&$a) {$a = "I am ".$a;});
i am not sure what exactly you are looking for, but what i get is, you want to pass object in a function which can be acheive by
Type Hinting in PHP.
class MyClass {
public $var = 'Hello World';
}
function myFunction(MyClass $foo) {
echo $foo->var;
}
$myclass = new MyClass;
myFunction($myclass);
OP, perhaps closures are what you're looking for?
It doesn't do EXACTLY what you're looking for (actually add function to class), but can be added to a class variable and executed like any normal anonymous function.
$myClass->addFunc(function($arg) { return 'test: ' . $arg });
$myClass->execFunc(0);
class myClass {
protected $funcs;
public function addFunc(closure $func) {
$this->funcs[] = $func;
}
public function execFunc($index) { $this->funcs[$index](); } // obviously, do some checking here first.
}

Categories