Одна точка входа для Andvanced приложения Yii2

В этой статье мы рассмотрим то, как сделать одну точку входа для andvanced приложения средствами PHP и фреймворка.

Автор . Дата: 03.01.2018

Andvanced приложение - это более функциональный шаблон приложение Yii2 чем basic. В нем есть несколько application а так же генератор окружений. Это удобно для больших проектов, например интернет магазинов. Обычно application frontend используют для публичной части сайта, а backend для админпанели. Командой Yii Framework сделано так, что точки входа для каждого приложения находятся отдельно, и их обычно монтируют на разные домены на стороне nginx. Например frontend монтируют на http://siteexample.ru а backend на http://admin.siteexample.ru. У этого подхода есть свое право на существование, но обычно люди задаются желанием разместить backend в том же домене, например вот так: http://siteexample.ru/admin. В интернете есть информация как это сделать настройками веб сервера, но на мой взгляд это не очень удобно, т.к. помимо боевого сервера, вам так же придется мудрить с настройками окружения. А если вы хотите использовать, например Laravel Homestead, то вас ждет много боли. В этой статье мы рассмотрим как это сделать на стороне сайта.

Для начала подготовим файлы зависящие от окружения. По умолчанию в backend и frontend есть свои папки web, и в них папки assets. Будем использовать только одну папку. Поэтому создаем в корне проекта папку web, в ней папку assets, а так же добавляем .gitignore файлы как в оригинальных папках.

В папке environments хранятся файлы зависящие от окружения. Обычно там папки dev и prod. В моем случае есть ещё папка test, она используется во время запуска тестов через Jenkins или Bitbucket Pipelines. Вам нужно сначала отредактировать index.php в корне папки environments, на наши изменения которые мы произвели в структуре проекта. У меня это выглядит вот так:

<?php

return [
    'Development' => [
        'path' => 'dev',
        'setWritable' => [
            'backend/runtime',
            'frontend/runtime',
            'web/assets',
        ],
        'setExecutable' => [
            'yii',
            'yii_test',
        ],
        'setCookieValidationKey' => [
            'backend/config/main-local.php',
            'frontend/config/main-local.php',
        ],
    ],
    'Production' => [
        'path' => 'prod',
        'setWritable' => [
            'backend/runtime',
            'frontend/runtime',
            'web/assets',
        ],
        'setExecutable' => [
            'yii',
        ],
        'setCookieValidationKey' => [
            'backend/config/main-local.php',
            'frontend/config/main-local.php',
        ],
    ],
];

Т.е. вместо 2х папок backend/web/assets и frontend/web/assets оставляем одну web/assets в секции setWritable. Теперь переходим к самому интересному. Открываем папку dev. В ней старая структура, т.е. есть папки backend/web и frontend/web. Удаляем их. В корне создаем папку web. В ней создаем index.php со следующим содержимым:

<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');

require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../common/config/bootstrap.php');

if (($pos = strpos($_SERVER['REQUEST_URI'], 'admin')) === 1) {
    require(__DIR__ . '/../backend/config/bootstrap.php');

    $config = yii\helpers\ArrayHelper::merge(
        require(__DIR__ . '/../common/config/main.php'),
        require(__DIR__ . '/../common/config/main-local.php'),
        require(__DIR__ . '/../backend/config/main.php'),
        require(__DIR__ . '/../backend/config/main-local.php')
    );
} else {
    require(__DIR__ . '/../frontend/config/bootstrap.php');

    $config = yii\helpers\ArrayHelper::merge(
        require(__DIR__ . '/../common/config/main.php'),
        require(__DIR__ . '/../common/config/main-local.php'),
        require(__DIR__ . '/../frontend/config/main.php'),
        require(__DIR__ . '/../frontend/config/main-local.php')
    );
}

(new yii\web\Application($config))->run();

Что же у нас тут произошло? Во первых мы поправили пути в require функциях, потому что сейчас точка входа находится на другом уровне вложенности, и старые пути не работали б. Во вторых, у нас есть условие, где мы проверяем $_SERVER['REQUEST_URI'] на наличии слова admin в начале. Если такое слово было найдено, то мы в переменную $config загружаем все конфиги из папки backend. Если же нет, то загружаем конфиги из папки frontend. Ну и конечно же из папки common, там грузится одинакого в обоих случаях. В самом конце мы создаем web приложение на основе загруженных настроек и запускаем его. Изменить index-test.php по примеру будет вашим домашним заданием :-) Так же вам нужно произвести соотвествующие изменения в папке prod. Это тоже сделайте сами по примеру.

Изначально, когда я это делал в первый раз, я думал, что этого должно хватить. Но нет, нужно внести её небольшие изменения в файлы настроек. В backend/config/main.php вам нужно найти в секции components настройки компонента assetManager. Если настроек этого компонента у вас в конфиге нет, то необходимо добавить. В настройках этого компонента необходимо указать baseUrl для папки с asset'ами, которая сейчас находится у нас в корне:

        'assetManager' => [
            'baseUrl' => '/assets/',
        ],

Так же ищем настройки компонента request. Там так же необходимо указать baseUrl, но на этот раз для папки admin, т.к. Yii думает, что наше приложение лежит в корне:

        'request' => [
            'csrfParam' => '_csrf-backend',
            'baseUrl' => '/admin',
        ],

Вот в принципе и все, теперь вы можете настроить свой web сервер как для basic приложения. После выполнения команды php init.php у вас все должно работать. Если появятся какие-то вопросы: спрашивайте в коментариях. Так же выкладываю ссылку на свой проект, где эти изменения уже сделаны, и вы можете подсмотреть некотороые моменты: https://github.com/webdragons/bulldozer_app