Search code examples
phpcodeigniter-4

Codeigniter4 how to call parent controller's constructor from derived class constructor


In Codeignter 4 we can't use constructor in BaseController. But the method initController() will do it. But how can call this method from derived controller's constructor?

My question is that BaseController::is_allowed() method will do all basic features that are commonly useful for all derived controller classes. But to work BaseController::is_allowed() , BaseController::__construct() should be execute before this. But as in CI-4, constructor is not allowed in BaseController. It can have BaseController::initController(). But the problem is that this method will execute only after DerivedClass::__construct().

I need to execute BaseController::is_allowed() before executing every derived class methods. So I call BaseController::is_allowed() method in constructor of derived controllers. But derived class constructor executes before the execution of BaseController::initController(). So BaseController::is_allowed() not works.

BaseController.php

<?php

namespace App\Controllers;

use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;


class BaseController extends Controller
{
    public $request;

    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        
        // Doing all basic setups here that are needed to all other methods in this class.

        // This method will be called only after derivedClass::__construct().
        // But CI-4 not allows to use __construct() method in BaseController class.
        // This causes my problem.
    }

    function is_allowed()
    {
        // Provides all basic features for all derived controller classes.
        // But to work code in this method, initController() method should execute first.
    }
}

And the derived class as

Users.php

<?php

namespace App\Controllers;

class Users extends BaseController
{
    public function __construct()
    {
        // BaseController::is_allowed() will provide all basic features for this controller.
        // To work this method, BaseController::initController() should execute.
        // But this will execute only after this ( __construct()) constuctor.
        // In Codeignier-3, BaseController::__construct() was possible.
        // It will execute before derived class constructor.
        $this->is_allowed();
    }
}

Solution

  • Basically your Users Controller should use the iniController and not the construct, like so:

    <?php
    
    namespace App\Controllers;
    use CodeIgniter\HTTP\RequestInterface; 
    use CodeIgniter\HTTP\ResponseInterface; 
    use Psr\Log\LoggerInterface;
    
    class Users extends BaseController
    {
        public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
        {
            parent::initController($request, $response, $logger);
            $this->is_allowed();
        }
    }
    

    However its a good practice to create your is_allowed function in your BaseController as a protected function, otherwise one might be able to access it via any url like site.com/users/is_allowed

    I might even add that if the purpose of the is_allowed function is to check if the user has permission to do an action or even be in that controller your should look into Filters and not this