Перейти к содержанию

Как работает Flex

Прежде чем создавать свой первый тип Flex, полезно иметь ясную мысленную модель составных частей и того, как они соединяются. Flex состоит из нескольких небольших понятий, каждое из которых делает одну работу. Как только вы сможете их назвать, схемы, экраны Admin Next и REST API начнут складываться в понятную картину.

Эта страница проходит по каждой части, объясняет, как запрос превращается в загруженные объекты, и показывает три способа регистрации типа Flex в Grav.

Составные части

Flex — это две вещи, работающие вместе: основной фреймворк (Grav\Framework\Flex), который живёт в самом Grav, и плагин Flex Objects, который строит на нём фичи (регистрацию директорий, интерфейс Admin Next, REST API, шорткод [flex-objects], а также маршрутизацию страниц фронтенда и шаблоны). Фреймворк даёт объекты и хранилище; плагин даёт инструменты для управления ими.

Вот понятия, с которыми вы встретитесь, от контейнера до отдельной записи.

Flex

Flex — контейнер и реестр всех директорий сайта.

Это единая точка доступа ко всем вашим данным. После регистрации директории любая страница, плагин и тема могут добраться до её объектов через Flex. Grav поставляется со своими встроенными директориями (например, учётные записи пользователей и страницы), а плагины и темы могут регистрировать свои.

Примечание

Даже если версии Flex для учётных записей пользователей или страниц не включены для редактирования, вы всё равно можете читать их версии Flex и на фронтенде, и в Admin Next.

Тип Flex

Тип Flex — схема для директории.

Он определяет всё необходимое для хранения, отображения и редактирования данных: структуру данных, поля формы, права доступа, слой хранения и файлы шаблонов. Тип описывается одним YAML-файлом схемы. С его разделами (title, description, type, config, blueprints, form) вы познакомитесь на следующих страницах.

Директория Flex

Директория содержит все объекты одного типа.

Если тип — это форма для отливки, то директория — ящик, в котором хранится каждый объект, созданный по этой форме. Каждая директория владеет коллекцией объектов, опираясь на индекс для быстрых запросов и слой хранилища для чтения и записи файлов.

Flex-объект

Flex-объект — отдельная запись, один экземпляр типа.

Объект даёт доступ к своим свойствам и связанным данным, включая медиафайлы, когда хранилище это поддерживает. Объект знает, как отрендерить себя, какую форму использовать при редактировании и как сохранить или удалить себя. Если вы не определяете собственный класс, объекты используют по умолчанию Grav\Common\Flex\Types\Generic\GenericObject.

Коллекция Flex

Коллекция — набор объектов, к которому можно делать запросы.

Коллекция обычно содержит только объекты, нужные для текущей страницы или действия, а не всю директорию. Она даёт инструменты для фильтрации, сортировки, поиска, постраничного вывода и работы с набором, а также методы для рендеринга всей группы сразу. Класс по умолчанию — GenericCollection.

Индекс Flex

Индекс — лёгкий и быстрый поиск по директории.

Он хранит метаданные об объектах (ключи, временные метки, контрольные суммы), но не полные данные объектов. Grav использует индекс, чтобы быстро отвечать на операции списков и запросов, а полные объекты загружает из хранилища только тогда, когда они действительно нужны. Класс по умолчанию — GenericIndex.

Важно

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

Хранилище Flex

Хранилище — слой, который читает и записывает данные объектов на диск.

Flex поставляется с тремя стратегиями, выбираемыми через config.data.storage:

Стратегия Что делает Медиафайлы
SimpleStorage Хранит каждый объект в одном общем файле. Нет медиафайлов для отдельных объектов
FileStorage Один файл на объект, все внутри одной папки. Нет медиафайлов для отдельных объектов
FolderStorage Одна папка на объект. Поддерживает медиафайлы

Хранилище также можно задать короткой однострочной формой (путь потока user-data:// к файлу .json), когда вам нужно простое расположение. Данные читаются и записываются через форматтер (Json, Yaml, Markdown, Serialize, Ini или Csv). Подробно хранилище настраивается на странице Схема.

Форма Flex

Форма создаёт и редактирует объект.

Flex интегрируется с плагином Form, поэтому те же типы полей, что вы используете в других местах Grav, работают и здесь. Тип может определять несколько представлений, позволяя разным формам редактировать разные части объекта. Admin Next использует эти формы для экранов создания и редактирования.

Как части соотносятся

     ┌───────────────────────────────────────────────┐
     │                     Flex                       │
     │            (container / registry)              │
     │                                                │
     │   ┌───────────────┐      ┌───────────────┐     │
     │   │   Directory   │      │   Directory   │  …  │
     │   │  (one Type)   │      │  (one Type)   │     │
     │   └───────┬───────┘      └───────────────┘     │
     └───────────┼───────────────────────────────────┘
                 │
     ┌───────────┴───────────────────────────────┐
     │                                            │
┌────┴─────┐   ┌───────────┐   ┌─────────┐   ┌────┴─────┐
│  Index   │   │Collection │   │  Form   │   │ Storage  │
│(metadata)│   │(a queried │   │(create/ │   │(files on │
│          │   │  set)     │   │  edit)  │   │  disk)   │
└────┬─────┘   └─────┬─────┘   └─────────┘   └────┬─────┘
     │               │                            │
     │          ┌────┴─────┐                      │
     └─────────▶│  Object  │◀─────────────────────┘
                │ (one     │
                │  record) │
                └──────────┘

Читайте сверху вниз: Flex содержит много директорий. Каждая директория — это один тип, она управляет индексом, выдаёт коллекции, редактируется через форму и сохраняется через хранилище. И индекс, и хранилище в конечном счёте ведут к отдельным объектам.

Жизненный цикл объекта

Вы редко работаете с этим механизмом напрямую, но знание порядка событий объясняет, почему Flex ведёт себя именно так.

  1. Запрос. Страница, плагин, шорткод или REST-вызов запрашивает у директории объекты: полный список, отфильтрованную коллекцию или один объект по ключу.
  2. Сначала индекс. Flex отвечает из индекса. Вывод списка, поиск, сортировка и постраничный вывод работают с этими облегчёнными метаданными, поэтому список из тысячи записей никогда не загружает тысячу файлов.
  3. Загрузка из хранилища по требованию. Когда вы действительно читаете данные объекта (или рендерите его), Flex загружает этот объект из хранилища через его форматтер и наполняет им экземпляр объекта.
  4. Кэш. Загруженные объекты и данные индекса кэшируются, поэтому повторное обращение в рамках запроса (и между запросами, в зависимости от настроек кэша) не перечитывает диск. Сохранение или удаление объекта обновляет индекс и сбрасывает соответствующие записи кэша.

Вывод: дешёвые операции (подсчёт, вывод списка, фильтрация) остаются на индексе, а дорогая операция (чтение полных данных объекта) выполняется только когда она нужна.

Где что находится и как тип регистрируется

Тип Flex должен быть зарегистрирован в контейнере Flex, прежде чем Grav узнает о его существовании. Это происходит тремя способами.

1. Схема, которую вы включаете (обычный случай)

Поместите схему в:

user/blueprints/flex-objects/<type>.yaml

Затем активируйте её в Admin Next в разделе Plugins > Flex Objects, в поле directories. Добавление там дописывает путь к схеме в конфигурацию плагина, и плагин Flex Objects регистрирует директорию при следующем запросе. Так появляются большинство типов данных для конкретного сайта (список контактов, каталог товаров, таблица событий). PHP не требуется.

Совет

<type> в имени файла становится ключом директории и появляется в пути REST API (/flex-objects/<type>) и при поиске шаблонов Twig (flex/<type>/...). Держите его в нижнем регистре и неизменным.

2. Плагин или тема, поставляющая схему

Плагин или тема может содержать собственную схему и регистрировать директорию из PHP, слушая событие FlexRegisterEvent. При запуске Flex вызывает это событие, чтобы расширения могли программно добавить свои типы в контейнер. Это правильный подход, когда вы распространяете тип в составе плагина или темы, потому что пользователю не нужно ничего включать вручную. Схема путешествует вместе с расширением, а не лежит в user/blueprints.

3. Встроенные типы ядра

Некоторые типы Grav регистрирует сам. Учётные записи пользователей и страницы — встроенные директории Flex, доступные даже когда их редактируемые версии Flex не включены. Их регистрировать не нужно; они часть фреймворка.

Предупреждение

Регистрация типа — не то же самое, что предоставление доступа к нему. Начиная с Flex Objects 1.4.3 (исправление безопасности GHSA-23vq-365v-qcmh) директория, схема которой не объявляет блок разрешений, закрыта для всех, кроме суперадминистраторов, по REST API. Прочитайте страницу Права доступа, прежде чем открывать тип редакторам.

Что дальше