Is there a way to bind an existing function to an anonymous one in php? Something like
$my_func = strip_tags();
Or must I half-redefine it, as a sort of anonymous wrapper, with the proper arguments and return value?
I tried googling this, but I suppose I didn't correctly suss the proper search phrase, as I didn't find results on the first page.
Edit I'm making a sort of function pipeline(?) where I can pass data and functions, and I want to pass functions as variables. I would like to keep the syntax the same and be able to use $output = $function($data) without having to write a bunch of anonymous wrappings for native functions. Also I would like to avoid using call_user_func so I don't have to re-write my existing code.
Simple.
$my_func = 'strip_tags';
$output = $my_func($data);
You can bind the function by it's name. Have a look at the callable Interface from php
Code from the manual mentioned above
<?php
// An example callback function
function my_callback_function() {
echo 'hello world!';
}
// An example callback method
class MyClass {
static function myCallbackMethod() {
echo 'Hello World!';
}
}
// Type 1: Simple callback
call_user_func('my_callback_function');
// Type 2: Static class method call
call_user_func(array('MyClass', 'myCallbackMethod'));
// Type 3: Object method call
$obj = new MyClass();
call_user_func(array($obj, 'myCallbackMethod'));
// Type 4: Static class method call (As of PHP 5.2.3)
call_user_func('MyClass::myCallbackMethod');
// Type 5: Relative static class method call (As of PHP 5.3.0)
class A {
public static function who() {
echo "A\n";
}
}
class B extends A {
public static function who() {
echo "B\n";
}
}
call_user_func(array('B', 'parent::who')); // A
?>
Related
Is there a way to call a function through variables?
For instance, I want to call the function Login(). Can I do this:
$varFunction = "Login"; //to call the function
Can I use $varFunction?
Yes, you can:
$varFunction();
Or:
call_user_func($varFunction);
Ensure that you validate $varFunction for malicious input.
For your modules, consider something like this (depending on your actual needs):
abstract class ModuleBase {
public function main() {
echo 'main on base';
}
}
class ModuleA extends ModuleBase {
public function main() {
parent::main();
echo 'a';
}
}
class ModuleB extends ModuleBase {
public function main() {
parent::main();
echo 'b';
}
}
function runModuleMain(ModuleBase $module) {
$module->main();
}
And then call runModuleMain() with the correct module instance.
You can use...
$varFunction = "Login";
$varFunction();
...and it goes without saying to make sure that the variable is trusted.
<?php
$fxname = 'helloWorld';
function helloWorld(){
echo "What a beautiful world!";
}
$fxname(); //echos What a beautiful world!
?>
I successfully call the function as follows:
$methodName = 'Login';
$classInstance = new ClassName();
$classInstance->$methodName($arg1, $arg2, $arg3);
It works with PHP 5.3.0+
I'm also working in Laravel.
If it's in the same class:
$funcName = 'Login';
// Without arguments:
$this->$funcName();
// With arguments:
$this->$funcName($arg1, $arg2);
// Also acceptable:
$this->{$funcName}($arg1, $arg2)
If it's in a different class:
$someClass = new SomeClass(); // create new if it doesn't already exist in a variable
$someClass->$funcName($arg1, $arg2);
// Also acceptable:
$someClass->{$funcName}($arg1, $arg2)
Tip:
If the function name is dynamic as well:
$step = 2;
$this->{'handleStep' . $step}($arg1, $arg2);
// or
$someClass->{'handleStep' . $step}($arg1, $arg2);
This will call handleStep1(), handleStep2(), etc. depending on the value of $step.
You really should consider using classes for modules, as this would allow you to both have consistent code structure and keep method names identical for several modules. This will also give you the flexibility in inheriting or changing the code for every module.
On the topic, other than calling methods as stated above (that is, using variables as function names, or call_user_func_* functions family), starting with PHP 5.3 you can use closures that are dynamic anonymous functions, which could provide you with an alternative way to do what you want.
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.
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.
}
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);
Is there a way to call a function through variables?
For instance, I want to call the function Login(). Can I do this:
$varFunction = "Login"; //to call the function
Can I use $varFunction?
Yes, you can:
$varFunction();
Or:
call_user_func($varFunction);
Ensure that you validate $varFunction for malicious input.
For your modules, consider something like this (depending on your actual needs):
abstract class ModuleBase {
public function main() {
echo 'main on base';
}
}
class ModuleA extends ModuleBase {
public function main() {
parent::main();
echo 'a';
}
}
class ModuleB extends ModuleBase {
public function main() {
parent::main();
echo 'b';
}
}
function runModuleMain(ModuleBase $module) {
$module->main();
}
And then call runModuleMain() with the correct module instance.
You can use...
$varFunction = "Login";
$varFunction();
...and it goes without saying to make sure that the variable is trusted.
<?php
$fxname = 'helloWorld';
function helloWorld(){
echo "What a beautiful world!";
}
$fxname(); //echos What a beautiful world!
?>
I successfully call the function as follows:
$methodName = 'Login';
$classInstance = new ClassName();
$classInstance->$methodName($arg1, $arg2, $arg3);
It works with PHP 5.3.0+
I'm also working in Laravel.
If it's in the same class:
$funcName = 'Login';
// Without arguments:
$this->$funcName();
// With arguments:
$this->$funcName($arg1, $arg2);
// Also acceptable:
$this->{$funcName}($arg1, $arg2)
If it's in a different class:
$someClass = new SomeClass(); // create new if it doesn't already exist in a variable
$someClass->$funcName($arg1, $arg2);
// Also acceptable:
$someClass->{$funcName}($arg1, $arg2)
Tip:
If the function name is dynamic as well:
$step = 2;
$this->{'handleStep' . $step}($arg1, $arg2);
// or
$someClass->{'handleStep' . $step}($arg1, $arg2);
This will call handleStep1(), handleStep2(), etc. depending on the value of $step.
You really should consider using classes for modules, as this would allow you to both have consistent code structure and keep method names identical for several modules. This will also give you the flexibility in inheriting or changing the code for every module.
On the topic, other than calling methods as stated above (that is, using variables as function names, or call_user_func_* functions family), starting with PHP 5.3 you can use closures that are dynamic anonymous functions, which could provide you with an alternative way to do what you want.