【问题标题】:How to Stop constructor of base class to be called in child class如何停止在子类中调用基类的构造函数
【发布时间】:2013-12-30 12:01:24
【问题描述】:

下面是我的基类,即数据库方法。

// Constructor
public function __construct($argHost, $argUsername, $argPassword, $argDatabase)
{
    $this->_host = $argHost;
    $this->_username = $argUsername;
    $this->_password = $argPassword;
    $this->_database = $argDatabase;
}

// Connect to the database
public function Connect()
{
    if (!$this->Is_Connected()) {
        $this->_connection = mysqli_connect($this->_host,$this->_username,$this->_password,$this->_database);    
    } else {
        return $this->_connection;
    }

}
// Run query
public function Run($query)
{
    if ($this->result = mysqli_query($this->_connection,$query)) {
        return $this->result;
    } else {
        die("Couldn't perform the request");
    }
}

我的子类是下面的分类方法

class Categories extends Database
{    
    public $category_id = '';
    public $category_name = '';
    public $category_image = '';

    // View Category
    public function ViewCategories() 
    {
        return $this->Run("SELECT * FROM categories");
    }       
}

现在的问题是,当我通过创建基类的对象来运行 Run() 方法时,它工作正常。但是当我创建对象对象时,子类即类别并执行方法 viewCategories();我收到以下错误

警告:Database::__construct() 缺少参数 1,调用 E:\xampplite\htdocs\ecommerce\index.php 在第 16 行并在 E:\xampplite\htdocs\ecommerce\classes\class.database.php 第 17 行

警告:缺少调用 Database::__construct() 的参数 2 E:\xampplite\htdocs\ecommerce\index.php 在第 16 行并在 E:\xampplite\htdocs\ecommerce\classes\class.database.php 第 17 行

警告:Database::__construct() 缺少参数 3,调用 E:\xampplite\htdocs\ecommerce\index.php 在第 16 行并在 E:\xampplite\htdocs\ecommerce\classes\class.database.php 第 17 行

警告:Database::__construct() 缺少参数 4,调用 E:\xampplite\htdocs\ecommerce\index.php 在第 16 行并在 E:\xampplite\htdocs\ecommerce\classes\class.database.php 第 17 行

警告:mysqli_query() 期望参数 1 为 mysqli,给定 null 在 E:\xampplite\htdocs\ecommerce\classes\class.database.php 第 35 行 无法执行请求

更新:这就是我调用方法的方式

<?php
function __autoload($class_name) {
    include 'classes/class.'.$class_name . '.php';
}
$connection = new Database("localhost", "raheel", "raheel786", "ecommerce");
$connection->Connect();
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ecommerce</title>
</head>
<body>
   <?php 
   $category = new Categories();
   $category_list = $category->ViewCategories();
   var_dump($category_list);
   ?> 
</body>
</html>

请帮我解决这个问题。

【问题讨论】:

  • 你没有将任何参数传递给构造函数
  • 在你的子类中定义一个空的构造函数来覆盖父类中的构造函数;否则继承规则适用,父构造函数将被调用
  • 我通过它让我更新代码

标签: php oop


【解决方案1】:

您不应该对has-a relationship 使用继承,继承描述了is-a relationship。在您的情况下,类别不是数据库,类别有一个数据库。

改用合成:

class Categories
{
    private $database;

    function __construct(Database $database)
    {
        $this->database = $database;
    }

    public function ViewCategories()
    {
        return $this->database->Run("SELECT * FROM categories");
    }
}

及用法:

$connection = new Database("localhost", "raheel", "raheel786", "ecommerce");
$connection->Connect();
// ...
$category = new Categories($connection);
$category_list = $category->ViewCategories();
var_dump($category_list);

【讨论】:

  • 非常感谢您清除了我的概念,您的技术奏效了谢谢:)
【解决方案2】:

在您的情况下,您需要重载构造函数。只需将空的__construct() 方法添加到子类

class Categories extends Database{

    public function __construct() {}

    ...

}

但它不会解决你的问题:)

作为一种解决方案,我可以看到 2 个变体:

1) 制作静态变量_connection,使其在所有对象中都可用

public function Connect(){
    if( ! self::$_connection){
        self::$_connection = mysqli_connect($this->_host,$this->_username,$this->_password,$this->_database);    
    }

    return self::$_connection;
}

public function Run($query){
    if($this->result = mysqli_query(self::$_connection,$query)){
    return $this->result;
                }
                else 
                   die("Couldn't perform the request");
}

2) 我认为这是更好的方法。使用连接和查询创建 2 个独立的类,以便其中一个包含另一个

class Database {
    // Constructor
    public function __construct($argHost,$argUsername,$argPassword,$argDatabase){
        $this->_host = $argHost;
        $this->_username = $argUsername;
        $this->_password = $argPassword;
        $this->_database = $argDatabase;
    }

    // Connect to the database
    public function Connect(){
        if(!$this->Is_Connected()){
            $this->_connection = mysqli_connect($this->_host,$this->_username,$this->_password,$this->_database);    
        } else {
            return $this->_connection;
        }
    }
    // Run query
    public function Run($query){
        if($this->result = mysqli_query($this->_connection,$query)){
            return $this->result;
        }
        else 
           die("Couldn't perform the request");
    }
}


class Categories extends Database{
    private $db;

    public function __construct(Database $db) {
        $this->db = $db;
    }

    public $category_id = '';
    public $category_name = '';
    public $category_image = '';

    // View Category
    public function ViewCategories() {
        return $this->db->Run("SELECT * FROM categories");
    }   
}

所以用法是:

$connection = new Database("localhost", "raheel", "raheel786", "ecommerce");
$connection->Connect();

$category = new Categories($connection);

注意!我没测试,举个例子吧

【讨论】:

  • 我试过这个,但这样做我的连接链接来自受保护的基类 $_connection;正在返回 null 并且我收到以下错误警告:mysqli_query() 期望参数 1 为 mysqli,第 35 行的 E:\xampplite\htdocs\ecommerce\classes\class.database.php 中给出的 null 无法执行请求
  • 是的。我刚刚回答了你的问题“如何防止调用基类的构造函数”:) 我的答案发生了变化
  • 明白你的意思,但 public function __construct(Database $db) 是什么意思?
  • 表示如果不传递Database对象就会报错。 php.net/manual/en/language.oop5.typehinting.php
  • 非常感谢,这似乎很有用
猜你喜欢
  • 2012-01-25
  • 1970-01-01
  • 2014-02-19
  • 1970-01-01
  • 2018-05-25
  • 2018-03-31
  • 2021-03-14
  • 2016-07-19
相关资源
最近更新 更多