php 在 Laravel 中放置/如何处理枚举?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25705878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 17:57:36  来源:igfitidea点击:

Where to put/how to handle enums in Laravel?

phplaravelenums

提问by mpen

Laravel has a <select>form helperwhich takes as input a dictionary. I like to keep the values for all of these in a central place. For example, I might have an enum that looks like this:

Laravel 有一个<select>表单助手,它将字典作为输入。我喜欢将所有这些的价值观放在一个中心位置。例如,我可能有一个看起来像这样的枚举:

$phoneTypes = [
    'CELL' => "Cellular",
    'HOME' => "Home",
    'WORK' => "Work",
];

Which I want to use in both my view/template, and in the database:

我想在我的视图/模板和数据库中使用它:

Schema::create('customers', function (Blueprint $table) {
    $table->increments('id');
    $table->enum('pri_phone_type',array_keys($phoneTypes));
    ...
});
  1. Is there a recommended place to put these?
  2. Can I make them global so I can access them easily in all my views?
  1. 有没有推荐的地方放这些?
  2. 我可以将它们设为全局,以便我可以在所有视图中轻松访问它们吗?

回答by jszobody

You have several options for handling enums. Before we look at a few though, I would first strongly encourage you notto use the DB enumcolumn type.

您有多种处理枚举的选项。在我们看一些之前,我首先强烈建议您不要使用 DBenum列类型。

Database enums are problematic for a number of reasons. I suggest reading this article for example:

由于多种原因,数据库枚举存在问题。我建议阅读这篇文章,例如:

http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

So with that let's look at a few other options.

因此,让我们看看其他一些选项。

Using Laravel config

使用 Laravel 配置

Since you're using Laravel, one very simple option is to stick an array of options in a config file.

由于您使用的是 Laravel,因此一个非常简单的选择是在配置文件中粘贴一组选项。

Say you create a new file config/enums.phpwith the following:

假设您config/enums.php使用以下内容创建一个新文件:

return [
    'phone_types' => [
        'CELL' => "Cellular",
        'HOME' => "Home",
        'WORK' => "Work",
    ]
];

You can now access config('enums.phone_types')anywhere in your code, including your Blade template.

您现在可以访问config('enums.phone_types')代码中的任何位置,包括 Blade 模板。

Using a PHP package

使用 PHP 包

@Banford's answer shows how to do basic enum-type behavior with class constants. If you like that approach, I recommend looking at this article and package which builds on this concept to provide strongly type enums:

@Banford 的回答显示了如何使用类常量进行基本的枚举类型行为。如果您喜欢这种方法,我建议您查看本文和基于此概念的包,以提供强类型枚举:

https://stitcher.io/blog/php-enums

https://stitcher.io/blog/php-enums

https://github.com/spatie/enum

https://github.com/spatie/enum

You would create a class like this:

你会创建一个这样的类:

/**
 * @method static self cell()
 * @method static self home()
 * @method static self work()
 */
class PhoneTypes extends Enum
{
}

And now you can call PhoneTypes::home()in your app. Check out the documentation for that package to see how you can create a map of values, if you want.

现在您可以PhoneTypes::home()在您的应用程序中调用。如果需要,请查看该包的文档以了解如何创建值映射。

Using DB relationships

使用数据库关系

If you reallywant to manage your options in the database, I'd create a separate phone_typesdatabase table and create a relationship with your customerstable. This is stilla much better option than using enumcolumn type.

如果您真的想在数据库中管理您的选项,我会创建一个单独的phone_types数据库表并与您的customers表建立关系。这仍然是比使用enum列类型更好的选择。

回答by Banford

I disagree with the accepted answer here. I feel that enums can be very useful for this kind of thing. I prefer to treat enums as types, and implement the methods you need on the Enum base class to give you the functionality you need such as getting a dictionary.

我不同意这里接受的答案。我觉得枚举对于这种事情非常有用。我更喜欢将枚举视为类型,并在 Enum 基类上实现您需要的方法,以提供您需要的功能,例如获取字典。

My simple example below:

我的简单示例如下:

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());
    }
}

Example usage:

用法示例:

PhoneType::getKeys();

See PHP and Enumerationsfor further details and a more in depth example.

有关更多详细信息和更深入的示例,请参阅PHP 和枚举

回答by Kirill Fuchs

Building on @Banfords answer, with PHP7 constants can now be arrays:

基于@Banfords 的回答,PHP7 常量现在可以是数组:

class User extends Authenticatable
{
    /**
     * The possible genders a user can be.
     */
    const GENDER = [
        'Male',
        'Female',
        'Unspecified'
    ];

...

回答by BenSampo

In addition to @Banford's answer:

除了@Banford 的回答:

I have recently put together a package which makes working with enums in Laravel much nicer. It's a combination of various implementations I had found while researching how to do the very same thing (hence why I'm here).

我最近整理了一个包,它使在 Laravel 中使用枚举变得更好。这是我在研究如何做同样的事情时发现的各种实现的组合(因此我在这里的原因)。

https://github.com/BenSampo/laravel-enum

https://github.com/BenSampo/laravel-enum

In this case, you could do something like the following:

在这种情况下,您可以执行以下操作:

final class PhoneTypes extends Enum
{
    const Cellular = 0;
    const Work = 1;
    const Home = 2;
}

The values can then be accessed using:

然后可以使用以下方法访问这些值:

PhoneTypes::Work // 1

I would recommend always setting the values to integers and subsequently storing them in the DB as ints.

我建议始终将值设置为整数,然后将它们作为整数存储在数据库中。

The base Enum class has methods for getting all keys and values as arrays. The package also features a couple of other benefits which may be useful in this case such as validation - so that a user couldn't add a non-existent value to the DB.

基本 Enum 类具有将所有键和值作为数组获取的方法。该包还具有其他一些在这种情况下可能有用的好处,例如验证 - 以便用户无法向数据库添加不存在的值。

There's also a generator which is pretty handy.

还有一个非常方便的发电机。

I hope this comes in useful for someone.

我希望这对某人有用。

回答by lchachurski

Just had similar issue, for me Eloquent Accessors and mutatorsworked the best. For this question it would go like:

刚刚遇到了类似的问题,对我来说,Eloquent Accessors 和 mutator效果最好。对于这个问题,它会是这样的:

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);
    }
}

Please note that in database you should save numeric values, where 0 is cell, 1 is home and 2 is work. Secondly it would be wise to use translations here instead protected property.

请注意,在数据库中您应该保存数值,其中 0 是单元格,1 是家,2 是工作。其次,在这里使用翻译而不是受保护的财产是明智的。

回答by Yevgeniy Afanasyev

You should not use enum at all.

你根本不应该使用枚举。

The official Laravel 5.1 documentationstates:

Laravel 5.1 官方文档指出:

Note: Renaming columns in a table with a enum column is not currently supported.

注意:当前不支持使用枚举列重命名表中的列。

It happens when you have a enumcolumn in your database table. Whether you are trying to renameanothercolumn, or change anothercolumn to nullable, the bug will appear. It's an issue with Doctrine\DBAL.

当您enum的数据库表中有列时会发生这种情况。无论您是尝试rename另一列,还是将另一列更改为nullable,都会出现该错误。这是 Doctrine\DBAL 的问题。

Unknown database type enum requested

请求的未知数据库类型枚举

Even with laravel 5.8, problem is not resolved.

即使使用 laravel 5.8,问题也没有解决。

I need to add that you will have the same problem when adding available optionsinto enumcolumn declaration.

我需要补充一点,在将可用选项添加enum列声明中时,您会遇到同样的问题。

It brings me to a conclusion that You should use enum with care.or even You should not use enum at all.

它使我得出一个结论,您应该谨慎使用 enum。甚至你根本不应该使用枚举。

Here is an example of how difficult would it be adding available optionsinto enumcolumn declaration

这是将可用选项添加enum列声明中的难度示例

say you have this:

说你有这个:

Schema::create('blogs', function (Blueprint $table) {
    $table->enum('type', [BlogType::KEY_PAYMENTS]);
    $table->index(['type', 'created_at']);
...

and you need to make more types available

并且您需要提供更多类型

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']);
    });
}