PROGRAMMING

m9/ PHP
REMEMBERS




Last update:   23-07-2021

Templates Controller

Our framework hardcodes how the templates are used v3.0 (front.php) If you want to add logic, you would be forced to put the logic into the template itself.
 
// public/front.php
...

extract($matcher->match($request->getPathInfo(), EXTR_SKIP));
ob_start();
include sprintf(__DIR__.'/../src/pages/%s.phtml', $_route);
$response = new Response(ob_get_clean());

...
... 1 lines
 
! Lets separate the template code from the logic (a new layer: the controller). Render controller.
 
// public/front.php
...

function render_template($request)
{
    extract($request->attributes->all(), EXTR_SKIP);
    ob_start();
    include sprintf(__DIR__.'/../src/pages/%s.phtml', $_route);
    return new Response(ob_get_clean());
}

$request->attributes->add(
    $matcher->match($request->getPathInfo())
);
$response = call_user_func('render_template', $request); // Look here
... 7 lines
 
! We can replace call_user_func argument with any valid callback (function, anonymous function, or class method, etc). As a convention, for each route, the associated controller is $_controller route attribute.
 
// src/app.php

use Symfony\Component\Routing;

$routes = new Routing\RouteCollection();
$routes->add('hello', new Routing\Route('/hello/{name}', [
    'name' => 'World',
    '_controller' => 'render_template', // Look here

]));
$routes->add('bye', new Routing\Route('/bye'));

return $routes;
... 3 lines
 
 
// public/front.php
...

$response = call_user_func(
    $request->attributes->get('_controller'), $request
);
This is rather flexible as you can change Response object afterwards.
 
// src/app.php

use Symfony\Component\Routing;

$routes = new Routing\RouteCollection();
$routes->add('hello', new Routing\Route('/hello/{name}', [
    'name' => 'World',
    '_controller' => function($request) {

        // $foo is now available in template
        $request->attributes->set('foo', 'bar');

        $response = render_template($request);

        // change header
        $response->headers->set('Content-Type', 'text/plain');

        return $response;
    }

]));
$routes->add('bye', new Routing\Route('/bye'));

return $routes;
... 10 lines
 

Controller

Lets update our framework and add some logic.
 
// public/front.php

require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;

$request = Request::createFromGlobals();
$routes = include __DIR__.'/../src/app.php';

$context = new Routing\RequestContext();
$context->fromRequest($request);
$matcher = new Routing\Matcher\UrlMatcher($routes, $context);

try {
    $request->attributes->add(
        $matcher->match($request->getPathInfo())
    );
    $response = call_user_func( // Look Here
        $request->attributes->get('_controller'), $request
    );
} catch(Routing\Exception\ResourceNotFoundException $e) {
    $response = new Response('Not found', 404);
} catch (Exception $e) {
    $response = new Response('An error occured', 500);
}

$response->send();
... 17 lines
 
 
// src/app.php

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;

$routes = new Routing\RouteCollection();
$routes->add('hello', new Routing\Route('/hello/{name}', [
    'name' => 'World',
    '_controller' => function($request) {

        $request->attributes->set('name', // Look here
            strtoupper($request->attributes->get('name'))
        );

        $response = render_template($request);
        return $response;
    }
]));

function render_template($request)
{
    extract($request->attributes->all(), EXTR_SKIP);
    ob_start();
    include sprintf(__DIR__.'/../src/pages/%s.phtml', $_route);
    return new Response(ob_get_clean());
}

return $routes;
... 16 lines
 
 
http://tests.local/php/framework/public/hello/catalin 
    // Hello CATALIN
Framework v4.0 Fork v4.0c Application - Is Even    (2/2)

Application - is even

Lets create a brand new application that say if a number is even or not.
 
// public/front.php

require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;

$request = Request::createFromGlobals();
$routes = include __DIR__.'/../src/app.php';

$context = new Routing\RequestContext();
$context->fromRequest($request);
$matcher = new Routing\Matcher\UrlMatcher($routes, $context);

try {
    $request->attributes->add(
        $matcher->match($request->getPathInfo())
    );
    $response = call_user_func( // Look here
        $request->attributes->get('_controller'), $request
    );
} catch(Routing\Exception\ResourceNotFoundException $e) {
    $response = new Response('Not found', 404);
} catch (Exception $e) {
    $response = new Response('An error occured', 500);
}

$response->send();
... 17 lines
 
 
// src/app.php

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing;

$routes = new Routing\RouteCollection();

// isEven route
$routes->add('isEven', new Routing\Route('/isEven/{no}', [
    'no' => null,
    '_controller' => function($request) {

        if (isEven($request->attributes->get('no'))) {
            return new Response("Yes, the number is even!");
        }
        return new Response("No, the number is odd of null.");
    }
]));

function isEven($no)
{
    if (null === $no) return false;
    return $no % 2 == 0;
}

return $routes;
... 14 lines
 
 
http://tests.local/php/framework/public/isEven/2 
    // Yes, the number is even!

http://tests.local/php/framework/public/isEven/23 
    // No, the number is odd of null.
Framework v4.2
Questions    
Resolver

        A B C D E F
🔔
1/2