HttpFoundation

Objektová práca s HTTP

01/2015 / Milan "perun" Herda / @moriquend / hrad.perunhq.org

Obsah

  • čo je to HttpFoundation?
  • request
  • response
  • session

Čo je HttpFoundation?

  • samostatne použiteľný Symfony komponent
  • umožňuje objektovo-orientovaný prístup k dátam a vlastnostiam http requestu, http response a k session
  • abstrahuje od používania superglobálnych premenných
  • zjednodušuje testovanie
  • obsahuje zopár cool vecí, ktoré nemusíte implementovať od nuly (cacheovacie hlavičky, flash správy...)

Inštalácia a použitie

Composer


{
    "require": {
        "symfony/http-foundation": "~2.6.3"
    }
}
                    

PHP


use Symfony\Component\HttpFoundation\Request;

$request = Request::createFromGlobals();
                    

Request

Request

  • objektový prístup ku GET, POST, COOKIE, SERVER, FILES
  • jednoduchý prístup k hlavičkám http requestu
  • môžete filtrovať vstupné premenné

Predtým


$id       = array_key_exists($_GET['id']) ? $_GET['id'] : 0;
$uri      = $_SERVER['REQUEST_URI'];
$hostname = $_SERVER['HTTP_HOST'];
$agent    = $_SERVER['HTTP_USER_AGENT'];
                    

Teraz


$id       = $request->query('id', 0);
$uri      = $request->getPathInfo();
$hostname = $request->getHost();
$agent    = $request->headers->get('User-Agent')
                        

Kde sú uložené dáta requestu?

$_GET $request->query
$_POST $request->request
$_COOKIE $request->cookies
$_FILES $request->files
$_SERVER $request->server
http hlavičky $request->headers
iné $request->attributes

Každá z vlastností query, request, cookies, files, server, headers a attributes je public premenná typu ParameterBag

ParameterBag - vrece parametrov

  • all()
  • keys()
  • replace()
  • add()
  • get()
  • set()
  • has()
  • remove()

ParameterBag#get


public function get($key, $default = null, $deep = false)
                    
$default
predvolená hodnota, ktorá sa vráti v prípade, že vo vreci neexistuje parameter s daným názvom
$deep
umožňuje vrátiť vnorený prvok poľa, pokiaľ ako $key použime niečo takéto "foo[bar]"

Session


$request->getSession()
                    

Volanie vráti inštanciu SessionInterface

Jednoduchšie testy

Už nemusíme vymýšľať, ako otestovať kontroler, ktorý pracuje s $_GET, $_POST. Vytvoríme si Request a pošleme ho kontroleru.


$request = Request::create(
    '/hello-world',
    'GET',
    [
        'name' => 'Fabien'
    ]
);
                    

Response

Response

  • objekt predstavujúci odpoveď servera/aplikácie
  • jednoduché nastavovanie http hlavičiek
  • jednoduché odosielanie súborov
  • jednoduché cachovanie

Predtým


header('HTTP/1.0 404 Not Found');

echo 'oops';
                    

Teraz


use Symfony\Component\HttpFoundation\Response;

$response = new Response(
    'oops',
    Response::HTTP_NOT_FOUND,
    [
        'content-type' => 'text/html',
    ]
);

$response->send();
                        

Predtým: problémy


header('HTTP/1.0 404 Not Found');

echo 'oops';
                    
  • ako presne má vyzerať hlavička, ktorú idem posielať?
  • je toto správne miesto pre nastavenie hlavičky?
  • je toto správne miesto pre vypísanie výstupu?

Teraz: riešenie


use Symfony\Component\HttpFoundation\Response;

$response = new Response(
    'oops',
    Response::HTTP_NOT_FOUND,
    ['content-type' => 'text/html']
);

//...

$response->setContent('tak sme predsa našli')
$response->setStatusCode(Response::HTTP_OK);
$response->headers->set('Content-Type', 'text/plain');

//...

$response->send();
                    

Cookie


use Symfony\Component\HttpFoundation\Cookie;

$response->headers->setCookie(new Cookie('foo', 'bar'));
                    

Práca s HTTP cache


$response->setCache([
    'etag'          => 'abcdef',
    'last_modified' => new \DateTime(),
    'max_age'       => 600,
    's_maxage'      => 600,
    'private'       => false,
    'public'        => true,
]);
                    

Práca s HTTP cache

Jednotlivé cachovacie hlavičky sa dajú nastaviť aj samostatne.

  • setPublic();
  • setPrivate();
  • expire();
  • setExpires();
  • setMaxAge();
  • setSharedMaxAge();
  • setTtl();
  • setClientTtl();
  • setLastModified();
  • setEtag();
  • setVary();

Not modified?

Metóda isNotModified skontroluje hlavičky a pokiaľ nedošlo k zmene dokumentu, tak nastaví status 304 a odstráni telo odpovede.


if ($response->isNotModified($request)) {
    $response->send();
}
                    

Redirect


use Symfony\Component\HttpFoundation\RedirectResponse;

$response = new RedirectResponse('http://example.com/');
                    

JSON


use Symfony\Component\HttpFoundation\JsonResponse;

$response = new JsonResponse();
$response->setData([
    'data' => 123
]);
                    

Súbory


use Symfony\Component\HttpFoundation\BinaryFileResponse;

$file = 'path/to/file.pdf';
$response = new BinaryFileResponse($file);
                    

Session

Príklad


use Symfony\Component\HttpFoundation\Session\Session;

$session = new Session();
$session->start();

$session->set('username', 'Fero');

$session->get('username');
                        

Flash správy

Po spracovaní formuláru nastavím info hlášku


$session->getFlashBag()->add('notice', 'Vaša objednávka bola spracovaná');
                        

Po redirecte stránka zobrazí všetky doteraz nevypísané flash správy


foreach ($session->getFlashBag()->get('notice', []) as $msg) {
    echo '<div class="flash-notice">' . $msg . '</div>';
}
                        

Testy


use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;

// unit testy, ktoré nepotrebujú ukladať session
$session = new Session(new MockArraySessionStorage());

// funkcionálne testy, ktoré potrebujú perzistované session dáta
$session = new Session(new MockFileSessionStorage());

                    

Použitie v legacy aplikácii


use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage;

// legacy application configures session
ini_set('session.save_handler', 'files');
ini_set('session.save_path', '/tmp');
session_start();

// Get Symfony to interface with this existing session
$session = new Session(new PhpBridgeSessionStorage());

// symfony will now interface with the existing PHP session
$session->start();
                    

Viac informácií

http://symfony.com/doc/current/components/http_foundation/index.html

Otázky?

Ďakujem za pozornosť