【问题标题】:PHP - class does not call constructor of extended class, while it works fine in an other classPHP - 类不调用扩展类的构造函数,而在其他类中工作正常
【发布时间】:2017-01-12 14:28:30
【问题描述】:

我的问题:

所以,我有一个名为“Home”的类,它扩展了“Controller”类,控制器类需要构造函数中的所有模型。这很好用。

现在我有第二个名为“Login”的类,它还扩展了“Controller”类,但是它不调用构造函数,我很困惑为什么它不调用此类中的构造函数。

我找到了一种解决方法,那就是在登录类中使用Parent::__construct() 创建一个构造函数,当我这样做时,一切正常。

但我正在研究为什么它在 Home 类中有效,而在 Login 类中无效。

一些信息:

家用控制器:(没有任何问题的)

不强制调用扩展类的构造函数时的回溯:

0 Core\Controller->__construct() 在 [/var/www/html/site.luukwuijster.eu/core/Router.php:26] 调用 #1 App->__construct() 在 [/var/ 调用www/html/site.luukwuijster.eu/public/index.php:5]

当我强制调用扩展类的构造函数时的回溯:

0 Core\Controller->__construct() 在 [/var/www/html/site.luukwuijster.eu/app/controllers/home.php:12] 调用 #1 Home->__construct() 在 [/ var/www/html/site.luukwuijster.eu/core/Router.php:26] #2 App->__construct() 在 [/var/www/html/site.luukwuijster.eu/public/index.php 调用: 5]

登录控制器:(有问题的那个)

当我不强制调用扩展类的构造函数时:

致命错误:未捕获的错误:在 /var/www/html/site.luukwuijster.eu/app/controllers/login.php:21 中找不到类“App\User”:21 堆栈跟踪:#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} 在第 21 行的 /var/www/html/site.luukwuijster.eu/app/controllers/login.php 中抛出

当我强制调用扩展类的构造函数时的回溯:

Core\Controller->__construct() 在 [/var/www/html/site.luukwuijster.eu/app/controllers/login.php:11] 调用 #1 Login->__construct() 在 [/var 调用/www/html/site.luukwuijster.eu/core/Router.php:26] #2 App->__construct() 在 [/var/www/html/site.luukwuijster.eu/public/index.php:5 调用]

如你所见,当我强制调用构造函数时它工作正常,但当我不强制它时,它只在 Home 类中工作。 (家庭控制器)

代码:

家庭控制器:

use App\User;
use Core\Controller;
use Core\DB;

class Home extends Controller
{
    public function test()
    {
        return User::name();
    }
}

登录控制器:

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();
    }

}

扩展类(控制器)

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 我把它放在这里是因为当我不强制在扩展类上调用构造函数时,它会在此处的规则 26 上被调用。 ($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;
        }
    }
}

我的问题:

为什么它在 Home 控制器中工作正常,而不是在 Login 控制器中?

我必须做些什么才能使它在登录控制器中以相同的方式工作?

我希望一切都清楚,如果您需要更多代码或信息,可以在 cmets 中询问我。

【问题讨论】:

  • 你是在静态调用 Login::login() 吗?
  • 是的,但我不是我的问题的重点

标签: php


【解决方案1】:

根据手册:

为了向后兼容 PHP 3 和 4,如果 PHP 找不到 __construct() 函数,它将通过类的名称搜索旧式构造函数。有效, 这意味着唯一会出现兼容性问题的情况是 该类有一个名为 __construct() 的方法,用于 不同的语义。

由于您的Login 类中有一个login() 方法,php 将使用它作为构造函数。请注意,函数名称不区分大小写。

另请注意,此行为在 php 7 中已弃用,但尚未删除。

【讨论】:

  • 我的 php 版本是:PHP 版本 7.0.8-0ubuntu0.16.04.3,所以我使用的是 PHP 7。
  • @LuukWuijster 它已在 php 7 中被弃用,尚未删除,所以我更新了我的答案。
  • @LuukWuijster 您可以重命名login() 方法或手动调用它。为了安全起见,最好添加一个构造函数来手动调用父构造函数,因为否则每次创建对象时 php 都会调用您的 login() 方法,这可能会导致意外结果。并且不要在 login() 方法中调用父构造函数以避免将来出现问题。
【解决方案2】:

根据手册说明:

注意:如果子类不隐式调用父构造函数 定义了一个构造函数。为了运行父构造函数,调用 子构造函数中的 parent::__construct() 是必需的。如果 child 没有定义构造函数,那么它可以从 父类就像一个普通的类方法(如果它没有被声明 作为私人)。

Login 类有一个构造,因此不会隐式调用父构造。我必须显式调用它。

【讨论】:

  • 好的,但是当我在登录类中没有__construct() 时,不会调用构造函数。我可以删除构造函数并且它没有被调用。
【解决方案3】:

总而言之,页面上的内容是什么,我收集到我做对了:

Login 类有一个名为 login() 的方法,但 Class Home 没有名为 home() 的方法。

在旧版本的 PHP 中,如果没有找到名为 __construct() 的构造方法,则:

首先:它检查与 Class 同名的方法并使用它。

下一步:如果没有找到与该类同名的方法 - 它使用扩展类的构造方法。

谢谢!

【讨论】:

    猜你喜欢
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 2017-03-08
    • 2011-07-28
    • 2021-06-15
    • 2018-09-26
    • 2014-04-18
    相关资源
    最近更新 更多