Welcome Guest, Not a member yet? Register   Sign In
Custom controller - request object empty in constructor
#1

Hi,

i created my own controller:

PHP Code:
class CustomController extends BaseController {
  public function 
__construct() {
   
var_dump($this->request// NULL Why?
 
}
}
class 
Home extends CustomController {} 

The request object is empty. Can i use a constructor in controllers? I have no access to the request object and i think the __constuct will be called before initController but how can i access the request object in the constructor?
Reply
#2

The $request property is set in the initController() method. Therefore, it is not available in the class constructor.
If you need access to an instance of the request class use the \Config\Services::request() service;
Reply
#3

This means if i want to use the __construct i have to use \Config\Services::request().
In the meantime i used the initController in my custom controller and all the code from the constructor must be in the initController function but your solution is much better.

Thank you @iRedds
Reply
#4

(06-22-2022, 11:41 AM)groovebird Wrote: This means if i want to use the __construct i have to use \Config\Services::request().
In the meantime i used the initController in my custom controller and all the code from the constructor must be in the initController function but your solution is much better.

It is not good practice. Because CI Controller is designed to be set the request object in initController().
You are against it, and force to get the request object before CI injects it into the controller.

I recommend you not use the tricky way.

See the documentation. Using initController() is a normal way.
https://codeigniter4.github.io/CodeIgnit...components
Reply
#5

(06-24-2022, 02:56 PM)kenjis Wrote:
(06-22-2022, 11:41 AM)groovebird Wrote: This means if i want to use the __construct i have to use \Config\Services::request().
In the meantime i used the initController in my custom controller and all the code from the constructor must be in the initController function but your solution is much better.

It is not good practice. Because CI Controller is designed to be set the request object in initController().
You are against it, and force to get the request object before CI injects it into the controller.

I recommend you not use the tricky way.

See the documentation. Using initController() is a normal way.
https://codeigniter4.github.io/CodeIgnit...components

I do not agree with this statement.
The initController() method is used because CI doesn't use a service container and can't inject dependencies.

In my opinion, the controller should not be dependent on other classes by default, and CodeIgniter\Controller and App\Controllers\BaseController should only add additional functionality/helper methods.

Since Services::request() returns the same class instance as set in $this->request, I don't see any bad practice in using a factory service in a constructor.
Reply
#6

(This post was last modified: 06-24-2022, 04:45 PM by kenjis.)

(06-24-2022, 04:01 PM)iRedds Wrote: The initController() method is used because CI doesn't use a service container and can't inject dependencies.

In my opinion, the controller should not be dependent on other classes by default, and CodeIgniter\Controller and App\Controllers\BaseController should only add additional functionality/helper methods.

Since Services::request() returns the same class instance as set in $this->request, I don't see any bad practice in using a factory service in a constructor.

CI could inject dependencies into __constuct(), but it does inject into initController().

Why does your controller depend on Services?
It is better that your controller does not depend on Services.
You can use $this->request after it is injected by CI.

"Since Services::request() returns the same class instance" Yes, it does now.
But if it changes, the controller will not work.

(Added) Service::request() and Services::response() are special services. I think it might be better to be `internal`. Personally I recommend not to use, and you probably don't need to use them.
Reply
#7

(06-24-2022, 04:22 PM)kenjis Wrote: Why does your controller depend on Services?
It is better that your controller does not depend on Services.
You can use $this->request after it is injected by CI.

$this->request is only defined in the initController() method. And further is available only in "action". But the logic of the whole controller can depend on the request data and it is reasonable to place this logic in the constructor.

(06-24-2022, 04:22 PM)kenjis Wrote: "Since Services::request() returns the same class instance" Yes, it does now.
But if it changes, the controller will not work.

The state of an incoming request cannot be changed. Except for some points that should not affect the consistency of the data.
So if you need to change the incoming request, then there are some design problems.

(06-24-2022, 04:22 PM)kenjis Wrote: (Added) Service::request() and Services::response() are special services. I think it might be better to be `internal`. Personally I recommend not to use, and you probably don't need to use them.

I respect you as a developer and I am glad that often our views on the development of the framework coincide. Maybe I misunderstood you, but how do you propose to be if an instance of the Response class is not passed to the FilterInterface::before() filter method, but the returned result can be an instance of the Response class.
I think that your attitude to request and response services is wrong.
Reply
#8

I'd like to know what is the reason behind the initController? The __construct() is for such things right? in the CI3 version this was mor understandable

(06-24-2022, 04:22 PM)kenjis Wrote: Why does your controller depend on Services?
It is better that your controller does not depend on Services.
You can use $this->request after it is injected by CI.

I looked into the myth auth lib and the controller also depends on services. This service is called in the constructor. Where should we call the services if not in the controller? I think of the session service i use in the controller.
Reply
#9

(This post was last modified: 06-26-2022, 03:12 PM by kenjis.)

"Why does your controller depend on Services?" is my question because iRedds said
"In my opinion, the controller should not be dependent on other classes by default"

I would prefer that controllers do not depend on the Services, but I don't think that is possible for normal use of CI4.
Also, there is nothing wrong with a controller depends on Services (except request and response),
which is the normal expected use of CI4.

But Services::request() and Services::response() are special services. I think it is better NOT to use in controllers.
And CI4 provides them as $this->request and $this->response.

The initController() is a CI4-style constructor of controllers.
The comment says it is Constructor.
https://github.com/codeigniter4/CodeIgni...er.php#L70

If you want to write some code in controller constructor, you can write it in initController().
https://github.com/codeigniter4/CodeIgni...hp#L48-L50
Reply
#10

How the request/response object and Services::request()/Services::response() will change in the future is still undetermined and uncertain.

However, it has been decided that they will be PSR-7/15 compliant and will definitely be changed in v5 or later.
The request/response object will be immutable.

I am giving my current opinion on how to write code that will make the controller as unbreakable as possible in the future.

I have not gone into detail on how to implement these in CI4 inside in the future.

(06-24-2022, 09:36 PM)iRedds Wrote: $this->request is only defined in the initController() method. And further is available only in "action". But the logic of the whole controller can depend on the request data and it is reasonable to place this logic in the constructor.

The initController() is a CI4-style constructor of the controller.

(06-24-2022, 09:36 PM)iRedds Wrote: The state of an incoming request cannot be changed. Except for some points that should not affect the consistency of the data.
So if you need to change the incoming request, then there are some design problems.

You are correct. Services::request() might not be problem, but there is still chance that Services::request() will be removed.
Because if it is not needed at all, it is simpler to remove it.

And there are users that change the state (values from suprglobals) of incoming request. I don't know why.

(06-24-2022, 09:36 PM)iRedds Wrote: how do you propose to be if an instance of the Response class is not passed to the FilterInterface::before() filter method, but the returned result can be an instance of the Response class.

Maybe we will create an instance of the Response with PSR-17 factory.
So Services::response() might become the factory.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB