- Bindto function for closure implementation
- Closure::bindTo how it’s work?
- How to bind $this to a closure that is passed as a method parameter in PHP 5.4?
- How to use bindTo in PHP
- How can I make a call to desired function using Closure object?
- How to reference this in closure
- index.php
- RouteCollection
- RouteGroup
Bindto function for closure implementation
When a closure is created within a class instance, it has access to the private and protected properties of that class as its scope. However, if the closure is unscoped, it will not behave as if it is part of the class or any of its extending classes, and therefore will not have access to the protected or private properties.
Closure::bindTo how it’s work?
Allow me to assist you in comprehending the instructions located at http://php.net/Closure.bindTo.
newscope
Specify the class scope to which the closure should be associated — either the current one using ‘static’ or use the type of a given object. This choice affects the visibility of protected and private methods associated with the bound object.
Yes, it implies that the code is interpreted as a method of the A class in response to your initial query.
In case the scenario is referred to as «static» in the second question, the output obtained upon execution will be:
The PHP shell code on line 1 encountered a fatal error as it was unable to access the private property A::$value.
The reason for this is because the «static» will maintain the current [scope] of the Closure, which means that it will continue to be bound to the same scope as before (for example, if it was bound to A , it will remain bound to A ). Even though it was previously unscoped and still remains unscoped, it should not be assumed to be a part of the A class or any of its subclasses, and therefore it will not have access to private or protected properties.
Concerning the third inquiry, «static» merely maintains the existing range and holds no additional significance. The rationale for utilizing «static» as an identifier is that static cannot be used as a class name, ensuring that there will be no conflicts with any potential class names.
That is to say, (employing $closure as illustrated initially):
$binding = $closure->bindTo($a, "A"); // scope is now A class $second_binding = $binding->bindTo($a, "static"); // scope is still A class $second_binding(); // works fine, no access issues
Is it right to avoid closures using bind in JavaScript, var oControl = new Control( < var self = this; click: function(e)< //closure that's accessing self var self.performAction(); >>); I have been told to avoid writing code as shown above. Reason given — a closure is created in the above code. I have been suggested using bind to overcome the above problem. …
How to bind $this to a closure that is passed as a method parameter in PHP 5.4?
I couldn’t comprehend why the bindTo approach failed to work in this scenario, yet I managed to make it function by utilizing the Closure::bind technique.
public function get($callback) < if (!is_callable($callback)) < throw new InvalidArgumentException('Param must be callable.'); >$bound = Closure::bind($callback, $this); $bound(); >
It seems that the method identified by bindTo demonstrates identical behavior. Therefore, you must assign the output of this method to $callback . Consider the following illustration:
public function get($callback) < if (!is_callable($callback)) < throw new InvalidArgumentException('Param must be callable.'); >$callback = $callback->bindTo($this); $callback(); >
class APP < public $var = 25; public function __construct() <>public function get($callback) < if (!is_callable($callback)) < throw new InvalidArgumentException('Param must be callable.'); >// $callback->bindTo($this); // you must save result in another var and call it $callback1 = $callback->bindTo($this, $this); $callback1(); > > $app = new APP(); $app->get(function() use ($app) < echo '
'; var_dump($app); echo '
'; var_dump($this); >);Just pass it as an argument:
public function get($callback) < if (!is_callable($callback)) < throw new InvalidArgumentException('Paran must be callable.'); >// $callback->bindTo($this); return $callback($this); > . $app = new APP(); $app->get(function($that) use ($app) < echo '
'; var_dump($app); echo '
'; var_dump($that); >);In case binding is necessary, you can achieve it by using a function that returns another function.
public function getCallback($callback) < return function($app)< return $callback($this, $app); >> . $app = new APP(); $f = $app->get(function($that, $app) < echo '
'; var_dump($app); echo '
'; var_dump($that); >); $f($app);Php - Using $this in "anonymous" object, You can use the bind() or bindTo() method of the Closure instance that represents the anonymous function. Every time you call ->bindTo() or ::bind() it returns a new instance. So there should be no worries about external side effects. – ircmaxell. Jul 12, 2015 at 16:57.
How to use bindTo in PHP
The query you posed entails a rather complex example to elucidate the functioning of bindTo . Presumably, the purpose is to demonstrate the ability to re-bind $this instead of binding an object to a closure. However, this may complicate comprehension.
The concept is to generate a duplicate of a given closure and define its enclosing scope. A basic illustration of this is shown in this demo.
$closureThatShowsTheProperty = function() < echo $this->prop; >; $objectThatHasTheProperty = new class() < public $prop = 123; >; $closureThatShowsTheProperty->bindTo($objectThatHasTheProperty)();
It should be noted that the class and function remain separate entities until bindTo is invoked. Your illustration proves that a closure created within a class instance can be reassigned to another instance, though this scenario may not be the most prevalent.
An anonymous function created outside of a class instance would not have access to private and protected properties of the class. In order to achieve this, you would have to use the second parameter of bindTo to set the scope. However, a closure generated within the class instance would already have the class as its scope and therefore allow accessing private and protected properties.
$closureThatShowsTheProperty = function() < echo $this->prop; >; $objectThatHasTheProperty = new class() < private $prop = 123; >; $closureThatShowsTheProperty->bindTo($objectThatHasTheProperty)();
An unrecoverable mistake has occurred due to the inability to reach a private property.
$closureThatShowsTheProperty->bindTo($objectThatHasTheProperty, $objectThatHasTheProperty)();
JavaScript closures vs. anonymous functions, According to the closure definition:. A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).. You are using closure if you define a function which use a variable which is defined outside of the function. …
How can I make a call to desired function using Closure object?
The type hint in the method declaration ( Closure ) ensures that you won't require the ( is_callable() ) check. Additionally, omitting the ( call_user_func() ) will result in the creation of a ( get() ) method.
public static function get($binding, Closure $dispatch) < if(!in_array($binding, self::$bindings)) < die("Binding is not found in bindings array."); >return $dispatch(); >
At present, the $binding parameter only serves as a means of verification and is not utilized as an input for $dispatch() . This is not what I anticipated, and I am unable to discern the rationale behind this decision. It is advisable to reconsider this aspect.
I stumbled upon an additional concealed inquiry within your post.
// Let's try doing a get call with parameter "account" Route::get('account', function() < // This is where I'm stuck. See below examples: // Route::test(); // return "test"; // return "testa"; // return self::test(); >);
// Let's try doing a get call with parameter "account" Route::get('account', function() < // Both should work well: // Route::test(); // .. or // return self::test(); >);
PHP 7 - Closure::call(), PHP 7 - Closure::call () Closure::call () method is added as a shorthand way to temporarily bind an object scope to a closure and invoke it. It is much faster in performance as compared to bindTo of PHP 5.6.
How to reference this in closure
I am using PHP Version 7.1.1. In index.php of my MVC I create a route collection ( $routes ). To it I want to add a route group (with addGroup ). This addition process relies on a closure (e.g. an anonymous function), passed as argument to addGroup . Inside of closure I am trying to reference the collection with $this , so that I can add one or more routes to it (with addRoute , a method of the collection). Unfortunately I could not achieve that, although I made some tries. I miss a piece of the closures theory, somewhere. I would appreciate, if you would provide me an advice. The "problem" is, that, in order to achieve a simplified usability for the user, I am trying to avoid the direct use of a closure parameter. Why? Because inside addGroup I am already in the collection's scope and from there I am calling the closure. This way I can pass the collection's instance ( $this ) as argument to the executeGroupHandler method and, therefore to executeGroupHandler as well. Thank you for your time and patience!
index.php
$routes = new RouteCollection(); $routes->addGroup('/test', function() < $this->addRoute('GET', '/group', function() < echo 'Hello from route /test/group'; >); >);
RouteCollection
class RouteCollection implements CollectionInterface < public function addGroup(string $groupPattern, callable $groupHandler) < $group = new RouteGroup($groupPattern, $groupHandler); return $group->executeGroupHandler($this); > public function addRoute($httpMethod, string $routePattern, $routeHandler) < //. return $this; >>
RouteGroup
class RouteGroup < private $groupPattern; private $groupHandler; public function __construct(string $groupPattern, callable $groupHandler) < $this->groupPattern = $groupPattern; $this->groupHandler = $groupHandler; > public function executeGroupHandler(CollectionInterface $routeCollection) < return call_user_func_array($this->groupHandler, [$routeCollection]); > >