As seen previously, a closure is nothing but an instance of the Closure class, and different methods can be invoked on them. One of them is bindTo, which, given a closure, will return a new one that is bound to a given object. For example:
Basic usage of a closure
A closure is the PHP equivalent of an anonymous function, eg. a function that does not have a name. Even if that is technically not correct, the behavior of a closure remains the same as a function's, with a few extra features.
A closure is nothing but an object of the Closure class which is created by declaring a function without a name. For example:
The classic case you would need a Closure is when you have to give a callable to a function, for instance usort.
Here is an example where an array is sorted by the number of siblings of each person:
Binding a closure for one call
Since PHP7, it is possible to bind a closure just for one call, thanks to the call method. For instance:
As opposed to the bindTo method, there is no scope to worry about. The scope used for this call is the same as the one used when accessing or invoking a property of $myInstance.
Closure binding and scope
Let's consider this example:
Try to change the property visibility to either protected or private. You get a fatal error indicating that you do not have access to this property. Indeed, even if the closure has been bound to the object, the scope in which the closure is invoked is not the one needed to have that access. That is what the second argument of bindTo is for.
The only way for a property to be accessed if it's private is that it is accessed from a scope that allows it, ie. the class's scope. In the just previous code example, the scope has not been specified, which means that the closure has been invoked in the same scope as the one used where the closure has been created. Let's change that:
As just said, if this second parameter is not used, the closure is invoked in the same context as the one used where the closure has been created. For example, a closure created inside a method's class which is invoked in an object context will have the same scope as the method's:
Use closures to implement observer pattern
In general, an observer is a class with a specific method being called when an action on the observed object occurs. In certain situations, closures can be enough to implement the observer design pattern.
Here is a detailed example of such an implementation. Let's first declare a class whose purpose is to notify observers when its property is changed.
Then, let's declare the class that will represent the different observers.
Let's finally test this:
Note that this example works because the observers share the same nature (they are both "named observers.")
Using external variables
It is possible, inside a closure, to use an external variable with the special keyword use. For instance:
You can go further by creating "dynamic" closures. It is possible to create a function that returns a specific calculator, depending on the quantity you want to add. For example:
This modified text is an extract of the original Stack Overflow Documentation created by following contributors and released under CC BY-SA 3.0