Skip to main content
CakeDC Blog

Dynamic Enums (CakePHP 5 / PHP 8.3)

This article is part of the CakeDC Advent Calendar 2024 (December 3rd 2024)

In modern PHP development, utilizing constants and enums can significantly improve code readability, maintainability, and robustness. This article explores practical implementations of constants and enums in a CakePHP application.  By leveraging these features, developers can write cleaner and more efficient code. Let's dive into the specifics with code examples and practical use cases.
 

1.- Define a constant class of user roles:

src/Constants/UserRoles.php

namespace App\Constants;

class UserRoles
{
    public const string ADMIN = 'admin';
    public const string EDITOR = 'editor';
    public const string VIEWER = 'viewer';
}

2.- Define an Enum class for the status of the posts:

src/Enum/PostStatus.php

namespace App\Enum;

enum PostStatus: string
{
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';

    public static function list(): array
    {
        return [
            self::DRAFT->value => __('DRAFT'),
            self::PUBLISHED->value => __('PUBLISHED'),
            self::ARCHIVED->value => __('ARCHIVED'),
        ];
    }
}

3.- Define an Enum class for the status of the comments:

src/Enum/CommentStatus.php

namespace App\Enum;

enum CommentStatus: string
{
    case APPROVED = 'approved';
    case DECLINED = 'declined';

    public static function list(): array
    {
        return [
            self::APPROVED->value => __('APPROVED'),
            self::DECLINED->value => __('DECLINED'),
        ];
    }
}

4.- Check the dynamic use in the access to the Enums values.

templates/Pages/enums.php

// Dynamic constants new in php 8.3 and php 8.4
use App\Constants\UserRoles;
use App\Enum\PostStatus;

$roleName = 'ADMIN';
$roleValue = UserRoles::{$roleName}; // Dynamically accesses UserRoles::ADMIN

echo "Role Value: " . $roleValue; // Print “Role Value: admin”

// Dynamic Enum members new in php 8.3 and php 8.4
$statusName = 'PUBLISHED';
$statusValue = PostStatus::{$statusName}->value; // Dynamically accesses PostStatus::Published

echo "Post Status: " . $statusValue; // Print “Post Status: published”

5.- We can also use its functions, for example “list” for selectors, and print its value.

//generate a select element with all status options
echo $this->Form->control('status', ['options' => PostStatus::list(), 'empty' => true]);

//print the text associated with the status value
echo h(PostStatus::list()['published']);

6.- They can be used dynamically in query operations, for example: to get a post and only your comments approved.

src/Controller/PostsController.php

$postWithCommentsApproved = $this->Posts
            ->find('onlyCommentsByStatusEnum', status:  CommentStatus::APPROVED)
            ->contain(['Users'])
            ->where(['Posts.id' => $id])
            ->firstOrFail();

src/Model/Table/PostsTable.php

public function findOnlyCommentsByStatusEnum(SelectQuery $query, CommentStatus $status): SelectQuery
    {
        return $this->find()
            ->contain(['Comments' => function ($q) use ($status) {
                return $q->where([
                    'Comments.status' => $status->value,
                ]);
            }]);
    }

You can see a complete example in https://github.com/ACampanario/advent2024.

Back to all articles
We Bake with CakePHP