Некоторый функеционал не доработан, в следствии чего могут отсутствовать некоторые функции
Это ядро для сайта, которое привнесет немного структуры в ваш сайт, а также поможет проще управлять функционалом сайта. Данная версия была написана на php 8.3
Для начала убедитесь, что корень вашего сайта не является публичной директорией (сервер не должен иметь возможность запускать файлы ядра напрямую). Также убедитесь, что у php есть привелегии на создании файлов в корне сайта. Это потребуется позже, при генерации конфигурации.
- Создайте директорию для ядра сайта (назвать можете как угодно, например
core
). - Сделайте
git clone
в созданную директорию. - В корне сайта создайте файл
loader.php
с следующим содержимым
<?php
if (!defined("CORE")) {
define("ROOT",__DIR__);
define("ROOT_CORE","core");
define("PUBLIC_DIR","public_html");
require_once(ROOT."/".ROOT_CORE."/core.php");
}
В ROOT_CORE
необходимо поместить путь к файлам ядра (пути указываются относительно ROOT
). В данном случае core
В PUBLIC_DIR
укажите публичную директорию, в которой nginx (или любой другой php сервер) будет искать файлы сайта.
ОБРАТИТЕ ВНИМАНИЕ! Вы можете указать ".", однако тогда вам необходимо скрыть файлы ядра (а также при необходимости другие файлы, которые не должны быть доступны пользователю) от доступа из сервера. Это необходимо для того, чтобы потенциальный злоумышленник не смог вызвать нежелательные php файлы или получить информацию, которая не должна быть доступна, неавторизованным пользователям.
Также существуют дополнительные константы:
MODULES
- Путь к директории с модулямиCONFIGS
- Путь к директории с конфигурацией сайта
- В корне сайта дополнительно создайте файлы
console.php
иcron.php
в них должен быть импортloader.php
, а также одноименных файлов внутри ядра. Это необходимо, так как вloader.php
мы задали конфигурационные константы, которые необходимо инициализировать, при каждом вызове ядра.
Когда вы выполнили установку и попытаетесь вызвать console.php
, вы обнаружите, что вам недоступна ни одна команда.
Перед вызовом все команды должны быть предварительно зарегистрированы в ядре. Но так как нам она не доступна, нам необходимо выполнить файл install_min.php
. Все что он делает - это регистрирует команду php ./console command add
, которая отвечает за регистрацию других команд.
Используя эту команду вы можете добавить оставшиеся команды ядра или добавить собственные команды.
Как было описано ранее - файлы ядра не должны вызываться напрямую.
Вызов ядра должен происходить из php файлов, которые находятся в публичной директории.
Для использования ядра вам достаточно импортировать файл loader.php
, который был создан ранее.
Далее вам необходимо вызвать сервис, который выполнит, необходимую для вас задачу, при помощи метода \SCC\service($service_name)
.
Об устройстве сервисов будет описано позднее.
Необязательно создавать php файл для каждого url.
Динамеческого url можно достичь, используя функционал переадресации.
Для этого вам достаточно создать файл в публичной директории, например назовем его rewrite.php
.
Поместите в него следующее содержимое:
<?php
require(__DIR__."/../loader.php"); // Тут должен быть путь к файлу loader.php
require(ROOT."/".ROOT_CORE."/reroute.php");
Далее перенаправляем 404-ую ошибку на данный файл. В nginx это можно сделать следующим образом:
error_page 404 =200 /rewrite.php;
Подробнее о системе переадресации будет расказано позднее.
Данное ядро поддерживает простейшую систему, команд.
Как уже было упомянуто выше - по умолчанию ядро не знает о всех командах по умолчанию.
Для этого их необходимо предварительно зарегистрировать, при помощи команды command add.
После чего вы сможете добавить оставшиеся команды ядра или же добавить собственные.
Команды ядра находятся в директории Console
Вы можете написать союственную команду. Как пример - посмотрите реализацию команд ядра.
Для того, чтобы узкать как добавлять команды внутри кода - посмотрите в файл install_min.php
Сервисы это интерфейс, который служит прослойкой между сложной логикой и более примитивными вызовами из файлов входа (те, что вызываются сервером напрямую).
Сервисы предоставляются модулями (или ядром) и также должны быть предварительно зарегистрированы.
Посмотрите реализацию команды Service/AddCommand
, которая отвечает за регистрацию сервиса в ядре.
Также сервис может быть автоматически зарегистрирован при установке модуля (будет объяснено в разделе о модулях).
Для вызова события из кода используется команда ядра \SCC\service($service_name)
.
Где $service_name
это имя сервиса.
Данное ядро поддерживает событийность. Это означает что в ядре можно зарегистрировать событие. На это событие может подписаться неограниченное количество слушателей. Затем, когда будет вызвано событие - будут вызваны все слушатели события.
Для регистрации события можно использовать команду ядра Event/AddCommand
.
Для регистрации слушателя существует команда Event/AddListenerCommand
.
Для получения экземпляра события в ядре предусмотрена команда \SCC\event($event_name)
Где $event_name
это псевданим, на который было зарегистрировано событие.
Далее у этого события вы можете вызвать слушатели, при помощи метода call(): void
Или же вызвать только самый первый слушатель callFirst(): void
, проигнорировав остальные.
Также вы можете узнать существуют ли слушатели, подписаные на это событие (hasListeners(): bool
).
Вы также можете получить список всех слушателей события (getListeners(): array
) и вызывать слушателей в ручную используя у них методы validate():bool
(для валидации слушателя) и run(): void
для его вызова. А также error(): void
, который отвечает за обработку ошибок.
Для создания собственного слушателя на событие, посмотрите реализацию слушателей встроенных в фдро (директория EventListeners
).
Также вы можете создать собственный класс слушателя и при регистрации указать его.
Тогда функция \SCC\event($event_name)
будет возвращать экземпляр вашего класса. Однако все классы события должна быть унаследованы от класса \SCC\Event
Как уже было упомянуто выше точкой входа в php являются файлы php, лежащие в публичной директории.
Которые далее вызывают сервисы или события.
Однако, если мы имеем динамичный url, то такая реализация точек входа нам неподходит.
Для этого мы перенаправляем 404-ую ошибку, на файл reroute.php
(не забудьте, что нам необходимо ипортировать файл loader.php
для инициализации констант).
Данный файл автоматически вызовет событие reroute
.
Вы можете зарегистрировать собственный слушатель на событие и написать необходимую вам логику переадресации.
Или же использовать стандартную систему переадресации (смотрите файл EventListeners/RerouteEventListener
).
В данный момент не реализовано нормального функционала для создания роутов
Для упрощенного создания роутов вы можете использовать \SCC\RouteConfigurator
или создавать их в ручную при помощи \SCC\state
(Система конфигурации state будет объяснена позже)
Для упрощения работы с путями к файлам - в ядро была добавлена функция (\SCC\url_inner(string $url): string
) преобразующая "внутренний" путь в реальный путь до файла.
Это может потребоваться для того, чтобы вы из кода указывали путь к файлу модуля, не зная где реально находится сам модуль.
Для указания откуда будет указываться URL - необходимо указать контекст в схему пути. Есть 3 статических контекста:
core
- Путь будет начинаться от директории ядраcache
- Если задана константа CACHE, то путь будет считать от нее. Иначе путь будет от директорииcache
в корне.public
- Путь будет начинаться с публичной директории сайта
Если контекст не совпадает со статическим, то ядро попытается сопоставить название контекста с названием модуля и путь начнется от директории найденого модуля. Если модуль не был найден - будет вызван Exception.
Например путь к файлу слушателя retoure будет таким: core:/EventListeners/RerouteEventListener.php
.
А теперь представим, что у нас есть модуль auth
и вы хотите получить в нем файл script.js
.
Тогда путь будет выглядеть так: auth:/script.js
Иногда нам необходимо получить не просто файл, а целый класс. Для этого также существует отдельнная функция \SCC\url_inner_class(string $url): array
.
Она вернет массив, в котором будет два значения path
и class
.
path
- будет содержать реальный путь к файлу.
class
- будет содержать сгенерированное название класса (генерируется исходя из пути к файлу)
По задумке структуры ядра - вся сложная логика должна выполняться в модулях. Также модули должны предоставлять сервисы, которые уже после будут вызываться в файлах точек входа.
По умолчанию ядро не знает о том какие модули у вас существуют в файловой системе.
Модули необходимо предварительно зарегистрировать в ядре.
Для этого может помочь команда Module/InstallCommand
.
В каждом модуле должен присутствовать файл module.json
, который указывает некоторые константы и конфигурацию модуля.
Пример файла:
{
"version": "0.0.1",
"core": "^5",
"depends": [
"MySqli:~3.0.5"
]
}
version
- указывает на версию данного модуля
core
- Указывает на то, с какими версиями совместим модуль
depends
- Указываются зависимости модуля. Через двоеточие можно указывать шаблон версии модуля, для сранвивания.
Проверка версий осуществляется по следующему шаблону:
Условия разделяются пробелами
Каждая версия состоит из цифр, разделенных точкой. Количество цифр не ограничено
Каждая может быть разлелена на ветки. Напрмер stable, dev и д.р.
Ветки указываются после тире и рекомендуемая версия должна четко соответствовать.
Если не указано - идет проверка с веткой stable
Первым символом можно указать специальные знаки, которые зададут условие сравнивания
В числах может быть использован символ \*, который будет означать любую цифру.
Если в рекомендуемой версии меньше цифр, чем в реальной - лишние цифры проверены не будут, а версии считаются равными
~ Все цифры, кроме последней должны четко соответствовать.
Последняя цифра проверяется по условию "Больше либо равно"
^ Первая цифра должна строго соответствовать.
Остальные цифры сравниваются по условию "Больше либо равно"
> Все цифры сравниваются, по условию больше либо равно
< Все цифры сравниваются по условию меньше, либо равно
При установке модуля - автоматически регистрируются события, слушатели на события и сервисы. Для этого необходимо поместить их классы в соответствующую директорию в модуле и пометить соответствующей аннотацией
- Событие в директорию
Events
и пометить\SCC\EventInfo
- Слушатель на событие в директорию
EventListeners
и пометить\SCC\EventListenerInfo
- Сервис в директорию
Services
и пометить\SCC\ServiceInfo
Модуль может выполнять произвольный код при КАЖДОМ вызове ядра.
Для этого создайте файл autoload.php
в корне модуля.
Также модуль может иметь собственный сценарий установки.
Для его создания поместите сценарий в файл install.php
в корне модуля.
Удаление модулей в данный момент не реализовано
Информацию о модуле можно вызвать в любой момент, используя функцию \SCC\module(string $module_name): \SCC\Module
При создания сайта любой сложности очень часто возникает необходимость сохранить какую-либо информацию, а позже ее загрузить.
Для упрощения работы с сохранением/загрузкой, а также управлением этой информации существует класс \SCC\State
.
А также класс \SCC\state($alias)
, который быстро вызывает экземпляр state.
Где $alias
это псевданим State. State можегут быть вложенными, тогда необходимо указать путь используя /
state хранит массив данных и записывает их в файл, используя сериализацию php.
Для доступа к данным импользуется метод get
. Вы можете указывать сразу полный путь к нужному уровню в массиве, используя .
Вы можете получить полный массив, вызвав метод asArray
.
Также вы можете быстро создавать наследников конфигураций используя метод createChild(string $name): \SCC\State
.
Наследник означает то, что создастся директория с именем текущего state и дочерний элемент будет помещен внутрь.
Очень часто на сайте требуется проверить доступно ли какое-либо действие в данный момент. Например может ли пользователь оставлять комментарии.
Для универсализации и упрощения системы привилегий существует функция \SCC\isAllowed(string|array $action, bool $default = false): bool
Данная функция вызывает событие is_allowed
(класс события должен быть наследником от \SCC\AllowedEvent
).
Для реализации проверки привилегий вам необходимо зарегистрировать класс \SCC\AllowedEvent
(или его наследника) на событие is_allowed
.
А также подписать слушателя на это событие.
Теперь для проверки разрешения на действие, вам достаточно будет вызвать функцию \SCC\isAllowed
и проверить bool
значение, которое она вернет.
После конца обработки КАЖДОГО запроса будет вызвано событие shutdown
Вы можете его использовать, если вам необходимо выполнить какие-либо действия, после окончания обработки запроса.
Вы можете зарегестрировать файл cron.php
для регулярного вызова операционной системой (например через одноименный cron).
cron.php
будет вызывать событие bgwork
.
Подписав слушателей на это событие вы можете выполнять определенную работу в фоне.
Также вы можете подписать слушатель EventListteners/BgWorkEventListener
на событие shutdown
, для того, чтобы раз в определенное количество времени вызывалось событие bgwork
.
P.S. Это будет выполняться за счет запросов пользователей и неизвестно когда пользователь зайдет на сайт и вызовет следующую обработку события.
см. файл для подробной информации о временном лимите вызова события bgwork