Enable/Disable Http Methods for multiple controllers

Hello all!

I currently have some issues trying to enable/disable different Http methods for my controllers. I’d like to achieve the following:

  • By default disable OPTIONS on all Web Controllers
  • By default enable OPTIONS on all Rest Controllers

Is there any way to achieve this using for example Dependency Injection? I’d like to avoid updating every single Controller manually.

Thanks in advance!

Not sure if this is the best way to do it but I create a Controller that extends ActiveController with all my default information and I extend that one with my “real” controllers.

Seems to be working fine.

what do you mean by options? parameters?

Nope, I mean the HTTP Method OPTIONS :slight_smile:

Oh ok! Then you could update your urlManager or do what @echantigny said - create a custom controller, change its behavior and extend on the other controllers.

Some links that could help with urlManager:

Awesome thank you, I’ll take a look.

For defining allowed HTTP methods there is the VerbFilter behavior which can be attached to a controller and defines which actions can receive which HTTP methods. However it seems VerbFilter is not designed to be attached to the application directly as it is possible with AccessConrol filter for example.

To allow Verbfilter to work for multiple controllers you need to extend it:

<?php

namespace app\components;

class VerbFilter extends \yii\filters\VerbFilter
{
    public $controllers = [];
    
    /**
     * @param ActionEvent $event
     * @return bool
     * @throws MethodNotAllowedHttpException when the request method is not allowed.
     */
    public function beforeAction($event)
    {
        foreach($this->controllers as $controllerClass => $verbs) {
            if ($event->action->controller instanceof $controllerClass) {
                $this->actions = ['*' => $verbs];
                return parent::beforeAction($event);
            }
        }
        return $event->isValid;
    }
}

You can configure the application like this:

return [
    // ... application config ...
    'as verbFilter' => [
        'class' => \app\components\VerbFilter::class,
        'controllers' => [
            \app\controllers\SiteController::class => [
                ['GET', 'POST'], // only GET and POST allowed in web controllers
           ],
           // you may also specify an interface and implement
           // that in all RestControllers
            \app\components\RestControllerInterface::class => [
                ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], // all methods allowed in RestControllers
           ],
        ]
    ]

You may add additional VerbFilter in Controller classes which will limit HTTP methods for specific actions.

2 Likes