简体   繁体   中英

Problem with implicit Enum Binding on route in laravel

I have this route

Route::get('/post/{post:uuid}', [\App\Http\Controllers\PostController::class, 'showPost']);

And it works, if the user inputs an inexisting uuid, the app responses a 404 error, but now I want to add one more condition by using enums on route.

I have an enum called PostStateEnum.php

    <?php

namespace Modules\Muse\Enum;

use App\Http\Traits\EnumTrait;

enum PostStateEnum: string
{
    use EnumTrait;

    case DRAFT = 'draft';
    case WAITING_APPROVAL = 'waiting_approval';
    case APPROVED = 'approved';
    case REJECTED = 'rejected';
    case PUBLISHED = 'published';
    case UNPUBLISHED = 'unpublished';
}

I want to add a condition in the route: if the $post->state is PostStateEnum::PUBLISHED I want to go to the 'showPost' in my PostController

Currently, I'm handle that logic on my controller

public function showPost(Post $post)
{
    if ($post->state == PostStateEnum::PUBLISHED)
    {
        dump($post);
    } else {
        return abort(404);
    }
}

According to the laravel 9 docs I understand is that I need to create another enum with only one state to be able to validate that from the route, is that correct?

Is possible? Or my way is better?

I think you are confusing what enums in the route can bring. It is not about what is already saved, but more to use it as a filter / input. Imagine you want to have a route, that show posts based on status.

Route::get('posts/{PostStateEnum}');

In your controller you would be able to filter based on that.

public function index(PostStateEnum $enum) {
    if ($enum ==PostStateEnum::PUBLISHED) {
        // query filter published
    } else if ($enum ==PostStateEnum::UNPUBLISHED) {
        // query filter unpublished
    }
}

Your enum is not from the input, but from the model, therefor what you are doing is actually the correct aproach. If not done, remember to cast your enum.

class Post extends Model {
    protected $casts = [
        'status' => PostStateEnum::class,
    ];
}

As a more general code improvement tip, doing if else, like you did in your example is non optimal for readability, you can in these cases, reverse the if logic and do an early return approach.

public function showPost(Post $post)
{
    if ($post->state !== PostStateEnum::PUBLISHED)
    {
        return abort(404);
    }

    return $post;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM