Парсинг php-файла для создания опций
В последнюю версию Albireo CMS добавил возможность работать с php-файлом конфигурации через обычную форму. Это сильно упрощает администрирование сайта.
В системе для хранения опций используются разные конфигурационные php-файлы. Это совершенно стандартный подход, когда файл возвращает массив по return
. Что-то вроде такого:
return [ 'siteTitle' => 'Создание своего сайта - MAXSITE.ORG', 'siteDescription' => 'Создание своего сайта', 'siteYearCreation' => '2006', 'homeOutputModule' => 'home/home1.php', 'homeTPLfile' => 'one-column-3.php', 'homeLimitPagination1' => 10, 'homeLimitPagination2' => 12, ];
В админ-панели есть специальная страница Config, где собраны все конфиг-файлы сайта. По клику открывается стандартный текстовый редактор, где и можно редактировать файл.
Но мне было интересно решить другую задачу.
Часть config-файлов достаточно простая — в них, как в приведенном примере, нет сложного форматирования: просто 'key' => value
. Фактически это сразу годится для парсинга в форму, где будет ключ массива и input-поле для ввода значения. Таким образом можно взять произвольный конфиг-файл, распарсить его в форму, потом, при сохранении, всё собирается обратно в тот же php-файл.
В чём «фишка»? Мы работаем с нативным php-файлом. Обычно для таких задач используется более удобные форматы данных, тот же JSON или серилизация. То есть данные в файле хранятся особым образом. Но поскольку я принципиально использую только PHP, то всё это не годится. Потому что файл можно править ручками как текст, а можно через админ-панель через парсинг. И важно, чтобы в каждом случае сохранить исходное форматирование, например комментарии.
Провозился я с этим несколько недель, за которые перепробовал самые разные подходы и варианты и в итоге остановился на самом простом, когда поле принимает значение в чистом php-формате.
В админке это выглядит так:

Но в реальности это такой файл (привожу весь код для полноты понимания):
<?php if (!defined('BASE_DIR')) exit('No direct script access allowed'); /** * (c) Albireo CMS, https://maxsite.org/albireo, 2020-2025 */ // default page data return [ // Сжатие html-кода 'compress' => 1, // Включить сбор статистики посещений страницы 'stat' => 1, // Навигация под текстом по страницам type: blog по дате публикации date: дата 'nav' => 1, // Навигация перед текстом по страницам type: blog по дате публикации date: дата 'nav-top' => 1, // Файлы шапки шаблон/modules/* 'headers' => 'headers/header12.php', // Файлы подвала 'footers' => 'footers/footer1.php', // Файл в виде <style> ... </style> в HEAD 'css.layout' => 'fields.css', 'headers.title' => 'Albireo CMS', 'headers.subtitle' => 'The best site', 'headers.subtitle2' => '', 'headers.logo' => UPLOADS_URL . 'images/logo.webp', 'headers.namesite' => 'Albireo CMS', // Разметка Open Graph protocol 'ogp[og:site_name]' => 'Website on Albireo CMS', ]; # end of file
Строчка с //
над значением считается комментарием и выводится в описании поля. При этом можно использовать любые другие комментарии — они просто игнорируются для формы. Алгоритм парсинга достаточно «хитрый» для того, чтобы сохранить все строки файла нетронутыми. Но при этом, если нужно добавить новую опцию, они автоматом будут размещены в конце массива.
Я довольно много времени потратил на то, что пытался «играть» с типами данных. Изначально мне хотелось сделать так, чтобы строки автоматом сами оборачивались кавычками, массивы скобками, числа и bool как есть. В теории это позволило бы исключать кавычки, как это принято в PHP. Я столкнулся с проблемой когда пробовал ввести php-выражение, например 'my' => 1 + 2
. Здесь невозможно привести фрагмент 1 + 2
к числу, который и есть итоговый, но для парсера (любого) это будет строчка '1 + 2'
, что очевидно является ошибкой.
Другой пример: 'debug' => LOCALHOST
. Здесь любой парсер поймёт, что «LOCALHOST» — это строка, и никогда не будет знать, что это константа.
Ещё вариант: 'userLang' => detectUserLang('ru', ['en', 'ru', 'uk'])
. То есть для парсера это всё очень сложные варианты.
В итоге я понял, что проще и надёжней выводить всё как есть в формате PHP: если это строка, то должны быть кавычки, если массив, то скобки и т.п. Конечно, если пользователь ошибётся в редактировании, например не закроет или не укажет кавычку, то это будет php-ошибкой. Но это тоже самое, что и при редактировании всего файла как текст, то есть нет принципиальной разницы.
В Albireo CMS есть два файла, которые можно использовать как опции: config.php
, где хранится основная информация и настройки сайта, и page-data.php
, где хранятся дефолтные настройки (поля) записей. Остальные конфигурации в общем-то редко используются, поэтому их нет смысла править через форму. Но, если пользователю это нужно, то можно добавить любые config-файлы в настройках админ-панели.
Я думаю, что такая возможность достаточно крутая штука. С её помощью можно организовать любые опции сайта в виде нативного php-кода. В других системах ничего подобного нет.