Yii2-advanced: альтернативное размещение папок для нескольких приложений

в 13:29, , рубрики: php, yii, yii2 advanced, yii2 multi-application, метки: ,

Хочу поделиться альтернативным рецептом файловой структуры для нескольких приложений в Yii2-advanced, не прибегая к модулям. Внешние отличия, к которым мы придем, выглядят следующим образом:

Конечная файловая архитектура

Вступление

Я видел на Хабре статью, как разные окружения превратить в модули и сложить их аккуратно внутри проекта. Мне кажется идея, которую мне показал коллега — намного круче и удобнее!

  • Идея такова, что мы не пишем в коде /site/site/index: мы пишем /site/index!
  • Мы не мучаемся с настройкой виртуальных хостов, сим-линков и реврайтов: мы все кидаем в один и тот же файл!
  • Мы можем иметь на бюджетном хостинге (теоретически) любое количество доменов, оплатив опцию «1 сайт»!

Разве это не круто?!

PS: Да, и кстати, к радости начинающих: вы можете решить проблему «как сделать общий upload для front&back».
PPS: Я рассчитываю, что вы уже установили и опробовали YII2 Advanced, и понимаете, зачем вам именно этот вариант.

Интересно? Тогда — вперед! Для примера беру последнюю, на текущий момент версию: 2.0.10.

Переходим к рефакторингу: первые шаги

  1. Если вы в предвкушении революции на работающем проекте, срочно жмем в папке своего проекта «tar -cf saveAndProtect.tar ./» Или выражаясь проще: предохраняемся, путем бекапа последней работающей версии. У меня чистая версия всего с одной вьюхой.
  2. Как видели на скриншоте выше: нужные нам приложения (applications) складываем в папку apps в корне проекта (да, ее нужно создать самому).
  3. В корне создаем папку web и перекидываем в нее содержимое своего фронт-энда (frontend). В папке backend удаляем папку web: теперь она общая. Лично мы тут храним лишь статику из картинок и шрифтов. Стили и JS так часто меняются, что лучше пользоваться ассетами (assets).
  4. Теперь перенастройте свои домены на новую папку web, в корне проекта, и приступаем к более сложным манипуляциям.

Шаг второй: немного доработать напильником (с)

  1. Правим первые три инклуда (include) в index.php, где подключается autoload, Yii и common/ bootstrap: просто убрать один уровень соответственно. Последний инклуд мы подключить пока не можем, т.к. это уже bootstrap, который относится к конкретному приложению из папки apps.
  2. Различать приложения, для старта будем банально: $_SERVER['HTTP_HOST']. Пишем switch-case и заменяем этим кодом последний инклуд и на этом с index.php мы закончили. Должно получится так:
    // определяем запрошенный APP
    switch ($_SERVER['HTTP_HOST']) {
    	case 'frontend.dev':
    	case 'site.ru':
    		define('YII_APP', 'frontend');
    		break;
    	case 'backend.dev':
    	case 'admin.site.ru':
    		define('YII_APP', 'backend');
    		break;
    	default:
    		// лично у меня тут 301й редирект на главную
    		exit("domain not defined");
    }
    
    // определяем папку приложения и подключаем его конфиг
    define('YII_APP_DIR', Yii::getAlias('@apps') . '/' . YII_APP);
    require(YII_APP_DIR . '/config/bootstrap.php');
    

  3. Могли обратить внимание, что добавился новый алиас(alias) @apps: это как раз наша новая папка. А константа YII_APP — конкретное приложение-папка, что необходимо подключить. Все прозрачно! Выглядит — ну да, соглашусь: может слегка «топористо». Но именно то, что нужно для быстрого старта.
  4. В мерже (merge) конфига у нас остались старые пути. В одном случае понижаем инклуд на уровень, во втором — используем нашу новую константу:
    $config = yiihelpersArrayHelper::merge(
    	require(__DIR__ . '/../common/config/main.php'),
    	require(__DIR__ . '/../common/config/main-local.php'),
    	require(YII_APP_DIR . '/config/main.php'),
    	require(YII_APP_DIR . '/config/main-local.php')
    );
    

  5. Теперь пора определить алиас @apps и поправить наши имеющиеся. Это правится в третьем подключаемом файле: commonconfigbootstrap.php

    Добавляем алиас: Yii::setAlias('@apps', dirname(dirname(__DIR__)). '/apps');
    Наши приложения правим по принципу: Yii::setAlias('@console', Yii::getAlias('@apps'). '/console');.

  6. И последнее: осталось настроить нашу console. Вы можете это сделать сами, из спортивного интереса. А можете открыть спойлер и получить готовое решение:
    Настройка консольной части Yii2

    ./yii.php

    #!/usr/bin/env php
    <?php
    
    defined('YII_DEBUG') or define('YII_DEBUG', true);
    defined('YII_ENV') or define('YII_ENV', 'dev');
    define('YII_APP', 'console');
    
    require(__DIR__ . '/vendor/autoload.php');
    require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
    require(__DIR__ . '/common/config/bootstrap.php');
    require(__DIR__ . '/apps/console/config/bootstrap.php');
    
    $config = yiihelpersArrayHelper::merge(
        require(__DIR__ . '/common/config/main.php'),
        require(__DIR__ . '/common/config/main-local.php'),
        require(__DIR__ . '/apps/console/config/main.php'),
        require(__DIR__ . '/apps/console/config/main-local.php')
    );
    
    $application = new yiiconsoleApplication($config);
    $exitCode = $application->run();
    exit($exitCode);
    

    appsconsoleconfigmain.php правим участок с merge

    $params = array_merge(
        require(__DIR__ . '/../../../common/config/params.php'),
        require(__DIR__ . '/../../../common/config/params-local.php'),
        require(__DIR__ . '/params.php'),
        require(__DIR__ . '/params-local.php')
    );
    

Все!

Работающий сайт после смены архитектуры
Работающая консоль после смены архитектуры

Резюме

Довольно простыми манипуляциями для человека немного поработавшего с YII2 мы получили структурированный по приложениям проект, который откликается на любое количество доменов и удобен на бюджетных хостингах, когда у нас есть лишь 1 каталог. Либо манипуляции с каталогами и сим-линками вызывает определенные проблемы.

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

В: У меня, на шаге Х просто белый экран!
О: Вы допустили опечатку до инициализации Yii. Временно добавьте в самое начало index.php строку: ini_set(«display_errors»,«1»); ini_set(«error_reporting», E_ALL);

В: Скомпиленные Ассеты могут смешаться?
О: Вряд ли. Почти за год работы проекта не отмечено ни одного случая

В: Robots и favico не для каждого домена, а смешаны в кучу?
О: Всегда можно разрулить реврайтами апача по RewriteCond %{HTTP_HOST}

В: А как можно получить ссылку из другого приложения? На примере «модулей», это было бы элементарно.
О: Создайте дополнительную компоненту и Yii::$app->urlManagerFrontend->createUrl(...);

Автор: lgXenos

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js