Pulse Boson PHP #1

от автора

Привет, коллеги!
Решил организовать небольшую рубрику с новостями по проекту 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 развивается! Приглашаю участвовать в разработке и тестировании. Присоединяйтесь!


ссылка на оригинал статьи https://habr.com/ru/articles/944716/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *