Nova 操作使您可以在一個或多個 Eloquent 模型上執(zhí)行自定義任務(wù)。例如,您可以編寫一個操作,向用戶發(fā)送一封電子郵件,其中包含他們所請求的帳戶數(shù)據(jù)?;蛘?,您可以編寫一個操作來將一組記錄轉(zhuǎn)移給另一個用戶。
將操作附加到資源定義后,可以從資源的索引或詳細(xì)信息屏幕啟動該操作:
如果啟用了在資源的表行上顯示的操作,則可以從資源的操作下拉菜單中啟動該操作。這些稱為 “內(nèi)聯(lián)操作”:
Nova 動作可以使用 nova:action
Artisan 命令生成。默認(rèn)情況下,所有操作都放置在 app/Nova/Actions
目錄中:
php artisan nova:action EmailAccountProfile
您可以通過傳遞以下選項來生成破壞性操作--destructive
:
php artisan nova:action DeleteUserData --destructive
要了解如何定義 Nova 動作,我們來看一個示例。在此示例中,我們將定義一個向用戶或用戶組發(fā)送電子郵件的操作:
<?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
方法接收該操作所附的任何字段的值,以及選定模型的集合。即使僅針對單個模型執(zhí)行操作,該 handle
方法也始終接收 Collection
模型。
在該 handle
方法內(nèi),您可以執(zhí)行完成操作所需的任何任務(wù)。您可以自由更新數(shù)據(jù)庫記錄,發(fā)送電子郵件,致電其他服務(wù)等。
默認(rèn)情況下,操作在資源索引和詳細(xì)信息屏幕上都是可見的。此外,默認(rèn)情況下,內(nèi)聯(lián)操作從表行的操作下拉列表中隱藏。定義動作時,可以通過在動作上設(shè)置以下方法之一來指定其可見性:
onlyOnIndex
exceptOnIndex
showOnIndex
onlyOnDetail
exceptOnDetail
showOnDetail
onlyOnTableRow
exceptOnTableRow
showOnTableRow
您可以通過讓動作類繼承自來將某動作指定為破壞性或危險動作 Laravel\Nova\Actions\DestructiveAction
。這會將操作的確認(rèn)按鈕的顏色更改為紅色:
破壞性行動與政策
將破壞性操作添加到具有關(guān)聯(lián)授權(quán)策略的資源時,該策略的 delete
方法必須返回 true
才能運行該操作。
有時,您可能希望在分派操作之前從用戶那里收集其他信息。因此,Nova 允許您將 Nova 支持的大多數(shù)字段直接附加到動作上。啟動操作時,Nova 將提示用戶提供以下字段的輸入:
要將字段添加到動作,請將字段添加到該動作的 fields
方法返回的字段數(shù)組中:
use Laravel\Nova\Fields\Text;
/**
* Get the fields available on the action.
*
* @return array
*/
public function fields()
{
return [
Text::make('Subject'),
];
}
最后,在您的操作 handle
方法內(nèi),您可以使用提供的 ActionFields
實例上的動態(tài)訪問器來訪問字段:
/**
* 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);
}
}
默認(rèn)情況下,操作將在運行前要求用戶確認(rèn)。您可以自定義確認(rèn)消息,確認(rèn)按鈕和取消按鈕,以在執(zhí)行操作之前為用戶提供更多上下文。這是通過指定的完成 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"),
];
}
這將自定義模式,如下所示:
通常,執(zhí)行操作時,Nova UI 中會顯示通用的 “成功” 消息。但是,您可以使用 Action
類上的各種方法來自定義此響應(yīng)。
要顯示自定義的 “成功” 消息,可以 Action::message
從您的 handle
方法中返回該方法的結(jié)果:
/**
* 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!');
要在執(zhí)行操作后將用戶重定向到一個全新的位置,可以使用以下 Action::redirect
方法:
return Action::redirect('https://example.com');
要將用戶重定向到內(nèi)部路由,請使用以下 Action::push
方法:
return Action::push('/resources/posts/new', [
'viaResource' => 'users',
'viaResourceId' => 1,
'viaRelationship' => 'posts'
]);
要在執(zhí)行操作后啟動文件下載,可以使用該 Action::download
方法。該 download
方法將要下載的文件的 URL 作為其第一個參數(shù),并將文件的所需名稱作為其第二個參數(shù):
return Action::download('https://example.com/invoice.pdf', 'Invoice.pdf');
有時,您可能需要花費一些時間才能完成運行。出于這個原因,Nova 讓您排隊行動很容易。要指示 Nova 將操作排入隊列而不是同步運行,請在 ShouldQueue
界面上標(biāo)記該操作:
<?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;
// ...
}
使用排隊操作時,請不要忘記為應(yīng)用程序配置和啟動隊列工作器。否則,您的操作將不會被處理。
排隊的操作文件
目前,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
特征附加到資源的相應(yīng) 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 將自動開始在資源的詳細(xì)信息屏幕底部顯示操作日志:
如果您不想在操作日志中記錄操作,則可以通過 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()
];
}
當(dāng)排隊的操作正在運行時,您可以為通過其模型集合傳遞給該操作的任何模型更新該操作的 “狀態(tài)”。例如,您可以使用操作的 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);
}
}
}
更多建議: