Я хочу использовать Ben Sampo Package для перечисления в laravel. этот пакет имеет свойство с именем «описание» в качестве нового свойства. но я не могу добавить дополнительные свойства (атрибуты) в свои перечисления.
Я хочу иметь статус перечисления с атрибутом isfinal. чтобы определить, является ли этот ключ окончательным или нет?
Мне действительно нужно добавить некоторые атрибуты к некоторым перечислениям. там в любом случае ?
Я проверил этот пакет тоже. это так хорошо и действительно легко добавить дополнительные свойства. но мне тоже нужна локализация, а ее по умолчанию нет.
Редактировать: перечисление, которое мне нужно, выглядит примерно так:
final class Status extends Enum
{
#[Color('red')]
#[Description('Initial status')]
#[IsFinal(false)]
const Initial = 1;
#[Color('blue')]
#[Description('suspended status')]
#[IsFinal(false)]
const Pending = 2;
#[Color('white')]
#[Description('completed status')]
#[IsFinal(true)]
const Completed = 3;
#[Color('red')]
#[Description('canceled status')]
#[IsFinal(true)]
const Canceled = 4;
}
И затем я хочу получить значение цвета или окончательное значение, подобное этому:
Status::getColor(1);
и
Status::Initial->getColor();
и
$enum->getColor();
Обновление: теперь у меня есть эта черта:
<?php
namespace App\Enums\Concerns;
use BenSampo\Enum\Attributes\Description;
use Exception;
/**
* Get Enum attributes
*/
trait GetEnumAttributes
{
public $color;
public $isFinal;
public function __construct(mixed $enumValue)
{
$this->color = $this->getCustomAttribute($enumValue, 'color');
$this->isFinal = $this->getCustomAttribute($enumValue, 'is_final');
$this->description = self::getDescription($enumValue);
parent::__construct($enumValue);
}
protected static function getCustomAttribute(mixed $value, $key)
{
$reflection = self::getReflection();
$constantName = static::getKey($value);
$constReflection = $reflection->getReflectionConstant($constantName);
if ($constReflection === false) {
return null;
}
switch ($key) {
case 'color':
// dd( $constReflection->getAttributes(Color::class));
$customAttributes = $constReflection->getAttributes(Color::class);
break;
case 'is_final':
$customAttributes = $constReflection->getAttributes(IsFinal::class);
break;
case 'description':
$customAttributes = $constReflection->getAttributes(Description::class);
break;
default:
$customAttributes = [];
break;
}
return match (count($customAttributes)) {
0 => null,
1 => $customAttributes[0]->newInstance()->$key,
default => throw new Exception('You cannot use more than 1 custom attribute on ' . class_basename(static::class) . '::' . $constantName),
};
}
public static function getCustomInstances()
{
return array_map(
function ($constantValue) {
$newStatic = new static($constantValue);
$newStatic = (array) $newStatic;
$newStatic['description'] = self::getCustomAttribute($constantValue,'description');//getDescription($constantValue);
$newStatic['color'] = self::getCustomAttribute($constantValue,'color');
$newStatic['isFinal'] = self::getCustomAttribute($constantValue,'is_final');
$newStatic = (object) $newStatic;
return $newStatic;
},
static::getConstants(),
);
}
}
И это происходит, когда я использую:
dd(Status::getInstances());
результат:
array:4 [▼ // app\Http\Controllers\testController.php:19
"Initial" => App\Enums\Status {#416 ▼
+value: 1
+key: "Initial"
+description: "initial status"
+color: null
+isFinal: null
}
"Pending" => App\Enums\Status {#418 ▼
+value: 2
+key: "Pending"
+description: "suspended status"
+color: null
+isFinal: null
}
"Completed" => App\Enums\Status {#421 ▶}
"Canceled" => App\Enums\Status {#422 ▶}
]
Я проверил проблему в «getCustomAttribute» на случай:
case 'color':
dd( $constReflection->getAttributes(Color::class));
$customAttributes = $constReflection->getAttributes(Color::class);
break;
возвращает null, однако $constReflection имеет все атрибуты правильно. то же самое происходит, когда я использую
Status::getCustomInstances();






Для пакета BenSampo вы можете сделать это следующим образом:
Создайте черту:
<?php
namespace App\Traits;
/**
* Get Enum Description
*/
trait GetEnumDescription
{
private static $thisClass;
public static function getCustomEnumDescription($enumValue = 0)
{
return __(self::getEnumDescription(intval($enumValue)));
}
private static function getEnumDescription($enumValue = 0)
{
self::$thisClass = static::class;
$key = self::$thisClass::getKey($enumValue);
return ucwords(str_replace('_', ' ', $key));
}
public static function getCustomInstances()
{
return array_map(
function ($constantValue) {
$newStatic = new static($constantValue);
$newStatic = (array) $newStatic;
$newStatic['custom_description'] = self::getCustomEnumDescription($constantValue);
$newStatic = (object) $newStatic;
return $newStatic;
},
static::getConstants(),
);
}
}
Создайте Enum (обычно я делаю значения перечисления с числовыми именами и именами переменных в змеином регистре. Вы можете настроить методы по своему усмотрению):
<?php
declare(strict_types=1);
namespace App\Enums;
use App\Traits\GetEnumDescription;
use BenSampo\Enum\Enum;
/**
* Menu item types
*/
final class MenuItemType extends Enum
{
use GetEnumDescription;
const both = 0;
const only_customer = 1;
const only_vendor = 2;
const closed = 3;
}
Убедитесь, что вы используете черту GetEnumDescription. Примеры:
// app()->setLocale('tr');
// dd(MenuItemType::getCustomInstances());
// RESULT:
array:4 [▼
"both" => {#1156 ▼
+"value": 0
+"key": "both"
+"description": "Both"
+"custom_description": "Her ikisi de"
}
"only_customer" => {#1157 ▼
+"value": 1
+"key": "only_customer"
+"description": "Only customer"
+"custom_description": "Sadece müşteri"
}
"only_vendor" => {#1159 ▼
+"value": 2
+"key": "only_vendor"
+"description": "Only vendor"
+"custom_description": "Sadece bayi"
}
"closed" => {#1158 ▼
+"value": 3
+"key": "closed"
+"description": "Closed"
+"custom_description": "Closed"
}
]
Пример:
public static function getCustomInstances()
{
return array_map(
function ($constantValue) {
$newStatic = new static($constantValue);
$newStatic = (array) $newStatic;
$newStatic['custom_description'] = self::getCustomEnumDescription($constantValue);
$newStatic['color'] = 'red';
$newStatic['is_final'] = true;
$newStatic = (object) $newStatic;
return $newStatic;
},
static::getConstants(),
);
}
Результат:
// after attributes added: dd(MenuItemType::getCustomInstances());
array:4 [▼
"both" => {#1156 ▼
+"value": 0
+"key": "both"
+"description": "Both"
+"custom_description": "Her ikisi de"
+"color": "red"
+"is_final": true
}
"only_customer" => {#1157 ▼
+"value": 1
+"key": "only_customer"
+"description": "Only customer"
+"custom_description": "Sadece müşteri"
+"color": "red"
+"is_final": true
}
"only_vendor" => {#1158 ▼
+"value": 2
+"key": "only_vendor"
+"description": "Only vendor"
+"custom_description": "Sadece bayi"
+"color": "red"
+"is_final": true
}
"closed" => {#1159 ▼
+"value": 3
+"key": "closed"
+"description": "Closed"
+"custom_description": "Kapalı"
+"color": "red"
+"is_final": true
}
]
Создайте два атрибута, чтобы сделать его в нужной вам структуре:
Color Атрибут:
<?php
declare(strict_types=1);
namespace App\Attributes;
use Attribute;
#[Attribute(Attribute::TARGET_CLASS_CONSTANT | Attribute::TARGET_CLASS)]
class Color
{
public function __construct(
public string $color,
) {
}
}
И IsFinal Атрибут:
<?php
declare(strict_types=1);
namespace App\Attributes;
use Attribute;
#[Attribute(Attribute::TARGET_CLASS_CONSTANT | Attribute::TARGET_CLASS)]
class IsFinal
{
public function __construct(
public bool $is_final,
) {
}
}
Вот как я создал ваше перечисление:
<?php
declare(strict_types=1);
namespace App\Enums;
use App\Attributes\Color;
use App\Attributes\IsFinal;
use BenSampo\Enum\Attributes\Description;
use BenSampo\Enum\Enum;
use Exception;
/**
* Menu item types
*/
final class MenuItemType extends Enum
{
public $color;
public $isFinal;
public function __construct(mixed $enumValue)
{
$this->color = $this->getCustomAttribute($enumValue, 'color');
$this->isFinal = $this->getCustomAttribute($enumValue, 'is_final');
parent::__construct($enumValue);
}
protected static function getCustomAttribute(mixed $value, $key)
{
$reflection = self::getReflection();
$constantName = static::getKey($value);
$constReflection = $reflection->getReflectionConstant($constantName);
if ($constReflection === false) {
return null;
}
switch ($key) {
case 'color':
$customAttributes = $constReflection->getAttributes(Color::class);
break;
case 'is_final':
$customAttributes = $constReflection->getAttributes(IsFinal::class);
break;
default:
break;
}
return match (count($customAttributes)) {
0 => null,
1 => $customAttributes[0]->newInstance()->$key,
default => throw new Exception('You cannot use more than 1 custom attribute on ' . class_basename(static::class) . '::' . $constantName),
};
}
const both = 0;
const only_customer = 1;
#[Color('blue')]
#[Description('test')]
#[IsFinal(true)]
const only_vendor = 2;
#[Color('red')]
#[IsFinal(false)]
const closed = 3;
}
Сделайте это с помощью dd(MenuItemType::getInstances()); Результат, когда я печатаю экран с помощью:
array:4 [▼ // app\Providers\AppServiceProvider.php:24
"both" => App\Enums\MenuItemType {#1156 ▼
+value: 0
+key: "both"
+description: "Both"
+color: null
+isFinal: null
}
"only_customer" => App\Enums\MenuItemType {#1157 ▼
+value: 1
+key: "only_customer"
+description: "Only customer"
+color: null
+isFinal: null
}
"only_vendor" => App\Enums\MenuItemType {#1158 ▼
+value: 2
+key: "only_vendor"
+description: "test"
+color: "blue"
+isFinal: true
}
"closed" => App\Enums\MenuItemType {#1160 ▼
+value: 3
+key: "closed"
+description: "Closed"
+color: "red"
+isFinal: false
}
]
Наслаждайся работой.
могу ли я использовать этот код для любых других атрибутов? как "цвет", "конечный", ...
Я хочу иметь статус перечисления с атрибутом isfinal. чтобы определить, является ли этот ключ окончательным или нет?
@ERasekh Да, можешь. Я добавил свойства color и is_final в качестве примера и обновил ответ.
Пожалуйста, добавляйте код и данные в виде текста (с использованием форматирования кода ), а не изображений. Изображения: A) не позволяйте нам копировать и вставлять код/ошибки/данные для тестирования; Б) не разрешать поиск по коду/ошибке/содержимому данных; и много других причин. Изображения должны использоваться в дополнение к тексту в формате кода только в том случае, если изображение добавляет что-то важное, что не передается только текстовым кодом/ошибкой/данными.
В вашем wxample цвет и isFinal всегда одинаковы. Я хочу определить эти свойства следующим образом: #[Color('red')] выше для каждого ключа перечисления, который я хочу.
Хорошо, вы можете сделать эту функцию, создав Attribute. Вскоре я добавлю пример в конец своего ответа.
Я обновил свой вопрос и добавил то, что хочу, в примере кода. Вы знаете, что я имею в виду?
мой вопрос, как добавить дополнительный атрибут? спасибо за ваши быстрые ответы. но я думаю, вы неправильно понимаете.
спасибо @cengsemihsahin. Я создал атрибут рядом с «описанием» в пакете bensampo. но я не знал, что мне делать, чтобы получить значения этого атрибута, которые выше ключей перечисления.
возвращает null для двух моих новых атрибутов. вы сообщаете getInstances(), но определили getCustomInstances сегодня утром. теперь оба метода возвращают null для новых атрибутов.
Вы не должны использовать оба способа вместе. Можете ли вы поделиться полным содержанием классов атрибутов и Enum, которые вы создали, обновив свой вопрос?
Я обновил, можешь проверить?
Я путаюсь. Я удаляю свой трейт и пишу код, как вы, в классе enum. оно работает!! почему черта не работает? есть подвох????
так красиво! Огромное спасибо. Я понял ваш код и поведение. и теперь я могу настроить его. большое спасибо.
Пакет BenSampo Laravel Enum отлично подходит для простой настройки перечислений в Laravel. Однако добавление дополнительных настраиваемых атрибутов может быть немного сложным, так как на данный момент он не поддерживается пакетом.
Вот несколько возможных подходов к достижению вашей цели:
Вы можете расширить базовый класс Enum для поддержки дополнительных атрибутов. Однако для этого требуется изменить сам класс Enum, что может быть не идеально, если вы работаете в команде или планируете обновить пакет в будущем.
namespace App\Enums;
use BenSampo\Enum\Enum as BaseEnum;
class Enum extends BaseEnum
{
public static function isFinal($value) {
// define the logic here
}
}
А затем используйте этот базовый класс для своих перечислений:
namespace App\Enums;
class Status extends Enum
{
const DRAFT = 0;
const FINAL = 1;
public static function getDescription($value): string
{
if ($value === self::FINAL) {
return 'Final';
}
return parent::getDescription($value);
}
}
С помощью описанного выше метода теперь вы можете проверить, является ли значение перечисления окончательным или нет:
Status::isFinal(Status::FINAL); // Should return true
Другой подход может заключаться в создании отдельных Enum для этих особых случаев. Например, у вас может быть класс перечисления FinalStatus для статусов, которые являются окончательными.
namespace App\Enums;
use BenSampo\Enum\Enum;
final class FinalStatus extends Enum
{
const PUBLISHED = 1;
// Add more final statuses here
}
Затем вы можете использовать функции локализации Laravel для локализации ваших перечислений. Вы должны создать языковые файлы для каждого языка, который хотите поддерживать, и использовать функцию __() в коде вашего приложения для извлечения локализованной строки.
В любом случае, самым чистым решением было бы наличие в пакете встроенной поддержки дополнительных атрибутов. Вы можете создать проблему или запрос на извлечение в репозитории пакета GitHub, чтобы узнать, будут ли сопровождающие открыты для такой функции.
спасибо, я отредактировал свой вопрос и добавил код. Я хочу написать код как это.
о проблеме с пакетом, да, я сначала отправил проблему, но он закрыл ее без какого-либо надлежащего ответа, который решил мою проблему.
Я думаю, вы слишком все усложняете. Класс Enum из этого пакета является классом php, как и любой другой, поэтому в вашем случае я бы посоветовал добавить некоторые статические методы в класс Status, которые возвращают соответствующее значение в зависимости от случая ввода.
например это может выглядеть примерно так:
<?php
use BenSampo\Enum\Enum;
final class Status extends Enum
{
const Initial = 1;
const Pending = 2;
const Completed = 3;
const Canceled = 4;
public static function getColor(Status $status): string
{
return match ($status->value) {
self::Initial => 'gray',
self::Pending => 'yellow',
self::Completed => 'green',
self::Canceled => 'red',
};
}
public static function isFinal(Status $status): bool
{
return in_array($status->value, [self::Completed, self::Canceled]);
}
}
Который вы можете использовать следующим образом:
$status = Status::Completed();
Status::getColor($status); // "green"
Status::isFinal($status); // true
PR на упаковке приветствуются и учитываются, если они хорошо продуманы и правильно реализованы. Более динамичная система атрибутов может быть хорошим дополнением.
спасибо, но если подход @cengsemihsahin решил мою проблему, мне это нравится больше.
хотя, в вашем методе, я могу добавить локализацию, запросто. Я думаю...
спасибо, в приведенном выше посте один программист решил мою проблему и помог мне лучше понять ваш пакет. Я могу отправить вам обновление Documentaion, чтобы добавить его в ваш гайд, если хотите.
спасибо, но где мне определить значение custon_description для всех ключей в перечислении? Я добавляю #[custom_description('red')] но это не работает.