Cовременный подход к HTTP с PHPixie и PSR-7

    image
    Стандартный PHP API для работы с HTTP запросами давно устарел. Программисты научились не использовать глобальные переменные, но стандартные суперглобалы как $_GET, $_SERVER все еще напоминают нам о далеком прошлом. Конечно фреймворки инкапсулируют эту информацию в свои Request\Response классы, но таких реализаций очень много и пока еще не было единственного стандарта. Стандарт PSR-7 от PHP-FIG как раз должен привести репрезентацию HTTP протокола к единственному знаменателю что позволит писать Middleware который будет работать сразу на многих фреймворках. Он пока еще не принят, но досрочное голосование показало практически единоголосную поддержку нового стандарта. PHPixie готовясь к релизу версии 3.0 уже приняла и имплементировала PSR-7, а также предоставляет обертки для упрощенной работы с интерфейсом. Если вы хотите создать свой микрофреймворк то взяв PHPixie HTTP за основу, сможете добиться результатов уже за один вечер.

    Теперь посмотрим на саму реализацию:

    $slice = new \PHPixie\Slice();
    $http  = new \PHPixie\HTTP($slice);
    


    Request
    PSR-7 довольно упрощенный интерфейс и предоставляет параметры $_GET и $_POST в виде массивов как и сам PHP, обертки PHPixie значительно упрощают работу с ними:

    //Строим запрос из глобальных переменных
    $request = $http->request();
    
    //Можно также явно предоставить уже полученную 
    //имплементацию PSR-7 ServerRequestInterface
    $request = $http->request($serverRequest);
    
    //$_GET
    $query = $request->query();
    
    //$_POST
    $query = $request->data();
    
    //Дополнительные аттрибуты
    //Например данные из рутинга
    $query = $request->attributes();
    
    //$_GET['pixie']
    $query->get('pixie');
    
    //С дефолтным значением
    $query->get('pixie', 'Trixie');
    
    //Выбросит ошибку если параметр отсутствует
    $query->getRequired('pixie');
    
    //$_GET['user']['name'];
    $query->get('user.name');
    
    //Или так
    $userData = $query->slice('user');
    $userData->get('name');
    
    //Кстати в таком случае $userData
    //это экземпляр \PHPixie\Slice\Data
    //никак не связанного с HTTP
    //и его можно смело передать куда-то еще
    
    //Доступ к параметрам сервера аналогичен
    $request->server()->get('http_host');
    
    //получит все значение хедера через кому
    $request->headers()->get('host');
    $request->headers()->getRequired('host');
    
    //значения хедера как массив
    $request->headers()->getLines('accept');
    
    //Загруженные файлы по стандарту PSR-7
    $uploadedFile = $request->uploads()->get('file');
    $uploadedFile->move('/images/fairy.png');
    
    //Информация о URI запроса
    $uri = $request->uri();
    $path = $uri->getPath();
    
    //И наконец-то чтобы получить чистую
    //реализацию ServerRequestInterface
    $serverRequest = $request->serverRequest();
    
    


    Response
    Кроме самой обертки над HTTP ответами, PHPixie также сможет построить часто используемые ответы автоматически, чтобы избавить вас от возни с хедерами. Конечно после того как ответ построен его можно модифицировать по вкусу.

    $responses = $http->responses();
    
    //Самый простой ответ
    $response = $responses->string('hello world');
    
    //JSON с правильными хедерами что запрещают кэш
    $responses->json(array('name' => 'Pixie'));
    
    //Редирект
    $responses->redirect('http://phpixie.com/');
    
    //Стриминг файла
    $responses->streamFile('pixie.png');
    
    //Скачка текста как файл на компьютер пользователя
    //например для CSV, TXT
    $responses->download('name.txt', 'text/plain', 'Trixie');
    
    //Скачка реального файла
    $responses->downloadFile('pixie.png', 'image.png', 'images/fairy.png');
    
    //Модификация статуса
    $response->setStatus('404', 'Not Found');
    
    //Стандартный текст ответа подставится автоматически
    $response->setStatus('404');
    
    //Модификация хедеров
    $response->headers->set('Content-Type', 'text/csv');
    
    
    //Получить PSR-7 ResponseInterface
    $response->asResponseMessage();
    
    //И вывести
    $http->output($response);
    
    


    Context
    Казалось бы это все, но мы пропустили cookies и сессию. Они относятся как до запроса так и до ответа и часто к ним требуется доступ не только в контроллере, но и в других местах, например в модуле авторизации. PHPixie выделяет их в отдельный Context.

    //Сначало надо получить контекст относительно запроса
    $context = $http->context($request);
    
    //А дальше все просто и по аналогии
    $cookies = $context->cookies();
    $session = $context->session();
    
    $cookies->set('lang', 'en');
    $session->getRequired('user_id');
    
    //Надо только помнить указывать контекст
    //при выводе ответа
    $http->output($response, $context);
    $response->asResponseMessage($context);
    


    Существуют и другие имплементации PSR-7, но они пока без оберток и контекста что делает работу с ними довольно неудобной. Довольно большое число из них используют трейты и тем самым нуждаются в версии PHP 5.4+.

    В то время все библиотеки PHPixie работают под любой версией PHP старше 5.3 (включая новую 7 и HHVM) и вдобавок на 100% покрыты юнит тестами. Сам код можно найти на github.com/phpixie/http

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 7

      +6
      Поражает упорство, с каким вы, несмотря на простреленные обе ноги и гирю на шее (я про выбранное название фреймворка и общий брендинг) продолжаете ползти к цели. Молодцы.
        +1
        Спасибо =)
        Брендинг чуть изменится когда все будет готово
        0
        А разве голосование по PSR-7 не отменено? С объяснением, что нужно дорабатывать…
          0
          Не совсем так, но да.
            0
            Отменено, но только ради маленьких поправок. Довольно скоро будет уже полностью принят
            0
            В PSR-7 используются object-values, т.е. не изменяемые объекты, например $message = $message->withHeader('Location', 'http://example.com');

            А у вас выглядит как мутабельный объект $response->setStatus('404'); — ваш response действительно меняется или надо переприсваивать $response = $response->setStatus('404')?
              0
              Наш меняется, но наш Response это не PSR-7 ResponseInterface. Зато он умеет превращатся в таковой:

              $psrResponse = $response->asResponseMessage($context);
              


              Конечно можно сразу по желанию построить и PSR Response:
              $psrResponse = $http->messages()->response($protocolVersion, $headers, $body);
              

            Only users with full accounts can post comments. Log in, please.