在 Laravel Nova 中对多个布尔属性进行分组

发布于 作者:

Group multiple boolean attributes in Laravel Nova image

Laravel Nova 带来了大量令人惊叹的字段。默认情况下,这些字段非常智能,几乎可以适应任何情况。但是,如果您的 UI 符合您的需求,但字段处理数据的方式却有所不同,该怎么办?您是否必须 创建自定义字段?答案可能是否定的。

自定义字段

Laravel Nova 的字段包含许多方法,允许您自定义其行为。如文档中所述,您可以通过附加 fillUsing() 回调来自定义相应模型的 数据填充 方式。您还可以通过附加 resolveUsing() 回调来自定义字段的 解析 方式。因此,让我们使用这些函数来创建自己的“自定义”字段。

将多个布尔值分组到 BooleanGroup

假设您有一个 Message 模型,它表示可以在多个范围内显示的消息,例如:websiteapprss。您希望能够根据范围轻松查询这些消息,因此您添加了 3 个布尔字段:scope_websitescope_appscope_rss

是的,您可以创建类别并创建一个中间表;但是,您只有这些范围,然后您就想起了这是一个示例。.

<?php
 
namespace App\Nova\Resources;
 
use App\Nova\Resource;
use Illuminate\Http\Request;
use Laravel\Nova\Fields\BooleanGroup;
 
class MessageResource extends Resource
{
// ...
 
public function fields(Request $request): array
{
return [
BooleanGroup::make('Scopes')->options($options = [
'scope_website' => 'Website',
'scope_app' => 'Application',
'scope_rss' => 'RSS Feed',
])
];
}
}

填充模型属性

我们不希望将 3 个不同的字段添加到 Nova Resource 中,而是希望添加一个包含这些范围的 BooleanGroup。默认情况下,BooleanGroup 字段会将其选项存储为单个属性上的 JSON 块。为了改变此行为,我们将通过使用此回调函数调用 fillUsing 方法来自定义字段的填充。

use App\Model\Message;
use Laravel\Nova\Http\Requests\NovaRequest;
 
// this function goes inside ->fillUsing(...)
function (NovaRequest $request, Message $model, string $attribute, string $requestAttribute) {
// Make sure the `scopes` value exists on the request.
if (!$request->exists($requestAttribute)) {
return;
}
// Decode the values because it is send as a JSON blob.
$values = json_decode($request[$requestAttribute], true);
// Hydrate the model.
foreach ($values as $key => $value) {
$model->{$key} = $value;
}
}

fillUsing() 的回调函数接收 4 个参数

  • NovaReqeust $request 具有 POST 值的请求对象
  • Message $model 我们要填充的模型
  • string $attribute 模型上的属性名称(在本示例中我们不使用它)
  • string $requestAttribute $request 对象中包含我们 POST 值的属性名称

在确保我们发布了值后,我们可以将所有这些选项映射到其模型属性。实际上,相当于调用类似以下内容:

$model->scope_website = 1; // or 0

解析字段

现在,我们已经将布尔值存储在正确的属性上,现在该看看在 Nova 中如何解析字段了。虽然模型可能设置了范围,但所有复选框都将处于“关闭”状态。这是因为该字段仍然尝试从 $model->scopes 中检索其值;而 $model->scopes 不存在。因此,让我们通过添加 resolveUsing 回调来修复它。

您可能已经注意到,我们在 $options 变量中定义了字段选项。这是故意的,因为我们需要这些选项的键。到目前为止,resolveUsing 回调无法访问该字段本身来检索这些选项。这是我们的解决方法。

// this function goes inside ->resolveUsing(...)
function ($value, Message $model, string $attribute) use ($options) {
$keys = array_keys($options);
$values = array_map(function($value, $key) use ($model) {
return $model->{$key};
}, $options, $keys);
 
return array_combine($keys, $values);
}

resolveUsing() 的回调函数接收 3 个参数

  • mixed $value Laravel Nova 尝试检索的值
  • Message $model 提供该值的模型
  • string $attribute 模型上的属性名称(同样,我们不需要它)

我们的回调函数唯一需要做的就是从模型中检索每个布尔值的值,并将这些值作为数组返回。这段代码有点乱。很难看懂它在做什么,而且我们需要在多个函数范围内 use 值。让我们使用简写函数和一些 Laravel collect 魔法来清理代码。

fn($value, Message $model) => collect($options)->map(fn($value, $key) => $model->{$key})

瞧,一个简洁的单行代码,可以从正确的模型属性中解析字段。刷新 Nova 页面后,复选框应该会正确地显示其状态。

附加:将此字段设为 required

为了好玩,假设您需要选择至少一个范围。您可能最先想到的是在字段上设置 ->required(),但这实际上不起作用,虽然它会在表单上显示一个漂亮的星号 *。幸运的是,我们也可以通过在字段上调用 rules() 方法来添加自定义验证规则。

$field->rules('required', function (string $attribute, $value, callable $fail) {
if (!array_filter(json_decode($value, true) ?? [])) {
return $fail(sprintf('The "%s" field must have at least one option selected.', $attribute));
}
})

设置 required 规则也会在表单上添加星号 *。该回调函数会快速检查是否有任何值被返回为 true。如果没有,我们会调用 $fail 可调用函数并提供验证失败的原因。

就这样;一个自定义字段,无需实际构建自定义字段。

Doeke Norg photo

来自荷兰格罗宁根的 PHP 开发人员。主要使用 Symfony、Laravel 和一些 WordPress 插件。测试爱好者。最近开始 博客

归档于
Cube

Laravel 新闻稿

加入 40,000 多名其他开发人员,绝不错过新的技巧、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

不妥协

Joel 和 Aaron,两位来自“不妥协”播客的经验丰富的开发人员,现在可以为您的 Laravel 项目提供服务。⬧ 固定价格为每月 7500 美元。⬧ 无需冗长的销售流程。⬧ 无需合同。⬧ 100% 退款保证。

不妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,以确保您的 Web 应用程序成功。

Kirschbaum
Shift logo

Shift

正在运行旧版本的 Laravel?即时、自动化的 Laravel 升级和代码现代化,让您的应用程序始终保持新鲜。

Shift
Bacancy logo

Bacancy

与经验丰富的 Laravel 开发人员一起为您的项目注入活力,他们拥有 4-6 年的经验,每月仅需 2500 美元。获得 160 小时的专业服务和 15 天的无风险试用。立即预约电话!

Bacancy
Lucky Media logo

Lucky Media

立即获得幸运 - Laravel 开发的理想之选,拥有超过十年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel 电子商务

Laravel 电子商务。一个开源软件包,将现代无头电子商务功能的力量带入 Laravel。

Lunar: Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 职位招聘网站

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS 启动套件

SaaSykit 是一个 Laravel SaaS 启动套件,包含运行现代 SaaS 所需的所有功能。付款、漂亮结账、管理面板、用户仪表盘、身份验证、现成组件、统计数据、博客、文档等等。

SaaSykit: Laravel SaaS 启动套件
Rector logo

Rector

您的无缝 Laravel 升级合作伙伴,降低成本,加快创新,助力企业成功

Rector
MongoDB logo

MongoDB

通过将 MongoDB 和 Laravel 强力集成,增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。在使用熟悉的 Eloquent API 的同时,支持事务、搜索、分析和移动用例。了解灵活的现代数据库 MongoDB 如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的无依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

将 Swagger UI 添加到您的 Laravel 应用程序

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包将评论添加到您的 Laravel 应用程序

阅读文章