Опубликовано исследование о том что индексирование сайтов поисковиком (Google) не зависит от того, SPA ли это или же он SSR. Также пару лет назад делал аналогичное расследование и пришел к тому же выводу.
Вообще, мы пришли к идеалу достаточно давно - когда сервер занимается своими делами, а клиент статический, минифицирован, и раздается из CDN для быстроты и без траты ресурсов сервера.
Автоматическое подключение локализации для веб-ассета в Joomla
Начиная с Joomla 4 в ядре реализована концепция веб-ассетов. Управление JavaScript и CSS в Joomla значительно упростилось благодаря классу WebAssetManager. Есть замечательная статья Как правильно подключать JavaScript и CSS в Joomla 4, в которой подробно и с примерами кода рассказывается об этой концепции и её применении. Например, в web asset мы можем оформить какую-нибудь готовую js-карусель или библиотеку.
Также можно оформить веб-ассетом и свой собственный js-скрипт, которому могут понадобиться дополнительные данные для работы на странице: как данные из PHP, так и языковые константы. С помощью WebAssetManager мы можем получить эти данные в момент сразу при подключении ассета. Как это сделать?
Для веб ассетов в Joomla создаётся файл joomla.asset.json, в котором описываются url подключаемых файлов, версии, их зависимости друг от друга, собираются пресеты для подключения пачкой и т.д. В нём можно указать пользовательский класс WebAssetItem, который будет выполнять нужную работу для вашего ассета. Для этого определите свойства namespace и class для всего файла или же для каждого ассета.
Ассет foo будет работать с классом Joomla\Component\Example\Administrator\WebAsset\FooAssetItem, а ассет bar с классом MyFooBar\Library\Example\WebAsset\BarAssetItem. Если namespace не указан, будет использоваться Joomla\CMS\WebAsset по умолчанию. Ну и сам класс должен находиться по указанному неймспейсу.
<?php
/**
* Класс WebAssetItem для подключения данных для работы веб ассета
*/
namespace Joomla\Component\Example\Administrator\WebAsset\AssetItem;
\defined('_JEXEC') or die;
use Joomla\CMS\Document\Document;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\WebAsset\WebAssetAttachBehaviorInterface;
use Joomla\CMS\WebAsset\WebAssetItem;
class FooAssetItem extends WebAssetItem implements WebAssetAttachBehaviorInterface
{
/**
* Method called when asset attached to the Document.
*
* @param Document $doc Active document
*
* @throws \Exception
*
* @since 1.0.0
*/
public function onAttachCallback(Document $doc)
{
Factory::getApplication()->getLanguage()->load('com_example');
// Add my-js-script.js language strings
Text::script('COM_EXAMPLE_LANGUAGE_STRING_FOR_FRONTEND');
/** @var array $data Данные для фронтенда, чтобы получать их
* в js через Joomla.getOptions('com_example.foo.js.data';)
*/
$data = [
'any' => 'data',
];
/** @var bool $merge Whether merge with existing (true) or replace (false) */
$merge = true;
$doc->addScriptOptions('com_example.foo.js.data', $data, $merge);
}
}
Таким образом для нашего js-скрипта мы получили и локализованные стринги сообщений (как? - пост на Хабре) и дополнительные данные из PHP для фронтенда (статья на Хабре - в середине). Теперь когда вы где-то в любом месте Joomla подключаете веб ассет с помощью $wa->useScript('foo') - автоматически подключится всё необходимое для его работы.
Совет по Joomla: dot-нотация для доступа к значениям вложенных массивов.
Позволю себе немного ребячества ))
Наткнулся на пост в одном из php-шных каналов о том, как в Laravel можно использовать нотацию "точка" для доступа к значениям вложенных массивов. И тем самым упростить доступ к многомерным массивам с помощью одной строки, разделенной точками.
Multipart Upload в Laravel: загрузка больших файлов в S3
Что такое Multipart Upload и зачем он нужен?
Multipart Upload - это метод загрузки больших файлов в S3, при котором файл разбивается на части (чанки) и загружается параллельно. Это решает несколько ключевых проблем:
Надёжность - при обрыве соединения можно перезагрузить только failed-часть
Производительность - параллельная загрузка частей ускоряет процесс
Обход ограничений - позволяет загружать файлы больше 5 ГБ (максимальный размер для простой загрузки)
Как реализовать Multipart Upload в Laravel
1. Установка зависимостей
Убедитесь, что у вас установлен AWS SDK (обычно идёт с Laravel): composer require aws/aws-sdk-php
2. Пример реализации
use Illuminate\Http\UploadedFile;
use Aws\S3\MultipartUploader;
use Aws\Exception\MultipartUploadException;
private function uploadFileToS3(UploadedFile $file, string $fileName): string
{
// Получаем клиент S3 из Storage фасада
$client = Storage::disk('s3')->getClient();
// Путь для сохранения в S3 (можно добавить подпапки по дате и т.д.)
$s3Path = $this->s3path.'/'.$fileName;
// Настройки загрузчика
$uploader = new MultipartUploader($client, $file->getPathname(), [
'bucket' => config('filesystems.disks.s3.bucket'),
'key' => $s3Path,
'part_size' => 5 * 1024 * 1024, // 5 MB за часть чанка
'concurrency' => 3, // Количество параллельных загрузок
'before_initiate' => function ($command) {
// Можно добавить метаданные или ACL
$command['ACL'] = 'public-read';
},
'before_upload' => function ($command) {
// Логирование перед загрузкой каждой части
Log::info('Uploading part', [
'part_number' => $command['PartNumber'],
'upload_id' => $command['UploadId']
);
},
]);
try {
// Запускаем процесс загрузки
$result = $uploader->upload();
// Возвращаем полный путь к файлу в S3
return $s3Path;
} catch (MultipartUploadException $e) {
// Логируем ошибку
Log::error('Multipart upload failed', [
'file' => $fileName,
'error' => $e->getMessage(),
'upload_id' => $e->getUploadId()
]);
// Можно попробовать возобновить загрузку
// $this->resumeUpload($e->getUploadId(), $s3Path);
throw new \Exception('File upload failed: '.$e->getMessage());
}
}
3. Дополнительные методы для работы с Multipart Upload
В Joomla 4 и Joomla 5 появилась концепция Web Assets и WebAssetManager, с помощью которого можно управлять подключениями css, js файлов, подключением. Все css и js файлы включаются в общий реестр ассетов, затем выстраивается граф зависимостей и в итоге на генерируемую страницу подключается только то что нужно на данной странице.
Поскольку веб-ассеты можно добавлять с помощью плагинов (ссылка на статью ниже) - можно сказать, что появилось новое направление для плагинов - веб-ассеты. Вы можете устанавливать плагины, включающие веб-ассеты и использовать их как зависимости в самых разных местах Joomla: в шаблоне, в макетах модулей и плагинов.
Одним из таких плагинов веб-ассетов является WT JSwiper.js. Плагин добавляет в Joomla Web Assets Registry ассет популярного скрипта swiper.js, который потом легко можно использовать в коде:
use Joomla\CMS\Factory;
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
// Локальный файл
$wa->useScript('swiper-bundle')->useStyle('swiper-bundle');
// Подключение из CDN
$wa->usePreset('swiper-bundle-remote');
😐 Например, было: иконочный шрифт могут использовать 2 разных модуля. CSS обычно подключается в шаблоне и он грузится везде, даже там, где не надо. Если же подключать CSS в одном модуле, а в другом нет - на странице стиль есть ровно до тех пор, пока опубликован модуль с этим подключением.
👍 Стало: теперь в макетах расширений мы просто пишем $wa->useStyle('my.style'); и за необходимостью подключения нужного ассета (в данном случае CSS с иконочным шрифтом) следит Web Asset Manager. Если мы снимем один модуль с публикации, то нужный ассет подключит другой модуль.
Поскольку плагин - расширение Joomla - его можно обновлять обычным для Joomla способом и всегда иметь самую свежую версию любимого js-скрипта или веб-ассета на всех своих сайтах и сайтах ваших клиентов.
В этой версии, кроме обновления собственно ассета до версии 11.2.5 к нему добавился пока что частичный перевод документации Swiper на русский язык.
Некоторых разработчиков и вебмастеров интересует останется ли плагин обратной совместимости в Joomla 6. Этот плагин был создан для того, чтобы сделать переход от версии к версии более гладким и бесшовным. Подробнее почитать о роли плагина можно в официальной документации на manual.joomla.org: Compatibility Plugin.
Устаревший код МОЖЕТ быть перемещен в плагин совместимости. Плагин обеспечивает более плавное обновление между основными версиями. Он содержит код из предыдущей версии, который может сломать сайт после обновления, поскольку расширение использует устаревший код. Расширение полностью совместимо только тогда, когда оно работает без проблем с отключенным плагином совместимости.
От версии к версии часть кода ядра Joomla помечается как устаревшая, а затем, спустя некоторое время удаляется из основного ядра и МОЖЕТ быть перемещена в плагин обратной совместимости. Эта концепция появилась при переходе от Joomla 4 к Joomla 5.
Важным уточнением является то, что для новой мажорной версии (joomla 3, joomla 4, joomla 5 и т.д.) плагин содержит устаревший код предыдущей версии. То есть для Joomla 5 это код из Joomla 4. Для Joomla 6 - код из Joomla 5.
Таким образом расширения, использующие методы и функции ядра Joomla и всё ещё работающие даже с плагином обратной совместимости на Joomla 5 в Joomla 6 скорее всего работать уже не будут. В Joomla 6 из плагина обратной совместимости будет удален код, поддерживающий обратную совместимость с Joomla 4. Таким образом стабильно работать в Joomla 6 будет то, что сейчас стабильно работает на Joomla 5 с отключённым плагином обратной совместимости.
Joomla-разработчикам: обращение к методам модели в HtmlView напрямую
Когда-то, давным-давно в одной далёкой галактике кто-то решил, что было бы неплохой идеей ввести в Joomla косвенный доступ к методам модели (MVC) для получения данных, добавив метод AbstractView::get(). Этот метод извлекает модель и затем запускает get(). Простыми словами, когда мы во View (файл HtmlView нашего компонента) видим конструкцию $this->item = $this->get('Item') это означает обращение к методу getItem() модели для текущего View.
Но такой подход исключает любую возможность подсказки типов, аргументов и т. д. и делает все излишне сложным. Поэтому разработчики ядра Joomla объявили этот метод устаревшим с этим PR 44162.
Новый способ выглядит так:
// Файл HtmlView компонента
public function display($tpl = null)
{
$model = $this->getModel();
$this->items = $model->getItems();
parent::display($tpl);
}
Старый подход (то есть метод get() во View) будет удалён в Joomla 7. Памятуя о релизном цикле Joomla, это означает, что:
осенью 2025г выйдет Joomla 6.
2 года она будет основной веткой. Joomla 5 будет в режиме поддержки
через 2 года, в 2027 выйдет Joomla 7, в которой будет удалён этот метод.
но Joomla 6 будет ещё 2 года в режиме тех.поддержки и в ней (до 2029 года) этот метод останется.
Таким образом у разработчиков есть от 2,5 до 4,5 лет (на момент написания этого поста) на то, чтобы сделать этот рефакторинг.
Совет по Joomla: показ уведомлений Joomla.renderMessages.
Пользователь совершает какие-то действия на сайте и получает сообщения об успешном или не успешном их результате, а также просто информационные сообщения. В php коде мы привыкли использовать для этого метод enqueueMessage():
use Joomla\CMS\Factory;
$html = 'Message';
Factory::getApplication()->enqueueMessage($html, 'warning');
Чаще всего в качестве сообщения используются языковые константы, чтобы пользователи могли получать сообщения на своём языке:
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
Factory::getApplication()->enqueueMessage(Text::_('SOME_LANG_CONSTANT'), 'info');
Рендер сообщений Joomla во фронтенде.
Здесь нам потребуется файл подключённые файлы ядра core.js и messages.js. Немного выдержки из кода:
/**
* Рендер сообщений, отправленных через JSON
* Используется некоторыми javascript, в частности validate.js
*
* @param {object} messages JavaScript объект, содержащий сообщения для рендера.
* Пример:
* const messages = {
* "message": ["Это будет зелёное сообщение", "И это тоже"],
* "error": ["Это будет красное сообщение", "И это тоже"],
* "info": ["Это будет синее сообщение", "И это тоже"],
* "notice": ["Какое-то информационное сообщение", "И это тоже"],
* "warning": ["Оранжевое сообщение", "И это тоже"],
* "my_custom_type": ["Такое же как инфо-сообщение", "И это тоже"]
* };
* @param {string} selector CSS-селектор контейнера для рендера сообщений
* @param {bool} keepOld Удалить предыдущие сообщения? Да, если true
* @param {int} timeout Таймаут исчезновения сообщения в миллисекундах
* @return void Метод ничего не возвращает
*/
Теперь мы видим, что в качестве сообщения мы и в Javascript можем использовать языковые константы. Для этого мы используем метод Joomla.Text._() (по аналогии с Text::_() в PHP). Но Javascript откуда-то должен получить значения этих языковых констант. И для этого в php коде нашей страницы мы должны позаботиться о нём и добавить нужные для js языковые константы с помощью метода Text::script().
use Joomla\CMS\Language\Text;
Text::script('SOME_LANG_CONSTANT_SUCCESS');
Text::script('SOME_LANG_CONSTANT_FAIL');
Таким образом я смогу получить в js доступ к значениям языковых констант SOME_LANG_CONSTANT_SUCCESS и SOME_LANG_CONSTANT_FAIL.
Событие Pizza, Bugs & Fun приближается - 22 февраля 2025 года
Уже несколько лет в мире Joomla проводятся мероприятия "Pizza, Bugs & Fun" (#PBF), где каждый может посвятить несколько часов своего мозгового времени тому, чтобы наша любимая CMS стала ближе к идеалу.
Видео из этого поста рассказывает об организационных вопросах, которые пригодятся для участия в PBF:
как создать аккаунт в Mattermost (чат международного Joomla-сообщества)
как создать аккаунт в Joomla! Documentation
как написать статью в Joomla! Documentation
как создать аккаунт на GitHub (у разработчиков обычно уже он есть)
как настроить патч тестер
как протестировать патч
как получить вознаграждение
В рамках события PBF все желающие могут собираться в общий онлайн чат, обсудить вопросы Joomla и приложить к их разрешению свою руку. Самый классный вариант, когда эта встреча происходит оффлайн: тогда организовывается пицца, напитки по вкусу и несколько часов совместного творчества.
Каждый помогает тем, что он умеет:
кто-то пишет недостающую документацию,
кто-то пишет код,
кто-то тестирует как исправлены ошибки или сделан новый функционал.
На сайте события есть карта, можно "захостить" свою локацию. Практически все движки в мире развиваются за счёт спонсирующих их компаний. Joomla одна из немногих, где развитие идёт только усилиями международного сообщества энтузиастов.
На момент написания данного поста в репозитории Joomla 752 открытых Issue (как правило это баги) и 223 Pull request (PR, исправление багов и новый функционал). Все PR обязательно тестируются минимум двумя участниками сообщества, дабы в конечный код движка не проскочила ошибка.
Если каждый из участников только нашего сообщества сделает даже одно тестирование, то, боюсь, PR и Issue на всех не хватит 😀
Модули порой удобно использовать в местах, которые в Joomla не всегда предназначены для этого 😀. Например, в переопределениях макета. Из материала делаем посадочную страницу: часть инфы находится в самом материале, часть - в полях, а часть удобно вывести модулем. При этом модуль этот должен находиться между телом материала и данными из пользовательских полей.
Для реализации берём в руки ModuleHelper и приступаем.
<?php
use \Joomla\CMS\Helper\ModuleHelper;
$modules = ModuleHelper::getModules('landing-masonry');
if(!empty($modules))
{
foreach ($modules as $module)
{
// рендерим всё, что нашли в позиции landing-masonry
echo ModuleHelper::renderModule($module);
}
}
А что если посложнее?
В этом случае всё просто. Но здесь в тему будет упомянуть ещё один способ работы с модулями. Контекст: магазин одежды. В карточке товара нужно вывести информацию о размерной сетке, типовые рекомендации по уходу и т.д. Это короткие тексты, которые повторяются из товара в товар и не нужно их копировать многажды. Эти тексты отображались простым аккордеоном Bootstrap.
Вид карточки товара JoomShopping. Все тексты, кроме описания товара - одинаковые во всех товарах. Описание товара уникальное для каждого товара.
Но! В этот же аккордеон нужно было добавить и описание товара JoomShopping. Поэтому я сделал с помощью своего модуля WT Quick links следующее.
Создал модуль типа WT Quick Links, в котором в список элементов занёс все нужные тексты.
Не стал назначать модуль какой-либо позиции. В шаблоне JoomShopping захардкодил id модуля. Хотя лучше было бы назначить модуль в некой уникальной позиции, которая встречалась бы только в нужном нам месте на сайте.
Программным способом в данные модуля добавил нужные данные из JoomShopping так, как мне нужно (в начало списка - описание товара).
Отрендерил модуль с помощью ModuleHelper в product_default.php шаблона JoomShopping.
<?php
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\Registry\Registry;
// Модуль id 136 - Доставка, оплата и гарантии в карточку товара + ОПИСАНИЕ ТОВАРА JoomShopping
$module = ModuleHelper::getModuleById('136');
$module_params = new Registry($module->params);
// Формируем новые параметры модуля перед рендером.
$new_module_params = [];
$i = 1;
// Помещаем описание товара в самое начало
if (!empty($this->product->description)){
$new_module_params['fields']['fields0'] = (object) [
'item_header' => Text::_('JSHOP_DESCRIPTION'),
'item_text' => $this->product->description
];
}
// Переименовываем все остальные ключи массива элементов из модуля
foreach ($module_params->get('fields') as $key => $value)
{
$new_module_params['fields']['fields' . $i] = $value;
$i++;
}
$new_module_params = new Registry($new_module_params);
// Соединяем старые и новые параметры модуля.
$module_params->merge($new_module_params);
$module->params = $module_params->toString();
// Всё готово! Рендерим модуль.
echo ModuleHelper::renderModule($module);
Разработчикам мобильных и WEB-приложений (и не только) весьма и весьма пригодится готовая коллекция для Postman. В коллекцию добавлены endpoint для REST API Joomla, с параметрами и примерами запросов.
Коллекция составлена трудами французского Joomla-разработчика Alexandre J-S William ELISÉ.
Совет по Joomla: метод debug() для отладки лейаутов
В Joomla есть понятие layout. Это кусочек вёрстки, который можно многажды использовать в любом месте сайта: как в панели администратора, так и во фронтенде. Можно рассматривать лейауты как оторванные от контекста элементы дизайна. Находятся они в папке layouts в корне сайта. Также, в случае с модулями они могут находиться в папке tmpl модуля. А в случае с плагинами - в tmpl плагина.
Их можно переопределять в шаблонах, в чём и заключается одна из главных фишек Joomla. Лейауты чаще всего рендерятся с помощью классов LayoutHelper или напрямую FileLayout. Писал о них ранее тут и тут.
А вот как увидеть какой именно файл переопределения используется? Сколько их вообще есть и по каким путям идёт поиск макетов? Для этого есть метод debug() (и у LayoutHelper и у FileLayout).
<?php
/**
* Method to render a layout with debug info
*
* @param string $layoutFile Dot separated путь к файлу относитеьлно basePath
* @param mixed $displayData Объект с данными для рендера
* @param string $basePath Base path, где будет поиск файлов лейаутов
* @param mixed $options Дополнительные опции для FileLayout
*
* @return string
*
* @since 3.5
*/
public static function debug($layoutFile, $displayData = null, $basePath = '', $options = null)
{
// Так проще показать параметры метода.
}
E-mail шаблоны Joomla 5: добавление и просмотр своих переменных
В Joomla 5 появились настраиваемые email-шаблоны, как системные, так и сторонних компонентов. Их нельзя (пока что) добавить самостоятельно, они добавляются расширениями при установке. Но их можно отредактировать в Система - Шаблоны - Шаблоны писем. В настройках шаблонов писем (кнопка настроек компонента в верхнем правом углу) мы выбираем формат писем текст или HTML. Тогда становятся доступны настройки макетов шаблонов писем Joomla. Эти глобальные параметры можно переопределить в каждом конкретном email-шаблоне. Таким образом для каждого из email-шаблонов можно указать свою вёрстку и настройки логотипа. Это, конечно, требует отдельной подробной статьи...
Для разработчиков: как добавить свои переменные для e-mail шаблонов Joomla?
Полезны окажутся 2 триггера для плагинов: onMailBeforeTagsRendering и onMailBeforeRendering.
onMailBeforeRendering - триггер, который позволяет добавлять свои шорт-коды для строковой замены в плагине. Отдать туда надо массив вида [ variable_name => variable_value ]. Из админки свои переменные нужно добавлять уже с фигурными скобками: {variable_name} заменится на variable_value. Аргументом $event плагина является экземпляр класса BeforeRenderingMailTemplateEvent, в котором есть кроме прочих 2 метода: getTemplate() (получение объекта мейлера, куда можно добавлять свои данные) и getTemplateId() (получение id шаблона письма вида com_users.registration.admin.new_notification), по которому мы определяем нужный ли это для нас email-шаблон или нет. Аналогично контексту в контент-плагинах.
Также полезное свойство класса для передачи данных из плагина в лейаут письма для рендера - $layoutTemplateData. Это ассоциативный массив.
// Получаем текущий мейлер
$mailTemplate = $event->getTemplate();
$data = [
'variable_name' => 'variable_value'
];
// с Joomla 4 для всех типов писем. 2-й аргумент - plain - текстовый формат письма
$mailTemplate->addTemplateData($data, false);
// с Joomla 5.2 - для HTML-писем
$mailTemplate->addLayoutTemplateData($data);
// пример из ядра Joomla
// Add additional data to the layout template
$this->addLayoutTemplateData([
'siteName' => $app->get('sitename'),
'lang' => substr($this->language, 0, 2),
]);
onMailBeforeTagsRendering - триггер, который добавляет ваши переменные в список доступных переменных для замены в окне редактирования email шаблона Joomla. Отдать туда нужно массив с переменными, но без их значений.
Подготовка расширений к Joomla 6: CMSObject -> stdClass
В Joomla 6 метод getItem() в Adminmodel будет возвращать \stdClass вместо CMSObject. Это означает, что все устаревшие функции этого класса будут недоступны.
Разработчики в Joomla 6 должны напрямую работать со свойствами объекта item и не использовать устаревшие методы set() и get().
В современном мире разработка корпоративных приложений требует высокой скорости, гибкости и использования проверенных решений. Проект Enterprise Skeleton был создан, чтобы помочь разработчикам сосредоточиться на бизнес-логике, а не на рутинных задачах настройки инфраструктуры. Этот шаблон включает современные инструменты, лучшие практики и интеграции для построения масштабируемых приложений.
Особенность проекта в его модульной архитектуре, которая поддерживает популярные PHP-фреймворки (Symfony и Laravel), и в возможности быстро адаптировать его под нужды конкретной команды или компании.
4) Для смены фреймворка используйте команду (symfony по умолчанию):
make framework laravel
5) Устанавливаем зависимости и запустите проект:
make install
Основные возможности
Поддержка современных PHP-фреймворков (Symfony, Laravel).
Возможность работы с SQL и NoSQL базами данных (PostgreSQL, MySQL, MongoDB, Cassandra).
Интеграция с брокерами сообщений (RabbitMQ, Kafka).
Мониторинг с использованием Zabbix и Grafana.
Кеширование через Redis и Memcached.
Логирование и аналитика с использованием ELK-стека (Elasticsearch, Logstash, Kibana) или Graylog.
Автоматическое тестирование API через Postman.
Удобный запуск и настройка крон-задач через Docker.
и другие...
Каждая из этих функций адаптируется под ваш проект, что делает Enterprise Skeleton универсальным инструментом для разработки.
Помимо описанных возможностей, проект интересен своей структурой. Например, благодаря доменно-ориентированной архитектуре можно эффективно разделять логику приложения. Это особенно полезно для больших команд, где разработчики работают над отдельными доменами.
Кроме того, я бы рекомендовал использовать Enterprise Skeleton как для вашего нового проекта так и для обучения junior-разработчиков. Он помогает изучить современные подходы в разработке, такие как DDD (Domain-Driven Design), автоматизация тестирования и CI/CD.
Нам нужны контрибьюторы
Проект активно развивается, и мы всегда рады новым участникам. Если вы хотите присоединиться, вот направления, где особенно нужна помощь:
Интеграция Sentry: реализация мониторинга и отслеживания ошибок.
Интеграция других фреймворков: добавление поддержки Yii, Slim и других популярных PHP-фреймворков.
Чтобы начать, просто форкните репозиторий, создайте новую ветку, внесите изменения и отправьте Pull Request. Мы ждем ваши идеи и улучшения!
Выводы
Enterprise Skeleton — это мощный инструмент для быстрой разработки и масштабирования корпоративных приложений. Он подходит как для небольших стартапов, так и для крупных компаний, которым нужна стабильная основа для приложений.
Пробуйте, участвуйте в разработке и делитесь своим опытом. Вместе мы можем сделать проект еще лучше!
Всегда интересно посмотреть на свой продукт глазами других разработчиков. Особенно когда это честное сравнение, без попытки кого-то выделить или принизить. Автор очень детально разобрал оба пакета, и что меня особенно порадовало — отметил именно те моменты, на которые мы делали упор при разработке MoonShine.
Главный вывод автора — ключевое различие между пакетами в использовании Livewire. И тут я полностью согласен! Мы специально отказались от Livewire в MoonShine, чтобы добиться максимальной производительности. Например, при работе с модальными окнами мы делаем всего один запрос при первом открытии, а дальше работаем с кешированными данными.
Кстати, автор также отметил нашу встроенную систему импорта/экспорта и отдельную таблицу для администраторов — это действительно важные фичи, которые мы добавили исходя из реального опыта разработки админок.
Приятно видеть, что наши архитектурные решения замечают и ценят. Хотя, конечно, выбор между Filament и MoonShine всегда будет зависеть от конкретного проекта и предпочтений команды.
Совет о Joomla: использование FileLayout для рендера элементов макета.
Этот механизм используется под капотом Joomla для рендера отображения почти всех элементов интерфейса как фронта, так и админки. Обычно переиспользуемые "запчасти" выносятся в отдельные файлы: кнопки, тулбары, меню, табы и т.д. Для унификации отображения каждого элемента нужны некие данные данные и/или параметры: например, заголовок таба, надпись или onclick для кнопки, CSS класс и т.д.
<?php
use Joomla\CMS\Layout\FileLayout;
/**
* Method to instantiate the file-based layout.
*
* @param string $layoutId Dot separated путь к файлу, включая имя файла относительно base path
* @param string $basePath Основной путь к папке с макетами
* @param mixed $options Данные, нужные для работы макета. Registry или массив
*
* @since 3.0
*/
$layout = new FileLayout('layout_file_name', JPATH_SITE . '/path/to/your/layout', ['buttonName' => 'Button name']);
// Рендерим наш макет
echo $layout->render();
Внутрь файла (/path/to/your/layout/layout_file_name.php в нашем случае) передаются данные и параметры для рендера. Получить эти данные можно следующим образом.
<?php
// Это содержимое файла /path/to/your/layout/layout_file_name.php
// Переданные данные приходят в формате Registry. Можно указать значение по умолчанию
$buttonName = $this->options->get('buttonName', 'Default name if value is empty');
?>
<button class="btn btn-primary"><?php echo $buttonName;?></button>