Розробка сайту на CMS Sulu

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

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

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка сайту на CMS Sulu
Складна
~2-4 тижні
Часті питання

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

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

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

  • 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

Розробка сайту на CMS Sulu

Sulu — enterprise CMS на Symfony. Headless з коробки, REST та JSON:API, мультисайт, мультиязичність, Webspaces. Побудований на Doctrine ORM, працює з MySQL/MariaDB/PostgreSQL. Цільова аудиторія — корпоративні сайти, портали, мультибрендові платформи.

Архітектура

my-sulu-project/
├── assets/              # фронтенд ресурси (webpack/vite)
├── bin/
├── config/
│   ├── packages/
│   │   ├── sulu.yaml    # конфіг Sulu
│   │   └── webspaces/
│   │       └── example.xml
│   ├── routes_admin.yaml
│   ├── routes_website.yaml
│   └── services.yaml
├── src/
│   ├── Controller/
│   │   ├── Admin/       # кастомні API для backoffice
│   │   └── Website/     # публічні контроллери
│   ├── Entity/          # Doctrine-сущності
│   ├── EventSubscriber/
│   └── Twig/
├── templates/           # Twig-шаблони
│   ├── base.html.twig
│   └── pages/
│       ├── homepage.html.twig
│       └── article.html.twig
└── public/

Конфігурація Webspace

<!-- config/packages/webspaces/example.xml -->
<?xml version="1.0" encoding="utf-8"?>
<webspace xmlns="http://schemas.sulu.io/webspace/webspace"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://schemas.sulu.io/webspace/webspace
          http://schemas.sulu.io/webspace/webspace-1.1.xsd">

    <name>Example</name>
    <key>example</key>

    <localizations>
        <localization language="uk" default="true"/>
        <localization language="en"/>
    </localizations>

    <default-templates>
        <default-template type="page">homepage</default-template>
        <default-template type="home">homepage</default-template>
    </default-templates>

    <templates>
        <template type="page">homepage</template>
        <template type="page">article</template>
        <template type="page">article-list</template>
        <template type="page">contact</template>
    </templates>

    <portals>
        <portal>
            <name>Example</name>
            <key>example</key>
            <environments>
                <environment type="prod">
                    <urls>
                        <url language="uk">example.com</url>
                        <url language="en">en.example.com</url>
                    </urls>
                </environment>
                <environment type="dev">
                    <urls>
                        <url language="uk">example.localhost</url>
                    </urls>
                </environment>
            </environments>
        </portal>
    </portals>
</webspace>

Page Template

<!-- config/templates/article.xml -->
<?xml version="1.0" encoding="utf-8"?>
<template xmlns="http://schemas.sulu.io/template/template"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://schemas.sulu.io/template/template
          http://schemas.sulu.io/template/template-1.0.xsd">

    <key>article</key>
    <view>pages/article</view>
    <controller>Sulu\Bundle\WebsiteBundle\Controller\DefaultController::indexAction</controller>
    <cacheLifetime>3600</cacheLifetime>

    <properties>
        <property name="title" type="text_line" mandatory="true">
            <meta>
                <title lang="uk">Заголовок</title>
            </meta>
            <tag name="sulu.rlp.part"/>
        </property>

        <property name="article" type="text_editor" colspan="12">
            <meta>
                <title lang="uk">Текст статті</title>
            </meta>
        </property>

        <property name="header_image" type="single_media_selection" colspan="12">
            <meta>
                <title lang="uk">Зображення</title>
            </meta>
            <params>
                <param name="types" value="image"/>
            </params>
        </property>

        <section name="seo">
            <meta>
                <title lang="uk">SEO</title>
            </meta>
            <properties>
                <property name="seo_title" type="text_line" colspan="6">
                    <meta><title lang="uk">SEO заголовок</title></meta>
                </property>
                <property name="seo_description" type="text_area" colspan="6">
                    <meta><title lang="uk">SEO опис</title></meta>
                </property>
            </properties>
        </section>
    </properties>
</template>

Twig-шаблон

{# templates/pages/article.html.twig #}
{% extends 'base.html.twig' %}

{% block title %}{{ content.seo_title ?: content.title }} | {{ app.request.host }}{% endblock %}

{% block body %}
<article class="page-article">
    <header class="article-header">
        {% if content.header_image %}
            {% set image = sulu_resolve_media(content.header_image, 'uk') %}
            <figure>
                <img
                    src="{{ image.thumbnails['800x450'] }}"
                    srcset="{{ image.thumbnails['400x225'] }} 400w,
                            {{ image.thumbnails['800x450'] }} 800w"
                    alt="{{ image.title }}"
                >
            </figure>
        {% endif %}
        <h1>{{ content.title }}</h1>
    </header>

    <div class="article-body">
        {{ content.article|raw }}
    </div>
</article>
{% endblock %}

Користувацький контроллер

// src/Controller/Website/ArticleListController.php
namespace App\Controller\Website;

use Sulu\Bundle\WebsiteBundle\Resolver\TemplateAttributeResolverInterface;
use Sulu\Component\Content\Compat\StructureInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class ArticleListController extends AbstractController
{
    public function __construct(
        private readonly TemplateAttributeResolverInterface $resolver,
        private readonly ArticleRepository $repository
    ) {}

    public function indexAction(StructureInterface $structure, bool $preview = false): Response
    {
        $page = max(1, (int) $this->container->get('request_stack')
            ->getCurrentRequest()
            ->query->get('page', 1));

        $articles = $this->repository->findPublished(page: $page, limit: 12);

        $attributes = $this->resolver->resolve([
            'content'  => $structure->getContent(),
            'articles' => $articles,
            'pagination' => [
                'current' => $page,
                'total'   => $articles->getTotalPages(),
            ],
        ], $structure, true, $preview);

        return $this->render('pages/article-list.html.twig', $attributes);
    }
}

Sulu Media та ресайз

{% set media = sulu_resolve_media(content.image, locale) %}

{# передопреділений формат #}
<img src="{{ media.thumbnails['sulu-400x400'] }}" alt="{{ media.title }}">

{# довільний ресайз через URL-параметри #}
<img src="{{ media.url }}?w=800&h=600&fm=webp&q=85" alt="">

Формати конфігурюються в config/packages/sulu.yaml:

sulu_media:
    image_format_files:
        - '%kernel.project_dir%/config/image-formats.xml'
<!-- config/image-formats.xml -->
<formats>
    <format key="article-cover">
        <commands>
            <command>
                <action>resize</action>
                <parameters>
                    <parameter name="x">800</parameter>
                    <parameter name="y">450</parameter>
                </parameters>
            </command>
        </commands>
    </format>
</formats>

Smart Content та автосписки

<property name="articles" type="smart_content">
    <meta><title lang="uk">Статті</title></meta>
    <params>
        <param name="provider" value="pages"/>
        <param name="types" value="article"/>
        <param name="max_per_page" value="6"/>
        <param name="page_parameter" value="p"/>
    </params>
</property>

У шаблоні:

{% for article in content.articles %}
    {% include 'snippets/article-card.html.twig' with { page: article } %}
{% endfor %}

Терміни розробки

Корпоративний сайт з двома мовами, 5–8 типів сторінок, медіа-менеджером та кастомними шаблонами: 4–6 тижнів. З кастомними контроллерами, Smart Content, інтеграцією з зовнішніми сервісами: 6–10 тижнів.