夏期劇場
夏期劇場

Reputation: 18327

Slim Framework: How to catch multiple fully OPTIONAL routes?

What i already have

Main thing is that, my base route is already an Optional route. Which is, like:

$app->get('/{id}', function(...){
    if ( $args['id'] ) {
        /**
         * Show Item Details
         */
    } else {
        /**
         * Redirects to Home
         */
    }
});

That's perfectly working. And that translates to:

www.example.com/DRX1487

What i want to achieve

Now what i want is something like:

www.example.com/DRX1487/reorder

www.example.com/DRX1487/cancel

I tried:

$app->get('/{id}/{action}', function(...){...});

$app->get('/:id/:action', function(...){...});

Both doesn't work.

How do i achieve this please? All the example i've found (for Optional Routing) are all based on the static base route first. But my base route is already an Optional Route.

Please kindly advise.

Upvotes: 0

Views: 800

Answers (1)

Zamrony P. Juhara
Zamrony P. Juhara

Reputation: 5262

With separate routes, each codes that handle action can be simple and lean in size. For example.

 $app->get('/', HomeController::class); 
 $app->get('/{id}', ItemDetailController::class);
 $app->get('/{id}/reorder', ItemDetailReorderController::class);
 $app->get('/{id}/cancel', ItemDetailCancelController::class);

Controller for homepage

class HomeController 
{
    public function __invoke($request, $response, $args)
    {  
        //do something   
        return $response;
    }
} 

Base controller for item-related thing

abstract class BaseItemDetailController 
{
     protected function isValidId($id)
     {
          //do validation of id here
     }

     abstract public function __invoke($request, $response, $args);
} 

Controller dthat display item detail

class ItemDetailController extends BaseItemDetailController
{
    public function __invoke($request, $response, $args)
    {  
        $id = $args['id'];
        if ($this->isValidId($id)) {
            //do something to display item detail
        }
        return $response;
    }
} 

Controller for reorder item

class ItemDetailReorderController extends BaseItemDetailController
{
    public function __invoke($request, $response, $args)
    {  
        $id = $args['id'];
        if ($this->isValidId($id)) {
            //do something to reorder item
        }
        return $response;
    }
} 

Controller that handle cancelling item

class ItemDetailCancelController extends BaseItemDetailController
{
    public function __invoke($request, $response, $args)
    {  
        $id = $args['id'];
        if ($this->isValidId($id)) {
            //do something to cancel item ordered
        }
        return $response;
    }
} 

Optional parameter is defined using bracket. With your initial approach, things can get convoluted very easily, avoid this following code if you can.

$app->get('/[{id}[/{action}]]', function(...) {
     if (isset($args['id'])) {
          if (isValid($args['id'])) {
             if (isset($args['action'])) {
                 if ($args['action'] === 'reorder') {
                     //do item reorder
                     return $response;
                 }
                 if ($args['action'] === 'cancel') {
                     //do item cancel
                     return $response;
                 }   
                 //do something (display item detail?)
                 return $response;
             } else {
                 //show item detail
             }
          }
     } else {
          /**
          * Redirects to Home
          */
     }
});

Upvotes: 2

Related Questions