В прошлой статье была описана теория CMG (Content Management Generator). Основная идея — генерация кода сайта на основе настроек заданных кодом. Т.е. фактически кэширование всех настроек в коде при генерации, а не при развертывании на хостинге.


В данной статье описан процесс установки и генерации тестового сайта. Итоговый сайт и код примера прилагается. Также сайт содержит страницу с технической информаций (картинка именно оттуда).



Установка


Для запуска достаточно наличие скрипта s-cmg-generate.php. Скрипт имеет следующий набор параметров:


  php s-cmg-generate.php -param1=value -param2=value ...

  • packageSite — пакет сайта (обязательный параметр);
  • classSite — класс настроек сайта (обязательный параметр);
  • pathSite — директория для сгенерированного кода (обязательный параметр);
  • mode — режим работы (если не указан, то = dev):
    • prod — создать дистрибутив для развертывания на хостинге;
    • test — сборка для тестирования;
    • dev — сборка для разработки.
  • env — файл с параметрами окружения;
  • repositories — директория с локальными пакетами (можно указывать несколько раз).

Запуск


Для запуска необходимо указать обязательные параметры: packageSite, classSite и pathSite. В результате скрипт через composer установит указанный пакет packageSite, создаст объект класса classSite и сгенерирует в указанной директории pathSite/<режим работы> код для указанного режима. Для режима prod будет создана папка dist с файлами install.php и install.zip. Для разворачивания на хостинге необходимо эти файлы закачать на хостинг в нужную папку и запустить скрипт install.php. Дальше скрипт всё сам развернёт. Если на хостинге была установлена более ранняя версия, то она будет удалена и установится новая версия. ВАЖНО: удалены будут только файлы и директории, которые были сгенерированы, все другие файлы останутся в неизменном виде.


Локальные пакеты


При разработке удобно использовать локальные пакеты. Однако, так как код генерируется, то разработчик не имеет возможности устанавливать дополнительные локальные пакеты в сгенерированный код. Именно для этого существует параметр repositories для указания локальных пакетов. Достаточно в указанной папке разместить свой пакет и он будет автоматически добавлен в сгенерированный код. В режиме разработки код будет добавлен через ссылку, что позволяет изменять пакет и тут же проверять результат. В режиме продуктива локальные пакеты добавляются в файл install.zip для дальнейшего разворачивания. В режиме test пакеты также упаковываются в файлы, как для режима prod, но при этом не создаётся дистрибутив. Т.е. данный режим служит для тестирования, но непригоден для разработки.


Параметры окружения


Полезно указывать разные параметры для разных режимов в отдельном файле .env. Формат аналогичен формату подобного файла в Laravel. Однако его использование отличается. Во-первых доступ к параметрам осуществляется через функцию s_env. Во-вторых (ВАЖНО!) значения доступны только во время генерации. Т.е. при вызове функции на сгенерированном сайте вы не сможете получить значения.


Пример


Рассмотрим подробно пример. Для этого скачаем его в любую папку и распакуем. Для запуска можно использовать demo.bat, в этом случае подключается локальная папка с пакетами composer-local-repositories и пример создаётся в текущей папке в директории @s-demo.


Файлы настроек .env.prod, .env.test, .env.dev служат для установки глобальных параметров. А именно:


  • domain — Домен генерируемого сайта.
  • serverPath — Директория для привязки сгенерированного www сервера. т.е. тут указывается директория, которая после установки будет ссылаться на созданный нами сайт.

Так как я использую при разработке Open Server, то для режима dev и test устанавливается директория в папке domains Open Server с соответствующим доменом


domain=samoyed-cmg.ru
serverPath=${HOME}/domains/${domain}

HOME — это переменная окружения с корневой папкой Open Server.
domain — это домен из первой строки.


При генерации в режиме prod


domain=samoyed-cmg-demo.shasoft.com
serverPath=./public_html

указываю домен сайта samoyed-cmg-demo.shasoft.com И директорию public_html, которая находится в той же папке (именно её мой хостинг использует в качестве входной точки).


Код класса настроек сайта Shasoft\SDemo\SiteDemo
<?php

namespace Shasoft\SDemo;

use Shasoft\STwig\ServiceGeneratorTwig;
use Shasoft\SDemo\Controller\HomeController;
use Shasoft\SamoyedCMG\Generator\PathGenerator;
use Shasoft\SamoyedCMG\Generator\SiteGenerator;
use Shasoft\SamoyedCMG\Generator\RouteGenerator;
use Shasoft\SamoyedCMG\Generator\DomainGenerator;
use Shasoft\SDemo\Controller\ShowImageController;
use Shasoft\SDemo\Middleware\ModifyHeaderMiddleware;
use Shasoft\SamoyedCMG\Generator\Route\RouteGeneratorLink;
use Shasoft\SamoyedCMG\Generator\Service\ServiceGeneratorPath;
use Shasoft\SamoyedCMG\Generator\Route\RouteGeneratorPhpScript;
use Shasoft\SamoyedCMG\Generator\Route\RouteGeneratorController;

// Пример настройки сайта
class SiteDemo extends SiteGenerator
{
    // Конструктор
    public function __construct()
    {
        parent::__construct();
        // Установить внешнюю директорию www сервера
        $this->setServerPath(s_env('serverPath'));
        // Добавить домен
        $this->addDomain(s_env('domain'), function (DomainGenerator $domain) {
            // Добавить тестовые пути
            $this->addRoutes($domain);
            // Добавить путь для маршрутов с посредником
            $domain->addPath('middleware', 'middleware', function (PathGenerator $path) {
                // Добавить посредник
                $path->addMiddleware(ModifyHeaderMiddleware::class, ['name' => 'SamoyedCMG']);
                // Добавить тестовые пути
                self::addRoutes($path);
            });
            // Добавить маршрут со ссылкой на дистрибутив
            $domain->addRoute(new RouteGeneratorLink(__DIR__ . '/../@assets/samoyed-cmg-demo.zip', true), function (RouteGenerator $route) {
                // Установить маршрут
                $route->setRoute('samoyed-cmg-demo.zip');
                // Установить имя маршрута
                $route->setName('dist');
            });
            // Добавить маршрут с технической информацией
            $domain->addRoute(new RouteGeneratorLink(__DIR__ . '/../@assets/debug'), function (RouteGenerator $route) {
                // Установить маршрут
                $route->setRoute('debug');
                // Установить имя маршрута
                $route->setName('debug');
            });
        });
    }
    // Добавить тестовые пути
    static private function addRoutes(PathGenerator $path)
    {
        //-- Добавить маршрут на основе КОНТРОЛЛЕРА
        $path->addRoute(new RouteGeneratorController(HomeController::class), self::getFunctionConfigRoute());
        //-- Маршруты на основе ССЫЛКИ
        $path->addPath('link', 'link', function (PathGenerator $path) {
            // Маршрут на основе ссылки на файл
            $path->addPath('file.ico', 'file', function (PathGenerator $path) {
                $path->addRoute(new RouteGeneratorLink(__DIR__ . '/../@assets/favicon.ico'));
            });
            // Маршрут на основе ссылки на директорию
            $path->addPath('folder', 'folder', function (PathGenerator $path) {
                $path->addRoute(new RouteGeneratorLink(__DIR__ . '/../@assets/images'));
            });
        });
        //-- Маршруты на основе ССЫЛКИ
        $path->addPath('phpScript.php', 'script', function (PathGenerator $path) {
            //-- Добавить маршрут на основе PHP скрипта
            $path->addRoute(new RouteGeneratorPhpScript(__DIR__ . '/../@assets/phpScript.php'));
        });
        // Галерея картинок для демонстрации маршрута на основе ссылки на папку + параметры маршрута
        $path->addPath('show-images/$width', 'images', function (PathGenerator $path) {
            //-- Добавить маршрут на основе контролллера с параметрами маршрута
            $path->addRoute(new RouteGeneratorController(ShowImageController::class), self::getFunctionConfigRoute());
        });
    }
    // Добавить параметры маршрута
    static private function getFunctionConfigRoute(): \Closure
    {
        return function (RouteGenerator $route) {
            $route
                //-- Добавить генератор сервиса работы с путями
                ->addGenerator(new ServiceGeneratorPath('demo'))
                //-- Добавить генератор сервиса работы с шаблонами
                ->addGenerator(new ServiceGeneratorTwig())
                //-- Добавить шаблоны
                ->tune(function (ServiceGeneratorTwig $twig) {
                    // Добавить пространство имён main И папку с шаблонами
                    $twig->addNamespace('main', __DIR__ . '/../@twig');
                });
        };
    }
}

Данный код содержит маршруты всех поддерживаемых (на текущий момент) классов:


  • Ссылка на файл (класс Shasoft\SamoyedCMG\Generator\Route\RouteGeneratorLink)
  • Ссылка на директорию (класс Shasoft\SamoyedCMG\Generator\Route\RouteGeneratorLink)
  • Контроллер (класс Shasoft\SamoyedCMG\Generator\Route\RouteGeneratorController)
  • PHP скрипт (класс Shasoft\SamoyedCMG\Generator\Route\RouteGeneratorPhpScript)

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


Все эти маршруты вызываются как напрямую, так и через посредник Shasoft\SDemo\Middleware\ModifyHeaderMiddleware, который добавляет в список заголовков ответа сервера заголовок с именем, указанным в параметрах (SamoyedCMG) и значением ModifyHeaderMiddleware.


Для каждого маршрута указано имя маршрута, поэтому можно получить ссылку по имени через сгенерированный класс UrlBuilder.


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


  • Список генераторов (те что генерируют код) + параметры которые были переданы в эти классы. В примере используется два генератора: Shasoft\SamoyedCMG\Generator\Service\ServiceGeneratorPath и Shasoft\STwig\Twig
  • Информация о маршруте (класс + параметры класса) (только для узлов маршрутов).
  • Данные файла .htaccess (только для узлов маршрутов).
  • Список сгенерированных скриптов. В частности тут можно поглядеть файл который вызывается из .htaccess — это файл класса Shasoft\SamoyedCMG\AppRoute + файл для генерации содержимого страницы для указанного класса маршрута — файл Shasoft\SamoyedCMG\AppRouteOnRequest.
  • Список сервисов. Если сервис является сгенерированным то имеется ссылка на сгенерированный скрипт. Если ссылки нет — значит данный класс не является результатом кодогенерации.
  • Список посредников.

Если информация для узла отсутствует, то соответствующая вкладка не выводится.


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


Страница с технической информацией генерируется и сохраняется в директории debug соответствующего режима. Доступна для просмотра в локальном режиме. Для этого необходимо открыть в браузере файл debug/index.html.

Комментарии (0)