Calling closure assigned to object property directly
As of PHP7, you can do
$obj = new StdClass;
$obj->fn = function($arg) { return "Hello $arg"; };
echo ($obj->fn)('World');
or use Closure::call(), though that doesn't work on a StdClass
.
Before PHP7, you'd have to implement the magic __call
method to intercept the call and invoke the callback (which is not possible for StdClass
of course, because you cannot add the __call
method)
class Foo
{
public function __call($method, $args)
{
if(is_callable(array($this, $method))) {
return call_user_func_array($this->$method, $args);
}
// else throw exception
}
}
$foo = new Foo;
$foo->cb = function($who) { return "Hello $who"; };
echo $foo->cb('World');
Note that you cannot do
return call_user_func_array(array($this, $method), $args);
in the __call
body, because this would trigger __call
in an infinite loop.
Declaring closure to class attribute in PHP
PHP Currently doesn't allow directly calling a function stored as an object property.
It allows properties and methods of an object to have the same name actually.
One suggested solution to this issue is from another, almost identical question
class Totalizer
{
public $count;
public function __construct()
{
$this->count = function ($product) {
return $product;
};
}
public function __call($method, $args)
{
if (is_callable(array($this, $method))) {
return call_user_func_array($this->$method, $args);
} else {
// else throw exception
}
}
}
Calling closure assigned to object property directly
As of PHP7, you can do
$obj = new StdClass;
$obj->fn = function($arg) { return "Hello $arg"; };
echo ($obj->fn)('World');
or use Closure::call(), though that doesn't work on a StdClass
.
Before PHP7, you'd have to implement the magic __call
method to intercept the call and invoke the callback (which is not possible for StdClass
of course, because you cannot add the __call
method)
class Foo
{
public function __call($method, $args)
{
if(is_callable(array($this, $method))) {
return call_user_func_array($this->$method, $args);
}
// else throw exception
}
}
$foo = new Foo;
$foo->cb = function($who) { return "Hello $who"; };
echo $foo->cb('World');
Note that you cannot do
return call_user_func_array(array($this, $method), $args);
in the __call
body, because this would trigger __call
in an infinite loop.
PHP: Using globally defined closure in a class method
Because $this->globalfunction
is a variable, not a method, you need to wrap it in parentheses to force PHP to evaluate $this->globalfunction
before attempting to call it as a function i.e.
function testFunc(){
($this->globalFunction)('a');
}
Output:
works a
Demo on 3v4l.org
PHP closure function appended to stdObject and chained
Because this is currently a limitation of PHP. What you are doing is logical and should be possible. In fact, you can work around the limitation by writing:
function one(){
call_user_func($this->two()->func);
}
or
function one(){
$f = $this->two()->func;
$f();
}
Stupid, I know.
How to call a closure that is a class variable?
In PHP, methods and properties are in a separate namespace (you can have a method and a property with the same name), and whether you are accessing a property or a method depends of the syntax you are using to do so.
$expr->something()
is a method call, so PHP will search something
in the class' list of methods.
$expr->something
is a property fetch, so PHP will search something
in the class' list of properties.
$myInstance->lambda();
is parsed as a method call, so PHP searches for a method named lambda
in your class, but there is no such method (hence the Call to undefined method error).
So you have to use the fetch property syntax to fetch the lambda, and then call it.
Since PHP 7.0, you can do this with
($obj->lambda)()
:($obj->lambda)();
The parentheses make sure that PHP parses
($obj->lambda)
as fetch the property named lambda. Then,()
calls the result of fetching the property.or you can do this with
->lambda->__invoke()
:$myInstance = new MyClass();
$myInstance->lambda->__invoke();__invoke
is one of PHP's magic methods. When an object implements this method, it becomes invokable: it can be called using the$var()
syntax. Anonymous functions are instances ofClosure
, which implements__invoke
.Or assign it to a local variable:
$lambda = $myInstance->lambda;
$lambda();Or call it using call_user_func:
call_user_func($myInstance->lambda);
call_user_func
can call anycallable
, including anonymous functions.Alternatively, if this is a common pattern in your code, you can setup a
__call
method to forward calls to your lambda:class MyClass
{
private $lambda;
public function __construct()
{
$this->lambda = function() {
echo "Hello world!\n";
};
}
public function __call($name, $args)
{
return call_user_func_array($this->$name, $args);
}
}Now this works:
$myInstance = new MyClass();
$myInstance->lambda();Since PHP 5.4 you can even do that in a trait:
trait LambdasAsMethods
{
public function __call($name, $args)
{
return call_user_func_array($this->$name, $args);
}
}
class MyClass
{
use LambdasAsMethods;
private $lambda;
public function __construct()
{
$this->lambda = function() {
echo "Hello World!\n";
};
}
}
$myInstance = new MyClass();
$myInstance->lambda();
Closure object cannot have properties in Laravel middleware
Your return statement is wrong, you have to return $next($request);
instead of return $next;
I would personally change your code to this:
use Illuminate\Http\Response;
public function __construct()
{
parent::__construct();
// Return 404 if not AJAX request
$this->middleware(function ($request, $next) {
if (! $request->ajax()) {
abort(Response::HTTP_NOT_FOUND);
}
return $next($request);
})->only(['list', 'publish', 'unpublish', 'delete']);
}
PHP Call closure under stdClass
In general it's nicer to just make a class if you want to attach functions to objects
but in case you really want this then this should work:
$x = new \stdClass();
$x->cast = function($y){
return $y;
};
$y = $x->cast;
var_dump($y(5));
or
call_user_func($x->cast, 5);
Related Topics
Getting the Location from an Ip Address
How to Prevent Browser Cache For PHP Site
How to Get Numeric Types from MySQL Using Pdo
Woocommerce: Auto Complete Paid Orders
How to Let PHP to Create Subdomain Automatically For Each User
How to Savehtml of Domdocument Without HTML Wrapper
Accessing $_Cookie Immediately After Setcookie()
Run PHP Script as Daemon Process
How to Implement Authorization Using a Telegram API
Access a JavaScript Variable from PHP
How to Use MySQLi Prepared Statements
Automated or Regular Backup of MySQL Data
Doctrine2: Best Way to Handle Many-to-many With Extra Columns in Reference Table
Fatal Error: Uncaught Error: Call to Undefined Function MySQL_Connect()