Laravel Nova 定义 Actions

2023-02-16 17:09 更新

Nova 操作使您可以在一个或多个 Eloquent 模型上执行自定义任务。例如,您可以编写一个操作,向用户发送一封电子邮件,其中包含他们所请求的帐户数据。或者,您可以编写一个操作来将一组记录转移给另一个用户。

将操作附加到资源定义后,可以从资源的索引或详细信息屏幕启动该操作:


如果启用了在资源的表行上显示的操作,则可以从资源的操作下拉菜单中启动该操作。这些称为 “内联操作”:


概述

Nova 动作可以使用 nova:actionArtisan 命令生成。默认情况下,所有操作都放置在 app/Nova/Actions 目录中:

php artisan nova:action EmailAccountProfile

您可以通过传递以下选项来生成破坏性操作--destructive

php artisan nova:action DeleteUserData --destructive

要了解如何定义 Nova 动作,我们来看一个示例。在此示例中,我们将定义一个向用户或用户组发送电子邮件的操作:

<?php

namespace App\Nova\Actions;

use App\AccountData;
use Illuminate\Bus\Queueable;
use Laravel\Nova\Actions\Action;
use Illuminate\Support\Collection;
use Laravel\Nova\Fields\ActionFields;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class EmailAccountProfile extends Action
{
  use InteractsWithQueue, Queueable;

  /**
   * Perform the action on the given models.
   *
   * @param  \Laravel\Nova\Fields\ActionFields  $fields
   * @param  \Illuminate\Support\Collection  $models
   * @return mixed
   */
  public function handle(ActionFields $fields, Collection $models)
  {
    foreach ($models as $model) {
      (new AccountData($model))->send();
    }
  }

  /**
   * Get the fields available on the action.
   *
   * @return array
   */
  public function fields()
  {
    return [];
  }
}

动作最重要的方法是 handle 方法。该 handle 方法接收该操作所附的任何字段的值,以及选定模型的集合。即使仅针对单个模型执行操作,该 handle 方法也始终接收 Collection 模型。

在该 handle 方法内,您可以执行完成操作所需的任何任务。您可以自由更新数据库记录,发送电子邮件,致电其他服务等。

动作可见度

默认情况下,操作在资源索引和详细信息屏幕上都是可见的。此外,默认情况下,内联操作从表行的操作下拉列表中隐藏。定义动作时,可以通过在动作上设置以下方法之一来指定其可见性:

  • onlyOnIndex
  • exceptOnIndex
  • showOnIndex
  • onlyOnDetail
  • exceptOnDetail
  • showOnDetail
  • onlyOnTableRow
  • exceptOnTableRow
  • showOnTableRow

破坏性行动

您可以通过让动作类继承自来将某动作指定为破坏性或危险动作 Laravel\Nova\Actions\DestructiveAction。这会将操作的确认按钮的颜色更改为红色:


破坏性行动与政策

将破坏性操作添加到具有关联授权策略的资源时,该策略的 delete 方法必须返回 true 才能运行该操作。

行动领域

有时,您可能希望在分派操作之前从用户那里收集其他信息。因此,Nova 允许您将 Nova 支持的大多数字段直接附加到动作上。启动操作时,Nova 将提示用户提供以下字段的输入:


要将字段添加到动作,请将字段添加到该动作的 fields 方法返回的字段数组中:

use Laravel\Nova\Fields\Text;

/**
 * Get the fields available on the action.
 *
 * @return array
 */
public function fields()
{
    return [
        Text::make('Subject'),
    ];
}

最后,在您的操作 handle 方法内,您可以使用提供的 ActionFields 实例上的动态访问器来访问字段:

/**
 * Perform the action on the given models.
 *
 * @param  \Laravel\Nova\Fields\ActionFields  $fields
 * @param  \Illuminate\Support\Collection  $models
 * @return mixed
 */
public function handle(ActionFields $fields, Collection $models)
{
    foreach ($models as $model) {
        (new AccountData($model))->send($fields->subject);
    }
}

动作模式自定义

默认情况下,操作将在运行前要求用户确认。您可以自定义确认消息,确认按钮和取消按钮,以在执行操作之前为用户提供更多上下文。这是通过指定的完成 confirmTextconfirmButtonText 以及 cancelButtonText 定义操作时的方法:

/**
 * Get the actions available for the resource.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
public function actions(Request $request)
{
    return [
        (new Actions\ActivateUser)
            ->confirmText('Are you sure you want to activate this user?')
            ->confirmButtonText('Activate')
            ->cancelButtonText("Don't activate"),
    ];
}

这将自定义模式,如下所示:


动作回应

通常,执行操作时,Nova UI 中会显示通用的 “成功” 消息。但是,您可以使用 Action 类上的各种方法来自定义此响应。

要显示自定义的 “成功” 消息,可以 Action::message 从您的 handle 方法中返回该方法的结果:

/**
 * Perform the action on the given models.
 *
 * @param  \Laravel\Nova\Fields\ActionFields  $fields
 * @param  \Illuminate\Support\Collection  $models
 * @return mixed
 */
public function handle(ActionFields $fields, Collection $models)
{
    // ...

    return Action::message('It worked!');
}

要返回红色的 “危险” 消息,可以使用以下 Action::danger 方法:

return Action::danger('Something went wrong!');

重定向响应

要在执行操作后将用户重定向到一个全新的位置,可以使用以下 Action::redirect 方法:

return Action::redirect('https://example.com');

要将用户重定向到内部路由,请使用以下 Action::push 方法:

return Action::push('/resources/posts/new', [
  'viaResource' => 'users',
  'viaResourceId' => 1,
  'viaRelationship' => 'posts'
]);

下载回应

要在执行操作后启动文件下载,可以使用该 Action::download 方法。该 download 方法将要下载的文件的 URL 作为其第一个参数,并将文件的所需名称作为其第二个参数:

return Action::download('https://example.com/invoice.pdf', 'Invoice.pdf');

排队的动作

有时,您可能需要花费一些时间才能完成运行。出于这个原因,Nova 让您排队行动很容易。要指示 Nova 将操作排入队列而不是同步运行,请在 ShouldQueue 界面上标记该操作:

<?php

namespace App\Nova\Actions;

use App\AccountData;
use Illuminate\Bus\Queueable;
use Laravel\Nova\Actions\Action;
use Illuminate\Support\Collection;
use Laravel\Nova\Fields\ActionFields;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class EmailAccountProfile extends Action implements ShouldQueue
{
  use InteractsWithQueue, Queueable;

  // ...
}

使用排队操作时,请不要忘记为应用程序配置和启动队列工作器。否则,您的操作将不会被处理。

排队的操作文件

目前,Nova 不支持将 File 字段附加到排队的操作。如果需要将 File 字段附加到操作,则该操作必须同步运行。

自定义连接和队列

您可以通过在操作上定义 $connection 和 $queue 属性来自定义操作排队的队列连接和队列名称:

/**
 * The name of the connection the job should be sent to.
 *
 * @var string|null
 */
public $connection = 'redis';

/**
 * The name of the queue the job should be sent to.
 *
 * @var string|null
 */
public $queue = 'emails';

动作日志

查看针对资源运行的操作的日志通常很有用。此外,在对操作进行排队时,知道它们何时真正完成通常很重要。值得庆幸的是,Nova 通过将 Laravel\Nova\Actions\Actionable 特征附加到资源的相应 Eloquent 模型来轻松地向该资源添加操作日志。

例如,我们可以将 Laravel\Nova\Actions\Actionable 特征附加到 UserEloquent 模型:

<?php

namespace App;

use Laravel\Nova\Actions\Actionable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
  use Actionable, Notifiable;

  // ...
}

将特征附加到模型后,Nova 将自动开始在资源的详细信息屏幕底部显示操作日志:


禁用操作日志

如果您不想在操作日志中记录操作,则可以通过 withoutActionEvents 在操作类上添加属性来禁用此行为:

/**
 * Disables action log events for this action.
 *
 * @var bool
 */
public $withoutActionEvents = true;

或者,使用该 withoutActionEvents 方法,可以在将操作附加到资源时为该操作禁用操作日志:

/**
 * Get the actions available for the resource.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return array
 */
public function actions(Request $request)
{
    return [
        (new SomeAction)->withoutActionEvents()
    ];
}

排队的动作状态

当排队的操作正在运行时,您可以为通过其模型集合传递给该操作的任何模型更新该操作的 “状态”。例如,您可以使用操作的 markAsFinished 方法来指示该操作已完成对特定模型的处理:

/**
 * Perform the action on the given models.
 *
 * @param  \Laravel\Nova\Fields\ActionFields  $fields
 * @param  \Illuminate\Support\Collection  $models
 * @return mixed
 */
public function handle(ActionFields $fields, Collection $models)
{
    foreach ($models as $model) {
        (new AccountData($model))->send($fields->subject);

        $this->markAsFinished($model);
    }
}

或者,如果您想指示某个动作对于给定的模型 “失败”,则可以使用以下 markAsFailed 方法:

/**
 * Perform the action on the given models.
 *
 * @param  \Laravel\Nova\Fields\ActionFields  $fields
 * @param  \Illuminate\Support\Collection  $models
 * @return mixed
 */
public function handle(ActionFields $fields, Collection $models)
{
    foreach ($models as $model) {
        try {
            (new AccountData($model))->send($fields->subject);
        } catch (Exception $e) {
            $this->markAsFailed($model, $e);
        }
    }
}


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号