PHPackages                             govorun/framework - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. govorun/framework

ActiveLibrary[Framework](/categories/framework)

govorun/framework
=================

Multi-messenger bot framework for PHP

v4.1.0(3w ago)0531MITPHPPHP ^8.3

Since Mar 27Pushed 3w agoCompare

[ Source](https://github.com/bromimo/govorun-framework)[ Packagist](https://packagist.org/packages/govorun/framework)[ RSS](/packages/govorun-framework/feed)WikiDiscussions develop Synced 3w ago

READMEChangelogDependencies (66)Versions (33)Used By (1)

Govorun Framework
=================

[](#govorun-framework)

Мульти-мессенджер бот-фреймворк на PHP 8.3+. Один код — разные мессенджеры (на сегодня поддерживается Telegram; интерфейсы готовы под Viber/WhatsApp). Используется визуальным билдером [`govorun-factory`](https://github.com/bromimo/govorun-factory) как целевой рантайм для сгенерированных проектов.

> **v3.x (breaking, краткая шпаргалка по миграции с v1.x):**
>
> - `Keyboard::button()` / `->row()` удалены. Только `Keyboard::make()->buttons([[Button::make('…')->action('…'), …], …])`.
> - `Button::make(...)` + fluent: `->action()`, `->url()`, `->requestContact()`, `->requestLocation()`.
> - `Keyboard::reply()->resize()->oneTime()` — fluent-флаги для reply-клавиатуры.
> - `Step::ask(string|OutgoingMessage $msg, Closure|Keyboard|null $keyboard)` — клавиатуру можно передавать напрямую.
> - В `Controller` и `Flow` подмешан трейт `MakesHttpCalls` — `$this->http()->connection('slug')->...`.

Быстрый старт
-------------

[](#быстрый-старт)

```
composer create-project govorun/skeleton my-bot
cd my-bot
```

Положите токен в `.env`:

```
TELEGRAM_BOT_TOKEN=your-token
```

Установите вебхук:

```
php govorun webhook:install
```

Подробный пользовательский гид — [`govorun-skeleton`](https://github.com/bromimo/govorun-skeleton). Если бот сгенерирован фабрикой — просто разверните ZIP, `composer install`, заполните `.env` и `php govorun webhook:install`.

---

Архитектура
-----------

[](#архитектура)

### Жизненный цикл запроса

[](#жизненный-цикл-запроса)

```
HTTP POST → public/index.php → Application::handleWebhook()
  1. loadEnvironment()             — загрузка .env
  2. loadConfiguration()           — загрузка config/*.php
  3. registerCoreProviders()       — EventServiceProvider, LogServiceProvider, StateServiceProvider
  4. registerConfiguredProviders() — провайдеры из config('app.providers')
  5. boot()                        — boot всех провайдеров
  6. loadRoutes()                  — routes/messenger.php
  7. resolveDriverName()           — драйвер из URL
  8. resolveDriver()               — экземпляр драйвера
  9. verifyWebhook()               — проверка подписи
 10. parseUpdate()                 — парсинг в IncomingMessage
 11. FlowHandler::handle()         — возобновление активного Flow (если есть)
 12. Router::dispatch()            — диспатч в Controller или Flow-старт

```

### Структура пакета

[](#структура-пакета)

```
src/
├── Console/            CLI: make:controller, make:flow, make:api-client,
│                       migrate, state:clear, test, webhook:install/remove,
│                       bot:profile-sync
├── Contracts/          MessengerDriver, StateStorage, StateAccessor
├── Database/Migrations CreateGovorunStatesTable
├── Drivers/Telegram/   TelegramDriver (URL и локальный файл через multipart)
├── Events/             EventServiceProvider
├── Exceptions/         SendFailedException, ApiException
├── Foundation/         Application (Illuminate Container), ServiceProvider
├── Http/               Request, ApiClient (abstract), HttpManager,
│                       ConnectionClient, HttpResponse, MakesHttpCalls trait
├── Log/                LogServiceProvider, Log facade
├── Messaging/          IncomingMessage, OutgoingMessage, Message, Button,
│                       Keyboard, Media + Dto/{User,Media,Location,Contact}
├── Routing/            Route, Router, Controller, Middleware, MiddlewarePipeline
├── State/              Flow, Step, FlowHandler, StateData, PersistentState,
│                       File/Database/CacheStateStorage, StateServiceProvider
├── Support/            helpers.php, Validator
└── Testing/            TestCase, FakeMessenger, FakeDriver, FakeApiClient, traits

```

---

Application
-----------

[](#application)

Ядро. Наследует `Illuminate\Container\Container`.

```
$app = new Application(dirname(__DIR__));
```

МетодОписание`basePath($path)`Базовый путь проекта`configPath($path)`Путь к `config/``storagePath($path)`Путь к `storage/``databasePath($path)`Путь к `database/``register(ServiceProvider)`Зарегистрировать провайдер`boot()`Загрузить все провайдеры`handleConsole()`Обработать CLI-запрос`handleWebhook(Request)`Обработать вебхук`loadRoutes()`Загрузить `routes/messenger.php`---

Маршрутизация
-------------

[](#маршрутизация)

### DSL

[](#dsl)

```
use Govorun\Routing\Route;

Route::command('start', StartController::class);
Route::phrase('привет', HelloController::class);
Route::pattern('/^\d+$/', NumberController::class);
Route::action('confirm', ConfirmController::class);
Route::event('member_joined', WelcomeController::class);
Route::media('photo', PhotoController::class);
Route::location(LocationController::class);
Route::contact(ContactController::class);
Route::referral('promo', PromoController::class);
Route::fallback(FallbackController::class);
```

`Route::command('start', ...)` нормализуется к `/start` — слеш можно опускать.

### Приоритет

[](#приоритет)

`event` &gt; `command` &gt; `action` &gt; `referral` &gt; `media` &gt; `location` &gt; `contact` &gt; `pattern` &gt; `phrase` &gt; `fallback`

### Middleware

[](#middleware)

```
Route::middleware(AuthMiddleware::class, function () {
    Route::command('admin', AdminController::class);
});
```

### Вложенные phrase

[](#вложенные-phrase)

```
Route::phrase('меню', function () {
    Route::phrase('цены', PriceController::class);
    Route::phrase('контакты', ContactInfoController::class);
});
```

### Алиасы

[](#алиасы)

```
Route::phrase('привет', HelloController::class)
    ->alias(['здравствуйте', 'добрый день']);
```

---

Controller
----------

[](#controller)

Базовый класс контроллера бота.

```
use Govorun\Routing\Controller;

class StartController extends Controller
{
    public function handle(): void
    {
        $name = $this->message->user->firstName;
        $this->reply("Привет, {$name}!");
    }
}
```

`handle()` вызывается без аргументов; альтернатива — `__invoke()`.

Свойство / методТипОписание`$this->message``IncomingMessage`Входящее сообщение (предпочтительный доступ; `$this->incomingMessage` — deprecated алиас)`$this->driver``MessengerDriver`Драйвер мессенджера`$this->state``StateAccessor``PersistentState` (write-through в storage), при отсутствии storage — пустая `StateData``reply(string $text)``void`Отправить текстовый ответ`send(OutgoingMessage $msg)``void`Отправить сообщение (с клавиатурой/медиа)`user()``UserDto`Данные отправителя`param(string $key)``?string`Параметр callback-действия (для `Route::action()`)`startFlow(string $class)``void`Запустить Flow-диалог`http()` (через `MakesHttpCalls`)`HttpManager`Доступ к подключениям (`$this->http()->connection('slug')->...`)### Auto-finalize inline-клавиатуры

[](#auto-finalize-inline-клавиатуры)

При отправке через `send()` сообщения с inline-клавиатурой, содержащей `action`-кнопки, контроллер сохраняет в storage контекст (`message_id`, `original_text`, `parse_mode`, текстовые лейблы кнопок). На следующем Action-сообщении исходное сообщение редактируется — клавиатура убирается, к тексту дописывается `(выбрано: )`. Ошибки `driver->edit()` не пробрасываются — это «вежливая» финализация.

Reply-клавиатуры, `Keyboard::remove()` и кнопки без `action` (только URL/requestContact/requestLocation) контекст не пишут.

---

Messaging
---------

[](#messaging)

### IncomingMessage

[](#incomingmessage)

СвойствоТипОписание`id``string`ID сообщения`chatId``string`ID чата`driverName``string`Имя драйвера (`telegram`, …)`text``?string`Текст`user``UserDto`Отправитель`type``ContentType`Тип контента`action``?string`Callback-action`actionParams``?array`Параметры action`event``?string`Имя события`media``?MediaDto`Медиа`location``?LocationDto`Геолокация`contact``?ContactDto`Контакт`referral``?string`Реферальный код`raw``array`Сырое тело апдейта### ContentType (enum)

[](#contenttype-enum)

`Text` | `Action` | `Media` | `Location` | `Contact` | `Event`.

### OutgoingMessage

[](#outgoingmessage)

```
use Govorun\Messaging\Message;

$msg = Message::make('Текст')
    ->keyboard($keyboard)
    ->parseMode('HTML');
```

### Keyboard

[](#keyboard)

```
use Govorun\Messaging\Button;
use Govorun\Messaging\Keyboard;

// Inline
Keyboard::make()->buttons([
    [
        Button::make('Текст')->action('confirm', ['id' => 42]),
        Button::make('Ссылка')->url('https://example.com'),
    ],
    [Button::make('Новый ряд')->action('continue')],
]);

// Reply (с fluent-флагами)
Keyboard::reply()
    ->resize()
    ->oneTime()
    ->buttons([
        [Button::make('Контакт')->requestContact()],
        [Button::make('Локация')->requestLocation()],
    ]);

// Снять клавиатуру
Keyboard::remove();
```

### Media

[](#media)

```
use Govorun\Messaging\Media;

Media::photo('https://example.com/img.jpg')->caption('Описание');
Media::document('https://example.com/file.pdf');
Media::video('https://example.com/clip.mp4');
Media::audio('https://example.com/track.mp3');
Media::voice('https://example.com/voice.ogg');
Media::animation('https://example.com/anim.gif');
```

Telegram-драйвер дополнительно умеет отправлять **локальные файлы** — если в `OutgoingMessage::$media['url']` лежит существующий локальный путь (а не URL), используется multipart-upload через Bot API.

### Button

[](#button)

```
Button::make('Текст')
    ->action('callback_action', ['key' => 'value'])
    ->url('https://...')
    ->requestContact()
    ->requestLocation();
```

---

DTO
---

[](#dto)

### UserDto

[](#userdto)

СвойствоТип`id``string``firstName``?string``lastName``?string``username``?string``phone``?string``locale``?string``raw``array`### MediaDto / LocationDto / ContactDto

[](#mediadto--locationdto--contactdto)

`MediaDto`: `type`, `url`, `fileId`, `mimeType`, `fileSize`, `raw`. `LocationDto`: `latitude`, `longitude`, `raw`. `ContactDto`: `phone`, `firstName`, `lastName`, `userId`, `raw`.

---

Flow (пошаговые диалоги)
------------------------

[](#flow-пошаговые-диалоги)

Многошаговый диалог. Состояние сохраняется между шагами в `StateStorage`.

```
use Govorun\State\Flow;
use Govorun\State\Step;
use Govorun\Messaging\Keyboard;
use Govorun\Messaging\Button;
use Govorun\Messaging\IncomingMessage;

class OrderFlow extends Flow
{
    protected array $steps = ['product', 'quantity', 'confirm'];
    protected array $interruptCommands = ['/start', '/cancel'];
    protected bool $interruptOnEvent = true;

    public function productStep(Step $step): void
    {
        $step->ask('Какой товар вас интересует?');

        $step->receive(function (IncomingMessage $msg) {
            if ($this->validator($msg->text)->required()->fails()) {
                return; // ошибка уже отправлена пользователю
            }

            $this->state->set('product', $msg->text);
            $this->nextStep();
        });
    }

    public function quantityStep(Step $step): void
    {
        $step->ask('Сколько штук?');

        $step->receive(function (IncomingMessage $msg) {
            $this->state->set('quantity', (int) $msg->text);
            $this->nextStep();
        });
    }

    public function confirmStep(Step $step): void
    {
        $product = $this->state->get('product');
        $qty = $this->state->get('quantity');

        $step->ask(
            "Заказ: {$product} x {$qty}. Подтвердить?",
            Keyboard::make()->buttons([[
                Button::make('Да')->action('yes'),
                Button::make('Нет')->action('no'),
            ]]),
        );

        $step->receive(function (IncomingMessage $msg) {
            if ($msg->action === 'yes') {
                $this->reply('Заказ принят!');
            }
            $this->nextStep(); // обязателен — завершает flow и чистит state
        });
    }

    public function onComplete(): void {}
    public function onCancel(): void { $this->reply('Заказ отменён.'); }
}
```

### Свойства

[](#свойства)

СвойствоТипОписание`$steps``array`Имена шагов в порядке выполнения`$interruptCommands``array`Команды, прерывающие flow`$interruptOnEvent``bool`Прерывать при событии`$state``StateData`In-memory данные шагов (сохраняются после ask/receive)### Методы

[](#методы)

МетодОписание`start()`Запуск с первого шага`resume()`Возобновление текущего шага (вызывает `FlowHandler`)`nextStep(?string $name)`Переход. Без аргумента — следующий по `$steps`; с именем — прыжок (`goTo`). Если текущий последний — `completeFlow()``reply(string $text)`Текстовый ответ`send(OutgoingMessage $msg)`Отправка сложного сообщения`validator(?string $value)`Создать `Validator` с автоматической отправкой ошибки пользователю`http()``HttpManager` (через трейт `MakesHttpCalls`)`onComplete()` / `onCancel()`Хуки### Step

[](#step)

```
$step->ask(
    string|OutgoingMessage $message,
    Closure|Keyboard|null  $keyboard = null,  // прямой Keyboard или Closure-билдер
);

$step->receive(Closure $callback);  // function (IncomingMessage $msg): void
```

Клавиатура-`Closure` исполняется в bind'е Flow, поэтому имеет доступ к `$this->state`.

### Прерывание

[](#прерывание)

`shouldInterrupt(IncomingMessage)` возвращает true когда:

1. Активна `ask_keyboard` (есть `__ask_keyboard_ctx` в state) и пришёл текст — это значит пользователь не нажал кнопку, а написал что-то ещё. События в этом режиме не прерывают.
2. `$interruptOnEvent === true` и пришло событие.
3. Текст совпадает с одной из `$interruptCommands` (или начинается на ` `).

### Auto-finalize ask\_keyboard

[](#auto-finalize-ask_keyboard)

Если в шаге задана inline-клавиатура с action-кнопками, при отправке `ask` контекст сохраняется в `state.__ask_keyboard_ctx`. На `nextStep()` / `onCancel()` исходное сообщение редактируется: `(выбрано: )` или `(отменено)`. При прерывании по команде до выбора — финализация с `(отменено)`.

---

State Storage
-------------

[](#state-storage)

```
interface StateStorage
{
    public function get(string $chatId, string $driver): ?array;
    public function set(string $chatId, string $driver, array $data): void;
    public function delete(string $chatId, string $driver): void;
}
```

КлассОписание`FileStateStorage`JSON-файлы в `storage/state/``DatabaseStateStorage`Таблица `govorun_states` (создаётся миграцией)`CacheStateStorage`Кеш Illuminate с TTLДрайвер выбирается в `config/state.php`: `driver` (`file`/`database`/`cache`) + `ttl` (секунды).

### StateAccessor

[](#stateaccessor)

Общий контракт чтения/записи произвольных ключей состояния. Две реализации:

РеализацияГдеСемантика записи`StateData``$this->state` во `Flow`In-memory, флашится в storage в конце `ask`/`receive``PersistentState``$this->state` в `Controller`Write-through — каждый `set()` сразу пишет в storageМетодОписание`get(string $key, mixed $default)`Получить значение`set(string $key, mixed $value)`Сохранить значение`has(string $key)`Проверить наличие`all()`Получить весь массив---

HTTP
----

[](#http)

### ConnectionClient (рекомендуемый путь)

[](#connectionclient-рекомендуемый-путь)

Подключения к внешним API описаны в `config/connections.php`:

```
return [
    'payment' => [
        'base_url' => 'https://api.payment.com/v1',
        'default_headers' => ['Accept' => 'application/json'],
        'auth' => ['type' => 'bearer', 'token' => env('PAYMENT_TOKEN')],
    ],
];
```

Трейт `MakesHttpCalls` подмешан в `Controller` и `Flow`:

```
$response = $this->http()->connection('payment')->post('/charge', [
    'json' => ['amount' => 100, 'currency' => 'RUB'],
]);

if ($response->successful()) {
    $payment = $response->json();
}
```

Тип authКонфиг`none`(без auth)`bearer``['type' => 'bearer', 'token' => '…']` → заголовок `Authorization: Bearer …``api_key` (header)`['type' => 'api_key', 'in' => 'header', 'key' => 'X-Api-Key', 'value' => '…']``api_key` (query)`['type' => 'api_key', 'in' => 'query', 'key' => 'api_key', 'value' => '…']``basic``['type' => 'basic', 'login' => '…', 'password' => '…']`Опции Guzzle (`json`, `form_params`, `query`, `headers`, …) пробрасываются через второй аргумент. Таймаут по умолчанию — 10 секунд, `http_errors=false` (не бросает исключения на 4xx/5xx).

`HttpResponse`:

МетодОписание`status(): int`HTTP-статус`successful(): bool`2xx`failed(): bool`не 2xx`body(): string`сырое тело`json(): ?array`JSON-декод (null при ошибке)### ApiClient (абстрактный, для собственных клиентов)

[](#apiclient-абстрактный-для-собственных-клиентов)

Альтернатива для случаев, когда удобнее иметь типизированный клиент-наследник, а не вызывать `connection('slug')`:

```
use Govorun\Http\ApiClient;

class PaymentClient extends ApiClient
{
    protected int $timeout = 10;
    protected int $retries = 2;

    public function baseUrl(): string
    {
        return 'https://api.payment.com/v1';
    }

    public function headers(): array
    {
        return ['Authorization' => 'Bearer ' . env('PAYMENT_KEY')];
    }
}
```

МетодОписание`get(string $uri, array $params)`GET`post(string $uri, array $data)`POST`put(string $uri, array $data)`PUT`delete(string $uri)`DELETE---

Validator
---------

[](#validator)

`Govorun\Support\Validator` — fluent-валидатор пользовательского ввода с lazy-load дефолтов из `resources/validation-messages.json` (синхронизирован с `govorun-factory/resources/validation-messages.json` — править одновременно).

```
use Govorun\Support\Validator;

$error = Validator::make($msg->text)
    ->required()
    ->numeric()
    ->min(1)
    ->max(999)
    ->validate();   // ?string — null если ок

if ($error !== null) {
    $this->reply($error);
    return;
}
```

В `Flow` есть шорткат `$this->validator($value)` — он сам отправит ошибку пользователю через `errorHandler`. Терминал — `->fails(): bool` (true = ошибка уже отправлена пользователю):

```
if ($this->validator($msg->text)->required()->email()->fails()) {
    return;
}
```

Доступные правила: `required`, `email`, `string`, `numeric`, `integer`, `url`, `phone`, `regex`, `min`, `max`, `between`, `in`, `date`. Полный список — `src/Support/Validator.php`. Шаблоны сообщений — `resources/validation-messages.json`.

---

Middleware
----------

[](#middleware-1)

```
use Govorun\Routing\Middleware;
use Govorun\Messaging\IncomingMessage;

class LogMiddleware implements Middleware
{
    public function handle(IncomingMessage $message, \Closure $next): void
    {
        logger()->info("Message from {$message->user->id}: {$message->text}");
        $next($message);
    }
}
```

Middleware складываются в pipeline. Если `$next` не вызван — цепочка прерывается.

---

Request
-------

[](#request)

МетодОписание`Request::capture()`Создать из глобальных переменных`getContent()`Сырое тело`json()`Декодированный JSON`header(string $name)`Значение заголовка`method()`HTTP-метод`uri()`Полный URI`path()`Путь без query`query(string $key, $default)`Параметр строки запроса---

ServiceProvider
---------------

[](#serviceprovider)

```
use Govorun\Foundation\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register(): void { /* привязки контейнера */ }
    public function boot(): void { /* после регистрации всех провайдеров */ }
}
```

Подключение в `config/app.php`:

```
'providers' => [
    App\Providers\AppServiceProvider::class,
],
```

---

MessengerDriver (интерфейс)
---------------------------

[](#messengerdriver-интерфейс)

МетодОписание`verifyWebhook(Request)`Проверить подпись запроса`parseUpdate(Request)`Распарсить в `IncomingMessage``send(OutgoingMessage)`Отправить сообщение (вернуть `?string` ID отправленного)`edit(string $id, OutgoingMessage)`Редактировать сообщение`delete(string $id, string $chatId)`Удалить сообщение`installWebhook(string $url)`Установить вебхук`removeWebhook()`Удалить вебхук`getUser(string $id)`Получить данные пользователяTelegram-драйвер дополнительно реализует методы для `bot:profile-sync`: `setMyName`, `setMyShortDescription`, `setMyDescription`, `setMyCommands`, `setMyProfilePhoto`, `removeMyProfilePhoto`.

---

CLI-команды
-----------

[](#cli-команды)

КомандаОписание`php govorun webhook:install`Установить вебхуки для активных драйверов`php govorun webhook:remove`Удалить вебхуки`php govorun migrate`Запустить миграции БД`php govorun make:controller {name}`Создать контроллер из stub'а`php govorun make:flow {name}`Создать Flow-диалог`php govorun make:api-client {name}`Создать API-клиент`php govorun state:clear`Очистить состояния Flow`php govorun bot:profile-sync`Идемпотентная синхронизация Telegram-профиля (name / short\_description / description / commands / photo) из `config/bot_profile.php` и `storage/app/bot-profile.{jpg,mp4}`. Флаги `--only=...` / `--skip=...``php govorun test`Запустить тесты проекта---

Тестирование
------------

[](#тестирование)

```
vendor/bin/phpunit                                    # все тесты
vendor/bin/phpunit --testsuite=Unit                   # только Unit
vendor/bin/phpunit --testsuite=Integration            # только Integration
vendor/bin/phpunit tests/Unit/State/FlowTest.php      # один файл
vendor/bin/phpunit --filter test_specific_thing       # по имени
```

В `src/Testing/` лежат `TestCase`, `FakeDriver`, `FakeMessenger`, `FakeApiClient` и трейты — используются как в тестах фреймворка, так и из проектов-потребителей.

Лицензия
--------

[](#лицензия)

MIT

###  Health Score

46

—

FairBetter than 92% of packages

Maintenance94

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 86.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

27

Last Release

25d ago

Major Versions

v1.1.0 → v2.0.02026-04-18

v2.1.0 → v3.0.02026-04-24

v3.7.0 → v4.0.02026-05-27

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/95697565?v=4)[bromimo](/maintainers/bromimo)[@bromimo](https://github.com/bromimo)

---

Top Contributors

[![bromimo-alef](https://avatars.githubusercontent.com/u/142026660?v=4)](https://github.com/bromimo-alef "bromimo-alef (134 commits)")[![bromimo](https://avatars.githubusercontent.com/u/95697565?v=4)](https://github.com/bromimo "bromimo (21 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/govorun-framework/health.svg)

```
[![Health](https://phpackages.com/badges/govorun-framework/health.svg)](https://phpackages.com/packages/govorun-framework)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9742.3M121](/packages/roots-acorn)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k14.1M122](/packages/laravel-pulse)[laravel/ai

The official AI SDK for Laravel.

9782.1M162](/packages/laravel-ai)[flarum/core

Delightfully simple forum software.

201.4M2.2k](/packages/flarum-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
