Настройка отображения материалов в Joomla

Это перевод статьи Брайана Тимана (Brian Teeman) о переопределении макета материала Joomla, с разделением блока вводного текста и полного текста материала. С примером возможного оформления.

Скриптовый язык общего назначения

Это перевод статьи Брайана Тимана (Brian Teeman) о переопределении макета материала Joomla, с разделением блока вводного текста и полного текста материала. С примером возможного оформления.

Сайт Словарус 2.0 – это вторая улучшенная версия сайта с русской заменой иностранных слов, который я ранее делал по заказу Love Media и лично господина Маркелова.
Задача. Восстановить сайт из веб-архива и сделать его лучше.

Это первая часть цикла статей о разработке системы публикации структурированных интерактивных постов через Telegram Bot API. В следующих частях — архитектура, рендеринг шаблонов и управление доступом к закрытым чатам.
С чего всё начинается
Представьте типичную задачу: пользователь вашего сервиса хочет опубликовать в своём Telegram-канале структурированный пост. Не просто текст — а пост с заголовком, многострочным описанием, блоком реквизитов, динамическим индикатором прогресса и интерактивными кнопками. Пост, который после публикации будет обновляться в реальном времени по мере поступления новых данных. Пост, под которым есть кнопка, открывающая отдельный диалог в боте — и всё это происходит без перехода в браузер, без форм, без лишних шагов.
На первый взгляд — ничего сложного. Telegram Bot API умеет отправлять текст, прикреплять медиа, рисовать inline-кнопки. Но именно в этот момент начинается то, что разработчики называют «дьявол в деталях».
На практике задача немедленно разбивается на несколько инженерных проблем, каждая из которых требует отдельного решения. И если пропустить хотя бы одну — система либо ломается при первом же граничном случае, либо создаёт такой UX, что пользователи просто не понимают, что происходит.

Привет, Хабр! (И тебе, страдалец, который три недели смотрит на мёртвого бота в Битриксе. И тебе, админ, который уже устал объяснять руководству, почему «оно перестало работать». И тебе, безопасник, который узнал, что данные компании летают через какой-то curator.pro и чуть не уронил кружку.)
Помните мою прошлую статью про разработку Битрикс-бота? Ту самую, где я рассказывал, как документация врала, облака смеялись, а трафик зачем-то летел через сторонние сервера? Так вот - продолжение банкета.
Спойлер: стало хуже. Но мы справились.

REST API на Symfony писать удобно, но есть одна скучная особенность: контроллеры быстро начинают обрастать повторяющимся кодом. Парсинг запроса, валидация, однотипная JSON‑обёртка, try/catch с преобразованием исключений в HTTP‑ответы. Всё это несложно, но со временем размазывается по десяткам эндпоинтов и отвлекает от основной задачи.
Ниже - способ привести все в порядок с помощью небольшого бандла, который я использую в своих проектах.

Брент Роуз, партийный функционер говорящая голова сообщества РНР и автор очередного конкурирующего стандарта фреймворка Tempest, объявил конкурс, весьма вторичный, после эпичного One billion row challenge (который и сам по себе уже был вторичен, по отношению к оригинальному 1brc), но кто ж считает, когда на кону такие призы, как плюшевый слон от JetBrains!
Каждый раз, когда хотелось быстро попробовать что‑то на Symfony, начиналась одна и та же история: поднять контейнер с PHP‑FPM или FrankenPHP, провалиться в контейнер, поставить symfony/skeleton, настроить Nginx или Caddyfile, прописать переменные окружения... И всё это до того, как написана хоть одна строчка кода.
DI‑контейнер, консольные команды, компонентная архитектура... Ни для кого не секрет, Symfony заметно ориентируется на Java‑экосистему. Почему бы не попробовать сделать что‑то подобии start.spring.io подумал я.
Так появился пет-проект symfony-init.dev

Scedel - это language- и protocol-agnostic язык для описания схем данных и контрактов. В статье я опишу сам язык, а также расскажу, зачем я его создал

RAG на PHP - звучит непривычно. Делюсь опытом построения чат-бота для поиска по внутренней базе документов: Symfony, Qdrant с гибридным поиском, YandexGPT для embedding и генерации ответов. Внутри — готовый код, подводные камни чанкинга и советы, которые сэкономят вам время.

У меня была привычка. Вижу классную статью про архитектуру —-сохраняю. Репозиторий с примерами DDD - в закладки. Видео про CQRS - в плейлист «Посмотреть потом».
Вы знаете, чем кончаются плейлисты «Посмотреть потом».
В какой-то момент закладок стало 300+. Половина ссылок битые, треть дублируют друг друга, остальное - статьи, которые казались гениальными в два часа ночи. Я сел и вычистил всё до 106 ресурсов. Собрал их в awesome-list на GitHub.
Но статья не про список. Статья про три вещи, которые я для себя открыл в процессе и которые почему-то мало обсуждают.

В комментариях к моей предыдущей статье про Waypoint прозвучало: «это стандартный алгоритм, ничего уникального». Trie — стандартный. Хеш-таблица — стандартная. Всё так. Но покажите мне PHP-роутер, который каскадирует O(1) хеш-таблицу, посегментный prefix-trie и prefix-grouped fallback в три уровня матчинга, генерирует именованный PHP-класс с immutable const для OPcache shared memory, а при диспатче не делает ни одного вызова Reflection. В этой статье — не маркетинг, а код и алгоритмы: разбираю каждое архитектурное решение и сравниваю с FastRoute и Symfony Routing.

В процессе работы с Joomla бывает необходимо работать с пользовательским интерфейсом более тонко, чем обычно. Все формы Joomla состоят из стандартных полей, содержанием, стилем отображения, состоянием (включено/выключено, доступно для редактирования или нет и т.д.) можно управлять с помощью плагинов. Да и для нестандартных проектов хорошей практикой является создание одного системного или нескольких плагинов групп "под проект", в которых хранится весь "нестандарт".
В этой статье описаны все триггеры (события), которые вызываются через Event Dispatcher из administrator/components/com_fields/src/Helper/FieldsHelper.php, с привязкой к жизненному циклу (порядку этапов работы запроса), аргументам, изменяемым данным и дальнейшему распространению по Joomla. Это поможет вам работать с Joomla свободнее и не опасаясь при этом потерять изменения при очередном обновлении движка.

Собрал три легковесных PHP-пакета — DI-контейнер с autowiring, DataMapper поверх PDO и PSR-15 роутер — и с помощью ИИ построил на них DDD-приложение с CQRS. Чистый домен без внешних зависимостей, 92 теста и vendor в 10 раз легче Symfony.

Production-ready PHP-роутер за один вечер: 2 100 строк кода, PHPStan level 9, полное покрытие тестами — и всё при помощи ИИ
Я решил проверить, можно ли за один вечер с помощью ИИ-ассистента создать не прототип и не «потом допилим», а полноценную библиотеку, готовую к публикации на Packagist. Результат — PSR-15 роутер с prefix-trie матчингом, атрибутной маршрутизацией, middleware-пайплайном и кешированием. 8 коммитов, 5 часов 40 минут, ~4 800 строк PHP-кода. Под катом — честный разбор: хронология по git log, где ИИ ускоряет в разы, а где без головы разработчика никуда.

Когда производитель с дилерской сетью из 85+ партнёров решает стандартизировать их сайты — первый инстинкт понятен: сделать JSON-фид с основного домена, настроить синхронизацию, и пусть у всех будет одинаковый актуальный каталог.
Проблема в том, что «одинаковый» и «хорошо индексируемый» — противоречащие друг другу требования, если реализовано наивно. Яндекс видит 85 сайтов с идентичным контентом и поступает предсказуемо.
Под катом — как мы решали эту задачу для крупнейшего производителя сельхозтехники в России (150+ моделей комбайнов и тракторов, 50 000 SKU запчастей): архитектура Lock/Edit на уровне инфоблоков Битрикс, Manticore Search для артикулов со спецсимволами, OpenAI Batch API для обогащения каталога и Python-автоматизация развёртывания 85 поддоменов.

Работая над корпоративным порталом большого предприятия, рано или поздно оказываешься лицом к лицу с типовыми проблемами работы с таблицами: данных много, требования к интерактивности и настройкам — ещё больше, а бизнес не хочет ждать «когда всё подгрузится». Мы вырастили свой универсальный компонент для работы с гридами — и теперь можем честно поделиться: как минимизировать боли, не разрабатывать раз за разом один и тот же функционал в разных сервисах и сделать жизнь разработчика проще.
Наша команда специализируется на развитии корп. портала Группы НЛМК на платформе Битрикс, и еще нескольких корпоративных сайтов.
Значимая часть портала — это широкий набор сервисов для решения задач бизнеса. Например, регистрация и обработка заявок на перевод документов, работа с приёмом делегаций, волонтёрской активностью, проведение оценки рабочих, работа с пользователями (поздравления, благодарности, знаки отличия сотрудников) и многое другое. Несмотря на всё разнообразие сервисов, для их разработки зачастую используются одни и те же функциональные блоки — универсальные "кирпичики" для решения типовых задач.
В предыдущей статье я рассказывал про опыт работы с бизнес процессами 1С-Битрикс. Сейчас хотелось бы затронуть другую, не менее востребованную задачу — задачу по удобному и структурированному выводу данных.

Про эталонный справочник, JWT-авторизацию, требования КИИ и почему 1С-Битрикс вместо Laravel
В 2022 году мы получили задачу: автоматизировать заказы запчастей для 40+ дилеров. Вызов был не в объёме данных (50,000 SKU), а в разнородности систем дилеров и требованиях безопасности КИИ.
Через 18 месяцев 65% заказов пошли через портал без участия операторов. REST API интегрирован с 28 дилерами (70% сети). Время оформления заказа сократилось с 45 минут до 7.
Под катом — архитектурные решения, почему эталонный справочник важнее REST API, и как обойти ограничения КИИ.

Мы сравнили OpenLiteSpeed и классический LEMP для WordPress на реальных серверах. RPS, latency, TTFB, потребление CPU и RAM, поведение под нагрузкой до 500 пользователей. И вот какие итоги у нас получились.
Шлифуя код своего пакета PHP MultiRunner с помощью статических анализаторов кода psalm и phpstan, столкнулся с интересной загадкой — а как в PHP узнать определена ли переменная или нет.
Казалось бы, есть хорошая функция (языковая конструкция) isset(mixed $var, ...$vars): bool. Но в ней есть подвох: если переменная определена значением null, то isset() вернёт для неё false.

Встав утром и посмотрев в профиль, отметил: на Хабре много лет, писал статьи, писал код. И ни разу не писал о коде на Хабре. А вообще‑то разработчик. Поззорище! Пора исправляться.
Поговорим о классической (и болезненной) проблеме кодирования «присваивание вместо равенства» которая в любой момент может создать очень много проблем. О логическом источнике этой ошибке, и о способах решения.
Ну и ещё слегка вспомним «Звездные войны»:-)