三元表达式中的 enum class
enum class in ternary expression
最近 PHP 引入了枚举。我正在 laravel 项目中试用它们。我的枚举 class 在这里:
namespace App\Enums;
enum AlertType
{
case SUCCESS;
case ERROR;
}
我正在尝试创建一个警报 class,它将在构造函数中使用枚举来设置警报的严重性,这将决定向用户呈现什么颜色。这是 class:
<?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 和 blade 组件构建的登录表单:
<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 组件中使用 enum 有问题,但我不确定在哪里。谁能指出我正确的方向。我查看了枚举的 rfc,但我看不到任何明显的错误
我能够重现这个错误;在我的例子中,堆栈跟踪返回到 barryvdh/laravel-debugbar
包,不确定这对你来说是否相同。我能够通过将枚举更改为 backed enum.
来解决它
无论如何我都建议进行此更改,因为我预计在很多情况下字符串比枚举实例更易于使用。 (尽管说实话,这看起来像是尝试使用一项新功能,只是因为它在那里,而不是因为它有意义。)
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)"/>
我认为这里的问题是由于依赖注入。在构造函数中,我输入了一个枚举,所以 Laravel 容器试图创建一个 class 的实例来传递,但它不起作用,因为枚举是可实例化的。
如果我更新容器以像这样手动解析类型提示实例:
$this->app->bind(Alert::class, function ($app) {
return new Alert('this is a message', AlertType::SUCCESS);
});
然后问题就解决了,一切正常。我需要更改我在这里使用枚举的方式,因为 @miken32 建议使用支持的枚举并改为依赖字符串。否则我需要为我想传递枚举的每个方法重写容器注入。
最近 PHP 引入了枚举。我正在 laravel 项目中试用它们。我的枚举 class 在这里:
namespace App\Enums;
enum AlertType
{
case SUCCESS;
case ERROR;
}
我正在尝试创建一个警报 class,它将在构造函数中使用枚举来设置警报的严重性,这将决定向用户呈现什么颜色。这是 class:
<?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 和 blade 组件构建的登录表单:
<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 组件中使用 enum 有问题,但我不确定在哪里。谁能指出我正确的方向。我查看了枚举的 rfc,但我看不到任何明显的错误
我能够重现这个错误;在我的例子中,堆栈跟踪返回到 barryvdh/laravel-debugbar
包,不确定这对你来说是否相同。我能够通过将枚举更改为 backed enum.
无论如何我都建议进行此更改,因为我预计在很多情况下字符串比枚举实例更易于使用。 (尽管说实话,这看起来像是尝试使用一项新功能,只是因为它在那里,而不是因为它有意义。)
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)"/>
我认为这里的问题是由于依赖注入。在构造函数中,我输入了一个枚举,所以 Laravel 容器试图创建一个 class 的实例来传递,但它不起作用,因为枚举是可实例化的。
如果我更新容器以像这样手动解析类型提示实例:
$this->app->bind(Alert::class, function ($app) {
return new Alert('this is a message', AlertType::SUCCESS);
});
然后问题就解决了,一切正常。我需要更改我在这里使用枚举的方式,因为 @miken32 建议使用支持的枚举并改为依赖字符串。否则我需要为我想传递枚举的每个方法重写容器注入。