Salta el contingut

Request i Response

Altres classes que solen trobar-se en les frameworks MVC són les classes Request i Response. El seu objectiu és encapsular les funcionalitats relacionades amb la sol·licitud de l'usuari i la resposta.

La classe Request

La classe Request serà la responsable de gestionar les sol·licituds dels usuaris. A més, pot tenir mètodes orientats a obtenir informació de la sol·licitud.

<?php

namespace App;

class Request {
    const GET = 'GET';
    const POST = 'POST';

    private $domain;
    private $path;
    private $method;
    private $request;
    private $query;
    private $cookies;

    public function __construct() {
        $this->domain = $_SERVER['HTTP_HOST'];
        $this->path = explode('?', $_SERVER['REQUEST_URI'])[0];
        $this->method = $_SERVER['REQUEST_METHOD'];
        $this->query = new FilteredMap($_GET);
        $this->request = new FilteredMap($_POST);
        $this->cookies = new FilteredMap($_COOKIE);
    }

    public function getUrl(): string {
        return $this->domain . $this->path;
    }

    public function getDomain(): string {
        return $this->domain;
    }

    public function getPath(): string {
        return $this->path;
    }

    public function getMethod(): string {
        return $this->method;
    }

    public function isPost(): bool {
        return $this->method === self::POST;
    }

    public function isGet(): bool {
        return $this->method === self::GET;
    }

    public function getRequest(): FilteredMap {
        return $this->request;
    }

    public function getQuery(): FilteredMap {
        return $this->query;
    }

    public function getCookies(): FilteredMap {
        return $this->cookies;
    }
}

La classe FilteredMap facilita l'accés a les dades de la sol·licitud.

lass FilteredMap {
    private $map;

    public function __construct(array $baseMap) {
        $this->map = $baseMap;
    }

    public function has(string $name): bool {
        return isset($this->map[$name]);
    }

    public function getInt(string $name) {
        return (int) $this->get($name);
    }

    public function getNumber(string $name) {
        return (float) $this->get($name);
    }

    public function getString(string $name, bool $filter = true) {
        $value = (string) $this->get($name);
        return $filter ? addslashes($value) : $value;
    }

    public function get(string $name) {
        return $this->map[$name] ?? null;
    }
}

La classe Response

Aquesta classe prepararà la resposta al navegador. Establirà el codi d'estat, el tipus del recurs i el propi recurs mitjançant un sistema de plantilles.

class Response
{
    private int $status;
    private string $mime;

    private string $layout = 'default';
    private string $view;
    private array $data = [];

    public function __construct(int $status = 200, string $mime = "text/html")
    {
        $this->status = $status;
        $this->mime = $mime;
    }

    public function writeHeaders() {
        header($_SERVER["SERVER_PROTOCOL"] . ' ' . $this->status);
        header('Content-Type: {$this->mime}; charset=UTF-8');
    }
    /**
     * @param string $view
     * @param string $layout
     * @param array $data
     * @return string
     */
    public function render(): string {

        extract($this->data);

        ob_start();
        require __DIR__ . "/../views/{$this->view}.view.php";
        $content = ob_get_clean();

        ob_start();
        require __DIR__ . "/../views/layouts/{$this->layout}.layout.php";

        return ob_get_clean();
    }


    public function setView(string $view)
    {
        $this->view = $view;
    }

    public function setLayout(string $layout)
    {
        $this->layout = $layout;
    }

    public function setData(array $compact)
    {
        $this->data = $compact;
    }

En executar un controlador caldrà que tornaren un objecte Response.

// MovieController.php
    public function list(): Response
    {
        $message = FlashMessage::get("message");

        $movies = $this->movieRepository->findAll();

        $logger = Registry::get(Registry::LOGGER);
        $logger->info("s'ha executat una consulta");

        $response = new Response();
        $response->setView("index");
        $response->setLayout("default");
        $response->setData(compact('movies'));

        return $response;
        //require __DIR__ . "/../../views/index.view.php";
    }

I caldrà modificar el controlador frontal:

    if (method_exists($controller, $method)) {
        $object = new $controller;        
        //call_user_func_array([$object, $method], $match['params']);
        $response = call_user_func_array([$object, $method], $match['params']);

        $response->writeHeaders(); 
        echo $response->render();