Simple, extensible and powerful enumeration implementation for Laravel.

Overview

Laravel Enum

Build Status Packagist Stable Version Packagist downloads MIT Software License

About Laravel Enum

Simple, extensible and powerful enumeration implementation for Laravel.

  • Enum key value pairs as class constants
  • Full featured suite of methods
  • Enum instantiation
  • Flagged/Bitwise enums
  • Type hinting
  • Attribute casting
  • Enum artisan generator
  • Validation rules for passing enum key or values as input parameters
  • Localization support
  • Extendable via Macros

Created by Ben Sampson

Jump To

Documentation for older versions

You are reading the documentation for 4.x.

  • If you're using Laravel 7 or below, please see the docs for 2.x.
  • If you're using Laravel 6 or below, please see the docs for 1.x.

Please see the upgrade guide for information on how to upgrade to the latest version.

Guide

I wrote a blog post about using laravel-enum: https://sampo.co.uk/blog/using-enums-in-laravel

Installation

Requirements

  • Laravel 8 or higher
  • PHP 7.3 or higher

Via Composer

composer require bensampo/laravel-enum

Enum Library

Browse and download from a list of commonly used, community contributed enums.

Enum library →

Basic Usage

Enum Definition

You can use the following Artisan command to generate a new enum class:

php artisan make:enum UserType

Now, you just need to add the possible values your enum can have as constants.

<?php

namespace App\Enums;

use BenSampo\Enum\Enum;

final class UserType extends Enum
{
    const Administrator = 0;
    const Moderator = 1;
    const Subscriber = 2;
    const SuperAdministrator = 3;
}

That's it! Note that because the enum values are defined as plain constants, you can simple access them like any other class constant.

UserType::Administrator // Has a value of 0

Instantiation

It can be useful to instantiate enums in order to pass them between functions with the benefit of type hinting.

Additionally, it's impossible to instantiate an enum with an invalid value, therefore you can be certain that the passed value is always valid.

For convenience, enums can be instantiated in multiple ways:

// Standard new PHP class, passing the desired enum value as a parameter
$enumInstance = new UserType(UserType::Administrator);

// Same as the constructor, instantiate by value
$enumInstance = UserType::fromValue(UserType::Administrator);

// Use an enum key instead of its value
$enumInstance = UserType::fromKey('Administrator');

// Statically calling the key name as a method, utilizing __callStatic magic
$enumInstance = UserType::Administrator();

// Attempt to instantiate a new Enum using the given key or value. Returns null if the Enum cannot be instantiated.
$enumInstance = UserType::coerce($someValue);

If you want your IDE to autocomplete the static instantiation helpers, you can generate PHPDoc annotations through an artisan command.

By default all Enums in app/Enums will be annotated (you can change the folder by passing a path to --folder)

php artisan enum:annotate

You can annotate a single class by specifying the class name

php artisan enum:annotate "App\Enums\UserType"

Instance Properties

Once you have an enum instance, you can access the key, value and description as properties.

$userType = UserType::fromValue(UserType::SuperAdministrator);

$userType->key; // SuperAdministrator
$userType->value; // 0
$userType->description; // Super Administrator

This is particularly useful if you're passing an enum instance to a blade view.

Instance Casting

Enum instances can be cast to strings as they implement the __toString() magic method.
This also means they can be echoed in blade views, for example.

$userType = UserType::fromValue(UserType::SuperAdministrator);

(string) $userType // '0'

Instance Equality

You can check the equality of an instance against any value by passing it to the is method. For convenience, there is also an isNot method which is the exact reverse of the is method.

$admin = UserType::fromValue(UserType::Administrator);

$admin->is(UserType::Administrator);   // true
$admin->is($admin);                    // true
$admin->is(UserType::Administrator()); // true

$admin->is(UserType::Moderator);       // false
$admin->is(UserType::Moderator());     // false
$admin->is('random-value');            // false

You can also check to see if the instance's value matches against an array of possible values using the in method, and use notIn to check if instance value is not in an array of values. Iterables can also be checked against.

$admin = UserType::fromValue(UserType::Administrator);

$admin->in([UserType::Moderator, UserType::Administrator]);     // true
$admin->in([UserType::Moderator(), UserType::Administrator()]); // true

$admin->in([UserType::Moderator, UserType::Subscriber]);        // false
$admin->in(['random-value']);                                   // false

$admin->notIn([UserType::Moderator, UserType::Administrator]);     // false
$admin->notIn([UserType::Moderator(), UserType::Administrator()]); // false

$admin->notIn([UserType::Moderator, UserType::Subscriber]);        // true
$admin->notIn(['random-value']);                                   // true

Type Hinting

One of the benefits of enum instances is that it enables you to use type hinting, as shown below.

function canPerformAction(UserType $userType)
{
    if ($userType->is(UserType::SuperAdministrator)) {
        return true;
    }

    return false;
}

$userType1 = UserType::fromValue(UserType::SuperAdministrator);
$userType2 = UserType::fromValue(UserType::Moderator);

canPerformAction($userType1); // Returns true
canPerformAction($userType2); // Returns false

Flagged/Bitwise Enum

Standard enums represent a single value at a time, but flagged or bitwise enums are capable of of representing multiple values simultaneously. This makes them perfect for when you want to express multiple selections of a limited set of options. A good example of this would be user permissions where there are a limited number of possible permissions but a user can have none, some or all of them.

You can create a flagged enum using the following artisan command:

php artisan make:enum UserPermissions --flagged

Defining values

When defining values you must use powers of 2, the easiest way to do this is by using the shift left << operator like so:

final class UserPermissions extends FlaggedEnum
{
    const ReadComments      = 1 << 0;
    const WriteComments     = 1 << 1;
    const EditComments      = 1 << 2;
    const DeleteComments    = 1 << 3;
    // The next one would be `1 << 4` and so on...
}

Defining shortcuts

You can use the bitwise or | to set a shortcut value which represents a given set of values.

final class UserPermissions extends FlaggedEnum
{
    const ReadComments      = 1 << 0;
    const WriteComments     = 1 << 1;
    const EditComments      = 1 << 2;
    const DeleteComments    = 1 << 3;

    // Shortcuts
    const Member = self::ReadComments | self::WriteComments; // Read and write.
    const Moderator = self::Member | self::EditComments; // All the permissions a Member has, plus Edit.
    const Admin = self::Moderator | self::DeleteComments; // All the permissions a Moderator has, plus Delete.
}

Instantiating a flagged enum

There are couple of ways to instantiate a flagged enum:

// Standard new PHP class, passing the desired enum values as an array of values or array of enum instances
$permissions = new UserPermissions([UserPermissions::ReadComments, UserPermissions::EditComments]);
$permissions = new UserPermissions([UserPermissions::ReadComments(), UserPermissions::EditComments()]);

// Static flags method, again passing the desired enum values as an array of values or array of enum instances
$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::EditComments]);
$permissions = UserPermissions::flags([UserPermissions::ReadComments(), UserPermissions::EditComments()]);

Attribute casting works in the same way as single value enums.

Empty flagged enums

Flagged enums can contain no value at all. Every flagged enum has a pre-defined constant of None which is comparable to 0.

UserPermissions::flags([])->value === UserPermissions::None; // True

Flagged enum methods

In addition to the standard enum methods, there are a suite of helpful methods available on flagged enums.

Note: Anywhere where a static property is passed, you can also pass an enum instance.

setFlags(array $flags): Enum

Set the flags for the enum to the given array of flags.

$permissions = UserPermissions::flags([UserPermissions::ReadComments]);
$permissions->flags([UserPermissions::EditComments, UserPermissions::DeleteComments]); // Flags are now: EditComments, DeleteComments.

addFlag($flag): Enum

Add the given flag to the enum

$permissions = UserPermissions::flags([UserPermissions::ReadComments]);
$permissions->addFlag(UserPermissions::EditComments); // Flags are now: ReadComments, EditComments.

addFlags(array $flags): Enum

Add the given flags to the enum

$permissions = UserPermissions::flags([UserPermissions::ReadComments]);
$permissions->addFlags([UserPermissions::EditComments, UserPermissions::WriteComments]); // Flags are now: ReadComments, EditComments, WriteComments.

addAllFlags(): Enum

Add all flags to the enum

$permissions = UserPermissions::flags([UserPermissions::ReadComments]);
$permissions->addAllFlags(); // Enum now has all flags

removeFlag($flag): Enum

Remove the given flag from the enum

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);
$permissions->removeFlag(UserPermissions::ReadComments); // Flags are now: WriteComments.

removeFlags(array $flags): Enum

Remove the given flags from the enum

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments, UserPermissions::EditComments]);
$permissions->removeFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // Flags are now: EditComments.

removeAllFlags(): Enum

Remove all flags from the enum

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);
$permissions->removeAllFlags();

hasFlag($flag): bool

Check if the enum has the specified flag.

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);
$permissions->hasFlag(UserPermissions::ReadComments); // True
$permissions->hasFlag(UserPermissions::EditComments); // False

hasFlags(array $flags): bool

Check if the enum has all of the specified flags.

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);
$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // True
$permissions->hasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // False

notHasFlag($flag): bool

Check if the enum does not have the specified flag.

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);
$permissions->notHasFlag(UserPermissions::EditComments); // True
$permissions->notHasFlag(UserPermissions::ReadComments); // False

notHasFlags(array $flags): bool

Check if the enum doesn't have any of the specified flags.

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);
$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::EditComments]); // True
$permissions->notHasFlags([UserPermissions::ReadComments, UserPermissions::WriteComments]); // False

getFlags(): Enum[]

Return the flags as an array of instances.

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);
$permissions->getFlags(); // [UserPermissions::ReadComments(), UserPermissions::WriteComments()];

hasMultipleFlags(): bool

Check if there are multiple flags set on the enum.

$permissions = UserPermissions::flags([UserPermissions::ReadComments, UserPermissions::WriteComments]);
$permissions->hasMultipleFlags(); // True;
$permissions->removeFlag(UserPermissions::ReadComments)->hasMultipleFlags(); // False

getBitmask(): int

Get the bitmask for the enum.

UserPermissions::Member()->getBitmask(); // 11;
UserPermissions::Moderator()->getBitmask(); // 111;
UserPermissions::Admin()->getBitmask(); // 1111;
UserPermissions::DeleteComments()->getBitmask(); // 1000;

Flagged enums in Eloquent queries

To use flagged enums directly in your Eloquent queries, you may use the QueriesFlaggedEnums trait on your model which provides you with the following methods:

hasFlag($column, $flag): Builder

User::hasFlag('permissions', UserPermissions::DeleteComments())->get();

notHasFlag($column, $flag): Builder

User::notHasFlag('permissions', UserPermissions::DeleteComments())->get();

hasAllFlags($column, $flags): Builder

User::hasAllFlags('permissions', [UserPermissions::EditComment(), UserPermissions::ReadComment()])->get();

hasAnyFlags($column, $flags): Builder

User::hasAnyFlags('permissions', [UserPermissions::DeleteComments(), UserPermissions::EditComments()])->get();

Attribute Casting

You may cast model attributes to enums using Laravel 7.x's built in custom casting. This will cast the attribute to an enum instance when getting and back to the enum value when setting. Since Enum::class implements the Castable contract, you just need to specify the classname of the enum:

use BenSampo\Enum\Tests\Enums\UserType;
use Illuminate\Database\Eloquent\Model;

class Example extends Model
{
    protected $casts = [
        'random_flag' => 'boolean',     // Example standard laravel cast
        'user_type' => UserType::class, // Example enum cast
    ];
}

Now, when you access the user_type attribute of your Example model, the underlying value will be returned as a UserType enum.

$example = Example::first();
$example->user_type // Instance of UserType

Review the methods and properties available on enum instances to get the most out of attribute casting.

You can set the value by either passing the enum value or another enum instance.

$example = Example::first();

// Set using enum value
$example->user_type = UserType::Moderator;

// Set using enum instance
$example->user_type = UserType::Moderator();

Customising $model->toArray() behaviour

When using toArray (or returning model/models from your controller as a response) Laravel will call the toArray method on the enum instance.

By default, this will return only the value in its native type. You may want to also have access to the other properties (key, description), for example to return to javascript app.

To customise this behaviour, you can override the toArray method on the enum instance.

// Example Enum
final class UserType extends Enum
{
    const ADMINISTRATOR = 0;
    const MODERATOR = 1;
}

$instance = UserType::Moderator();

// Default
public function toArray()
{
    return $this->value;
}
// Returns int(1)

// Return all properties
public function toArray()
{
    return $this;
}
// Returns an array of all the properties
// array(3) {
//  ["value"]=>
//  int(1)"
//  ["key"]=>
//  string(9) "MODERATOR"
//  ["description"]=>
//  string(9) "Moderator"
// }

Casting underlying native types

Many databases return everything as strings (for example, an integer may be returned as the string '1'). To reduce friction for users of the library, we use type coercion to figure out the intended value. If you'd prefer to control this, you can override the parseDatabase static method on your enum class:

final class UserType extends Enum
{
    const Administrator = 0;
    const Moderator = 1;

    public static function parseDatabase($value)
    {
        return (int) $value;
    }
}

Returning null from the parseDatabase method will cause the attribute on the model to also be null. This can be useful if your database stores inconsistent blank values such as empty strings instead of NULL.

Model Annotation

If you're using Laravel 7 casting, the laravel-ide-helper package can be used to automatically generate property docblocks for your models.

Migrations

Recommended

Because enums enforce consistency at the code level it's not necessary to do so again at the database level, therefore the recommended type for database columns is string or int depending on your enum values. This means you can add/remove enum values in your code without worrying about your database layer.

use App\Enums\UserType;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table): void {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->string('type')
                ->default(UserType::Moderator);
        });
    }
}

Using enum column type

Alternatively you may use Enum classes in your migrations to define enum columns. The enum values must be defined as strings.

use App\Enums\UserType;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table): void {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->enum('type', UserType::getValues())
                ->default(UserType::Moderator);
        });
    }
}

Validation

Array Validation

Enum value

You may validate that an enum value passed to a controller is a valid value for a given enum by using the EnumValue rule.

use BenSampo\Enum\Rules\EnumValue;

public function store(Request $request)
{
    $this->validate($request, [
        'user_type' => ['required', new EnumValue(UserType::class)],
    ]);
}

By default, type checking is set to strict, but you can bypass this by passing false to the optional second parameter of the EnumValue class.

new EnumValue(UserType::class, false) // Turn off strict type checking.

Enum key

You can also validate on keys using the EnumKey rule. This is useful if you're taking the enum key as a URL parameter for sorting or filtering for example.

use BenSampo\Enum\Rules\EnumKey;

public function store(Request $request)
{
    $this->validate($request, [
        'user_type' => ['required', new EnumKey(UserType::class)],
    ]);
}

Enum instance

Additionally you can validate that a parameter is an instance of a given enum.

use BenSampo\Enum\Rules\Enum;

public function store(Request $request)
{
    $this->validate($request, [
        'user_type' => ['required', new Enum(UserType::class)],
    ]);
}

Pipe Validation

You can also use the 'pipe' syntax for rules.

enum_value:enum_class,[strict]
enum_key:enum_class
enum:enum_class

'user_type' => 'required|enum_value:' . UserType::class,
'user_type' => 'required|enum_key:' . UserType::class,
'user_type' => 'required|enum:' . UserType::class,

Localization

Validation messages

Run the following command to publish the language files to your resources/lang folder.

php artisan vendor:publish --provider="BenSampo\Enum\EnumServiceProvider" --tag="translations"

Enum descriptions

You can translate the strings returned by the getDescription method using Laravel's built in localization features.

Add a new enums.php keys file for each of your supported languages. In this example there is one for English and one for Spanish.

// resources/lang/en/enums.php
<?php

use App\Enums\UserType;

return [

    UserType::class => [
        UserType::Administrator => 'Administrator',
        UserType::SuperAdministrator => 'Super administrator',
    ],

];
// resources/lang/es/enums.php
<?php

use App\Enums\UserType;

return [

    UserType::class => [
        UserType::Administrator => 'Administrador',
        UserType::SuperAdministrator => 'Súper administrador',
    ],

];

Now, you just need to make sure that your enum implements the LocalizedEnum interface as demonstrated below:

use BenSampo\Enum\Enum;
use BenSampo\Enum\Contracts\LocalizedEnum;

final class UserType extends Enum implements LocalizedEnum
{
    // ...
}

The getDescription method will now look for the value in your localization files. If a value doesn't exist for a given key, the default description is returned instead.

Overriding the getDescription method

If you'd like to return a custom value from the getDescription method, you may do so by overriding the method on your enum:

public static function getDescription($value): string
{
    if ($value === self::SuperAdministrator) {
        return 'Super admin';
    }

    return parent::getDescription($value);
}

Calling UserType::getDescription(3); now returns Super admin instead of Super administator.

Extending the Enum Base Class

The Enum base class implements the Laravel Macroable trait, meaning it's easy to extend it with your own functions. If you have a function that you often add to each of your enums, you can use a macro.

Let's say we want to be able to get a flipped version of the enum asArray method, we can do this using:

Enum::macro('asFlippedArray', function() {
    return array_flip(self::asArray());
});

Now, on each of my enums, I can call it using UserType::asFlippedArray().

It's best to register the macro inside of a service providers' boot method.

Laravel Nova Integration

Use the nova-enum-field package by Simple Squid to easily create fields for your Enums in Nova. See their readme for usage.

PHPStan integration

If you are using PHPStan for static analysis, you can enable the extension for proper recognition of the magic instantiation methods.

Add the following to your projects phpstan.neon includes:

includes:
- vendor/bensampo/laravel-enum/extension.neon

Artisan Command List

php artisan make:enum
Create a new enum class. Pass --flagged as an option to create a flagged enum.
Find out more

php artisan enum:annotate
Generate DocBlock annotations for enum classes.
Find out more

Enum Class Reference

static getKeys(mixed $values = null): array

Returns an array of all or a custom set of the keys for an enum.

UserType::getKeys(); // Returns ['Administrator', 'Moderator', 'Subscriber', 'SuperAdministrator']
UserType::getKeys(UserType::Administrator); // Returns ['Administrator']
UserType::getKeys(UserType::Administrator, UserType::Moderator); // Returns ['Administrator', 'Moderator']
UserType::getKeys([UserType::Administrator, UserType::Moderator]); // Returns ['Administrator', 'Moderator']

static getValues(mixed $keys = null): array

Returns an array of all or a custom set of the values for an enum.

UserType::getValues(); // Returns [0, 1, 2, 3]
UserType::getValues('Administrator'); // Returns [0]
UserType::getValues('Administrator', 'Moderator'); // Returns [0, 1]
UserType::getValues(['Administrator', 'Moderator']); // Returns [0, 1]

static getKey(mixed $value): string

Returns the key for the given enum value.

UserType::getKey(1); // Returns 'Moderator'
UserType::getKey(UserType::Moderator); // Returns 'Moderator'

static getValue(string $key): mixed

Returns the value for the given enum key.

UserType::getValue('Moderator'); // Returns 1

static hasKey(string $key): bool

Check if the enum contains a given key.

UserType::hasKey('Moderator'); // Returns 'True'

static hasValue(mixed $value, bool $strict = true): bool

Check if the enum contains a given value.

UserType::hasValue(1); // Returns 'True'

// It's possible to disable the strict type checking:
UserType::hasValue('1'); // Returns 'False'
UserType::hasValue('1', false); // Returns 'True'

static getDescription(mixed $value): string

Returns the key in sentence case for the enum value. It's possible to override the getDescription method to return custom descriptions.

UserType::getDescription(3); // Returns 'Super administrator'
UserType::getDescription(UserType::SuperAdministrator); // Returns 'Super administrator'

static getRandomKey(): string

Returns a random key from the enum. Useful for factories.

UserType::getRandomKey(); // Returns 'Administrator', 'Moderator', 'Subscriber' or 'SuperAdministrator'

static getRandomValue(): mixed

Returns a random value from the enum. Useful for factories.

UserType::getRandomValue(); // Returns 0, 1, 2 or 3

static getRandomInstance(): mixed

Returns a random instance of the enum. Useful for factories.

UserType::getRandomInstance(); // Returns an instance of UserType with a random value

static asArray(): array

Returns the enum key value pairs as an associative array.

UserType::asArray(); // Returns ['Administrator' => 0, 'Moderator' => 1, 'Subscriber' => 2, 'SuperAdministrator' => 3]

static asSelectArray(): array

Returns the enum for use in a select as value => description.

UserType::asSelectArray(); // Returns [0 => 'Administrator', 1 => 'Moderator', 2 => 'Subscriber', 3 => 'Super administrator']

static fromValue(mixed $enumValue): Enum

Returns an instance of the called enum. Read more about enum instantiation.

UserType::fromValue(UserType::Administrator); // Returns instance of Enum with the value set to UserType::Administrator

static getInstances(): array

Returns an array of all possible instances of the called enum, keyed by the constant names.

var_dump(UserType::getInstances());

array(4) {
  'Administrator' =>
  class BenSampo\Enum\Tests\Enums\UserType#415 (3) {
    public $key =>
    string(13) "Administrator"
    public $value =>
    int(0)
    public $description =>
    string(13) "Administrator"
  }
  'Moderator' =>
  class BenSampo\Enum\Tests\Enums\UserType#396 (3) {
    public $key =>
    string(9) "Moderator"
    public $value =>
    int(1)
    public $description =>
    string(9) "Moderator"
  }
  'Subscriber' =>
  class BenSampo\Enum\Tests\Enums\UserType#393 (3) {
    public $key =>
    string(10) "Subscriber"
    public $value =>
    int(2)
    public $description =>
    string(10) "Subscriber"
  }
  'SuperAdministrator' =>
  class BenSampo\Enum\Tests\Enums\UserType#102 (3) {
    public $key =>
    string(18) "SuperAdministrator"
    public $value =>
    int(3)
    public $description =>
    string(19) "Super administrator"
  }
}

static coerce(mixed $enumKeyOrValue): ?Enum

Attempt to instantiate a new Enum using the given key or value. Returns null if the Enum cannot be instantiated.

UserType::coerce(0); // Returns instance of UserType with the value set to UserType::Administrator
UserType::coerce('Administrator'); // Returns instance of UserType with the value set to UserType::Administrator
UserType::coerce(99); // Returns null (not a valid enum value)

Stubs

Run the following command to publish the stub files to the stubs folder in the root of your application.

php artisan vendor:publish --provider="BenSampo\Enum\EnumServiceProvider" --tag="stubs"
Comments
  • Laravel 7 native casts

    Laravel 7 native casts

    • [x] Added or updated tests
    • [x] Added or updated the README.md
    • [x] Detailed changes in the CHANGELOG.md unreleased section

    WIP PR for implementing native eloquent casting.

    Current issues:

    • ~Currently, we let laravel do native casting, then we apply the enum cast after.~ ~Ie. '6' cast by laravel -> 6 cast by us -> EnumInstance~

    ~With the new native casts, this isn't possible. I'm thinking we'll need to pass an additional attribute to the constructor to apply a native cast if required.~ ~Kind of a bit messy, but not sure if there's a better way?~ Fixed in the latest commit :)

    Also, it seems that natively cast attributes are not used in the toArray() which is a breaking change, so we need to see if we can return the object.

    Edit: also need some way of only running this test on L7 in CI. Should be easy to do via ENV :)

    opened by atymic 32
  • Laravel 9.x Compatibility

    Laravel 9.x Compatibility

    This is an automated pull request from Shift to update your package code and dependencies to be compatible with Laravel 9.x.

    Before merging, you need to:

    • Checkout the l9-compatibility branch
    • Review all comments for additional changes
    • Thoroughly test your package

    If you do find an issue, please report it by commenting on this PR to help improve future automation.

    opened by laravel-shift 8
  • Setting using casting

    Setting using casting

    Hey,

    Loving the new updates and just trying to refactor to use enum casting but having an issue. Not sure if it's a feature or bug but thought I'd ask anyway.

    So I thought to set the user status using the static method as follows:

    User::create([..., 'status' => UserStatus::Approved()]);
    

    This works fine when setting as it casts down to the value as an int. But when fetching back out of DB, the int is pulled as a string and when attempting to cast back to a UserStatus enum it fails on the strict checking and I get the following exception msg:

    BenSampo\Enum\Exceptions\InvalidEnumMemberException : Value 0 doesn't exist in [0, 1]
    

    So I thought to set the original cast as well which I was using before your enum casting. So the status attribute would cast to an int before being cast to the UserStatus enum.

    This seems to work when fetching, but then fails when setting. When setting via a new user create method call, as shown above, I get the following error:

    ErrorException : Object of class App\Enums\UserStatus could not be converted to int
    

    It seems we need to check when setting if it's already an enum object or not and act accordingly.

    I'm surprised this hasn't come up before though, so it's possible I'm missing something. I could work around it by using UserStatus::Approved as the value rather than an instance - perhaps that's the intended way...?

    More than happy to provide a PR and tests if needed but thought I'd open the discussion first.

    Thanks! Lee

    opened by leeovery 8
  • Add new instantiation methods `Enum::fromKey()` and `Enum::fromValue()`

    Add new instantiation methods `Enum::fromKey()` and `Enum::fromValue()`

    • [x] Added or updated tests
    • [x] Added or updated the README.md
    • [x] Detailed changes in the CHANGELOG.md unreleased section

    Related Issue/Intent

    This use case has come up for us because we use Enum's in two ways:

    • values are used for efficient storage in the database
    • keys are used for a nice client API

    Changes

    Add new instantiation methods Enum::fromKey() and Enum::fromValue()

    Deprecate Enum::getInstance() in favor of Enum::fromValue(), as the new name is consistent with Enum::fromKey()

    Breaking changes

    None, but i propose to remove getInstance() in an upcoming major version.

    opened by spawnia 7
  • Validation EnumKey

    Validation EnumKey

    Helllo,

    I'm trying to make the validation work but it behave very weird.

    class HardwareType extends Enum
    {
        public const Aio        = \App\Model\Types\Aio::class;
        public const Desktop    = \App\Model\Types\Desktop::class;
        public const MacBook    = \App\Model\Types\MacBook::class;
        public const Notebook   = \App\Model\Types\Notebook::class;
        public const Phone      = \App\Model\Types\Phone::class;
    
    }
    

    Form Request:

    public function rules() : array
    {
        return [
            'name' => 'required',
            'type' => ['required', new EnumKey(HardwareType ::class)],
        ];
    }
    

    And when I call this by API (with bad type: MacBook__i_), I always get message

    Cannot create an enum instance for MacBook__i_. The enum value MacBook__i_ does not exist.

    opened by rudashi 7
  • Can not store the key on db:seed

    Can not store the key on db:seed

    I'm using the attribute casting on my model. On my UserTableSeed i tried to store the key of Countries Enum instead of the value like this:

    country => Countries::getInstance(Countries::MA)->key;

    But it throws an exception BenSampo\Enum\Exceptions\InvalidEnumMemberException : Value MA doesn't exist in

    But if i store the value of Enum it works.

    Any suggestions to correct this.

    By the way thanks for your work.

    opened by omarherri 7
  • Installing with Laravel 9 blocked due to dependency on composer/composer

    Installing with Laravel 9 blocked due to dependency on composer/composer

    I cannot install this package with Laravel 9 because it depends on composer/composer. Its latest release does not support symfony/console:^6: https://github.com/composer/composer/blob/23b0a3819bb74214f04a0799c6f998c9822f54f4/composer.json#L35

    Why do we have a dependency on composer/composer anyway, is it needed?

    bug 
    opened by spawnia 6
  • Breaking changes in minor version

    Breaking changes in minor version

    Hello! Long-time package user here.

    The upgrade from 2.1.0 to 2.2.0 included a commit (https://github.com/BenSampo/laravel-enum/commit/ee0a511d5c6b562653ceaef4ce06515dc96a7aab) which introduced breaking changes:

    • Serialization to JSON changed from being an object containing the different forms of the instance to being only the value string.
    • toSelectArray became asSelectArray.

    Neither of these changes are wrong per se, but they were breaking and should only have been made with a major version number increment - we were fortunate to have caught these early (and have updated our codebases to match).

    Thank you for this wonderful package, look forward to using it on lots more projects in future!

    opened by jameswilddev 6
  • Add Laravel 7 support

    Add Laravel 7 support

    • [x] Added or updated tests
    • [x] Added or updated the README.md
    • [x] Detailed changes in the CHANGELOG.md unreleased section

    Related Issue/Intent

    This just bumps up the dependency constraints to allow for Laravel 7 (which will be released tomorrow!)

    opened by inxilpro 6
  • Make equality checks work with both enum instances and arbitrary values

    Make equality checks work with both enum instances and arbitrary values

    This PR adds the capability to directly compare Enum instances with each other and with arbitrary values.

    Comparing against values that are not valid allowed values of the Enum now simply returns false instead of throwing.

    You can check the equality of an instance against any value by passing it to the is method.

    $admin = UserType::getInstance(UserType::Administrator);
    
    $admin->is(UserType::Administrator);   // true
    $admin->is($admin);                    // true
    $admin->is(UserType::Administrator()); // true
    
    $admin->is(UserType::Moderator);       // false
    $admin->is(UserType::Moderator());     // false
    $admin->is('random-value');            // false
    

    You can also check to see if the instance's value matches against an array of possible values using the in method.

    $admin = UserType::getInstance(UserType::Administrator);
    
    $admin->in([UserType::Moderator, UserType::Administrator]);     // true
    $admin->in([UserType::Moderator(), UserType::Administrator()]); // true
    
    $admin->in([UserType::Moderator, UserType::Subscriber]);        // false
    $admin->in(['random-value']);                                   // false
    
    opened by spawnia 6
  • ERROR: Method Illuminate\Validation\Validator::validateEnumValue does not exist

    ERROR: Method Illuminate\Validation\Validator::validateEnumValue does not exist

    I'm getting the following error on production environment only when using the pipe validators. Any ideas why? dev env works fine.

    Laravel 5.7 Php 7.3.1 Laravel-enum 1.16

    FormRequest::

    <?php
    
    namespace App\Enums;
    
    use BenSampo\Enum\Contracts\LocalizedEnum;
    use BenSampo\Enum\Enum;
    
    final class Gender extends Enum implements LocalizedEnum
    {
        const MALE = 'male';
        const FEMALE = 'female';
        const UNKNOWN = 'unknown';
    }
    

    Validator:

    'gender' => 'required|enum_value:' . Gender::class,
    

    Stacktrace:

    [2019-01-28 10:58:16] production.ERROR: Method Illuminate\Validation\Validator::validateEnumValue does not exist. {"userId":2,"email":"xxxxx@xxxx","exception":"[object] (BadMethodCallException(code: 0): Method Illuminate\\Validation\\Validator::validateEnumValue does not exist. at /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Validation/Validator.php:1187)
    [stacktrace]
    #0 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Validation/Validator.php(398): Illuminate\\Validation\\Validator->__call('validateEnumVal...', Array)
    #1 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Validation/Validator.php(277): Illuminate\\Validation\\Validator->validateAttribute('gender', 'EnumValue')
    #2 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Validation/Validator.php(302): Illuminate\\Validation\\Validator->passes()
    #3 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Validation/ValidatesWhenResolvedTrait.php(25): Illuminate\\Validation\\Validator->fails()
    #4 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Foundation/Providers/FormRequestServiceProvider.php(30): Illuminate\\Foundation\\Http\\FormRequest->validateResolved()
    #5 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Container/Container.php(1069): Illuminate\\Foundation\\Providers\\FormRequestServiceProvider->Illuminate\\Foundation\\Providers\\{closure}(Object(App\\Http\\Requests\\RegistrationFormRequest), Object(Illuminate\\Foundation\\Application))
    #6 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Container/Container.php(1033): Illuminate\\Container\\Container->fireCallbackArray(Object(App\\Http\\Requests\\RegistrationFormRequest), Array)
    #7 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Container/Container.php(1018): Illuminate\\Container\\Container->fireAfterResolvingCallbacks('App\\\\Http\\\\Reques...', Object(App\\Http\\Requests\\RegistrationFormRequest))
    #8 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Container/Container.php(677): Illuminate\\Container\\Container->fireResolvingCallbacks('App\\\\Http\\\\Reques...', Object(App\\Http\\Requests\\RegistrationFormRequest))
    #9 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Container/Container.php(609): Illuminate\\Container\\Container->resolve('App\\\\Http\\\\Reques...', Array)
    #10 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(735): Illuminate\\Container\\Container->make('App\\\\Http\\\\Reques...', Array)
    #11 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/RouteDependencyResolverTrait.php(79): Illuminate\\Foundation\\Application->make('App\\\\Http\\\\Reques...')
    #12 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/RouteDependencyResolverTrait.php(46): Illuminate\\Routing\\ControllerDispatcher->transformDependency(Object(ReflectionParameter), Array)
    #13 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/RouteDependencyResolverTrait.php(27): Illuminate\\Routing\\ControllerDispatcher->resolveMethodDependencies(Array, Object(ReflectionMethod))
    #14 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(41): Illuminate\\Routing\\ControllerDispatcher->resolveClassMethodDependencies(Array, Object(App\\Http\\Controllers\\Platform\\Admin\\RegistrationController), 'update')
    #15 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Route.php(219): Illuminate\\Routing\\ControllerDispatcher->dispatch(Object(Illuminate\\Routing\\Route), Object(App\\Http\\Controllers\\Platform\\Admin\\RegistrationController), 'update')
    #16 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Route.php(176): Illuminate\\Routing\\Route->runController()
    #17 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Router.php(682): Illuminate\\Routing\\Route->run()
    #18 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #19 /var/www/myLaravelApp/vendor/santigarcor/laratrust/src/Laratrust/Middleware/LaratrustRole.php(57): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #20 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Laratrust\\Middleware\\LaratrustRole->handle(Object(Illuminate\\Http\\Request), Object(Closure), Array, 'myteam')
    #21 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #22 /var/www/myLaravelApp/app/Http/Middleware/Authenticate.php(52): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #23 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): App\\Http\\Middleware\\Authenticate->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #24 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #25 /var/www/myLaravelApp/app/Http/Middleware/IdentifyTenant.php(35): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #26 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): App\\Http\\Middleware\\IdentifyTenant->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #27 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #28 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(41): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #29 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #30 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #31 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(75): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #32 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #33 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #34 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #35 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #36 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #37 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #38 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Session\\Middleware\\StartSession->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #39 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #40 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #41 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #42 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #43 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(66): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #44 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #45 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #46 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #47 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Router.php(684): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
    #48 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Router.php(659): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request))
    #49 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Router.php(625): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route))
    #50 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Router.php(614): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request))
    #51 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request))
    #52 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(Illuminate\\Http\\Request))
    #53 /var/www/myLaravelApp/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php(58): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #54 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #55 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #56 /var/www/myLaravelApp/vendor/fideloper/proxy/src/TrustProxies.php(57): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #57 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Fideloper\\Proxy\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #58 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #59 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(31): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #60 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #61 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #62 /var/www/myLaravelApp/vendor/chaseconey/laravel-datadog-helper/src/Middleware/LaravelDatadogMiddleware.php(22): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #63 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): ChaseConey\\LaravelDatadogHelper\\Middleware\\LaravelDatadogMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #64 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #65 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(62): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #66 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(151): Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode->handle(Object(Illuminate\\Http\\Request), Object(Closure))
    #67 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))
    #68 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))
    #69 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(151): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))
    #70 /var/www/myLaravelApp/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(116): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))
    #71 /var/www/myLaravelApp/public/index.php(55): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))
    #72 {main}
    "}
    
    
    opened by jcalonso 6
  • Add test on many constants with long names

    Add test on many constants with long names

    This tests #293

    • [x] Added or updated tests
    • [ ] Added or updated the README.md
    • [ ] Detailed changes in the CHANGELOG.md unreleased section

    Related Issue/Intent

    This PR is intended to solve #293

    Changes

    Currently adds a test depicting behavior described in the issue. Using the php artisan enum:annotate command fails on a particular enumeration class.

    • Add ManyLongConstantNames testing class

    Breaking changes

    bug 
    opened by mikkoaf 0
  • classDeclarationOffset unavailable when content removed with existing docblock

    classDeclarationOffset unavailable when content removed with existing docblock

    $ php artisan enum:annotate --folder=app
    Wrote new phpDocBlock to /Foo/Etc/Enum.php
    
       TypeError 
    
      strpos(): Argument #1 ($haystack) must be of type string, null given
    
      at vendor/bensampo/laravel-enum/src/Commands/AbstractAnnotationCommand.php:138
        134▕             "\n" . $classDeclaration,
        135▕             $contents
        136▕         );
        137▕ 
      ➜ 138▕         $classDeclarationOffset = strpos($contents, $classDeclaration);
        139▕         // Make sure we don't replace too much
        140▕         $contents = substr_replace(
        141▕             $contents,
        142▕             sprintf("%s%s", $docBlock->generate(), $classDeclaration),
    
          +17 vendor frames
      18  artisan:35
          Illuminate\Foundation\Console\Kernel::handle()
    
    

    For context, the enumerated class which causes this issue has currently 177 items in the docblock. Each string has a comment as follows

    // This comment describes the foo bar enumerated constant
    public const FOO_BAR_ENUMERATION = 'foo_bar_enumeration'
    

    At a quick visual inspection I could not find any other cues besides these.

    bug 
    opened by mikkoaf 6
  • Error when running PHPstan on a Model using `QueriesFlaggedEnums` trait

    Error when running PHPstan on a Model using `QueriesFlaggedEnums` trait

    I'm using the QueriesFlaggedEnums trait in the Badge model. I've defined a local scope which use the hasAnyFlags(). PHPstan raises an error like:

    ------ ---------------------------------------------------------------------------------- 
      Line   app/Models/Badge.php                                                              
     ------ ---------------------------------------------------------------------------------- 
      109    Call to an undefined method Illuminate\Database\Eloquent\Builder::hasAnyFlags().  
     ------ ---------------------------------------------------------------------------------- 
    

    This is the Laravel code:

    107:    public function scopeWithActuatorsIn(Builder $query, array $actuators): Builder
    107:    {
    109:        return $query
    110:            ->where('active', true)
    111:            ->hasAnyFlags('actuators', $actuators);
    112:    }
    

    Someone was suggesting the use of PHP generics in order to avoid the problem. I've tried this approach using an stub file but nothing has changed.

    The code could be find here: https://github.com/pacoorozco/gamify-laravel

    Related to: nunomaduro/larastan#1307

    enhancement 
    opened by pacoorozco 2
  • Why jsonSerialize() does not return toArray() anymore?

    Why jsonSerialize() does not return toArray() anymore?

    @spawnia Hi,

    I want to talk about this change https://github.com/BenSampo/laravel-enum/commit/5094099a9ab9b710f6c262402598501886432699#diff-ee71af26064ea012953831df497c2297ea91606aa26bb133e73dc1b51deec2ccR603

    which was discussed here https://github.com/BenSampo/laravel-enum/issues/244

    I think this change must be documented, at leat, as it breaks the behavior explained in the documentation of the "Customising $model->toArray() behavior" https://github.com/BenSampo/laravel-enum#customising-model-toarray-behaviour

    Laravel for json responses uses jsonSerialize(), which previously used toArray() returned. Now both functions are independent, and for array AND json, we need to customize the return.

    Personally, I think this makes more sense to revert to the behavior of jsonSerialize() which returns the toArray() function.

    enhancement 
    opened by tancou 3
  • App breaks when using DB translation loaders in tests

    App breaks when using DB translation loaders in tests

    Whenever a translation is used in the service provider, an app that loads translations from the DB (e.g. using spatie/laravel-translation-loader) will break, cause the database hasn't been migrated yet when the app is bootstrapped.

    Steps:

    1. install both packages without migrating the db
    2. add a /test route:
      Route::get('test', function () {
          return 'hello';
      });
      
    3. go to /test
      Illuminate\Database\QueryException
      SQLSTATE[42S02]: Base table or view not found: 1146 Table 'homestead.language_lines' doesn't exist (SQL: select * from `language_lines` where `group` = *) 
      

    Normally this is not an issue, because you should have the language_lines table in the db, but it totally breaks testing.

    bug 
    opened by LucaPuddu 6
Owner
Ben Sampson
Full-stack web developer. Enjoys working with Laravel.
Ben Sampson
A PHP implementation of the GraphQL specification based on the JavaScript reference implementation

GraphQL This is a PHP implementation of the GraphQL specification based on the JavaScript reference implementation. Related projects DateTime scalar R

Digia 219 Nov 16, 2022
Shopware PHP SDK is a simple SDK implementation of Shopware 6 APIs

Shopware PHP SDK is a simple SDK implementation of Shopware 6 APIs. It helps to access the API in an object-oriented way.

Thuong Le 77 Dec 19, 2022
A powerful PHP Router for PSR7 messages inspired by the Laravel API.

Rare Router A simple PHP router built on AltoRouter but inspired by the Laravel API. Installation composer require rareloop/router Usage Creating Rou

Rareloop 74 Dec 17, 2022
Tukio is a complete and robust implementation of the PSR-14 Event Dispatcher specification

Tukio is a complete and robust implementation of the PSR-14 Event Dispatcher specification. It supports normal and debug Event Dispatchers, both runtime and compiled Providers, complex ordering of Listeners, and attribute-based registration on PHP 8.

Larry Garfield 70 Dec 19, 2022
GraphQL implementation with power of Laravel

Laravel GraphQL Use Facebook GraphQL with Laravel 5.2 >=. It is based on the PHP implementation here. You can find more information about GraphQL in t

Studionet 56 Mar 9, 2022
Pure PHP implementation of GraphQL Server – Symfony Bundle

Symfony GraphQl Bundle This is a bundle based on the pure PHP GraphQL Server implementation This bundle provides you with: Full compatibility with the

null 283 Dec 15, 2022
YouTrack RestAPI library for PHP. An implementation for communicating with your YouTrack instance.

YouTrack API PHP This is an implementation for communicating with the JetBrains YouTrack RestAPI. This library covers basic resource calls available i

Samih Soylu 4 May 3, 2022
GraPHPinator ⚡ 🌐 ⚡ Easy-to-use & Fast GraphQL server implementation for PHP

Easy-to-use & Fast GraphQL server implementation for modern PHP. Includes features from latest draft, middleware directives and modules with extra functionality.

Infinityloop.dev 34 Dec 14, 2022
PHP implementation of JSON schema. Fork of the http://jsonschemaphpv.sourceforge.net/ project

JSON Schema for PHP A PHP Implementation for validating JSON Structures against a given Schema with support for Schemas of Draft-3 or Draft-4. Feature

Justin Rainbow 3.4k Dec 26, 2022
A PHP port of GraphQL reference implementation

graphql-php This is a PHP implementation of the GraphQL specification based on the reference implementation in JavaScript. Installation Via composer:

Webonyx 4.4k Jan 7, 2023
A RESTful and extendable Backend as a Service that provides instant backend to develop sites and apps faster, with dead-simple integration for JavaScript, iOS, Android and more.

Welcome to hook ![Gitter](https://badges.gitter.im/Join Chat.svg) hook is a RESTful, extendable Backend as a Service that provides instant backend to

doubleleft 762 Dec 30, 2022
Simple and effective multi-format Web API Server to host your PHP API as Pragmatic REST and / or RESTful API

Luracast Restler ![Gitter](https://badges.gitter.im/Join Chat.svg) Version 3.0 Release Candidate 5 Restler is a simple and effective multi-format Web

Luracast 1.4k Dec 14, 2022
A simple and flexible PHP middleware dispatcher based on PSR-7, PSR-11, and PSR-15

Woohoo Labs. Harmony Woohoo Labs. Harmony is a PSR-15 compatible middleware dispatcher. Harmony was born to be a totally flexible and almost invisible

Woohoo Labs. 153 Sep 5, 2022
This API provides functionality for creating and maintaining users to control a simple To-Do-List application. The following shows the API structure for users and tasks resources.

PHP API TO-DO-LIST v.2.0 This API aims to present a brief to consume a API resources, mainly for students in the early years of Computer Science cours

Edson M. de Souza 6 Oct 13, 2022
Simple utility and class library for generating php classes from a wsdl file.

wsdl2phpgenerator Simple WSDL to PHP classes converter. Takes a WSDL file and outputs class files ready to use. Uses the MIT license. Announcement: We

null 802 Dec 10, 2022
A simple PHP package for sending messages to Slack, with a focus on ease of use and elegant syntax.

Slack for PHP | A simple PHP package for sending messages to Slack with incoming webhooks, focused on ease-of-use and elegant syntax. supports: PHP 7.

null 128 Nov 28, 2022
Quickly and easily expose Doctrine entities as REST resource endpoints with the use of simple configuration with annotations, yaml, json or a PHP array.

Drest Dress up doctrine entities and expose them as REST resources This library allows you to quickly annotate your doctrine entities into restful res

Lee Davis 88 Nov 5, 2022
A simple facade for managing the relationship between your model and API.

Table of Contents PhpGrape\Entity Introduction Installation Example Reusable Responses with Entities Defining Entities Basic Exposure Exposing with a

null 2 Oct 7, 2022
It helps to provide API support to projects. It is Simple, Safe and Fast.

apiservice It helps to provide API support to projects. It is Simple, Safe and Fast. Setup composer create-project mind/apiservice or After downloadin

Ali Yılmaz 5 Nov 3, 2022