Почему стоит попробовать Drupal 9

Если вы ищете современную, качественную, производительную и гибкую CMS/CMF, то вам определённо стоит обратить внимание на Drupal.

Материал может оказаться информативным если вы разработчик и:

  • Устали от своей текущей CMS.
  • Уже отлично знаете свою текущую CMS, но ощущаете что потолок слишком низкий или вы его достигли.
  • Желаете узнать больше и прокачать свои навыки.
  • Хотите посмотреть на альтернативы, но не можете их найти.
  • Считаете или вам рассказывают что Drupal старая и тормозная система.

В сети регулярно, то тут, то там, всплывает вопрос: «А как дела у Drupal?», за которым, с огромной вероятностью следует ответ: «Drupal — говно», «Drupal — мёртвая система», «Drupal — мамонт», «Drupal — глючный и тормоз» и т.п. Аргументация там обычно либо вообще отсутствует, либо уровня «потому что».

Я хочу пролить немного света на то, что сейчас на самом деле представляет собой Drupal. Я не буду рассказывать что Drupal лучший и всё в таком духе. Я приведу некоторые его достоинства, возможности и инструменты, которые, как мне кажется, могут вызвать интерес у разработчиков попробовать Drupal. А выводы вы делайте сами.

Высокий порог входа

Drupal кривая изучения

Многие приводят данный факт как недостаток Drupal, я считаю что это огромное преимущество, ведь он работает как естественный фильтр.

Современный стэк технологий требует современных знаний. Современные знания требуют временных затрат и усилий для их освоения и поддержки в актуальном состоянии.

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

В ключевом докладе DrupalCon 2019 Amsterdam, Дрис привёл результаты по опросу, который проводила команда Acquia UX.

Drupal кривая настроений на октябрь 2019

«Новички борются с Drupal, тогда как эксперты любят Drupal.» — Dries

Drupal кривая настроений на октябрь 2019

«Кривая настроений Drupal идёт в противоположном направлении от WordPress, AEM и Sitecore. Это предоставляет как большой вызов, так и возможность для Drupal.» — Dries

С каких пор высокая компетенция и актуальные знания стали недостатком?

Composer

Composer — де-факто стандарт в PHP разработке. Сложно представить современную разработку без него, тем не менее, многие системы до сих пор избегают его, от чего страдают, в первую очередь, сами разработчики.

Drupal начал адаптацию Composer начиная с 8-й версии, и уже сейчас является основным инструментом при разработке проектов. Проекты на Drupal можно целиком и полностью вести через Composer, без костылей и прослоек.

ООП

Релиз Drupal 8 ознаменовал переход на ООП. Для Drupal это глоток свежего воздуха, так как в нём можно практически всё расширять, заменять или изменять, и ООП только помогает в этом.

У нас до сих пор есть легаси API который работает на функциях, но его количество уже не так велико и постепенно остатки переводят на ООП.

Как подобает современным практикам, у нас есть сервисы и Dependency Injection.

Symfony

В Drupal используются компоненты Symfony, и не только, в качестве базы для своих разработок. Подобный подход позволяет Drupal не изобретать колесо и концентрировать свои силы на создании «космического корабля».

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

Маршрутизация и ЧПУ

Для маршрутизации Drupal использует компоненты Symfony и имеет свои собственные надстройки. Это позволяет делать маршрутизацию и ЧПУ любой сложности без каких-либо проблем. Сложная иерархия в пути материалов? Не проблема!

Хотите взять работу ЧПУ под полный контроль? Нужно сделать параметры фильтров частью пути? Пожалуйста, Inbound и Outbound обработчики позволят вам сделать всё что только придёт в голову.

Система рендера

Система рендера в Drupal унифицирует и стандартизует работу со всем что не является PHP кодом в PHP. Следовательно, никакого HTML, CSS, JavaScript прямо в коде у нас нет. Это решается при помощи рендер массивов, которые описывают требования и зависимости (этакий компонентный подход), а уже затем, Drupal это превращает в HTML или что требуется проекту.

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

TWIG (HTML)

Не пугайтесь, HTML и прочее у нас есть. За генерацию HTML разметки из рендер массивов отвечает шаблонизатор Twig.

Таким образом, PHP код выставляет требования и готовит данные, а Twig их превращает в результат. Это также позволяет иметь различные оформления для одих и тех же данных. Хотите сделать версию для слабовидящих которая должна быть сама по себе, или отдельную тему для определенного типа содержимого, пожалуйста — вы можете переключать темы оформления хоть по фазе луны. Все остальные темы даже не узнают что произошёл рендер и не создадут оверхеда.

Twig способствует снижению ошибок, максимально снижает возможность оставить дыры в шаблонах, делает синтаксис более читабельным и акцентирует внимание на разметке, а не коде. Писать бизнес-логику или запросы к БД в шаблонах — это не про Drupal, шаблоны работают с готовыми данными.

Тема оформления отвечает только за визуальную составляющую сайта — простое правило, но не все CMS это ещё усвоили.

CSS и JavaScript

Знакома проблема когда на страницах грузятся CSS и JavaScript какой-нибудь формы, которой даже нет не этой странице? В Drupal таких проблем не существует.

Drupal предоставляет Libraries API который позволяет централизованно объявлять и управлять библиотеками проекта. Библиотека — это именованный набор CSS и/или JS файлов. Библиотеки подключаются к рендер массивам или шаблонам только там где они нужны. Рендер массив или шаблон с библиотекой не использовался на странице? Не будет и библиотек. Таким образом Drupal автоматически понимает, какие файлы нужны на этой странице, а какие не нужны. Всё это работает автоматически.

Библиотеки могут объявлять зависимости на другие библиотеки, так Drupal выстраивает дерево зависимостей и подключает всё что нужно в нужном порядке. Никаких конфликтов что JS подключился раньше библиотеки, которую он использует. Попутно, Drupal может всё это сжать в один бандл.

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

function hook_page_attachments_alter(array &$attachments): void {
  // Conditionally remove an asset.
  if (in_array('core/jquery', $attachments['#attached']['library'])) {
    $index = array_search('core/jquery', $attachments['#attached']['library']);
    unset($attachments['#attached']['library'][$index]);
  }
}

Form API

В Drupal также стандартизована работа с формами. Form API построен поверх рендер массивов и предоставляет инструментарий для создания форм любой сложности.

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

Знакома ситуация когда на сайт можно отправить специально отформатированный POST запрос на любую страницу и система заметит его и обработает, даже если форма отключена? В Drupal таких проблем нет. Формы работают только там, где они выводятся, и больше нигде.

Элементарная задачка, которая может стать проблемой: Добавить всем формам на сайте CSS класс без использования JavaSсript. Это должно работать абсолютно со всеми формами: системными, сторонними, собственными, текущими и будущими. Например, в Drupal это делается в 3 строчки:

function example_form_alter(array &$form, FormStateInterface $form_state): void {
  $form['#attributes']['class'][] = 'hello-world';
}

Производительность

Drupal 9 производительность

ab -c 10 -n 1000, Linux (docker4drupal), Nginx 1.19.0, PHP 7.4.7, MySQL (MariaDB) 10.4, чистые установки (в одной сгенерено 10000 статей), никаких варнишей, редисов, мемкешей и прочего. Результаты:

  • Минимальный профиль. Min: 7ms, Max: 24ms, Avg: 10ms.
  • Демо Umami с контентом на двух языках. Min: 8ms, Max: 35ms, Avg: 14ms.
  • Стандартный профиль. Min: 7ms, Max: 27ms, Avg: 12ms.
  • Стандартный профиль + 10000 материалов (drush devel-generate:content 10000 --bundles=article). Min: 8ms, Max: 34ms, Avg: 15ms.

«Но мне говорили что Drupal тормоз» — сюрприз, сюрприз! При этом, кол-во данных и установленных модулей в Drupal не сильно влияет на его производительность.

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

Обновилась цена у товара? Drupal автоматически инвалидирует те куски кэша, где эта цена, конкретно данного товара использовалась, при этом, это не затронет кэш не связанный с данной ценой.

Хотите чтобы часть кэша хранилась в БД, другая в файлах, третья в оперативке, а четвертая ещё где-то? Не проблема, вы вольны хранить что и где угодно, и переносить стандартные хранилища куда это требуется.

«А что если у меня есть раздел на странице, который нельзя кэшировать, кэш отключится для всей страницы?» — нет! Для этого у нас есть ленивые билдеры — это как lazy load для картинок, только на бэкенде и для PHP. Не устраивает его работа? Пришла в голову более гениальная реализация или определённые элементы надо отдавать несколько иначе? Не проблема, стратегии рендера плейсхолдеров полностью передают процесс под контроль. Drupal может сам определять когда и где необходимо задействовать данное поведение, без вмешательства пользователя или разработчика.

Конечно, всё это отлично взаимодействует с остальными подсистемами, модулями и API, так и получается смесь, которая контролируют всё автоматически, вам лишь остаётся только писать код с использованием API и наслаждаться быстродействием.

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

Система плагинов

Многие решения в Drupal основаны на системе плагинов. Плагин — как правило это класс с аннотацией реализующий конкретный тип плагинов. Но они также могут быть объявлены в YAML файлах и функциях, а если потребуется, можно объявить собственные Discovery объекты и добавить возможность описывать плагины хоть в JSON, хоть в Markdown. Поведение и применение сильно зависит от назначения плагина.

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

Плагины в Drupal играют очень важную роль, на них базируются многие фундаментальные системы и появляются новые API. Далее, они ещё не раз всплывут.

Headless и Decoupled

Drupal — Headless CMS и Decoupled CMS. Маловероятно что вы увидите Drupal в списке подобных CMS. То ли авторы не в курсе, то ли выбирают только хайповые решения. Иронично, но единственная (как указано на их сайте) конференция посвящённая Headless CMS и Decoupled CMS — Decoupled Days, фактически конференция о Drupal.

Фронтед и бэкенд отделены друг от друга, не без помощи системы рендера. Это позволяет использовать Drupal как API-first решение, при желании можно оставить админку со всем функционалом. Например, мобильное приложение для автомобилей Tesla управляется Headless Drupal, а кому-то может приглянётся применение в качестве POS или в качестве бэкенда для weather.com. Drupal уже давно применяется не только для создания сайтов.

Ядро из коробки предоставляет поддержку HAL, JSON:API и при необходимости, вы можете объявлять свои REST ресурсы. Если хотите что-то иное, можете сделать сами, либо взять готовое, например GraphQL.

Вы можете собирать API мышкой в админке, а JSON:API и вовсе zero configuration решение. Вы просто включаете, и всё что есть в системе автоматически начинает отвечать на запросы, и API будет всегда в самом актуальном состоянии.

Drupal умеет отвечать в форматах HTML, JSON, XML, а при желании вы можете добавлять свои форматы.

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

Простенький пример REST ресурса, который отвечает «Hello World» на GET запросы:

<?php

namespace Drupal\example\Plugin\rest\resource;

use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;

/**
 * Provides a resource that returns "Hello World".
 *
 * @RestResource(
 *   id = "hello_world",
 *   label = @Translation("Hello World!"),
 *   uri_paths = {
 *     "canonical" = "/api/hello-world"
 *   }
 * )
 */
final class HelloWorldResource extends ResourceBase {

  /**
   * Responds to GET requests.
   */
  public function get() {
    return new ResourceResponse('Hello World!');
  }

}

Сущности

Entity API — это API позволяющий создавать, расширять и манипулировать сущностями при помощи CRUD операций. Сущность — это доменный объект с хранилищем данных. Это основной API, который используется для хранения и работы со всеми данными в системе. Фактически всё что хранится где-то — это сущности. Например: Содержимое, Пользователи, Файлы, Настройки и т.д. Один объект сущности представляет собой одну единицу данных. Это не ORM!

Сущности могут иметь бандлы (подтипы, варианты). Например, для сущности «Товар» бандлом может быть «Кружка» или «Одежда». Каждый бандл может иметь свои уникальные черты, наборы значений, поведение или требования, но все они имеют общие данные и требования выставляемые непосредственно сущностью. Если базовая сущность описывает значение «Цена», то все бандлы также унаследуют его. В общем, как в ООП.

Drupal предоставляет две базовые реализации сущностей из коробки: Content Entity и Configuration Entity — от них расширяются все сущности в ядре. Первый предназначен для хранения содержимого и хранит всё в БД, второй предназначен для хранения различного рода настроек и конфигураций, и хоть эти данные также хранятся в БД, они также хранятся и в виде YAML файлов. Вы можете описывать совершенно новые реализации сущностей. Но стандартные две покроют 99% задач.

Сущности базируются на системе плагинов. Таким образом, Content Entity и Configuration Entity — это лишь плагины, вы можете создавать свои собственные реализации для будущих сущностей.

Сущности очень гибкие, это достигается при помощи хендлеров. Хендлер — это расширение для сущности. Сущности или сторонние модули могут запрашивать эти хендлеры и влиять на процесс и работу сущностей. Например, поведение мультиязычности или ревизионности для сущности настраивается через хендлеры, а Drupal имеет множество готовых универсальных решений на все случаи жизни, так что вам можно просто использовать готовые.

Всё это интегрировано и взаимосвязано с остальными системами Drupal, из-за чего область их применения становится практически безграничной.

Пример создания простого типа сущности для хранения данных в БД:

/**
 * Defines the Product entity.
 *
 * @ContentEntityType(
 *   id = "product",
 *   base_table = "product",
 *   entity_keys = {
 *     "id" = "id",
 *   },
 * )
 */
final class Product extends ContentEntityBase {

  /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    parent::baseFieldDefinitions($entity_type);

    $fields['price'] = BaseFieldDefinition::create('integer')
      ->setLabel(new TranslatableMarkup('Price'))
      ->setRequired()
      ->setSetting('unsigned', TRUE);

    return $fields;
  }

}

Типы содержимого

Drupal Типы содержимого

«Ну вот, придётся писать много кода!» — нет! Хоть система сущностей и является фундаментальной для Drupal, это не значит что вам нужно описывать свои сущности. Это для более уникальных задач и более продвинутого уровня разработки.

Все самые необходимые сущности уже давно написаны и они есть в ядре. Например, Drupal предоставляет из коробки сущность node, которая может иметь бандлы, именуемые в интерфейсе как «Типы содержимого». Это очень универсальная сущность для хранения различного рода контента. Новости, акции, отзывы, публикации в блог и т.д. — всё это про типы материалов, а они, кликаются мышкой. Даже их отображание, что, как и где — всё делается мышкой. Каждый тип будет иметь свои собственные настройки и данные не мешающие друг другу.

Подобных сущностей в ядре достаточно, чтобы вы не сели писать свою сущность даже спустя годы работы с Drupal.

Система полей

Drupal поля

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

Хотите добавить текст в отзыв? Добавляете текстовое поле. Хотите фотографию? Добавляете поле для изображений. Друпал предоставляет обширный набор полей прямо из коробки, но также можно создавать свои собственные.

Система полей предоставляет три типа плагинов:

  • Тип поля — отвечает за хранилище, то как данные хранятся, какого типа, какая у них схема в БД, и непосредственно API поля.
  • Форматтер поля — отвечает за вывод значения для пользователя. Например, для поля хранящего координаты, можно сделать форматтер выводящий широту и долготу, а можно чтобы он выводил эти данные в виде карты.
  • Виджет поля — UI элемент отвечающий за визуальное управление значением поля, его добавление и редактирование.

Благодаря этому, можно добавлять что угодно, и расширять то что уже имеется, любом способом.

Также имеется механизм создания псевдо-полей, это такие произвольные поля, которые не хранят ничего в БД, а собирают свой результат в процессе рендера сущности (в HTML). А ещё можно создавать Computed поля, которые работают и имеют все возможности обычных полей, но также вычисляются в рантайме.

Например, у в Drupal есть тип поля Entity Reference — он позволяет связывать различные данные между собой и хранит эти связи, а через них можно запрашивать данные. Допустим, есть сайт афиши мероприятий. На нём есть тип материала «Место проведения», которое хранит адрес, телефон и т.д, а также «Мероприятие», которое хранит информацию о мероприятии и поле связи с местом проведения. Вы можете без проблем получить и вывести всю информацию о месте проведения, например адрес и телефон на странице мероприятия. Если обновить место проведения, обновится и у всех мероприятий. Таким образом, на Drupal очень просто собирать сложные иерархические контентные структуры.

Управление отображением

Drupal Управление отображением

А для всей этой связки из сущностей и полей, также имеется «Управление отображением». Это интерфейс, который позволяет настраивать различные варианты вывода сущности и значений полей кликая мышкой.

Конечно, иногда вы захотите «подкрутить» разметку чего-то, тогда вы сможете скорректировать это шаблонами. Но многие вещи можно просто кликать.

Кстати, все эти админки, возможности и прочее, к своим собственным сущностям подключаются в пару строк и всё будет автоматизировано! Как я и писал, всё уже готово, можно только корректировать, если это вообще нужно.

Layout Builder

Drupal Layout Builder

А если хотите более точечно настроить вывод конкретного типа материала (бандла) или конкретного материала, то в ядре есть Layout Builder, который позволяет собирать макеты мышкой.

Это не привычный для большинства конструктор — он может генерировать наичистейшую разметку, благодаря тому, что всё построено на компонентах и ядре Drupal, тесно интегрировано и предоставляется обширный API, для того чтобы влиять на всё это.

Система блоков

Drupal блоки

Блок — некая единица, которая выводится в регион темы оформления и что-то выводит. Результат страницы собирается из регионов и блоков внутри (по умолчанию, но можно и поменять).

Также есть блоки сущности. А это значит, всё что описано выше, да и дальше, применимо к ним. Можно делать кодом, можно делать простые с текстом, а можно делать различные типы блоков и добавлять поля, мышкой настраивать вывод и т.д. и т.п.

Управление контентом

А если хочется какое-то экзотическое управление содержимым, например хотим как в СМИ: черновики, модерация и прочее. Не проблема! У Drupal и на этот счёт есть штатные решения: Content Moderation, Workspaces и Workflows.

Drupal Workflows

Content Moderation и Workflows — позволяют создавать различные состояния для сущностей. Например: Черновик, Опубликовано, Архивировано. А затем, указывать переходы: «Архивировать» можно только «Опубликованный» контент, а публиковать только «Черновики».

Хотите вывести это на новый уровень? Здесь выходит на сцену Workspaces, который позволяет делать разные «Рабочие области» в пределах сайта, или более знакомый для нас термин — бранчи (из git).

По умолчанию есть рабочая область «Live» — это то что видит пользователь. Вы можете создавать сколько угодно различных областей и пользователи с соответствующими правами могут создавать свои. Затем, в этих областях можно добавлять новые материалы, и видны они будут только в данной рабочей области. А когда всё готово, они плавненько, по нажатию кнопочки, будут интегрированы в «Live».

Мультиязычность

Drupal переводы

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

Всё работает, ЧПУ будут какие хотите, никаких конфликтов и проблем. Для кастома можно просто и беззаботно деплоить переводы.

Даже добавить больше нечего, оно просто работает.

Контроль доступа

Drupal права доступа

В Drupal очень гибкая система настроек прав доступа. От привычных для остальных систем ролей и прав доступа, до более гибких и тонких настроек при помощи кода.

Всё меняется, настраивается и переопределяется. Не устраивает или не подходит аутентификация по логину и паролю? Можно добавить новый способ аутентификации с любой логикой, которая необходима. И все остальные подсистемы будут это учитывать.

CI/CD

Drupal Configuration Diff

«В деплой уж точно не умеет!» — умеет! Drupal, наверное, единственная CMS из известных и популярных, где этот процесс уже поставили на рельсы.

Все настройки проекта, всё что вы кликаете в админке, а накликать там можно полноценный сайт, всё хранится в конфигурациях. Вы можете создавать свои конфигурации для хранения данных, которые будут синхронизироваться и деплоится, либо использовать Form API и ConfigFormBase, где вам достаточно указать желаемое название, а всю остальную рутину возьмёт на себя Drupal.

Целый месяц работали на локалке, и вот, настал час переноса на продакшен. Что же делать? Экспортируете конфигурации (YAML файлы), при помощи Git, rsync, архива, или любого другого способа, они доставляются на нужный сервер и импортируются. Drupal сравнивает, где новее, что добавили, что удалили и вносит изменения. Всё это моментально и бесшовно для пользователей.

Это просто как:

  • На локалке:
    • drush config:export — экспортирует изменённые, удалённые или созданные конфигурации.
    • git add -A, git commit -m '', git push — попутно с кодом.
  • На продакшене. Тут уже можно использовать, например, GitLab CI или другие средства автоматизации.
    • git pull — получаем.
    • drush deploy — применяем.

Но и это не всё. У нас также есть хуки hook_update_N() и hook_post_update_NAME(), которые позволяют писать более точные и уникальные изменения для деплоя. Например, изменить схему БД, или всем товарам поставить какую-то галочку по условию? Не проблема, Drupal обнаружит обновление, применит и больше оно никогда не запустится.

Можно забыть что такое клонирование, экспорт и импорт БД. Оставьте продакшен посетителям сайта.

Кстати, конфигурации переводимы!

События и хуки

Для внедрения в различные процессы системы у нас есть события Symfony и хуки. Конечно, есть и другие способы менять всё и внедряться куда-то, но это два фундаментальных. Благодаря им, вы сможете поменять или повлиять на работу Drupal в практически любой ситуации.

Этим уже никого не удивить, тем не менее. Хуки в Drupal постепенно исчезают, что-то переносят в события, что-то в плагины и прочие подсистемы, либо вовсе создают новые API под задачу. В общем, постепенно, их количество сокращается. Хуки по большей части сейчас используются в качестве API для изменения данных, например форм. В общем, тренд на ООП.

Database API

Тут всё просто. Статичные запросы мы не пишем, потому что Drupal позволяет работать со множеством различных типов баз данных. Из коробки это MySQL (MariaDB), SQLite, PostgreSQL. Модули могут создавать свои драйвера баз данных, так Drupal начинает работать с MongoDB, MS SQL, Oracle и т.д.

У всех БД разные особенности, синтаксис, возможности и т.д. Писать статичные запросы, даже в кастоме — плохой тон в Drupal.

В связи с данной ситуацией у нас есть строители запросов (Query Builder). Всего их в ядре два: для создания динамических запросов, как бы вы писали статичный, но через ООП, и Entity Query, который, как не сложно догадаться, тесно связан с сущностями и сам соединяет пазл, вы просто просите что нужно (он даже может сам сделать проверку прав доступа к результатам). Всё это, как уже несложно догадаться, расширяется, перехватывается, меняется и заменяется.

// Динамический запрос.
$query
  ->select('upload', 'u')
  ->distinct()
  ->fields('u', ['nid', 'vid']);
$query->innerJoin('node', 'n');
$query->addField('n', 'type');
$query->addField('n', 'language');
$result = $query->execute();

// Entity Query
$query = $node_storage->getQuery();
$query
  ->condition('status', NodeInterface::PUBLISHED)
  ->condition('field_categories', [1, 2, 3], 'IN')
  ->condition('langcode', 'ru')
  ->accessCheck(FALSE)
  ->execute();

Media и oEmbed

Для хранения мультимедиа разного рода, включая oEmbed (youtube ролики, твитты, сообщения телеграма) у нас имеется Media модуль.

Он позволяет загружать и повторно использовать различные мультимедиа ресурсы. Все они отслеживаются, кем и где используются.

Медиа являются сущностями, поэтому им можно добавлять поля, кликать мышкой, настраивать вывод и всё что описано ранее и далее.

Обработка изображений

Drupal стили изображений

Больная тема многих CMS, но Drupal разработчики с таких проблем просто улыбаются. Для работы с изображениями у нас есть полноценный Image API, который решает вопрос с обработкой изображений. Всё это, как и полагается в Drupal, можно накликать мышечкой.

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

  • Обработчики изображений: Плагины, которые предоставляют интеграцию с любым желаемым инструментом обработки изображений. По умолчанию это GD, встроенный в PHP. Вы можете подключать ImageMagick и прочие инструменты.
  • Эффекты изображений: Плагины, которые при помощи обработчика производят какие-то действия над картинкой. Они могут предоставить пользователю настройки. Например, добавление водяного знака.
  • Стили изображений: Возможность создавать именованные стили изображений. Стиль содержит в себе набор эффектов которые будут применены к изображению в указанном порядке.

Всё это позволяет делать картинки сжатыми, нужных размеров и с нужными эффектами.

Поверх этой системы, в связке с брейкпоинтами (тип плагинов в Drupal) можно делать адаптивные картинки! Для каждого брейкпоинта вы выбираете какие стили отдавать, и Drupal выведет картинку, которая будет адаптивной.

Всё это, конечно, можно править, менять и расширять. Хотите добавить ленивую загрузку всем картинкам на сайте и подгружать JS библиотеку только на страницах где есть картинки? Libraries API, хук, и пара строк кода сделают свою работу.

Нужно на всём сайте перегенерировать конкретный стиль изображений, или сразу все? Не беда drush image-flush. Причём, генерация производится таким образом, что это не повесит сервер.

Файловая система

Ещё одна боль многих CMS — работа с файлами.

В Drupal мы не обращаемся к файлам напрямую. Для этого у нас есть специальная сущность «Файл». Она хранит всю самую необходиму информацию: название файла, размер, mime тип и URI до файла.

Drupal активно пользуется Stream Wrappers и поверх этого построен свой собственный штатный API. Все пути до файлов всегда указываются в виде URI.

По умолчанию, Drupal предоставляет три враппера:

  • public:// — для публичных файлов, доступных из вне.
  • private:// — для приватных файлов, доступ к которым контролируется системой.
  • temporary:// — путь для создания и хранения временных файлов.

Например, public:// после установки является обёрткой для sites/default/files (реальный путь где хранятся публичные файлы). Таким образом public://image/photo.jpg трактуется как sites/default/files/image/photo.jpg.

Это решает множество проблем, и открывает новые возможности. Например, вы хотите чтобы все публичные файлы теперь хранились в foo/bar/public_files вашего проекта? Вы меняете в настройках путь на новый, и переносите туда файлы любым способом. Всё готово. Вам не нужно ничего трогать в БД, в материалах, шаблонах. Так как везде будет храниться именно public://image/photo.jpg и враппер преобразует это в новый адрес, где уже будут файлы.

Эти обёртки также позволяют использовать и внешние хранилища. Нужно хранить что-то на Amazon S3? Вы ставите соответствующий модуль, и везде где нужно, указываете что сохранять нужно в s3://foo/bar.

Использование файлов также отслеживается, какой модуль и для чего использует, а также сколько раз. Благодаря этой информации можно искать мёртвые файлы в системе и удалять их, а также выводить сводку использования (из коробки).

Обработка больших объёмов данных

Нужно сделать импорт или экспорт большого количества данных, например, пару миллионов? Не проблема, на помощь вам приходят:

  • Queue API — позволяет программно создавать и управлять очередями. Есть специальный тип плагина @QueueWorker который позволяет производить обработку в формате ООП по крону, или не по крону. Эта связка может работать полностью автономно, написали и забыли.
  • Batch API — надстройка над Queue API, которая имеет UI и отображает процесс пользователю.

Возможно вы возразите: «Не всегда нужно обрабатывать такие объемы данных» — но если проявить смекалочку, то можно найти применение хоть для лендинга. Например, вы можете собранные с форм данные отправлять в очереди, а они уже будут отсылать письма.

Допустим, помимо письма вам ещё нужно передать данные в CRM, а его API упал или тормозит. Ведь пока это всё не закончится, пользователь будет сидеть и ждать ответа. Вы можете бросить задачу в очередь, пользователю сразу сказать «всё ушло», а затем, по крону, раз в минуту разгребать всё что скопилось. А если что-то упадёт или не получится отправить письмо, проблемный элемент можно отложить на следующий запуск обработчика. Для пользователя это будет моментально и приятный опыт, а вы гарантированно обработаете данные, особенно, если произойдут проблемы.

Токены

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

Дистрибутивы

Дистрибутив или же установочный профиль — это некая сборка из модулей и тем, а также установочного профиля, которая может развернуть какой-то проект на Drupal. Drupal в таком случае выступает как чистое ядро и API.

Заметили что клиентам на старте проекта всегда делаете одно и то же? Экспортируете нужные конфигурации, заворачиваете в дистрибутив и вуаля. Теперь при установке вы сможете его выбирать, а он вам создаст абсолютно чистую, новую копию со всеми возможностями и функционалом, но без содержимого (если не захотите).

Такие сборки даже можно найти в сети, или купить готовые. Благодаря дистрибутивам, можно сделать конвейер по производству сайтов на Drupal. Достаточно сделать сайт один раз, как из него уже можно штамповать копии. Фактически, вы делаете свою CMS, поверх Drupal.

Примеры сборок:

  • Thunder — сборка для создания СМИ.
  • Open Social — сборка для создания своих собственных сообществ. В июле они получили инвестиции на развитие в размере 1.25 млн. евро.
  • Opigno LMS — сборка для создания обучающих порталов, с лекциями, тестами, отчётами.
  • Varbase — Drupal на стероидах. Фактически, чтобы сразу начать кликать проект. Отлично может подойти новичкам, чтобы потыкать Drupal.
  • Lightning — ещё одна сборка для СМИ.

Все они бесплатные и есть ещё множество других, как платных, так и проприетарных.

Тестирование

Только в Drupal ядре, на момент написания материала, чуть больше 28000 тестов. Ошибки обнаруженные в Drupal, подтверждаются fail тестами, а затем, их исправляют, и делают новые тесты. В конечном итоге все тесты, попадают в ядро вместе с изменением. Вы никогда не внесете изменение кода в ядро без тестов. Вам придётся либо написать их самостоятельно, либо попросить сообщество сделает это за вас.

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

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

Стандарты кодирования и документирования

В Drupal имеются конкретные требования к тому, как нужно писать код и документировать его API. Объявить функцию или метод без комментария? Вам никто не запрещает гадить в своём коде, но в сообществе такое порицается. Если вы пишите модуль для публичного использования, это первое, на что вам ткнут пальцем. А получить права на публикацию первого модуля можно только вылизав код до последней строчки. Даже отсутствие точки в конце предложения или его начало со строчной буквы — ошибка.

Эти стандарты применяются как в ядре, так и в модулях. Есть правила для PHP CS которые будут проверять всё на стандарты. Опять, предложить изменения в ядро или популярный контриб без соблюдения код стайла — это всё равно что все свои труды сразу выбросить в корзину. Высока вероятность что даже изучать такой код не станут. Данные стандарты написаны сообществом для всех кто собрался писать код на Drupal, без исключений.

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

PhpStorm — идеальная IDE для работы с Drupal. Его очень легко настроить на то, чтобы он понимал что происходит и делал 90% рутины за вас.

Безопасность

В Drupal очень серьезно заботятся о безопасности. Крупных проблем было всего несколько за последние 10 лет, и то, только одна, требовала отреагировать оперативно. В сообществе имеется Drupal Security Team, которая занимается поиском, аудитом и закрытием подобных проблем. Иногда проводятся независимые аудиты безопасности.

За подобными проблемами и ситуациями наблюдают не только для ядра, но и для контрибных модулей.

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

То что в других системах не сочтут за ошибку, у нас могут признать угрозой безопасности системы. Даже если проблема только теоретическая и не имеет примера эксплуатации. И так с большинством обновлений безопасности. Чтобы ими воспользоваться, необходимо иметь определенный набор модулей, определённых версий, чтобы луна была в полной фазе, выдать все возможные администраторские права гостям, возможно тогда что-то и получится взломать.

Это только вершина айсберга

Можно также упомянуть:

  • Система фильтрации и обработки текста, позволяющая проводить операции над текстом.
  • Система типизированных данных. Хоть PHP и потихоньку получает возможность указывать типы для всего и вся, но ещё предстоит долгий путь совершенствования, а затем адаптации. В Drupal есть Typed Data API, который позволяет создавать свои типы данных, когда это необходимо.
  • Serialization API — позволяющий писать свои сериалайзеры, десириалайзеры и нормалайзеры. Это фактически компонент Symfony, но достаточно тесно интегрированный и широко применяемый в системе.
  • Modal API для работы с модальными окнами.
  • Блокировщики состояний для предотвращения ситуаций приводящих к сбою или дублированию операций.
  • Tour API для создания простеньких обучающих инструкций для различных частей сайта.
  • Множество инструментов которые помогу с SEO оптимизацией. Например, возможность легко и просто кастомизировать и гнуть хлебные крошки.
  • Logging API для логирования различных происшествий в системе или произведенных действий.
  • State API для хранения различных состояний. Это что-то типа переменных которые хранятся в БД.
  • Temp Store API для создания временных хранилищ данных, общих для проекта или специфичных для конкретного пользователя, которые в дальнейшем самоуничтожаются.
  • Middleware API позволяющий производить операции связанные с запросами на очень ранних этапах.
  • Система комментариев (сущности), которая позволяет создать различные типы комментариев, прикреплять их к чему угодно, добавлять различные поля и т.д.
  • Mail API, позволяющий централизованно отсылать письма, влиять на них, менять почтовые системы и т.д.
  • Search API (search) для создания поисков по сайту.
  • Migrate API инструментарий для переноса чего угодно куда угодно.

И многое, многое другое. Возможностей в ядре припасено на все случаи жизни. Если вы раньше слышали о Drupal, то могли обратить внимание, что я до сих пор не упомянул Views, а он никуда не делся, а в других CMS до сих пор нет его полноценной замены.

Drupal из коробки полностью соответствует спецификациям WCAG 2.0 и ATAG 2.0 и даже имеет команду, которая целиком занимается a11y.

Стоимость

Может возникнуть мысль, что всё это, либо в какой-то платной версии системы, либо базово стоит денег. Но нет, Drupal полностью OpenSource и абсолютно бесплатный.

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

Можно сказать что для Drupal практически отсутствует рынок платных модулей и тем. Для кого-то это будет плюс, для кого-то минус. Я лично вижу в этом только плюсы. Платные модули/плагины дробят сообщество и распыляют силы понапрасну. Ни один разработчик не будет инвестировать своё время и помогать развивать или покрывать тестами модуль, который продаёт другой разработчик. Это приводит к тому, что для решения одной задачи может существовать несколько популярных решений с небольшими отличиями, вместо одного. Другие расширения могут поддерживать только одного из них, а для поддержки 2+ сторонних API потребуется больше сил, это приведёт к тому, что придётся делать платную версию, и всё, круг замкнулся.

Это хорошая практика для супер-уникальных решений, и такие есть даже под Drupal. Решения, которые базово требуются на каждом сайте и имеются в различных вариантах исполнения, ничего хорошего не дадут, ни разработчику, ни владельцу сайта. Именно поэтому, в Drupal ядро добавили CCK, Views, недавно JSON:API, чтобы сконцентрировать все силы на одном решении и максимально интегрировать его с остальными.

Drupal мероприятия

What's DrupalCon All About?

Drupal ассоциация, а также участники сообщества, регулярно проводят мероприятия. От больших DrupalCon, до мелких посиделок типа DrupalCafe. Бывают даже очень тематические и узкоспециализированные, такие как Drupal GovCon где обсуждают и делятся опытом применения Drupal исключительно в контексте государственных проектов.

Также, регулярно проводятся Drupal Training Days, где заинтересованные в Drupal люди, могут получить помощь и свои первые знания.

Не так много CMS, да даже фреймворков, у которых проводятся такие масштабные мероприятия. В среднем, на одном DrupalCon выступают со 165 докладами, а конференцию посещают 3000 человек.

Из-за их обилия даже появился сайт с картой мероприятий (и это во время карантина).

Заключение

Всё что перечислено выше — возможности ядра и ни одного контрибного модуля. И да, они огромны, даже при том что это далеко не полный список.

Это может напугать, но посмотрите на это с другой стороны. Всё это так или иначе требуется на каждом проекте в том или ином виде, где-то прямо, где-то косвенно для других инструментов. Когда всё это в ядре и тесно интегрировано между собой, сторонние решения строятся вокруг одного и того же API — это позволяет решать задачи быстрее и более элегантными способами.

Потребуется время на то, чтобы познакомиться со всеми возможностями, но все сразу они вам и не нужны. Многие могут работать в автономном режиме очень длительное время и не беспокоить. Например, вникать в кэширование можно после нескольких проектов, стандартное поведение всё равно будет летать. Создавать различные листинги, выборки данных, каталоги и подобное? Всё это решается мышкой, а когда потребуется уже тотальный контроль, тогда и начнёте постепенно вникать.

Наоборот, чем скромнее API у системы, тем больше проблем на более сложных и нетипичных проектах. Отсутствие базового API в системе приводит к тому, что каждое расширение и разработчик будут изобретать колесо. Чем больше таких велосипедов, тем сложнее всем. Пример с добавлением класса на все формы разом, где нет централизованного API для работы с формами, наглядно проиллюстрирует проблему. Вы дополнительно будете тратить время на поиск решения, а затем его придётся изучать точно также. Например, вопрос с деплоем у других CMS, с вероятностью 99%, не решен вообще никак. Экспорт/импорт БД с фризом контента или перекликивание настроек на проде — это не деплой. Костыли, грабли, условности — всё это будет мешаться, увеличивать затраты времени, когда в Drupal вам достаточно выучить две команды и у вы уже можете деплоить и не париться о таких проблемах.

Все инструменты и решения в ядре оттачиваются уже давно. Drupal в январе исполняется 20 лет, всё это время он эволюционирует и развивается. Он мало того что в тренде современной веб-разработки, так по некоторым пунктам опережает своё время и даёт вам инструменты на будущее. Например, в 2010 году, когда начали разработку Drupal 8, понимали что в будущем всё больше трафика будет уходить в пользу мобильных устройств, и вообще, от сайтов потребуется API first, так как от CMS уже начинают требовать не только отвечать за сайтик с новостями. В то время даже адаптив был только у избранных. Теперь, когда всё больше и чаще на фронтенде требуется React, Vue и прочие Angular, вопрос уже активно поднимается и обсуждается, для многих это становится всё большей проблемой и REST в спешке приклеивают на сопли и скотч. А мы уже с 2015 вооружены до зубов.

Drupal не останавливается на этом, дорожная карта постоянно пополняется идеями и улучшениями, а также появляются новые стратегические инициативы, формируются команды и воплощают их в жизнь. Уже сейчас в Drupal можно опробовать новую административную тему Claro, а в Drupal 9.1, релиз которого запланирован на декабрь 2020, планируют завершить и выпустить новую тему оформления сайта Olivero, которую уже можно загрузить и попробовать.

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

Drupal постепенно воспитает в вас культуру написания кода. Со временем, если вы до сих пор этим не занимаетесь, начнёте писать код в соответствии кодстайлу, комментировать и документировать его в процессе написания. Количество ситуаций когда в процессе написания «и так ясно же что делает код», а через полгода в обнимку с дебагером пытаетесь понять что вообще происходит и нужен ли этот кусок кода, будет стремиться к нулю.

Drupal приучит вас разделять код, разметку и всё остальное. PHP сейчас уверенно развивается именно как язык программирования, а не как шаблонизатор. Умение писать код и мыслить в decoupled формате, определённо пригодится в будущем, ведь фронтенд уверенно уходит в JavaScript.

Знания, полученные в Drupal пригодятся и за его пределами. Как правило, после Drupal идут либо в чистые фреймворки, где опыт Drupal будет невероятно полезен, либо в другие языки. Возможно, даже при прочтении вы заметили, как у Drupal много общего с фреймворками, при этом, он остаётся CMS/CMF.

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

Да, мы пишем код, и иногда много, просто потому что некоторые вещи решаются быстрее кодом, даже если это можно накликать мышкой. С таким набором инструментов, намного легче писать индивидуальные решения, а код вовсе можно генерировать (drush generate). По моим, и не только, наблюдениям (мы мониторим как разделы на Тостере, так и множество чатов), как не парадоксально, в конкурирующих системах пишут код чаще и больше, особенно на простых задачах которые в Drupal решаются мышкой.

И тут мы приходим к закономерному вопросу: «А для каких проектов подходит Drupal?» — для многих. Всё это надо воспринимать в контексте возможностей Drupal. Да, сделать один лендинг на Drupal будет значительно дольше, сложнее и дороже, чем на том же конструкторе. Но не стоит забывать что второй такой лендинг будет сделать многократно быстрее, так как наработки первого можно завернуть в готовое решение. И если собрать множество таких решений с различных проектов, со временем, окажется что на Drupal будет делать быстрее, проще и дешевле. Дистрибутивы разворачиваются за секунды, и вот он, сайт готов.

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

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

Drupal — не золотой молоток и он не идеален. У него свои проблемы и недостатки.

Если вы решите познакомиться с сообществом или попробовать Drupal, добро пожаловать в русскоязычное сообщество.

А я пойду запасаться 🧯 для комментариев.

Everyday I'm Drupalin' Drupal Rap (Rick Ross - Hustlin)
Drupal

Комментарии

Павел Филинков   сб, 08/08/2020 - 23:31

Кто шарит Битрикс давно не выбирает. Вижу, что ты одного не понимаешь, Drupal - это в первую очередь не про то, когда распаковал архив с дистрибутивом, установил, настроил базу и делаешь сайт. Нет! Фишка Drupal - это конфигурация не хуже Битрикса, и когда это понимаешь и правильно ставишь проект на рельсы, то никакой Битрикс рядом не стоял.

Хорошая система может быть бесплатной! Конфигурация - платная, платят за готовое решение. Я с 2004 г. занимаюсь изучением только Drupal и могу сказать, что с каждым годом востребованность у крупных компаний только растет. Сейчас делаю проект для РОСНАНО на Drupal. Это не понт, просто информация для понимания масштаба интереса к этой платформе, они сами захотели.

Никлана очень уважаю как специалиста, делает большое не простое дело (сам преподавал в университете, знаю как это не легко доносить в массы правильную инфу).

Статья очень многое раскрывает для новичков. Я лично считаю, что современный Drupal превосходит Битрикс во всем.

Valer   вс, 02/08/2020 - 14:02

Все новшества для разрабов, а для людей - практически ничего для людей, которые собственно пишут, добавляют контент резона мигрировать с 7-ки нет

Вячеслав   вт, 25/08/2020 - 15:03

Ну не скажи! Начинал с установки Drupal 6 и сразу же изучения Drupal 7, сделал на нем несколько очень сложны проектов для себя с коммерцией, многочисленно автоматизацие все процессов и как только появился Drupal 8, начал следить за ним переживая, что будет сложно, но нет, следующи проект взялся делать на нем, параллельно все изучая заново и очень счастлив. Мечтаю нати время и перевести все остальные на Восьмерку. Восьмёрка - это Космос!

Петя   сб, 08/08/2020 - 11:27

не могу обновиться на 9-ку, потому что на паре критичных модулей разрабы забили и не шевелятся, при том, что еще несколько модулей пришлось вообще удалить, потому как они даже не релизнулись с альфы на протяжении всего времени существования восьмерки :(

но модуль paragraphs позволяет простить многое

Виктор Степаньков   вс, 09/08/2020 - 15:26

Не нужно зацикливаться на миграции модуль-в-модуль. Апгрейд это хороший вариант для небольшого рефакторинга. Модули устаревают, новые возможности появляются.

Скорее всего вы мигрируете с D7 или даже более ранних версий, я не могу сходу придумать незаменимых модулей, в крайнем случае, такие проблемы решаются покупкой 2-3 часов разработчика

Valer   пн, 10/08/2020 - 12:02

Мне показалось, что модуль параграф нужен в 1% случаев. Остальные 99% стандартные тексты (с картинками, вставляемые с помощью модуля insert)

Вячеслав   вт, 25/08/2020 - 15:06

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

Василий   чт, 03/09/2020 - 14:56

Мы так вообще от Insert отказались. Управляемости у него нет. Медиа, параграфы, LB. Всё прозрачно и связно.

Murz   ср, 09/09/2020 - 11:40

Мы вставку картинок сейчас реализовываем через Media Library и кнопку Add Media в CKEditor, получается гораздо удобнее и гибче, чем через поля и Insert.

Единственное неудобство - что нужно стили (размеры картинок) заранее продумать-прописать, т.к. клиент уже не сможет мышкой повазякать-подогнать картинку под нужный размер прям в визивиге, но наверное это и к лучшему - не будет вырвиглазного контента на сайте ;)

Валерий   ср, 14/10/2020 - 14:22

А юзеры могут этим функционалом пользоваться? (зарегенные пользователи) или только кто-то из редакторов?

Влад   чт, 15/10/2020 - 02:03

Статья огонь! Я уже долго работаю с Drupal и мне стыдно, что я еще не знаю так много.

  • Я вообще не знал про Workspaces – это для меня открытие №1, наверно! Нужно срочно опробовать и разобраться.
  • Layout Builder – открытие №2. Интересно, хоть я и вряд ли буду его часто использовать. Это что-то типа Panels или как?

Вообще огромное спасибо за статью, Никита, куча всего нового и интересного!

Добавить комментарий

Поддерживает синтаксис CommonMark.