Привет, коллеги!
Решил организовать небольшую рубрику с новостями по проекту Boson PHP. Вкратце о проекте, для тех, кто не в курсе.
Boson PHP — это платформа для создания кроссплатформенных настольных приложений, которая позволяет использовать веб-технологии (PHP, JavaScript, HTML, CSS) для создания native-приложений. Она сочетает в себе интерпретатор PHP и движок WebView, что позволяет собирать приложения в единый исполняемый файл для Windows, Linux и macOS. Для PHP-разработчиков, желающих выйти за рамки веба и создавать кроссплатформенные приложения с использованием знакомого стека технологий. Его ключевые преимущества — легкость, производительность и простота.
Хедлайнер проекта Кирилл Несмеянов, ну а коллектив разработчиков: Алексей Гагарин, Дмитрий Дерепко и я (Данил Щуцкий) помогаем ему.
20 августа состоялся второй стрим по Boson PHP. Расскажу вкратце, что там было интересного. За 4 месяца с момента предыдущего прямого эфира в проекте произошло много изменений:
Запуск нового лендинга bosonphp.com
Последний месяц команда работала над новым лендингом, который зарелизили в прямом эфире. Весь лендинг создан с использованием веб-компонентов (основа Boson). Верстая лендинг чуть не надорвался @krvvko, спасибо ему за работу!
Новая документация
-
Переход с JetBrains WriterSite на собственное решение — предыдущая система была не очень удобна для версионирования и переводов. Делали лендинг, решили заодно создать и движок документации
-
Версионирование документации — доступны версии 15, 16, 17 и master с возможностью переключения
-
Четкое разделение по разделам:
-
Application — общие вопросы приложения
-
Windows — управление окнами
-
WebView — веб-интерфейс и компоненты
-
Deployment — компиляция и сборка
-
Демонстрация веб-компонентов
Значительная часть стрима была посвящена детальной демонстрации веб-компонентов — главной особенности Boson, которые используют нативные возможности браузеров вместо виртуального DOM. Давайте разберемся на примерах, как это работает.
Создаем свой первый компонент
Все просто — регистрируем компонент и используем. Главное правило: в названии тега должен быть дефис!
class MyAwesomeButton {} $app = new Boson\Application(); // Tag component name $tag = 'my-button'; // Component class name $component = MyAwesomeButton::class; $app->webview->components->add('my-button', MyAwesomeButton::class); $app->webview->html = '<my-button>Нажми меня!</my-button>';
Делаем шаблоны
Обычный HTML-шаблон
Хотите кастомный внешний вид? Легко!
class MyAwesomeButton implements HasTemplateInterface { public function render(): string { return '<button class="fancy-btn">🎉 Крутая кнопка! 🎉</button>'; } }
Shadow DOM — для продвинутых
Shadow DOM изолирует ваши стили и добавляет поддержку слотов:
class MyCard implements HasShadowDomInterface { public function render(): string { return ' <div class="card"> <h3>Заголовок карточки</h3> <slot></slot> <!-- Сюда попадет содержимое --> </div> '; } }
Следим за жизненным циклом
Хотите знать, когда ваш компонент появился или исчез со страницы?
class MyComponent implements HasLifecycleCallbacksInterface { public function onConnect(): void { echo "Привет! Я появился на странице! 👋"; } public function onDisconnect(): void { echo "Пока! Меня удалили 😢"; } }
Добавляем интерактивность
Свойства — данные из JavaScript
Отслеживаем, когда JS меняет свойства компонента:
class Counter implements HasPropertiesInterface { public function onPropertyChanged(string $property, mixed $value): void { if ($property === 'count') { echo "Счетчик изменился! Новое значение: $value"; } } public static function getPropertyNames(): array { return ['count']; // Следим за свойством count } }
// В JavaScript let counter = document.createElement('my-counter'); counter.count = 42; // PHP получит уведомление!
Методы — вызываем PHP из JavaScript
Самое интересное! Можно вызывать PHP-методы прямо из браузера:
class Calculator implements HasMethodsInterface { public function onMethodCalled(string $method, array $args = []): mixed { switch ($method) { case 'add': return $args[0] + $args[1]; case 'greet': return "Привет из PHP! 🐘"; default: throw new \BadMethodCallException("Метод $method не найден"); } } public static function getMethodNames(): array { return ['add', 'greet']; } }
<!-- В HTML --> <my-calculator onclick="this.greet()">Калькулятор</my-calculator>
// Или асинхронно из JS const calc = document.createElement('my-calculator'); let result = await calc.add(5, 3); // Вернет 8!
Атрибуты — реагируем на изменения HTML
Следим за изменениями атрибутов в реальном времени:
class StatusBadge implements HasAttributesInterface { public function onAttributeChanged(string $attribute, ?string $value, ?string $previous): void { if ($attribute === 'status') { if ($value === null) { echo "Статус удален!"; } elseif ($previous === null) { echo "Добавлен статус: $value"; } else { echo "Статус изменен с '$previous' на '$value'"; } } } public static function getAttributeNames(): array { return ['status', 'priority']; } }
События — обрабатываем клики и прочее
Ловим события браузера в PHP:
class InteractiveWidget implements HasEventListenersInterface { public function onEventFired(string $event, array $args = []): void { if ($event === 'click') { $x = $args['x']; $y = $args['y']; echo "Кликнули по координатам: $x, $y"; } } public static function getEventListeners(): array { return [ 'click' => [ 'x' => 'clientX', // Переименовываем clientX в x 'y' => 'clientY' // Переименовываем clientY в y ], ]; } }
Реактивный контекст — управляем компонентом
Это ваш главный инструмент для программного управления компонентом:
use Boson\WebView\Api\WebComponents\ReactiveContext; class SmartComponent implements HasMethodsInterface { public function __construct(private ReactiveContext $ctx) {} public function refresh(): void { // Проверяем атрибуты if (!$this->ctx->attributes->has('loaded')) { $this->ctx->attributes->set('loaded', 'true'); } // Меняем содержимое if ($this->ctx->content->html === '') { $this->ctx->content->html = '<p>Контент загружен! ✅</p>'; } } public function onMethodCalled(string $method, array $args = []): mixed { if ($method === 'refresh') { $this->refresh(); return 'Обновлено!'; } } public static function getMethodNames(): array { return ['refresh']; } }
В документации можно изучить подробнее.
И помните: с Boson Web Components вы получаете всю мощь серверного PHP прямо в браузерных компонентах!
Демонстрация реального приложения: HappyWife HappyLife
Алексей Гагарин на стриме продемонстрировал своё приложение — систему с LLM-агентами для «спасения жизни мужиков», как он это назвал.
Изначальная архитектура: “обычное Spiral-приложение” на Roadrunner и FPM со стандартным веб-интерфейсом. Для создания приложения на Boson PHP потребовалось добавить только один файл — Boson bootloader из spiral-bridge пакета. Никаких изменений в коде — приложение заработало сразу.
В ходе тестирования приложения поняли, что для полного счастья не хватает:
-
WebSockets/Server-Sent Events — для real-time взаимодействия
-
Унифицированное API — одинаковый интерфейс для PHPS, Roadrunner и Boson
-
Стримовые ответы — для потокового вывода токенов от LLM
Технические детали архитектуры
Реактивность под капотом: как это работает изнутри
Кирилл подробно объяснил архитектуру системы и её особенности:
-
Единый процесс — PHP и WebView работают в одном процессе, общение между ними через shared memory без дополнительных накладных расходов.
-
API интеграция. Используется WebKit API и Blink API верхнего уровня. Вызовы проходят напрямую (в обход промежуточных слоев), а события DOM передаются напрямую в PHP-коллбеки.
-
Производительность. Позволяет выполнять ~100 тысяч операций в секунду, но есть узкое место — JSON encode/decode для сложных объектов
Операционные системы
Windows. Самая любимая у Boson PHP по состоянию на сегодняшний день:
-
Использует Edge WebView2 — самый стабильный движок
-
Сборка работает «из коробки» без дополнительных настроек
-
Есть проблема — готовый .exe имеет логотип PHP и метаданные от оригинального интерпретатора! Но есть план как победить это — требует патчинг COFF-файлов для замены иконки и версионной информации.
Linux. Работает, но с нюансами.
-
Проблемы с системами безопасности (AppArmor)
-
Не все дистрибутивы одинаково поддерживают WebKitGTK. Продумываются обходные пути: запуск в контейнере или отключение ограничений
macOS. Замыкает тройку лидеров.
-
Safari «не лучший браузер во вселенной» для таких задач
-
Полная поломка с Revolt — event loop не работает в принципе «На macOS даже простые вещи не работают. Revolt нарушает традиционные ценности macOS, его любовь к простоте и удобству» Отставание этой платфомы объясняется отсутствием у Кирилла устройства Mac для разработки (уже пофикшено и Кирилл купил себе для работы по Boson PHP).
Расширенная интеграция с PHP фреймворками
Уже реализованы:
-
Laravel: полноценный service provider
-
Symfony: готовый bundle
-
Spiral: встроенная интеграция
-
PSR-совместимые: через HTTP-мост
Размер и производительность: конкретные цифры
Сравнили Boson PHP и Native PHP. Как вы догадались Boson в руках своего автора не оставил шансов конкуренту — в разы легче и быстрее, как и написано на лендинге. Но всё равно есть куда стремиться и уже намечены еще варианты по дальнейшей оптимизации.
Ссылка на стрим:
Будущее проекта: планы и ожидания
Архитектурные улучшения
-
Система плагинов — вынос Network API, Battery API в отдельные расширения
-
Избежание конфликтов — не использовать существующие DI-контейнеры
-
Модульность — возможность включать в сборку только нужные компоненты
Ожидание релиза Saucer v7, обновления библиотеки для отображения WebView внутри нативных приложений. В нём ожидается:
-
Решение проблем с памятью — исправление багов PHP FFI с указателями
-
Нативные хендлы — прямой доступ к платформенным API
-
Новые возможности — камера, геолокация, нотификации через OS API
Boson PHP развивается! Приглашаю участвовать в разработке и тестировании. Присоединяйтесь!
-
Telegram-чат: https://t.me/boson_php
-
Discord: https://discord.gg/vCg52Jdwvc
-
GitHub: https://github.com/boson-php
-
Официальный сайт: https://bosonphp.com
-
Документация: https://bosonphp.com/doc/0.17/introduction
ссылка на оригинал статьи https://habr.com/ru/articles/944716/
Добавить комментарий