Налаштування Matrix Fields для гнучкого контенту Craft CMS

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Налаштування Matrix Fields для гнучкого контенту Craft CMS
Середня
від 1 робочого дня до 3 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Налаштування Matrix Fields для гнучкого контенту Craft CMS

Matrix Field — головний інструмент для page builder функціональності без сторонніх плагінів. Редактор додає блоки різних типів у довільному порядку, розробник рендерить їх через switch у Twig.

Коли використовувати Matrix

Matrix підходить для:

  • Тіл сторінок зі змішаним контентом (текст + зображення + цитати + CTA)
  • Секцій головної сторінки (hero + features + testimonials + pricing)
  • FAQ-блоків, таймлайнів, характеристик продукту

Matrix надлишковий для:

  • Простих списків однотипних елементів → використовуйте окремий Channel
  • Одного типу контенту, що повторюється кілька разів → використовуйте Table field

Проектування Matrix Block Types

Приклад для поля pageBody на корпоративному сайті:

pageBody (Matrix)
├── richText
│   └── content: Redactor (formatting: all)
│
├── image
│   ├── image: Assets (single)
│   ├── caption: Plain Text
│   ├── alignment: Dropdown (left/center/right/full)
│   └── linkUrl: URL (optional)
│
├── imageText
│   ├── image: Assets (single)
│   ├── imagePosition: Lightswitch (image left/right)
│   ├── heading: Plain Text
│   ├── text: Redactor (limited)
│   └── buttonLabel + buttonUrl: Plain Text + URL
│
├── gallery
│   ├── images: Assets (multiple)
│   ├── columns: Dropdown (2/3/4)
│   └── caption: Plain Text
│
├── codeBlock
│   ├── language: Dropdown (php/js/python/bash/json/yaml)
│   └── code: Plain Text (monospace)
│
├── testimonial
│   ├── quote: Plain Text (textarea)
│   ├── author: Plain Text
│   ├── role: Plain Text
│   └── avatar: Assets (single)
│
├── stats
│   └── items (Matrix nested or Table):
│       ├── value: Plain Text
│       ├── label: Plain Text
│       └── icon: Assets
│
└── cta
    ├── heading: Plain Text
    ├── text: Plain Text
    ├── primaryLabel + primaryUrl: Plain Text + URL
    └── secondaryLabel + secondaryUrl: Plain Text + URL (optional)

Twig-рендер Matrix

{# templates/_components/matrix-content.twig #}
{% for block in entry.pageBody.all() %}
  <div class="content-block content-block--{{ block.type.handle }}" id="block-{{ block.id }}">
    {% switch block.type.handle %}

      {% case 'richText' %}
        <div class="prose max-w-prose mx-auto">
          {{ block.content }}
        </div>

      {% case 'image' %}
        {% set img = block.image.one() %}
        {% if img %}
          <figure class="image-block align-{{ block.alignment }}">
            {% if block.linkUrl %}
              <a href="{{ block.linkUrl }}" target="_blank" rel="noopener">
            {% endif %}
            <img
              src="{{ img.getUrl({ width: 1200 }) }}"
              alt="{{ img.alt ?? '' }}"
              loading="lazy"
              width="{{ img.width }}"
              height="{{ img.height }}">
            {% if block.linkUrl %}</a>{% endif %}
            {% if block.caption %}
              <figcaption>{{ block.caption }}</figcaption>
            {% endif %}
          </figure>
        {% endif %}

      {% case 'imageText' %}
        <section class="image-text {{ block.imagePosition ? 'image-right' : 'image-left' }}">
          <div class="image-text__image">
            {% set img = block.image.one() %}
            {% if img %}
              <img src="{{ img.getUrl({ width: 600 }) }}" alt="{{ img.alt ?? '' }}" loading="lazy">
            {% endif %}
          </div>
          <div class="image-text__content">
            {% if block.heading %}<h2>{{ block.heading }}</h2>{% endif %}
            <div class="prose">{{ block.text }}</div>
            {% if block.buttonLabel and block.buttonUrl %}
              <a href="{{ block.buttonUrl }}" class="btn">{{ block.buttonLabel }}</a>
            {% endif %}
          </div>
        </section>

      {% case 'codeBlock' %}
        <pre class="code-block" data-language="{{ block.language }}">
          <code class="language-{{ block.language }}">{{ block.code | escape }}</code>
        </pre>

      {% case 'testimonial' %}
        <blockquote class="testimonial">
          <p>{{ block.quote }}</p>
          <footer>
            {% set avatar = block.avatar.one() %}
            {% if avatar %}
              <img src="{{ avatar.getUrl({ width: 80, height: 80, mode: 'crop' }) }}" alt="{{ block.author }}">
            {% endif %}
            <cite>
              <strong>{{ block.author }}</strong>
              {% if block.role %}<span>{{ block.role }}</span>{% endif %}
            </cite>
          </footer>
        </blockquote>

      {% case 'cta' %}
        <div class="cta-block">
          {% if block.heading %}<h2>{{ block.heading }}</h2>{% endif %}
          {% if block.text %}<p>{{ block.text }}</p>{% endif %}
          <div class="cta-block__buttons">
            {% if block.primaryLabel %}
              <a href="{{ block.primaryUrl }}" class="btn btn--primary">{{ block.primaryLabel }}</a>
            {% endif %}
            {% if block.secondaryLabel %}
              <a href="{{ block.secondaryUrl }}" class="btn btn--secondary">{{ block.secondaryLabel }}</a>
            {% endif %}
          </div>
        </div>

    {% endswitch %}
  </div>
{% endfor %}

Продуктивність: Eager Loading

Matrix-блоки з Assets та Relations створюють N+1 запити без eager loading:

{# Погано — N+1 для кожного блоку з image #}
{% for block in entry.pageBody.all() %}

{# Добре — preload всіх зв'язків #}
{% set blocks = entry.pageBody
  .with(['image', 'images', 'avatar'])
  .all() %}

Обмеження типів блоків через Entry Type

Різні Entry Types можуть використовувати різні набори блоків Matrix, але саме поле Matrix — спільне. Це реалізується через JavaScript у CP (умовна видимість), але не на рівні даних.

Налаштування Matrix з 5–8 типами блоків та шаблонами займає 2–4 дні.