spatie / laravel-options
从不同来源创建选项数组
Requires
- php: ^8.1
- illuminate/contracts: ^8.81|^9.0|^10.0|^11.0
- spatie/laravel-package-tools: ^1.9.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.8
- myclabs/php-enum: ^1.6
- nunomaduro/collision: ^6.0|^5.0|^8.0
- nunomaduro/larastan: ^2.0.1|^1.0.3
- orchestra/testbench: ^7.0|^v6.24.1|^8.0|^9.0
- pestphp/pest: ^v1.21.3|^2.34
- pestphp/pest-plugin-laravel: ^1.1|^2.3
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.5|^10.5
- spatie/enum: ^3.13
- spatie/laravel-model-states: ^2.0
- spatie/laravel-ray: ^1.26
README
典型的Web应用程序通常有许多带有选项的选择字段。这个包使将枚举、模型、状态和数组转换为统一的选项结构变得简单。
假设你有以下枚举
enum Hobbit: string { case Frodo = 'frodo'; case Sam = 'sam'; case Merry = 'merry'; case Pippin = 'pippin'; }
你可以将其转换为以下选项
Options::forEnum(Hobbit::class)->toArray();
这将返回以下数组
[ ['label' => 'Frodo', 'value' => 'frodo'], ['label' => 'Sam', 'value' => 'sam'], ['label' => 'Merry', 'value' => 'merry'], ['label' => 'Pippin', 'value' => 'pippin'], ]
支持我们
我们投入了大量资源来创建一流的开放式源代码包。你可以通过购买我们的付费产品之一来支持我们。
我们非常感激您从家乡寄给我们一张明信片,说明您正在使用我们的哪个包。您可以在我们的联系页面上找到我们的地址。我们将所有收到的明信片发布在我们的虚拟明信片墙上。
安装
您可以通过composer安装此包
composer require spatie/laravel-options
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="options-config"
这是已发布的配置文件的内容
return [ /* * The key used in an option to describe the label of the option */ 'label_key' => 'label', /* * The key used in an option to describe the value of the option */ 'value_key' => 'value', ];
用法
您可以这样创建一个Options
对象(我们将在后面讨论其他内容,如枚举)
Options::forEnum(Hobbit::class);
您可以通过这种方式获取选项的数组表示形式
Options::forEnum(Hobbit::class)->toArray();
或JSON版本
Options::forEnum(Hobbit::class)->toJson();
您可以将选项作为响应的一部分返回到控制器中,它们将自动转换为JSON
class ShowHobbitsController{ public function __invoke(RingBearer $ringBearer){ return [ 'ring_bearer' => $ringBearer, 'hobbit_options' => Options::forEnum(Hobbit::class) ] } }
操作选项
您可以按标签对选项进行排序
Options::forEnum(Hobbit::class)->sort();
或使用闭包来排序选项
Options::forEnum(Hobbit::class)->sort(fn(Hobbit $hobbit) => $hobbit->value);
您可以通过以下方式向选项添加额外的数据
Options::forEnum(Hobbit::class)->append(fn(Hobbit $hobbit) => [ 'ring_bearer' => $hobbit === Hobbit::Frodo || $hobbit === Hobbit::Sam ]);
这将导致以下选项数组
[ ['label' => 'Frodo', 'value' => 'frodo', 'ring_bearer' => true], ['label' => 'Sam', 'value' => 'sam', 'ring_bearer' => true], ['label' => 'Merry', 'value' => 'merry', 'ring_bearer' => false], ['label' => 'Pippin', 'value' => 'pippin', 'ring_bearer' => false], ]
您可以过滤要包含的选项
Options::forEnum(Hobbit::class)->filter(fn(Hobbit $hobbit) => $hobbit === Hobbit::Frodo);
这将创建一个较小的选项数组
[ ['label' => 'Frodo', 'value' => 'frodo'], ]
或拒绝特定的选项被包含
Options::forEnum(Hobbit::class)->reject(fn(Hobbit $hobbit) => $hobbit === Hobbit::Frodo);
这将创建此选项数组
[ ['label' => 'Sam', 'value' => 'sam'], ['label' => 'Merry', 'value' => 'merry'], ['label' => 'Pippin', 'value' => 'pippin'], ]
可以添加一个唯一的null
选项,如下所示
Options::forEnum(Hobbit::class)->nullable();
这将添加一个值为null
的选项
[ ['label' => '-', 'value' => null], ['label' => 'Frodo', 'value' => 'frodo'], ['label' => 'Sam', 'value' => 'sam'], ['label' => 'Merry', 'value' => 'merry'], ['label' => 'Pippin', 'value' => 'pippin'], ]
null
选项的标签可以按如下方式更改
Options::forEnum(Hobbit::class)->nullable('Gandalf');
可以为null设置另一个值如下
Options::forEnum(Hobbit::class)->nullable(label: 'Gandalf', value: 'You Shall Not Pass');
可以通过更改options.php
配置文件来更改选项中使用的键。例如
return [ /* * The key used in an option to describe the label of the option */ 'label_key' => 'name', /* * The key used in an option to describe the value of the option */ 'value_key' => 'id', ];
将导致以下选项
[ ['name' => 'Frodo', 'id' => 'frodo'], ['name' => 'Sam', 'id' => 'sam'], ['name' => 'Merry', 'id' => 'merry'], ['name' => 'Pippin', 'id' => 'pippin'], ]
与枚举一起使用
您可以创建原生PHP枚举、Spatie Enums和MyClabs Enums的选项,如下所示
Options::forEnum(Hobbit::class);
默认情况下,包将查找一个名为labels
的静态方法,将枚举的标签作为数组返回
enum Hobbit: string { case Frodo = 'frodo'; case Sam = 'sam'; case Merry = 'merry'; case Pippin = 'pippin'; public static function labels(): array { return [ 'frodo' => 'Frodo Baggins', 'sam' => 'Sam Gamgee', 'merry' => 'Merry Brandybuck', 'pippin' => 'Pippin Took', ]; } }
现在选项数组将看起来像这样
[ ['label' => 'Frodo Baggins', 'value' => 'frodo'], ['label' => 'Sam Gamgee', 'value' => 'sam'], ['label' => 'Merry Brandybuck', 'value' => 'merry'], ['label' => 'Pippin Took', 'value' => 'pippin'], ]
您可以使用另一个方法名来获取标签,如下所示
Options::forEnum(Hobbit::class, 'hobbitLabels');
或使用闭包来解析枚举的标签
Options::forEnum(Hobbit::class, fn(Hobbit $hobbit) => $hobbit->name. ' from the shire'));
与模型一起使用
您可以创建Laravel模型的选项,如下所示
Options::forModels(Wizard::class);
使用单个模型
Options::forModels(Wizard::first());
或模型集合
Options::forModels(Wizard::all());
您也可以传递一个Builder
实例
Options::forModels(Wizard::query()->where('name', 'gandalf'));
默认情况下,模型的关键字(通常是id
)将被用作值,而name
字段用作标签。
您可以像这样更改值字段
Options::forModels(Wizard::class, value: 'uuid');
或者使用闭包来确定值
Options::forModels(Wizard::class, value: fn(Wizard $wizard) => $wizard->uuid());
您可以这样更改标签字段
Options::forModels(Wizard::class, label: 'full_name');
或者您可以使用闭包来解析标签
Options::forModels(Wizard::class, label: fn(Wizard $wizard) => $wizard->getName());
带有选择选项
如果您在很多地方使用模型的选项,那么每次手动定义标签和/或值字段可能会变得相当繁琐
Options::forModels( Wizard::class, label: fn(Wizard $wizard) => $wizard->getUuid(), value: fn(Wizard $wizard) => $wizard->getName(), ); // A lot of times within your code base
您可以在模型(或任何PHP类)上实现Selectable
,这将自动将模型转换为具有正确字段的选项
class Wizard extends Model implements Selectable { public function toSelectOption(): SelectOption { return new SelectOption( $this->getName(), $this->getUuid() ) } }
现在您可以省略标签和值字段定义
Options::forModels(Wizard::class);
您还可以使用SelectOption
传递一些额外的数据,就像我们之前看到的append
方法一样
public function toSelectOption(): SelectOption { return new SelectOption( $this->getName(), $this->getUuid(), ['color' => $this->color] ) }
现在选项数组将看起来像这样
[ ['label' => 'Gandalf', 'id' => '...', 'color' => 'gray'], ['label' => 'Saruman', 'id' => '...', 'color' => 'white'], ]
如前所述,实现Selectable
不仅限于模型。您可以在任何PHP类上实现它。在这种情况下,您可以创建如下选项
Options::forSelectableOptions([ SelectableOption::find(1), SelectableOption::find(2), SelectableOption::find(3), ]);
带有状态
您可以使用Spatie的model-states包创建选项,如下所示
Options::forStates(RingState::class);
您可以传入一个模型(否则将创建一个临时模型)
Options::forStates(RingState::class, $ring);
该包将自动查找一个名为label
的公共方法,用作标签
class LostRingState extends RingsState { public function label(): string { return 'Lost'; } }
或一个名为label
的公共属性
class DestroyedRingState extends RingsState { public string $label = 'destroyed'; }
您可以更改用作标签的方法或属性的名称,如下所示
Options::forStates(RingState::class, label: 'ringLabel');
或使用闭包来解析状态的标签
Options::forStates(RingState::class, label: fn(RingState $state) => $state->label());
使用数组
您可以从关联数组创建一系列选项
Options::forArray([ 'gondor' => 'Gondor', 'rohan' => 'Rohan', 'mordor' => 'Mordor', ])
您也可以使用这样的普通数组
Options::forArray([ 'Gondor', 'Rohan', 'Mordor', ],useLabelsAsValue: true)
在这种情况下,标签和值将相等。
没有任何东西
最后,您可以创建一个空的选项列表,如下所示
Options::empty();
用于验证
选项可以被转换为Laravel验证规则
$request->validate([ // ['in:frodo,sam,merry,pippin'] 'hobbit' => Options::forEnum(Hobbit::class)->toValidationRule() ]);
当选项可为空时,验证规则将自动变为可为空
$request->validate([ // ['nullable', 'in:frodo,sam,merry,pippin'] 'hobbit' => Options::forEnum(Hobbit::class)->nullable()->toValidationRule() ]);
迭代
您可以对一系列选项进行迭代
foreach(Options::forEnum(Hobbit::class) as $option){ echo "<option value={$option['value']}>{$option['label']}</option>"; }
测试
composer test
更新日志
请参阅更新日志以获取有关最近更改的更多信息。
贡献
请参阅贡献指南以获取详细信息。
安全漏洞
请查阅我们的安全策略以了解如何报告安全漏洞。
鸣谢
许可证
MIT许可证(MIT)。请参阅许可证文件以获取更多信息。