PSR-7 фреймворк: Структура и работа с HTTP

Первый урок серии скринкастов по изучению PSR-7 микрофреймворков в PHP. Сегодня рассмотрим создание структуры директорий, написание объектов для взаимодействия с HTTP-протоколом и их тестирование с помощью PHPUnit:

Исходный код на GitHub

Для более комфортного просмотра откройте скринкаст на YouTube, разверните видео до оригинального размера значком и поставьте скорость 1,75:


Содержание:

  • 00:00:00 - Вступление
  • 00:01:09 - Что такое фреймворк
  • 00:06:29 - История JavaScript
  • 00:10:30 - История PHP
  • 00:15:18 - Ключевые нововведения в PHP
  • 00:19:13 - Composer - пакетный менеджер
  • 00:25:15 - Обратная сторона компонентного подхода
  • 00:28:00 - Начало создания проекта
  • 00:31:04 - GET-запрос
  • 00:32:45 - Что происходит на сервере, REST Client
  • 00:37:18 - Cуперглобальные массивы
  • 00:38:06 - Функция getLang
  • 00:42:50 - Ассоциативный массив
  • 00:44:07 - Класс Request
  • 00:46:04 - Вынесение классов проекта
  • 00:47:15 - Импорт классов
  • 00:49:46 - Правила именования методов
  • 00:54:19 - Автозагрузка с помощью Composer
  • 00:54:53 - Секция "require"
  • 00:55:42 - Секция "config"
  • 00:58:58 - Секция "autoload"
  • 01:03:31 - PHPUnit
  • 01:07:29 - RequestTest
  • 01:12:33 - Секция "require-dev"
  • 01:13:53 - Секция "scripts"
  • 01:17:16 - Неудобство глобальных параметров
  • 01:22:29 - Сеттеры и мутаторы
  • 01:26:25 - Недостатки сеттеров
  • 01:29:05 - Иммутабельные объекты
  • 01:33:08 - Фабрика RequestFactory
  • 01:34:24 - Ответ сервера
  • 01:36:54 - ResponseTest
  • 01:39:37 - Цикл жизни приложения
  • 01:41:09 - Класс Response
  • 01:42:56 - Повторное использование, адаптеры
  • 01:50:21 - PSR-7
  • 01:52:42 - ServerRequestInterface
  • 01:53:07 - ResponseInterface
  • 01:54:33 - Отличия наших интерфейсов от PSR
  • 01:58:32 - Подключение zend-diactoros
  • 02:03:02 - Удаление наших классов и тестов
  • 02:04:08 - ResponseSender и SapiEmitter
  • 02:06:43 - SapiStreamEmitter
  • 02:09:22 - Подведение итогов

Остальные части:

  1. Структура и работа с HTTP
  2. Контроллеры и маршрутизация
  3. Middleware и Pipeline
  4. Контейнер внедрения зависимостей
  5. Шаблонизаторы и вёрстка
  6. Обновление до PSR-15, вывод ошибок и логирование
  7. Консольные команды, базы данных и ресурсы

Задавайте вопросы в комментариях. Заранее спасибо и до встречи в следующем видео!

Комментарии

 

Sergey

Спасибо! На этот раз даже не 6 часов ;)

Ответить

 

Сергей

И все-равно первые 30 минут видео можно просто выкинуть, а остальное сжать до 30-60 минут

Ответить

 

Серега

Даже в 10 минут. Да и вообще странно что видео о создании собственного фреймворка на php начинается с описания jquery и написания echo 'hello'. Те, кто не знает как писать echo 'Hello' скорее всего даже не слышали о таком слове как "фреймворк"

Ответить

 

Артём Курдин (artemcodes)

Ну такое...

Ответить

 

Дмитрий Елисеев

Ну так выкиньте, сожмите и выложите к себе на канал. Мы вам все спасибо скажем.

Ответить

 

Дмитрий

А мне первые 30 минут было очень интересно послушать.

Ответить

 

Сергей

Вот так подарочек на новый год. Спасибо! Здоровья!

Ответить

 

Николай

Круто! Спасибо большое!

Ответить

 

Евгений

Отличный урок! То что надо. Жду продолжения!

Ответить

 

Александр Денисюк – denisyuk.by

Ещё можно выделить пакет HttpFoundation от Symfony, реализация которого во многом превосходит заявленный функционал в интерфейсах PSR-7. Но если нужно, то можно c помощью symfony/psr-http-message-bridge конвертировать HttpFoundation в Zend Diactoros или любое решение, реализующее PSR-7. Также можно любое решение на PSR-7 интерфейсах преобразовать в HttpFoundation. Может пригодиться разработчика на Symfony, которые притянули какой-нибудь пакет, работающий только с PSR-7.

Ответить

 

Дмитрий Елисеев

Можно. Про них упоминал во второй части при рассмотрении Symfony Router. Но если хотите делать фреймворконезависимые библиотеки - то только PSR-7.

Ответить

 

Александр Денисюк – denisyuk.by

Либо на своих адаптерах.

Ответить

 

Spirit Absolute

Дмитрий, если использовать chdir(dirname(__DIR__)); phpstorm не определяет файл указанный в пути и подсвечивает предупреждение. У вас видимо эта опция отключена. Но в таком случае, когда будет не правильный путь, подсказки не будет. Верно?

Ответить

 

Дмитрий Елисеев

Да, здесь отключена, чтобы в глаза не бросалась. Подсказки не будет.

Ответить

 

Spirit Absolute

У меня __DIR__ == "xdebug:" :)

Ответить

 

Spirit Absolute

Переопределение не помогает: $dir = __DIR__;
Потому что там далее в классах автозагрузчиков composer тоже используется константа __DIR__ который переопрёделен xdebug ом...

Ответить

 

Дмитрий Беженцев

как реализовать это правильно?

Ответить

 

Spirit Absolute

Не помню точно, но кажется это был баг xdebug

Ответить

 

Rafa

Добрый день, Дмитрий. Скажите, пожалуйста, какую тему (Color Scheme) для PhpStorm вы используете?

Ответить

 

Кирилл

Вроде Darcula стандартная

Ответить

 

Дмитрий Елисеев

Доработанная Darcula.

Ответить

 

Андрей

Спасибо, очень интересно...

Ответить

 

Сергей Шурьяков

Благодарю, шикарный материал. Особенно нравится слушать историю развития языков. Ты лучший!

Ответить

 

Виталий

Хотелось бы чтобы вы делали краткий письменный конспект к своим длинным видео.

А сами видео уроки хорошие, спасибо за информацию

Ответить

 

Леша Тимков

Дима, а можно попросить файлы после каждой части по PSR-7 фреймворку. Так как это на ваших интенсивах было.

Ответить

 

Дмитрий Елисеев

Можно. Либо клонируете репозиторий к себе и переключаетесь через git checkout, либо:

1. Заходите в историю коммитов
2. Справа от нужного коммита кликаете Browse the repository.
3. Смотрите файлы или скачиваете архив через Clone or download.

Ответить

 

Андрей

Дмитрий, спасибо! Узнал кое-что новое :)

Ответить

 

Леонид

для генерации phpunit.xml можно выполнить команду
vendor/bin/phpunit --generate-configuration
, а не копировать из каких-то других проектов

Ответить

 

Владимир

Просто шикарный урок, расставил все по полочкам, успехов тебе, лучший преподаватель которого я знаю)

Ответить

 

Амир

Спасибо за урок! Не знаю насколько моя информация будет полезна, но в zend-diactoros начиная с версии 1.8 класc Zend\Diactoros\Response\SapiEmitter считается устаревшим. Вместо этого рекомендуется использовать Zend\HttpHandlerRunner\Emitter\SapiEmitter.
Для этого необходимо подключить библиотеку zendframework/zend-httphandlerrunner и использовать вышеназванный класс.

Спасибо за внимание)

Ответить

 

Александр Пудич

для php 5.6 не подойдет к сожалению

Ответить

 

Артём Курдин (artemcodes)

Спасибо за уроки, Дмитрий!

Ответить

 

Shokha – shokha.uz

А о новых коммитах будет какая нибудь цитата? Я смотрел там 15 дней назад были изменения)

Ответить

 

Дмитрий Елисеев

Исправил EmptyResponseMiddleware.

Ответить

 

Bogdan899

Могу ошибаться, но на счет цепочечных вызовов, это больше похоже на функторы,
будет более правильней на мой взгляд возвращать не самого себя, а свежесозданный объект с модифицированными данными,
так доступ к аттрибутам будет более безопасным и не нужно вызывать clone(), хотя конструктор все же необходим.

<?php

namespace Framework\Http;

class Request
{
    private $queryParams;
    private $parsedBody;

    public function __construct($queryParams = [], $parsedBody = null)
    {
        $this->queryParams = $queryParams;
        $this->parsedBody = $parsedBody;
    }

    public function getQueryParams()
    {
        return $this->queryParams;
    }

    public function getParsedBody()
    {
        return $this->parsedBody;
    }

    public function withQueryParams($data)
    {
        return new self($data, $this->getParsedBody());
    }

    public function withParsedBody($data)
    {
        return new self($this->getQueryParams(), $data);
    }
}
Ответить

 

Александр Михайлов

Я не вполне уловил суть - зачем именно в этом случае нужна иммутабельность.
Это нужно только для того чтобы удобно было тестировать или есть еще какие то причины?

Ответить

 

Дмитрий Елисеев

Можно. Но чтобы это работало нужен конструктор, в котором будут присваиваться абсолютно все поля, а не только одно-два обязательных.

Ответить

 

Андрей

Дмитрий, хочу поблагодарить Вас за Ваши видеоуроки. Считаю их самыми лучшими из всех обучающих видео по программированию которые мне доводилось просматривать. Видеокурс про создание psr-7 фреймворка пересмотрел несколько раз - очень полезно для всех новичков. Очень жду новой серии про написание HTTP-фреймворка. Ещё раз большое спасибо за Вашу работу.

Ответить

 

Alexandr

With respect to the author!
Lessons very good...

Ответить

 

Артём

В классе Response не хватает метода :)

public function setBody(string $body): void
{
$this->body .= $body;
}

иначе не будет работать Before и After для Middleware

Ответить

 

Артём

вот что будет при реализации метода setBody():

class BeforeMiddleware implements MiddlewareInterface
{
public function handle(Request $request, callable $next): Response
{
$body = $next($request)->getBody();

$response = new Response();
$response->setBody('{BEFORE}' . $body);

return $response;
}
}

class Handler implements HandlerInterface
{
public function handle(Request $request): Response
{
return new Response('{BODY}');
}
}

class AfterMiddleware implements MiddlewareInterface
{
public function handle(Request $request, callable $next): Response
{
$response = $next($request);

$response->setBody('{AFTER}');

return $response;
}
}

выхлоп:

{BEFORE}{BODY}{AFTER}

Ответить

 

Артём

можно ещё дополнить Response методом send()

public function send(): void
{
header($_SERVER['SERVER_PROTOCOL'] . ' ' . $this->getStatusCode() . ' ' . $this->getReasonPhrase());

foreach ($this->getHeaders() as $name => $value) {
header($name . ': ' . $value);
}

echo $this->getBody();
}

Ответить

Оставить комментарий

Войти | Завести аккаунт | Войти через


(никто не увидит)





Можно использовать теги <p> <ul> <li> <b> <i> <a> <pre>