Yii3 Overview 3. Обзор app-* шаблонов и demo

от автора

Список всех статей:

  1. Вступление

  2. Вспомогательные инструменты разработки

  3. Обзор app-* шаблонов и demo

Текущая статья будет посвящена обзору app, app-api и app-console шаблонов, а также demo приложений.

Рассмотрим некоторые особенности конфигурирования шаблонов приложений по умолчанию, а также логику работы конфигов и расположение кодовой базы.

Начну с главного – различия app-* шаблонов и demo.

App

App-* – шаблоны приложения, готовые для использования в собственных проектах. Это просто болванка, скелетон или template готового приложения.

App – шаблон для классического PHP web + console приложения с server side rendering. То есть весь HTML страницы будет генерироваться на сервере.

App-api – шаблон для PHP web + console приложения с client side rendering. Обычно такие шаблоны используют для создания бэкендов для Single Page Application или различного рода “апишек”.

App-console – шаблон для написания console приложения. Из шаблона удалены все web-related things, однако вы можете в дальнейшем добавить туда их самостоятельно или воспользоваться одним из шаблонов выше.

На момент написания статьи в Yii3 существуют только 3 шаблона. В планах добавить еще несколько шаблонов для быстрого старта с асинхронными фреймворками, такими как AMPHP, ReactPHP, Swoole, RoadRunner, а также Temporal.

Demo

Demo – монорепозиторий с уже готовыми приложениями. В demo приложениях мы будем показывать вариации использования тех или иных библиотек. Приложения в demo предназначены просто для демонстрации работы фреймворка. Чтобы начать писать на Yii3, лучше создайте проект используя app-* шаблон.

На момент написания статьи demo содержит два приложения: blog и blog-api. В планах добавить еще интеграцию с RoadRunner и Temporal.

Если у вас есть желание создать новое приложение или улучшить существующее, то создайте Issue или PR, или просто напишите в чат, и мы обязательно рассмотрим любые доработки.

Начнем разбор фреймворка с app шаблона.

Установка

composer create-project yiisoft/app app --stability=dev

Флаг --stability=dev нужен потому, что шаблоны приложения не имеют релизов, так как зависят от других пакетов, которые не имеют релизов.

Внимательный читатель может заметить, что в первой статье я обещал обозревать только стабильные пакеты. Простите меня за мою ложь. Я больше так не буду. Но не обещаю 🙂

После выполнения команды по установке в текущей директории появится директория с именем app. Там и лежит наш “пациент”.

cd app – переходим в директорию с проектом.

Первым делом запускаем тесты:

./vendor/bin/codecept run

Тесты проходят. Всё отлично.

Структура

Общая структура app-* шаблонов и demo приложений покажется весьма знакомой современному разработчику.

Из непонятного – директории resources и runtime.

Runtime – директория, отвечающая за хранение промежуточных данных: кэша приложения, записей дебагера, ошибок от Codeception, кеша схемы Cycle и и прочих пользовательских файлов. Подобные директории, как правило, стоит скрывать от индексирования в IDE. В PHPStorm, например, нужно в контекстном меню выбрать Mark Directory as → Excluded .

Resources – директория для дополнительных ресурсов, таких как web assets, translator messages, layout + views, mail templates, rbac settings и любые другие ресурсы, которые вы захотите хранить у себя в приложении вне src и config.

Давайте заглянем глубже в директорию config.

С первого взгляда может показаться, что ничего не понятно – но давайте разбираться.

Директории web и console, а также файлы с суффиксами *-web и *-console подключаются, когда вы запускаете приложение из соответствующего окружения. yiisoft/config позволяет вам вручную манипулировать всеми этими файлами, но в yiisoft/yii-runner-* репозиториях все настройки по умолчанию прописаны за вас.

Директория common и файлы без префиксов будут подключаться во всех окружениях. Сначала они, потом *-webили *-console файлы, перезаписывая и дополняя то, что находится в общих конфигах.

Директории web и console отвечают за конфигурацию DI непосредственно для web и console приложений.

Например, конфигурация web содержит несколько файлов, которые объединяться в единый, и ими будет конфигурироваться контейнер зависимостей.

Также в директории config можно заметить 3 дочерние директории dev, prod и test. Они будут подключаться, когда переменная окружения YII_ENV будет равняться dev, prod или test соответственно.

Структура подключаемых конфигов

У вас может появиться потребность изменить конфиг так, чтобы с ним было удобнее работать – переименовать директорию config, поменять расположение файлов внутри неё, хранить конфигурации модулей внутри самих модулей или помимо dev, prod или test окружений создать дополнительные окружения.

За работу с конфигами отвечает пакет yiisoft/config. А все необходимые параметры подключения этих файлов лежат в корневом composer.json. Они выглядят примерно так:

"extra": {     "config-plugin-options": {         "source-directory": "config"     },     "config-plugin-environments": {         "dev": {             "params": [                 "test/params.php"             ]         },         "prod": {             "params": [                 "test/params.php"             ]         },         "test": {             "params": [                 "test/params.php"             ]         }     },     "config-plugin": {         "common": "common/*.php",         "params": [             "params.php",             "?params-local.php"         ],         "web": [             "$common",             "web/*.php"         ],         "console": [             "$common",             "console/*.php"         ],         ...     } },

Большую часть из примера я вырезал из-за одинаковости настройки.

Полную документацию работы пакета yiisoft/config вы можете найти в README репозитория. Более подробный разбор пакета будет в одной и следующих статей.

Точки входа в приложение

Точкой доступа для запуска приложения в web окружении является файл public/index.php.

В нем есть запуск так называемого “раннера”, который конфигурирует, инициализирует и запускает основное приложение.

<?php /// ...  // Run HTTP application runner $runner = (new HttpApplicationRunner(dirname(__DIR__), $_ENV['YII_DEBUG'], $_ENV['YII_ENV']))     ->withTemporaryErrorHandler(new ErrorHandler(         new Logger([new FileTarget(dirname(__DIR__) . '/runtime/logs/app.log')]),         new JsonRenderer(),     )) ; $runner->run();

Консольная версия раннера лежит в файле yii в корневом каталоге.

Запуск консольного приложения выглядит следующим образом:

Запуск консольного приложения выглядит следующим образом:

<?php /// ...  // Run console application runner $runner = new ConsoleApplicationRunner(__DIR__, $_ENV['YII_DEBUG'], $_ENV['YII_ENV']); $runner->run();

Интерфейсы использования раннеров довольно простые. Достаточно указать всего несколько аргументов и вызвать $runner->run() для его запуска. При желании раннеры можно сконфигурировать иначе. Разные раннеры предоставляют различные методы конфигурирования.

Полный разбор раннеров будет также в одной из следующих статей. Для справки, сейчас существуют следующие раннеры:

Также существует базовый раннер с общей функциональностью – yiisoft/yii-runner

Немного пояснений про withTemporaryErrorHandler()

При запуске HTTP раннера можно указать temporary error handler. Это обработчик, который будет обрабатывать все ошибки произошедшие до запуска основного приложения. Например, ошибка может произойти в момент конфигурирования DI контейнера. Так как контейнер еще не инициализирован, из него невозможно получить ErrorHandler. Для этих целей будет использоваться “временный”. Наличие такого временного обработчика ошибок позволит получить ответ в запрашиваемом формате – html, json или другом, который вы можете также сконфигурировать вручную.

Однако, использование “невременного” вам может тоже понадобиться. В нем можно подписаться на события приложения, заинжектить в него какой-то класс или что-то на ваш вкус. После запуска контейнера, временный обработчик отключается, и подключается обработчик из контейнера зависимостей.

Основные директории src и tests

Я уверен, что код в src вам покажется простым и понятным.

В src или tests нет каких-то Yii-specific мест. Максимум – это сконфигурированные классы по умолчанию. Всё взаимодействие классов происходит как во многих других фреймворках, с помощью ООП и Dependency Injection. Любые конфигурации классов вы можете переписать с помощью params.php . Об этом будет рассказано в следующих статьях.

По умолчанию в шаблонах app-* и demo приложениях мы инициализируем Codeception с базовыми настройками, потому как считаем, что он будет чаще использоваться при разработке реальных проектов. Этот тестовый фреймворк никак не привязан к Yii3, и вы спокойно можете удалить его и оставить классический PHPUnit, который тоже идет вместе с шаблонами.

Пример контроллера

Рассмотрим пример контроллера на основе файла src/Controller/SiteController.php:

<?php  declare(strict_types=1);  namespace App\Controller;  use Psr\Http\Message\ResponseInterface; use Yiisoft\Yii\View\ViewRenderer;  final class SiteController {     public function __construct(private ViewRenderer $viewRenderer)     {         $this->viewRenderer = $viewRenderer->withControllerName('site');     }      public function index(): ResponseInterface     {         return $this->viewRenderer->render('index');     } }

\Yiisoft\Yii\View\ViewRenderer – класс, который рендерит представление.

Метод ViewRenderer::withControllerName() меняет базовую директорию в контексте класса с @views на @views/site.

Метод ViewRenderer::render() вызывает непосредственно рендеринг представления @views/site/index.php. Помимо PHP шаблонов Yii3 поддерживает еще и Twig.

Полный список всех поддерживаемых шаблонизаторов вы можете найти здесь.

В Telegram чате недавно подняли вопрос поддержки Smarty. Если вы любитель Smarty и хотите поддержку этого или любого другого шаблонизатора в Yii3, то приносите ваши предложения в Issue или в наш Telegram чат.

withControllerName() – простой хелпер. Этот метод создан для того, чтобы не дублировать базовую директорию при каждом вызове метода render().

Вы можете не использовать этот метод и воспользоваться функцией внедрения зависимостей в action. В этом случае контроллер будет выглядеть следующим образом:

<?php  declare(strict_types=1);  namespace App\Controller;  use Psr\Http\Message\ResponseInterface; use Yiisoft\Yii\View\ViewRenderer;  final class SiteController {     public function index(ViewRenderer $viewRenderer): ResponseInterface     {         return $viewRenderer->render('site/index');     } }

Пример функционального теста

Рассмотрим пример функционального теста на основе файла tests/Functional/SiteControllerTest.php:

<?php  declare(strict_types=1);  namespace App\Tests\Functional;  use PHPUnit\Framework\TestCase; use Yiisoft\Yii\Testing\FunctionalTester;  final class SiteControllerTest extends TestCase {     private ?FunctionalTester $tester;      protected function setUp(): void     {         $this->tester = new FunctionalTester();     }      public function testGetIndex()     {         $method = 'GET';         $url = '/';          $this->tester->bootstrapApplication('web', dirname(__DIR__, 2));         $response = $this->tester->doRequest($method, $url);          $this->assertStringContainsString(             'Don\'t forget to check the guide',             $response->getContent()         );     } }

В данной реализации используется пакет yiisoft/yii-testing.

Данный пакет предоставляет тестовый раннер приложения с возможностью подставлять моки сервисов непосредственно в контейнер зависимостей.

В примере выше приложение инициализируется строчкой $this->tester->bootstrapApplication('web', dirname(__DIR__, 2)); . web указывает на окружение определений контейнера. Помните *-web и *-console файлы и директории? Это оно.

Далее в тесте происходит вызов маршрута GET / строчкой $response = $this->tester->doRequest($method, $url). В переменной $response будет объект класса \Yiisoft\Yii\Testing\ResponseAccessor . Этот объект создан для упрощения работы с объектом ответа сервера. В дальнейшем этот класс будет расширяться дополнительными удобными методами для работа с объектом ответа, но и сейчас вы можете выполнить все необходимые проверки.

Для того, чтобы подставить сервис-заглушку в ваше приложение, вы можете вызвать метод mockService$this->tester->mockService($className, $definition); . Вот реальный пример подстановки сервиса-заглушки. 

О том, какими могут быть $className и $definition вы узнаете в следующей статье.

Инструменты для разработки

В шаблонах мы предустанавливаем вспомогательные для разработки инструменты.

Такие инструменты, как Psalm, Codeception, Infection, PHPUnit и PHPUnit-watcher добавлены в каждый из шаблонов.

Наличие сразу и Codeception, и PHPUnit обусловлено тем, что Codeception не ограничивает в написании юнит тестов напрямую при помощи PHPUnit.


Несмотря на то, что мы стараемся придерживаться OCP в разработке, мы открыты к изменениям. Если вы считаете, что шаблон приложения будет удобнее с вашими идеями, то создайте Issue, и мы постараемся воплотить их в коде. Это относится как и к шаблонам, так и к вспомогательным инструментам, и к фреймворку в целом.

Полезные ссылки


ссылка на оригинал статьи https://habr.com/ru/post/697676/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *