Laravel有a <select>
form helper,它将词典作为输入。我喜欢把所有这些的价值保持在一个中心位置。例如,我可能有一个看起来像这样的枚举:
$phoneTypes = [
'CELL' => "Cellular",
'HOME' => "Home",
'WORK' => "Work",
];
我想在我的视图/模板和数据库中使用它:
Schema::create('customers', function (Blueprint $table) {
$table->increments('id');
$table->enum('pri_phone_type',array_keys($phoneTypes));
...
});
答案 0 :(得分:56)
我不同意这里接受的答案。我觉得枚举对于这种事情非常有用。我更喜欢将枚举视为类型,并在Enum基类上实现所需的方法,以便为您提供所需的功能,例如获取字典。
我的简单示例如下:
abstract class PhoneType extends Enum {
const Cell = "Cellular";
const Home = "Home";
const Work = "Work";
}
abstract class Enum {
static function getKeys(){
$class = new ReflectionClass(get_called_class());
return array_keys($class->getConstants());
}
}
使用示例:
PhoneType::getKeys();
有关详细信息和更深入的示例,请参阅PHP and Enumerations。
答案 1 :(得分:49)
您有多种处理枚举的选项。在我们看一些之前,我首先强烈建议您不使用数据库enum
列类型。
由于多种原因,数据库枚举存在问题。我建议阅读这篇文章,例如:
http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/
因此,让我们看一些其他选项。
由于您正在使用Laravel,一个非常简单的选择是在配置文件中添加一组选项。
假设您使用以下内容创建新文件config/enums.php
:
return [
'phone_types' => [
'CELL' => "Cellular",
'HOME' => "Home",
'WORK' => "Work",
]
];
您现在可以在代码中的任何位置访问config('enums.phone_types')
,包括您的Blade模板。
@ Banford的答案显示了如何使用类常量执行基本的枚举类型行为。如果您喜欢这种方法,我建议您查看本文和基于此概念构建的包,以提供强类型枚举:
https://stitcher.io/blog/php-enums
https://github.com/spatie/enum
你会创建一个这样的类:
/**
* @method static self cell()
* @method static self home()
* @method static self work()
*/
class PhoneTypes extends Enum
{
}
现在您可以在应用中拨打PhoneTypes::home()
了。查看该软件包的文档,了解如何创建值的映射。
如果确实想要管理数据库中的选项,我将创建一个单独的phone_types
数据库表并与您的customers
表创建关系。这仍然比使用enum
列类型更好的选择。
答案 2 :(得分:10)
基于@Banfords答案,PHP7常量现在可以是数组:
class User extends Authenticatable
{
/**
* The possible genders a user can be.
*/
const GENDER = [
'Male',
'Female',
'Unspecified'
];
...
答案 3 :(得分:7)
除了@ Banford的回答:
我最近整理了一个软件包,使得在Laravel中使用枚举更好。这是我在研究如何做同样事情时发现的各种实现的组合(因此我在这里)。
https://github.com/BenSampo/laravel-enum
在这种情况下,您可以执行以下操作:
final class PhoneTypes extends Enum
{
const Cellular = 0;
const Work = 1;
const Home = 2;
}
然后可以使用以下方法访问这些值:
PhoneTypes::Work // 1
我建议始终将值设置为整数,然后将它们作为整数存储在数据库中。
基本枚举类具有将所有键和值作为数组获取的方法。该软件包还具有一些其他好处,在这种情况下可能很有用,例如验证 - 这样用户就无法向DB添加不存在的值。
还有一个非常方便的发电机。
我希望这对某人有用。
答案 4 :(得分:4)
刚才有类似问题,对我来说Eloquent Accessors and mutators效果最好。对于这个问题,它会像:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model
{
/**
* @var array
*/
protected $phoneTypes = [
'Cellular',
'Home',
'Work'
];
/**
* @param int $value
* @return string|null
*/
public function getPhoneTypeAttribute($value)
{
return Arr::get($this->phoneTypes, $value);
}
}
请注意,在数据库中,您应该保存数值,其中0是单元格,1是主页,2是工作。其次,在这里使用翻译而不是保护财产是明智的。
答案 5 :(得分:1)
您完全不应使用枚举。
Laravel 5.1 documentation官方声明:
注意:当前不支持使用enum列重命名表中的列。
当数据库表中有一个enum
列时,就会发生这种情况。不管您是尝试rename
另一个列,还是将另一个列更改为nullable
,都会出现该错误。这是Doctrine \ DBAL的问题。
请求的未知数据库类型枚举
即使使用laravel 5.8,问题也无法解决。
我需要补充的是,当将可用选项添加到enum
列声明中时,您也会遇到同样的问题。
我得出的结论是,您应谨慎使用枚举。甚至您根本不应使用枚举。
下面是一个例子,说明如何在向enum
列声明中添加可用选项
说你有这个:
Schema::create('blogs', function (Blueprint $table) {
$table->enum('type', [BlogType::KEY_PAYMENTS]);
$table->index(['type', 'created_at']);
...
并且您需要提供更多类型
public function up(): void
{
Schema::table('blogs', function (Blueprint $table) {
$table->dropIndex(['type', 'created_at']);
$table->enum('type_tmp', [
BlogType::KEY_PAYMENTS,
BlogType::KEY_CATS,
BlogType::KEY_DOGS,
])->after('type');
});
DB::statement('update `blogs` as te set te.`type_tmp` = te.`type` ');
Schema::table('blogs', function (Blueprint $table) {
$table->dropColumn('type');
});
Schema::table('blogs', function (Blueprint $table) {
$table->enum('type', [
BlogType::KEY_PAYMENTS,
BlogType::KEY_CATS,
BlogType::KEY_DOGS,
])->after('type_tmp');
});
DB::statement('update `blogs` as te set te.`type` = te.`type_tmp` ');
Schema::table('blogs', function (Blueprint $table) {
$table->dropColumn('type_tmp');
$table->index(['type', 'created_at']);
});
}
答案 6 :(得分:0)
假设您需要一个下拉选项
试试这个:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model
{
const PHONE_TYPES = [
[
'label' => 'Cellular',
'value' => 'Cellular',
],
[
'label' => 'Home',
'value' => 'Home',
],
[
'label' => 'Work',
'value' => 'Work',
],
];
public function getPhoneTypesLabelAttribute()
{
return collect(static::PHONE_TYPES)->firstWhere('value', $this->phone_types)['label'] ?? '';
}
}
在您的控制器中,假设在 create 方法下执行以下操作:
public function create(Customer $customer)
{
return response([
'meta' => [
'customer' => Customer::get(['id', 'first_name']),
'phone_types' => Customer::PHONE_TYPES,
],
]);
}
然后,在您的刀片模板中
dd($phone_types);