定义 Actions
Nova操作使您可以在一个或多个Eloquent模型上执行自定义任务。例如,您可以编写一个操作,向用户发送一封电子邮件,其中包含他们所请求的帐户数据。或者,您可以编写一个操作来将一组记录转移给另一个用户。
将操作附加到资源定义后,可以从资源的索引或详细信息屏幕启动该操作:
如果启用了在资源的表行上显示的操作,则可以从资源的操作下拉菜单中启动该操作。这些称为“内联操作”:
#概述
Nova动作可以使用nova:action
Artisan命令生成。默认情况下,所有操作都放置在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);
}
}
#动作模式自定义
默认情况下,操作将在运行前要求用户确认。您可以自定义确认消息,确认按钮和取消按钮,以在执行操作之前为用户提供更多上下文。这是通过指定的完成confirmText
,confirmButtonText
以及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
特征附加到User
Eloquent模型:
<?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);
}
}
}
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。