Published Articles

Enter a search term to find articles.
backed-enums-with-collection-part-2-transforming-to-array-and-appending-attributes
2022-04-24

In this post I will show how we can transform enums to array format and dynamically append attributes to it. Disclaimer: This article is a continuation to the [Supercharged Backend Enums with Collection](https://marvinquezon.com/posts/supercharged-backed-enums-with-collection) post that I've previously published. If you haven't already, I would highly recommend reading through that article first as we will continue with the examples from there. Now that that's out of the way, let's begin. ***Enums, as objects, are plain and boring!*** Enums as objects are plain and boring - because they can never hold other properties except `name` and `value` of each case. PHP will actually throw an error when you try to declare properties within enum classes. However, there are times that you would want to append additional properties to an enum case. For instance, going back to our `TicketStatus` enum class, imagine that for each status, we also want them to have a `color` attribute. So that whenever our frontend consumes it, we can use it to design maybe the background color of the tickets based on the status. This is very useful since the enum class is becoming the single source of truth for the ticket status. # Create a method and match each case First, let's see how we can assign a color for each enum case: ```

supercharged-backed-enums-with-collection
2022-04-18

If you've been using PHP 8.1, chances are you already know about this new feature called [Enumerations or "Enums"](https://www.php.net/manual/en/language.enumerations.php). If not, then I suggest that you check it out as it is, in my opinion, one of the most powerful new feature PHP has added to the language. It might solve a lot of your use-cases as it did for me. As an example, let's say that we have a backed enum class that holds the cases for the status of the ticket in our app: ``` enum TicketStatus : string { case Draft = 'draft'; case Open = 'open'; case Ongoing = 'ongoing'; case Closed = 'closed'; } ``` One cool thing about enumerations is that you can call a `cases()` method on it to list all the cases like so: ``` $result = TicketStatus::cases(); dd($result); [ TicketStatus { +name: "Draft", +value: "draft", }, TicketStatus { +name: "Open", +value: "open", }, TicketStatus { +name: "Ongoing", +value: "ongoing", }, TicketStatus { +name: "Closed", +value: "closed", }, ] ``` As you can see, each element in the result is an instance of `TicketStatus` class with properties `name` and `value`. So it begs the question, what if I just want to get just the names or just the values? Unfortunately, this isn't something that comes out of the box and calling `TicketStatus::names()` or `TicketStatus::values()` would cause an error. One solution is to use `Illuminate\Support\Collection` class. ``` $names = collect(TicketStatus::cases())->pluck('name'); dd($names); Illuminate\Support\Collection { all: [ "Draft", "Open", "Ongoing", "Closed", ], } $values = collect(TicketStatus::cases())->pluck('values'); dd($values); Illuminate\Support\Collection { all: [ "draft", "open", "ongoing", "closed", ], } ``` Okay, now we're talking! Let's refactor that as methods in our enum class, like so: ``` enum TicketStatus : string { case Draft = 'draft'; case Open = 'open'; case Ongoing = 'ongoing'; case Closed = 'closed'; public static function names() { return collect(self::cases())->pluck('name'); } public static function values() { return collect(self::cases())->pluck('value'); } } ``` Now, calling `TicketStatus::names()` or `TicketStatus::values()` would definitely work! But wait, there's more! Since we are already using `Collection` class here, we might as well see to it that we are able to take advantage of the full features it can offer. How about refactoring to have something like `TicketStatus::collection()` ? Let's do it! ``` enum TicketStatus : string { case Draft = 'draft'; case Open = 'open'; case Ongoing = 'ongoing'; case Closed = 'closed'; public static function names() { return self::collection()->pluck('name'); } public static function values() { return self::collection()->pluck('value'); } public static function collection() { return collect(self::cases()); } } ``` Cool! Now we can take full advantage of collection features within our enum. In the future we can do something like `TicketStatus::collection()->map(...)` or `TicketStatus::collection()->each(...)` should we need to. It is now up to you if you want to add more convenience methods or just chain from the `collection()` method. Last thing that we would want to do is to be able to share these convenient functions with other enum classes. So let's wrap it within a trait... ``` trait Collectible { public static function names() { return self::collection()->pluck('name'); } public static function values() { return self::collection()->pluck('value'); } public static function collection() { return collect(self::cases()); } } ``` And just use the trait within your enum classes like so ``` enum TicketStatus : string { use Collectible; case Draft = 'draft'; case Open = 'open'; case Ongoing = 'ongoing'; case Closed = 'closed'; } ``` And there you have it! You have supercharged your backed enum classes using collection. Hope you enjoy!

Marvin Quezon · Copyright © 2024 · Privacy · Sitemap