Живые пропсы (live props) в Inertia, добавленные в v3.11.0, поддерживают актуальность страницы при изменении данных на сервере. Пометьте пропс как живой, отправьте событие, и каждая страница, отображающая этот пропс, перезагрузит его.
Давайте покажем, как работают живые пропсы, реализовав страницу статуса заказа с помощью Laravel Reverb, чтобы каждый, кто просматривает заказ, видел новый статус при его отправке. Вам понадобятся inertia-laravel 3.7 и Inertia.js 3.11 или более поздние версии:
composer require inertiajs/inertia-laravel:^3.7 npm install @inertiajs/vue3@^3.11
Для React или Svelte установите вместо этого @inertiajs/react или @inertiajs/svelte .
#Установка Reverb и Echo
Запустите установщик бродкастинга с опцией --reverb :
php artisan install:broadcasting --reverb
Это установит Reverb, добавит ключи REVERB_* и VITE_REVERB_* в .env и создаст routes/channels.php . Для приложений на Vue и React он также установит соответствующий пакет Echo ( @laravel/echo-vue или @laravel/echo-react ) и добавит вызов configureEcho() в resources/js/app.ts или app.tsx :
import { configureEcho } from '@laravel/echo-vue' configureEcho({ broadcaster: 'reverb', })
Установщик определяет только Vue и React, поэтому в приложении на Svelte вам нужно будет установить @laravel/echo-svelte и самостоятельно добавить тот же вызов configureEcho() .
#Создание события бродкастинга
Затем создайте событие, представляющее это изменение:
php artisan make:event OrderUpdated
Реализуйте для него ShouldBroadcast и верните канал, в который оно должно транслироваться:
namespace App\Events; use App\Models\Order; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class OrderUpdated implements ShouldBroadcast { use Dispatchable, InteractsWithSockets, SerializesModels; public function __construct(public Order $order) {} public function broadcastOn(): PrivateChannel { return new PrivateChannel("orders.{$this->order->id}"); } }
Приватным каналам требуется правило авторизации в routes/channels.php . Это позволяет прослушивать канал только владельцу заказа:
use App\Models\Order; use Illuminate\Support\Facades\Broadcast; Broadcast::channel('orders.{order}', function ($user, Order $order) { return $user->id === $order->user_id; });
#Пометка пропса как живого
В контроллере оберните пропс в Inertia::live() и передайте ему экземпляр события:
use App\Events\OrderUpdated; use App\Models\Order; use Inertia\Inertia; public function show(Order $order) { return Inertia::render('Orders/Show', [ 'order' => Inertia::live(fn () => $order->fresh(), on: new OrderUpdated($order)), ]); }
Создание события здесь не запускает его трансляцию. Inertia вызывает его метод broadcastOn() для поиска канала, а затем отправляет канал и имя события на страницу.
Передайте значение в виде замыкания (closure), так как Inertia выполняет его при первом рендеринге и каждый раз при перезагрузке пропса.
#Подключение клиента
Во фронтенде передайте транспорт echo() в createInertiaApp() в resources/js/app.ts , сразу после вызова configureEcho() , добавленного установщиком:
import { createInertiaApp } from '@inertiajs/vue3' import { echo } from '@inertiajs/vue3/echo' import { configureEcho } from '@laravel/echo-vue' configureEcho({ broadcaster: 'reverb', }) createInertiaApp({ // your existing options... live: echo(), })
Вам не нужно менять компонент страницы. Он читает пропс order в обычном режиме, а Inertia подписывается на канал при загрузке страницы.
#Трансляция события
Диспатчте (вызывайте) событие везде, где изменяется заказ:
$order->update(['status' => 'shipped']); OrderUpdated::dispatch($order);
Каждая открытая страница, отображающая этот заказ, затем выполняет частичную перезагрузку (partial reload) для пропса order . У пользователя, который внес изменения, новые данные обычно уже есть из собственного ответа, поэтому вы можете пропустить его вкладку с помощью toOthers() :
broadcast(new OrderUpdated($order))->toOthers();
Метод toOthers() опирается на ID сокета, который Inertia отправляет в заголовке X-Socket-Id с каждым запросом с тем же origin (same-origin).
#Запуск Reverb и воркера очередей
Запустите сервер Reverb:
php artisan reverb:start
События, реализующие ShouldBroadcast , добавляются в очередь, поэтому вам также потребуется запущенный воркер очередей (queue worker). Скрипт composer run dev в новых приложениях Laravel запускает его за вас. Если вы его не используете, запустите воркер самостоятельно:
php artisan queue:work
Чтобы пропустить очередь и выполнить трансляцию во время запроса, реализуйте вместо этого ShouldBroadcastNow .
#Отображение состояния загрузки
Используйте хук useProp() , чтобы показать, когда Inertia перезагружает пропс:
<script setup> import { useProp } from '@inertiajs/vue3' defineProps(['order']) const { loading } = useProp('order') </script> <template> <p>Status: {{ order.status }}</p> <span v-if="loading">Updating...</span> </template>
#Передача значения в событии
Каждое событие отправляет запрос на ваш сервер с каждой страницы, прослушивающей его. При большом количестве зрителей вы можете поместить новое значение в полезную нагрузку (payload) события и пропустить эти запросы:
use App\Http\Resources\OrderResource; use Inertia\Inertia; public function broadcastWith(): array { return [ ...Inertia::broadcastProps([ 'order' => OrderResource::make($this->order), ]), ]; }
Inertia записывает только те пропсы, которые прослушивают это событие, поэтому payload не может изменить пропс, для которого событие не объявлено. Поскольку каждый пользователь на канале получает один и тот же payload, не используйте его для значений, зависящих от того, кто просматривает страницу.
#Троттлинг частых обновлений
По умолчанию Inertia перезагружает каждый живой пропс не чаще одного раза в секунду. Для пропсов, которые часто меняются, установите больший интервал троттлинга в миллисекундах:
'activity' => Inertia::live(fn () => $order->activity, on: new ActivityLogged($order), throttle: 5000),
Inertia также приостанавливает перезагрузки, пока вкладка браузера скрыта, и выполняет их, когда пользователь возвращается. Значения, отправленные с помощью broadcastProps() , в любом случае записываются на страницу.
Комментарии (0)
Пока нет комментариев — будьте первым.