屏幕状态

建议编辑

在 PHP 中,当我们想要在请求之间存储中间结果时,通常会使用数据库(如 MySQL)或快速存储系统(如 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
{
    /**
     * 获取要在屏幕上显示的数据。
     *
     * @return array
     */
    public function query(): array
    {
        return [
            'clicks' => 0,
        ];
    }

    /**
     * 屏幕在头部显示的名称。
     *
     * @return string|null
     */
    public function name(): ?string
    {
        return 'State';
    }

    /**
     * 屏幕的布局元素。
     *
     * @return array
     */
    public function layout(): array
    {
        return [
            Layout::rows([
                Label::make('clicks')->title('点击次数:'),
            ]),
        ];
    }
}

让我们在浏览器中打开页面,看看屏幕的样子。它应该显示标签 “点击次数: 0”。现在,让我们在屏幕上添加一个简单的方法来查看请求内容:

/**
 * 屏幕的布局元素。
 *
 * @return array
 */
public function layout(): array
{
    return [
        Layout::rows([
            Label::make('clicks')
                ->title('点击次数:'),

            Button::make('增加点击')
                ->type(Color::DARK)
                ->method('increment'),
        ]),
    ];
}

/**
 * 增加点击次数。
 *
 * @param Request $request
 * @return \Illuminate\Http\RedirectResponse
 */
public function increment(Request $request)
{
    dd($request->all());
}

点击 “提交” 按钮后,你将看到请求内容。然而,请注意点击次数的值缺失。在传统的服务器应用程序中,我们可以通过添加一个隐藏的表单字段 <input type="hidden"> 并使用 GET 参数 ?count=1 进行重定向来实现这一点。

幸运的是,Orchid 提供了一个方便的解决方案,可以自动保存屏幕公共属性的状态。

class StateScreen extends Screen
{
    /**
     * 点击次数。
     *
     * @var int
     */
    public $clicks;

    //...

    /**
     * 增加点击次数。
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function increment(Request $request)
    {
        dd($this->clicks);
    }
}

现在,当我们提交表单时,属性值将被保留。在这个例子中,我们使用了一个简单的 int 类型,但它也可以用于更复杂的对象,如 Eloquent 模型。

在公共屏幕属性中存储大量数据可能会导致性能问题。因此,建议谨慎操作,避免在公共属性中存储过多信息。

要更新屏幕状态,我们只需修改公共属性即可。但在此之前,让我们更新 query 方法以返回一个包含键 clicks 的数组,其中包含属性的当前值。如果缺失,我们将其设置为 0

class StateScreen extends Screen
{
    /**
     * 点击次数。
     *
     * @var int
     */
    public $clicks;

    /**
     * 获取要在屏幕上显示的数据。
     *
     * @return array
     */
    public function query(): array
    {
        return [
            'clicks'  => $this->clicks ?? 0,
        ];
    }
}

让我们更新 increment() 方法,使其每次调用时将 clicks 属性的值增加一。

/**
 * 增加点击次数。
 */
public function increment()
{
    $this->clicks++;
}

现在,当用户点击 “增加点击” 按钮时,点击计数器将被更新。如果你刷新页面,计数器将被重置。

我们的朋友