Functional programming, though far from new, has gained much traction recently. Functional programming characteristics have started to appear in the PHP world, too. Microframeworks including Silex and Slim, middleware architectures (Stack) and even standards (PSR-7) rely on concepts such as lambdas, referential transparency and immutability, all of which come from functional programming.
I’ll give you a crash course in Erlang, a pragmatic functional language to make you feel familiar with the functional paradigm. By comparing code samples between Erlang and PHP, you’ll find out how and why you should employ functional programming in your PHP applications. You’ll see that functional programming is nothing to be scared of. On the contrary, understanding its concepts broadens your programming horizon and provides you with valuable solutions to your problems.
11. – Robert C. Martin
“There is a freight train barreling
down the tracks towards us, with
multi-core emblazoned on it; and
you’d better be ready by the time
it gets here.”
22. -module(math).
-export([sum/1]).
sum(Number) ->
Sum = 0,
Numbers = lists:seq(1, Number),
lists:foreach(
fun(N) ->
Sum = Sum + N
end,
Numbers
),
Sum.
math:sum(5).
no return
keyword
** exception error: no match
of right hand side value 1
23. 1> X = 5.
5
2> X.
5
3> X = X * 2.
** exception error: no match of right hand side value 10
4> 5 = 10.
** exception error: no match of right hand side value 10
but isn’t
looks like
assignment
52. $names = ['Billy', 'Bob', 'Thornton'];
$anonymise = anonymise('sha256');
var_dump(array_map($anonymise, $names));
// array(3) {
// [0]=>
// string(64) "85eea4a0285dcb11cceb68f39df10d1aa132567dec49b980345142f09f4cb05e"
// [1]=>
// string(64) "cd9fb1e148ccd8442e5aa74904cc73bf6fb54d1d54d333bd596aa9bb4bb4e961"
// [2]=>
// string(64) "d7034215823c40c12ec0c7aaff96db94a0e3d9b176f68296eb9d4ca7195c958e"
// }
function anonymise($algorithm)
{
return function ($value) use ($algorithm) {
return hash($algorithm, $value);
};
}
higher-order function
closure
using PHP built-ins
function as value
function as argument
53. Middleware<?php
use PsrHttpMessageRequestInterface;
function add_header($header, $value)
{
return function (callable $handler) use ($header, $value) {
return function (
RequestInterface $request,
array $options
) use ($handler, $header, $value) {
$request = $request->withHeader($header, $value);
return $handler($request, $options);
};
};
}
$myStack = (new MiddlewareStack())
->push(add_header('Silly-Header', 'and its value'));
call next
in stack
immutable
higher-order function
54. Middleware<?php
use PsrHttpMessageServerRequestInterface as Request;
use PsrHttpMessageResponseInterface as Response;
$app = new SlimApp();
$app->add(function (Request $request, Response $response, callable $next) {
$response->getBody()->write('Hey there, ');
$response = $next($request, $response);
$response->getBody()->write('up?');
return $response;
});
$app->get('/', function ($request, $response, $args) {
$response->getBody()->write('what’s');
return $response;
});
$app->run();
// Hey there, what’s up?
stream is not
immutable
before
after
56. Middleware<?php
use PsrHttpMessageRequestInterface as Request;
use PsrHttpMessageResponseInterface as Response;
$middlewares->add($callback);
class Middlewares
{
public function add(
callable($request, Response $response, callable $next):Response
) {
}
}
declaration of
callable arguments
57. Middleware<?php
use PsrHttpMessageRequestInterface as Request;
use PsrHttpMessageResponseInterface as Response;
$middlewares->add($callback);
class Action implements Middleware
{
public function __invoke(Request $request, Response $response, callable $next)
{
// do something before
$next($request, $response);
// do something after
}
}
wrap in class