Розробка кастомних колекцій (Collections) Payload CMS

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

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

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка кастомних колекцій (Collections) Payload CMS
Середня
~2-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

Кастомні колекції Payload CMS

Колекція (Collection) в Payload — тип контенту з REST API, GraphQL схемою і інтерфейсом в admin panel, генерованими автоматично з TypeScript-конфігурації. Кожна колекція зберігається в окремій таблиці PostgreSQL або колекції MongoDB.

Структура колекції

// collections/Products.ts
import { CollectionConfig } from 'payload/types'

const Products: CollectionConfig = {
  slug: 'products',           // URL сегмент: /api/products
  labels: {
    singular: 'Товар',
    plural: 'Товари',
  },
  admin: {
    useAsTitle: 'name',
    defaultColumns: ['name', 'price', 'category', 'inStock'],
    group: 'Каталог',
  },
  // ...
}

Типи полів

fields: [
  // Текстові
  { name: 'name', type: 'text', required: true },
  { name: 'description', type: 'textarea' },
  { name: 'content', type: 'richText' },

  // Числа і дати
  { name: 'price', type: 'number', min: 0, required: true },
  { name: 'publishedAt', type: 'date' },

  // Вибір
  {
    name: 'status',
    type: 'select',
    options: [
      { label: 'Активен', value: 'active' },
      { label: 'Архів', value: 'archived' },
    ],
    defaultValue: 'active',
  },

  // Медіа
  { name: 'image', type: 'upload', relationTo: 'media' },

  // Зв'язки
  {
    name: 'category',
    type: 'relationship',
    relationTo: 'categories',
    hasMany: false,
  },
  {
    name: 'tags',
    type: 'relationship',
    relationTo: 'tags',
    hasMany: true,
  },

  // Масив об'єктів
  {
    name: 'variants',
    type: 'array',
    fields: [
      { name: 'sku', type: 'text', required: true },
      { name: 'color', type: 'text' },
      { name: 'size', type: 'text' },
      { name: 'stock', type: 'number', defaultValue: 0 },
    ],
  },

  // Блоки (як Gutenberg)
  {
    name: 'sections',
    type: 'blocks',
    blocks: [TextBlock, ImageBlock, CTABlock],
  },

  // Група полів
  {
    name: 'seo',
    type: 'group',
    fields: [
      { name: 'title', type: 'text' },
      { name: 'description', type: 'textarea' },
    ],
  },
]

Контроль доступу (Access Control)

access: {
  // Читання — публічне
  read: () => true,

  // Створення — тільки авторизовані
  create: ({ req: { user } }) => Boolean(user),

  // Оновлення — тільки власник або admin
  update: ({ req: { user }, id }) => {
    if (!user) return false
    if (user.role === 'admin') return true
    return { author: { equals: user.id } }  // фільтр-умова
  },

  // Видалення — тільки admin
  delete: ({ req: { user } }) => user?.role === 'admin',
},

Hooks колекції

hooks: {
  beforeChange: [
    async ({ data, req, operation }) => {
      // Автоматичне створення slug
      if (operation === 'create' && !data.slug) {
        data.slug = data.name
          .toLowerCase()
          .replace(/\s+/g, '-')
          .replace(/[^\w-]/g, '')
      }
      // Встановити автора
      if (operation === 'create' && req.user) {
        data.author = req.user.id
      }
      return data
    },
  ],

  afterChange: [
    async ({ doc, operation }) => {
      // Інвалідація Next.js кеша
      if (operation === 'update') {
        await fetch(`/api/revalidate?path=/products/${doc.slug}`, {
          method: 'POST',
        })
      }
    },
  ],

  afterDelete: [
    async ({ doc }) => {
      // Очищення пов'язаних даних
      console.log(`Product ${doc.id} deleted`)
    },
  ],
},

Версіонування

versions: {
  maxPerDoc: 20,
  drafts: {
    autosave: {
      interval: 2000,  // автозбереження кожні 2 секунди
    },
  },
},

Запити до колекції

// На сервері (Next.js Server Component)
import { getPayload } from 'payload'
import config from '@payload-config'

const payload = await getPayload({ config })

// Знайти опубліковані товари в категорії
const result = await payload.find({
  collection: 'products',
  where: {
    and: [
      { status: { equals: 'active' } },
      { category: { equals: categoryId } },
      { price: { less_than: 10000 } },
    ],
  },
  sort: '-createdAt',
  limit: 20,
  page: 1,
  depth: 2,  // глибина populate зв'язків
})

const { docs, totalDocs, hasNextPage } = result

REST API (автогенерований)

# Список
GET /api/products?where[status][equals]=active&limit=20

# Один документ
GET /api/products/:id

# Створити (потрібна авторизація)
POST /api/products
Authorization: Bearer <token>
Content-Type: application/json

# Оновити
PATCH /api/products/:id

# Видалити
DELETE /api/products/:id

Часові рамки

Налаштування однієї колекції з полями, доступом і hooks — 2–4 години. Повний каталог (5–10 взаємопов'язаних колекцій) — 2–4 дні.