【问题标题】:enum class in ternary expression三元表达式中的枚举类
【发布时间】:2022-01-26 02:00:59
【问题描述】:

枚举是最近引入 PHP 的。我正在一个 laravel 项目中尝试它们。我在这里有我的枚举类:

namespace App\Enums;

enum AlertType
{
    case SUCCESS;
    case ERROR;
}

我正在尝试创建一个警报类,它将使用构造函数中的枚举来设置警报的严重性,这将决定它呈现给用户的颜色。这是那个类:

<?php

namespace App\View\Components;

use App\Enums\AlertType;
use Illuminate\View\Component;

class Alert extends Component
{
    public string $contextClass;

    public function __construct(public string $message, AlertType $alertType = AlertType::SUCCESS)
    {
        $this->setContextClassFromAlertType($alertType);
    }

    public function setContextClassFromAlertType(AlertType $alertType)
    {
        $this->contextClass = ($alertType === AlertType::SUCCESS ? 'success' : 'error');
    }

    public function getClassListFromType()
    {
        return [
            'border-' . $this->contextClass,
            'text-' . $this->contextClass
        ];
    }

    public function render()
    {
        return view('components.alert', [
            'class' => implode(' ', $this->getClassListFromType())
        ]);
    }
}

此警报将用于使用 Laravel Livewire 和刀片组件构建的登录表单:

<form class="grid grid-cols-min-auto-1 gap-x-2" id="login" action="/login" method="post">
    <x-alert :message="$errorMessage"/>
    @csrf
    <label for="email" class="mb-2 text-lg text-sans w-min mt-2 font-thin">Email</label>
    <x-basic-input wire:model="email" placeholder="{{ $emailPlaceholder }}"/>
    <label for="password" class="mb-2 text-lg text-sans w-min mt-2 font-thin">Password</label>
    <x-basic-input wire:model="password"/>
</form>

当我开始显示登录表单时,出现以下错误:

Cannot instantiate enum App\Enums\AlertType (View: /resources/views/livewire/forms/login.blade.php)

我认为我在 Alert 组件中的枚举使用有问题,但我不确定在哪里。谁能指出我正确的方向。我查看了枚举的 rfc,但看不到任何明显的错误

【问题讨论】:

    标签: php laravel enums php-8.1


    【解决方案1】:

    我能够重现此错误;在我的情况下,堆栈跟踪返回到 barryvdh/laravel-debugbar 包,不确定这对你来说是否相同。我可以通过将枚举更改为 backed enum 来解决它。

    无论如何,我都建议进行此更改,因为我希望在很多情况下,字符串比枚举实例更易于使用。 (虽然 TBH 这看起来像是尝试使用新功能只是因为它在那里,而不是因为它有意义。)

    namespace App\Enums;
    
    enum AlertType: string
    {
        case SUCCESS = 'success';
        case ERROR = 'error';
        case INFO = 'info';
    }
    

    在支持的枚举中,每个项目都有一个字符串表示,可以使用 value 属性访问,我们在构造函数中这样做:

    <?php
    
    namespace App\View\Components;
    
    use App\Enums\AlertType;
    use Illuminate\View\Component;
    
    class Alert extends Component
    {
        public string $contextClass;
    
        public function __construct(
            public string $message,
            AlertType $alertType = AlertType::SUCCESS,
        )
        {
            $this->contextClass = $alertType->value;
        }
    
        public function getClassListFromType()
        {
            return [
                'border-' . $this->contextClass,
                'text-' . $this->contextClass
            ];
        }
    
        public function render()
        {
            return view('components.alert', [
                'class' => implode(' ', $this->getClassListFromType())
            ]);
        }
    }
    

    您现在可以使用from()tryFrom() 方法,这些方法可以增加保存在变量中的警报类型的灵活性。例如:

    <x-alert :message="$errorMessage" :type="App\Enums\AlertType::from($errorType)"/>
    

    【讨论】:

    • 我没有使用 debugbar 包,所以不能这样
    • 您是否尝试过使用支持的枚举?可能是相同的问题出现在不同的代码中。
    • 我切换到使用支持的枚举,它似乎确实解决了这个问题。虽然它更多的是一种解决方法,而不是解决原始问题
    • 就像我说的那样,访问字符串值对于这个用例来说更有意义,无论如何 IMO。如果您真的想深入研究原始问题,则需要查看原始异常的堆栈跟踪。
    • 我想我已经弄清楚了最初的错误是什么,请参阅:stackoverflow.com/a/70551731/9578612。你怎么看?我认为您的解决方法是我的 Laravel 应用程序的方法,即使用支持的枚举。
    【解决方案2】:

    我认为这里的问题是由于依赖注入。在构造函数中我输入了一个枚举,所以 Laravel 容器试图创建一个该类的实例来传递,因为枚举是可实例化的,所以它不起作用。

    如果我更新容器以手动解析类型提示的实例,如下所示:

    $this->app->bind(Alert::class, function ($app) {
        return new Alert('this is a message', AlertType::SUCCESS);
    });
    

    然后问题得到解决,并按预期工作。我需要改变我在这里使用枚举的方式,因为@miken32 建议使用支持的枚举并依赖字符串。否则,我需要为要传递枚举的每个方法覆盖容器注入。

    【讨论】:

    • 这是有道理的;我正在使用的调试栏可能也在尝试实例化枚举以显示信息。您上面的代码在AppServiceProvider 类中?
    猜你喜欢
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-12
    • 1970-01-01
    相关资源
    最近更新 更多