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();