2

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();
    }
}
  • Do you try add `RequestInterface $request, ResponseInterface $response, LoggerInterface $logger` to construc params? – Pavlo Mezhevikin Oct 20 '21 at 18:08
  • No, I need to get this thing. How I get these variables, because it is available in parent controller but not available its constructor. Derived class:: __construct() method will execute before the execution of parent::initController() – Shihabu Rahman Oct 20 '21 at 18:18
  • https://codeigniter4.github.io/userguide/incoming/controllers.html#included-properties The application’s main Request Instance is always available as a class property, `$this->request`. From official documentation – Pavlo Mezhevikin Oct 20 '21 at 18:38

2 Answers2

3

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

marcogmonteiro
  • 2,061
  • 1
  • 17
  • 26
2

In Codeignter 4 we can't use constructor in controllers.

You don't use a typical constructor in the BaseController class, you can still use constructors in your App/Controller classes.

You do not need to manually make a call to initController, that is done for you during the bootstrap process. Remove that line from your App\Controllers\Users constructor function.

parttimeturtle
  • 1,125
  • 7
  • 22
  • I have edited my question with more explanations. This was my coding structure I used with **Codeigniter 3**. But in **CI-4**, I understood that, I should rewrite my coding structure and it is only the solution. Yes? – Shihabu Rahman Oct 21 '21 at 10:46
  • @ShihabuRahman The `initController` method that exists inside the default `App\Controllers\BaseController` is invoked during the bootstrap process; all of your Controller classes should extend this `BaseController` class but they do not need to manually invoke `initController` in any way. All the accepted answer does is initialize the Controller twice. Functions you define within the `BaseController` class will automatically be available to any class that extends it; if for some reason you have an identical method inside your Controller, you would have to use `parent::method()` – parttimeturtle Sep 12 '22 at 23:19