The PHP class does not call the constructor of the extended class, while it works fine in another class

My problem:

So, I have a class called "Home" and it extends the "Controller" class, for the controller class all models in the constructor are required. It works great.

Now I have a second class called "Login." It also extends the Controller class, but it does not invoke the constructor, and I am confused why it does not invoke the constructor in this class.

I found a workaround and I have to make a constructor in the Login class with Parent::__construct() , when I do this, everything works fine.

But I work, why it works in the Home class and does not work in the Login class.

Some information:

Home controller: (no problem)

Backtrace when I cannot call the constructor of the extended class:

0 Core \ Controller → __ construct () called in [/var/www/html/site.luukwuijster.eu/core/Router.php:26] # 1 App → __ construct () called in [/ var / WWW /HTML/site.luukwuijster.eu/open/index.php: 5]

Backtrace, when I force the constructor of the extended class to be called:

0 Core \ Controller → __ construct () called in [/var/www/html/site.luukwuijster.eu/app/controllers/home.php:12] # 1 Home → __ construct () called in [/ var /www/html/site.luukwuijster.eu/core/Router.php: 26] # 2 Application → __ construct () called in [/var/www/html/site.luukwuijster.eu/public/index.php: 5]

Login Controller: (one who has problems)

If I do not force to call the constructor of the extended class:

Fatal error: Failed Error: The Application \ User class was not found in /var/www/html/site.luukwuijster.eu/app/controllers/login.php:21 Stack trace: # 0 / var / www / html / site.luukwuijster.eu/core/Router.php(26): Login-> login () # 1 / var / www / html / site.luukwuijster.eu / public / index.php (5): App-> __construct ( ) # 2 {main} thrown at /var/www/html/site.luukwuijster.eu/app/controllers/login.php on line 21

Backtrace, when I force the constructor of the extended class to be called:

Core \ Controller → __ construct (), called in [/var/www/html/site.luukwuijster.eu/app/controllers/login.php:11] # 1 Login → __ construct (), called in [/ var / www / html / site.luukwuijster.eu / core / Router.php: 26] # 2 Application → __ construct (), called in [/var/www/html/site.luukwuijster.eu/public/index.phphaps ]

As you can see, it works great when I force the constructor to be called, but when I don't force it, it only works in the Home class. (Home controller)

Code:

Home controller:

 use App\User; use Core\Controller; use Core\DB; class Home extends Controller { public function test() { return User::name(); } } 

Input controller:

 use App\User; use Core\Controller; use Core\DB; class Login extends Controller { //This is the constructor I was talking about to force the calling of //the constructor in the extended class. public function __construct() { parent::__construct(); } public function login() { return User::name(); } } 

Advanced class (controller)

 namespace Core; class Controller { public $database; function __construct() { //I have put this here to see the backtrace. debug_print_backtrace(); $this->database = new DB(); foreach (glob('../app/models/*.php') as $model){ require_once $model; } } 

router.php I put this here because when I do not force a call to the constructor of the extended class, it receives a call from rule 26 here. ( $this->controller = new $this->controller; )

 class App { protected $controller = 'home'; protected $method = 'index'; protected $parameters = []; protected $a = 0; public function __construct() { $url = $this->Url(); if(file_exists('../app/controllers/'. $url[0] .'.php')){ $this->controller = $url[0]; unset($url[0]); } else { if (isset($url[0])) die(view('error404')); } require_once '../app/controllers/'. $this->controller .'.php'; $this->controller = new $this->controller; if (isset($url[1])){ if (method_exists($this->controller, $url[1])){ $this->method = $url[1]; unset($url[1]); }else{ die(view('error404')); } } $this->parameters = $url ? array_values($url) : ['']; echo call_user_func_array([$this->controller, $this->method], $this->parameters); } public function Url() { if(isset($_GET['url'])){ $url = filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL); $exploded_url = explode('/', $url); return $exploded_url; } } } 

My questions:

Why does it work fine in the home controller and not in the input controller?

And what do I need to do to make it work the same in the input controller?

I hope that everything will be clear, and if you need more code or information, you can ask me in the comments.

+5
source share
2 answers

According to the manual:

For backward compatibility with PHP 3 and 4, if PHP cannot find __construct () for a given class, it will look for an old-style constructor function by class name. Effectively, this means that the only case that would have compatibility issues is if the class had a method called __construct () that was used for different semantics.

Since you have a login() method in your Login class, php will use this as a constructor. Note that function names are case insensitive.

Also note that this behavior is deprecated in php 7 but not yet removed.

+9
source

In accordance with the instructions of the manual:

Note. Parent constructors are not called implicitly if the child class defines the constructor. To start the parent constructor, call parent :: __ construct () inside the child constructor. If child does not define a constructor, then it can be inherited from the parent class, as a regular class method (if it was not declared as private).

The Login class has a construct, so the parent construct is implicitly called. It must be explicitly specified.

+1
source

Source: https://habr.com/ru/post/1262696/


All Articles