PSR-7 фреймворк: Структура и работа с HTTP
Первый урок серии скринкастов по изучению PSR-7 микрофреймворков в PHP. Сегодня рассмотрим создание структуры директорий, написание объектов для взаимодействия с HTTP-протоколом и их тестирование с помощью PHPUnit:
Для более комфортного просмотра откройте скринкаст на 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 - Подведение итогов
Остальные части:
- Структура и работа с HTTP
- Контроллеры и маршрутизация
- Middleware и Pipeline
- Контейнер внедрения зависимостей
- Шаблонизаторы и вёрстка
- Обновление до PSR-15, вывод ошибок и логирование
- Консольные команды, базы данных и ресурсы
Задавайте вопросы в комментариях. Заранее спасибо и до встречи в следующем видео!
Спасибо! На этот раз даже не 6 часов ;)
И все-равно первые 30 минут видео можно просто выкинуть, а остальное сжать до 30-60 минут
Даже в 10 минут. Да и вообще странно что видео о создании собственного фреймворка на php начинается с описания jquery и написания echo 'hello'. Те, кто не знает как писать echo 'Hello' скорее всего даже не слышали о таком слове как "фреймворк"
Ну такое...
Ну так выкиньте, сожмите и выложите к себе на канал. Мы вам все спасибо скажем.
А мне первые 30 минут было очень интересно послушать.
Вот так подарочек на новый год. Спасибо! Здоровья!
Круто! Спасибо большое!
Отличный урок! То что надо. Жду продолжения!
Ещё можно выделить пакет 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.
Либо на своих адаптерах.
Дмитрий, если использовать chdir(dirname(__DIR__)); phpstorm не определяет файл указанный в пути и подсвечивает предупреждение. У вас видимо эта опция отключена. Но в таком случае, когда будет не правильный путь, подсказки не будет. Верно?
Да, здесь отключена, чтобы в глаза не бросалась. Подсказки не будет.
У меня __DIR__ == "xdebug:" :)
Переопределение не помогает: $dir = __DIR__;
Потому что там далее в классах автозагрузчиков composer тоже используется константа __DIR__ который переопрёделен xdebug ом...
как реализовать это правильно?
Не помню точно, но кажется это был баг xdebug
Добрый день, Дмитрий. Скажите, пожалуйста, какую тему (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 и использовать вышеназванный класс.
Спасибо за внимание)
Да, тоже хотел это добавить.
Тут об этом говорится
https://docs.zendframework.com/zend-diactoros/v1/emitting-responses/
Дмитрий, спасибо за труды!
для php 5.6 не подойдет к сожалению
Спасибо за уроки, Дмитрий!
А о новых коммитах будет какая нибудь цитата? Я смотрел там 15 дней назад были изменения)
Исправил EmptyResponseMiddleware.
Могу ошибаться, но на счет цепочечных вызовов, это больше похоже на функторы,
будет более правильней на мой взгляд возвращать не самого себя, а свежесозданный объект с модифицированными данными,
так доступ к аттрибутам будет более безопасным и не нужно вызывать clone(), хотя конструктор все же необходим.
Я не вполне уловил суть - зачем именно в этом случае нужна иммутабельность.
Это нужно только для того чтобы удобно было тестировать или есть еще какие то причины?
Можно. Но чтобы это работало нужен конструктор, в котором будут присваиваться абсолютно все поля, а не только одно-два обязательных.
Дмитрий, хочу поблагодарить Вас за Ваши видеоуроки. Считаю их самыми лучшими из всех обучающих видео по программированию которые мне доводилось просматривать. Видеокурс про создание psr-7 фреймворка пересмотрел несколько раз - очень полезно для всех новичков. Очень жду новой серии про написание HTTP-фреймворка. Ещё раз большое спасибо за Вашу работу.
Спасибо за отзыв! Новую уже начали в https://deworker.pro/edu/series/http-framework
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();
}