Lambda, Closure and Callback in PHP
- Tram Ho
- Hello everyone, in this article, I would like to share a little of what I have learned about Lambda, Closure and callbacks in PHP, hope everyone will follow.
1 Lambda
1.1) What is Lambda?
- Lambda is an anonymous function that can be declared and defined anywhere and is not reusable.
- Lambda only exists in the scope it defines, so if you use it out of scope, this function will no longer work.
- Lambda can be assigned to a variable to use
1.2) Syntax
- Regular function declaration in PHP:
1 2 3 4 5 | <span class="token keyword">function</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token double-quoted-string string">"Xin chào!"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">echo</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
- To declare lambda in PHP we use the syntax:
1 2 3 4 5 | <span class="token keyword">function</span> <span class="token punctuation">(</span>argument<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//code</span> <span class="token punctuation">}</span> |
- Or you can use the function create_function() in PHP
1 2 | <span class="token function">create_function</span><span class="token punctuation">(</span><span class="token single-quoted-string string">''</span><span class="token punctuation">,</span> argument<span class="token punctuation">)</span><span class="token punctuation">;</span> |
- Where argument are the parameters you want to pass in the anonymous parameter.
- Normal functions want to perform we need to call its name, and lambda is an anonymous function, so to call it, we will assign it to a variable or pass it as a parameter
1 2 3 4 5 6 7 | <span class="token variable">$hello</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token double-quoted-string string">"Xin chào!"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Gọi hàm này</span> <span class="token keyword">echo</span> <span class="token variable">$hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Xin chào!</span> |
- Above we have assigned lambda to a variable, but if we want to pass it as a parameter it will look like this:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">function</span> <span class="token function">speak</span><span class="token punctuation">(</span><span class="token variable">$message</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token variable">$message</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Gọi hàm</span> <span class="token function">speak</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token double-quoted-string string">"Xin chào"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
- Using anonymous functions or Lambda is very useful when functions we only need to use once.
- Usually, we will need a function to do a job, but that doesn’t mean we will use it in the global scope. Instead of having a function that is used once and then no longer used, we can use an anonymous function instead.
2) Closure
2.1) What is Closure?
- A Closure is essentially a lambda, but a closure has the added function of being able to use variables outside of the scope in which it was created.
- One defining characteristic of a Closure function is that it will have the keyword use after the function’s name.
2.2) Syntax
-To declare closure in PHP we will use the syntax:
1 2 3 4 | <span class="token keyword">function</span> <span class="token punctuation">(</span>argument<span class="token punctuation">)</span> <span class="token keyword">use</span> <span class="token punctuation">(</span>scope<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//code</span> <span class="token punctuation">}</span> |
- Inside:
- argument are the parameters you want to pass in closure
- scope is the list of variables outside closure that you want to use in closure.
For example:
1 2 3 4 5 6 7 8 9 | <span class="token variable">$name</span> <span class="token operator">=</span> <span class="token single-quoted-string string">'Dau Xanh'</span><span class="token punctuation">;</span> <span class="token variable">$sayHello</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">use</span> <span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token double-quoted-string string">"Xin chào <span class="token interpolation"><span class="token variable">$name</span></span>"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">echo</span> <span class="token variable">$sayHello</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//Kết quả: Xin chào Dau Xanh</span> |
- In the above example you can see that Closure can access variables $name because it is declared in the keyword use in the definition closure. Suppose if we change the value of the variable $name in closure, it will not affect the original value of the variable $name outside, To be able to change the value of the variable $name outside, we need to pass the reference (&$name) of that variable into the keyword use
For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token variable">$i</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token variable">$closure</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">use</span> <span class="token punctuation">(</span><span class="token variable">$i</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// ở đây mình tăng biến $i lên</span> <span class="token operator">++</span><span class="token variable">$i</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// Sau đó gọi hàm</span> <span class="token variable">$closure</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Kết quả $i ở ngoài không thay đổi</span> <span class="token keyword">echo</span> <span class="token variable">$i</span><span class="token punctuation">;</span> <span class="token comment">// 0</span> <span class="token variable">$i</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// Tăng biến $i trong phạm vi Closure nhưng sử dụng con trỏ tham chiếu &</span> <span class="token variable">$closure</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">use</span> <span class="token punctuation">(</span><span class="token operator">&</span><span class="token variable">$i</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token operator">++</span><span class="token variable">$i</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// Gọi hàm</span> <span class="token variable">$closure</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Biến $i ở ngoài đã thay đổi</span> <span class="token keyword">echo</span> <span class="token variable">$i</span><span class="token punctuation">;</span> <span class="token comment">// 1</span> |
- Closure is very useful when using PHP functions that accept a function callback like array_map, array_filter, array_walk…
- In the next example we use the function array_map to multiply elements by a pre-declared factor hệ
For example:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token comment">// hệ số nhân</span> <span class="token variable">$multiplier</span> <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span> <span class="token variable">$arr</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token variable">$newArr</span> <span class="token operator">=</span> <span class="token function">array_map</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token variable">$item</span><span class="token punctuation">)</span> <span class="token keyword">use</span> <span class="token punctuation">(</span><span class="token variable">$multiplier</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token variable">$item</span> <span class="token operator">*</span> <span class="token variable">$multiplier</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token variable">$arr</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">var_dump</span><span class="token punctuation">(</span><span class="token variable">$newArr</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
- Result:
1 2 3 4 5 6 7 8 9 10 11 12 13 | array(5) { [0]=> int(2) [1]=> int(4) [2]=> int(6) [3]=> int(8) [4]=> int(10) } |
- In the above example, we see that it is not necessary to create a function just to multiply two numbers, so we use Closure to do something like this and then never use it.
- Closure is a very popular concept in today’s PHP frameworks, using Lambda and Closure to perform small jobs without affecting the namespace of the project and especially using it very well in callbacks.
- Example in Laravel
1 2 3 4 | Route<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'user/(:any)'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token double-quoted-string string">"Xin chào "</span> <span class="token punctuation">.</span> <span class="token variable">$name</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
3 Callback
3.1) What is callback?
- Callback is the concept that a function is passed to another function as a parameter so that it can be executed before or after an event or a state change.
For example:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">function</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token variable">$callback</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token double-quoted-string string">"Xin chào!</br>"</span><span class="token punctuation">;</span> <span class="token comment">// code</span> <span class="token comment">// ...</span> <span class="token variable">$callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">sayGoodbye</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token double-quoted-string string">"Tạm biệt!"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'sayGoodbye'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
- Above I have defined two functions sayHello and sayGoodbye then I pass the function sayGoodbye into the function sayHello as a parameter, in the function sayHello then I can code stuff, then I’ll call the $callback (is the function sayGoodbye) at the end
- Above is a simple example of callback in PHP, function sayGoodbye passed to function sayHello as an argument.
- The above example is quite easy to understand, but not to mention using the result of the call function in the called function, I will go through an example later.
For Example:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">function</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token variable">$first_name</span><span class="token punctuation">,</span> <span class="token variable">$last_name</span><span class="token punctuation">,</span> <span class="token variable">$callback</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$full_name</span> <span class="token operator">=</span> <span class="token variable">$first_name</span> <span class="token punctuation">.</span> <span class="token single-quoted-string string">' '</span> <span class="token punctuation">.</span> <span class="token variable">$last_name</span><span class="token punctuation">;</span> <span class="token variable">$callback</span><span class="token punctuation">(</span><span class="token variable">$full_name</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">formatName</span><span class="token punctuation">(</span><span class="token variable">$full_name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token double-quoted-string string">"<h2>Xin chào <span class="token interpolation"><span class="token variable">$full_name</span></span> <h2>"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'Dau'</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'Xanh'</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'formatName'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
- In the above example, when calling the callback function, I also pass the callback value** $full_name** into the callback function
- The essence of $callback(full_name) is to call a built-in PHP function called call_user_func, so callback(full_name) is equivalent to call_user_func(callback,full_name). Using callback may have an error if we callback to an undefined function, so we need to check if callback exists before using it
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">function</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token variable">$first_name</span><span class="token punctuation">,</span> <span class="token variable">$last_name</span><span class="token punctuation">,</span> <span class="token variable">$callback</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token variable">$full_name</span> <span class="token operator">=</span> <span class="token variable">$first_name</span> <span class="token punctuation">.</span> <span class="token single-quoted-string string">' '</span> <span class="token punctuation">.</span> <span class="token variable">$last_name</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_callable</span><span class="token punctuation">(</span><span class="token variable">$callback</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">call_user_func</span><span class="token punctuation">(</span><span class="token variable">$callback</span><span class="token punctuation">,</span> <span class="token variable">$full_name</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">formatName</span><span class="token punctuation">(</span><span class="token variable">$full_name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">echo</span> <span class="token double-quoted-string string">"<h2>Xin chào <span class="token interpolation"><span class="token variable">$full_name</span></span> <h2>"</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token function">sayHello</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'Dau'</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'Xanh'</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'formatName'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
- Callback Usually used when the application needs to perform another function based on the context or state, or in other words wants to do something when an event occurs..
- Use with anonymous functions or with Closure.
- Multi-threaded programming (multiple thread).
Epilogue
- So I have finished presenting to everyone about anonymous lambda functions, closures and callbacks in PHP. Thank you everyone for following my post
Reference source