Состояние экрана

Suggest Edit

В PHP, когда мы хотим сохранить промежуточный результат между запросами, обычно используются хранилища, такие как базы данных или быстрые хранилища, например Redis. Для более простых случаев, можно передать состояние прямо в URL-адресе. Вы наверняка видели это, например, в operation?result=success. Каждый из этих способов является уместным и вполне применимым.

Однако в Laravel Orchid есть удобное решение для хранения небольшого количества информации, такой как модель Eloquent. Это возможно благодаря тому, что каждый запрос передает с собой состояние всех публичных свойств экрана.

Давайте попробуем это на практике и создадим новый экран под названием StateScreen с помощью команды Artisan:

php artisan orchid:screen StateScreen

Затем зарегистрируем его в файле маршрута:

use App\Orchid\Screens\StateScreen;

Route::screen('state', StateScreen::class)->name('state');

Классическим примером является подсчет количества кликов. Добавим следующий код в только что созданный экран:

<?php

namespace App\Orchid\Screens;

use Illuminate\Http\Request;
use Orchid\Screen\Screen;
use Orchid\Support\Color;
use Orchid\Screen\Fields\Label;
use Orchid\Screen\Actions\Button;
use Orchid\Support\Facades\Layout;

class StateScreen extends Screen
{
    /**
     * Fetch data to be displayed on the screen.
     *
     * @return array
     */
    public function query(): array
    {
        return [
            'clicks' => 0,
        ];
    }

    /**
     * The name of the screen displayed in the header.
     *
     * @return string|null
     */
    public function name(): ?string
    {
        return 'State';
    }

    /**
     * The screen's layout elements.
     *
     * @return \Orchid\Screen\Layout[]|string[]
     */
    public function layout(): array
    {
        return [
            Layout::rows([
                Label::make('clicks')->title('Click Count:'),
            ]),
        ];
    }
}

Перейдем в браузере на нашу страницу и посмотрим, как выглядит экран. На нем должна быть выведена надпись “Click Count: 0”. Добавим в наш экран простой метод, в котором посмотрим на содержимое запроса:

/**
 * The screen's layout elements.
 *
 * @return \Orchid\Screen\Layout[]|string[]
 */
public function layout(): array
{
    return [
        Layout::rows([
            Label::make('clicks')
                ->title('Click Count:'),

            Button::make('Increment Click')
                ->type(Color::DARK)
                ->method('increment'),
        ]),
    ];
}

/**
 * Increment the click count.
 *
 * @return \Illuminate\Http\RedirectResponse
 */
public function increment(Request $request)
{
    dd($request->all());
}

После нажатия на кнопку “Отправить” вы увидите содержимое запроса. Однако заметьте, что значение кликов отсутствует. В классическом варианте построения серверного приложения мы могли бы добавить скрытое поле формы <input type="hidden"> и делать редирект с GET параметром ?count=1.

Однако Orchid имеет удобное решение, позволяющее автоматически сохранять состояние публичных свойств экрана.

class StateScreen extends Screen
{
    /**
     * The number of clicks.
     *
     * @var int
     */
    public $clicks;

    //...

    /**
     * Increment the click count.
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function increment(Request $request)
    {
        dd($this->clicks);
    }
}

Теперь, если мы отправим форму, то значение свойства сохранится таким же, каким мы его задали в процессе. В данном примере мы использовали простой тип int, но это также можно использовать и для более сложных объектов, таких как модели Eloquent.

Сохранение больших объемов данных в публичных свойствах экрана может вызвать проблемы с производительностью. Поэтому рекомендуется быть осторожными и избегать хранения большого объема информации в публичных свойствах.

Чтобы обновить состояние экрана, нам достаточно изменить публичное свойство, но перед этим обновим наш query, чтобы он возвращал массив с ключом clicks, содержащим текущее значение свойства, и если оно отсутствует, устанавливал значение по умолчанию как 0:

class StateScreen extends Screen
{
    /**
     * The number of clicks.
     *
     * @var int
     */
    public $clicks;

    /**
     * Fetch data to be displayed on the screen.
     *
     * @return array
     */
    public function query(): array
    {
        return [
            'clicks'  => $this->clicks ?? 0,
        ];
    }
}

Обновим метод increment(), чтобы он увеличивал значение свойства clicks на единицу при каждом вызове.

/**
 * Increment the click count.
 */
public function increment()
{
    $this->clicks++;
}

Теперь, когда пользователь нажимает кнопку “Increment Click”, счетчик кликов будет обновляться. Если вы обновите страницу, счетчик будет сброшен.

Our Friends