【问题标题】:Extending a class from the class which is extended from mysqli从 mysqli 扩展的类扩展一个类
【发布时间】:2011-02-22 22:24:03
【问题描述】:

我不确定这是否可行,因为我还不太擅长 OOP 编程。

我有这个从 mysqli 扩展的 db 类,

class database extends mysqli
{
    # overwrite parent __construct
    public function __construct($hostname = null,$username = null,$password = null,$database = null,$port = null, $socket = null)
    {
        $hostname = $hostname !== null ? $hostname : ini_get("mysqli.default_host");
        $username = $username !== null ? $username : ini_get("mysqli.default_user");
        $password = $password !== null ? $password : ini_get("mysqli.default_pw");
        $database = $database !== null ? $database : "";
        $port     = $port     !== null ? $port     : ini_get("mysqli.default_port");
        $socket   = $socket   !== null ? $socket   : ini_get("mysqli.default_socket");

        parent::__construct($hostname,$username,$password,$database,$port,$socket);

        # check if connect errno is set
        if (mysqli_connect_errno()) 
        {
            throw new RuntimeException('Cannot access database: ' . mysqli_connect_error());
        }

    }


    # fetches all result rows as an associative array, a numeric array, or both
    # mysqli_fetch_all (PHP 5 >= 5.3.0)
    public function fetch_all($query) 
    {
        $result = parent::query($query);
        if($result) 
        {
            # check if mysqli_fetch_all function exist or not
            if(function_exists('mysqli_fetch_all')) 
            {
                # NOTE: this below always gets error on certain live server
                # Fatal error: Call to undefined method mysqli_result::fetch_all() in /.../class_database.php on line 28
                return $result->fetch_all(MYSQLI_ASSOC);
            }

            # fall back to use while to loop through the result using fetch_assoc
            else
            {
                while($row = $result->fetch_assoc())
                {
                    $return_this[] = $row;
                }

                if (isset($return_this))
                {
                    return $return_this;
                }
                else
                {
                    return false;
                }
            }
        }
        else
        {
            return self::get_error();
        }
    }

    # fetch a result row as an associative array
    public function fetch_assoc($query)
    {
        $result = parent::query($query);
        if($result) 
        {
            return $result->fetch_assoc();
        } 
        else
        {
            # call the get_error function
            return self::get_error();
            # or:
            # return $this->get_error();
        }
    }

    public function query($query)
{
    $result = $this->query($query);
    if($result) 
    {
        return $result;
    }
    else
    {
        return $this->get_error();
    }

}

    ...

    # display error
    public function get_error() 
    {
        if($this->errno || $this->error)
        {
            return sprintf("Error (%d): %s",$this->errno,$this->error);
        }
    }

    public function __destruct()
    {
       parent::close();
        //echo "Destructor Called";
    }
}

我有这种程序风格的代码,我想把它变成一个从上面的数据库类扩展的类,

if(isset($_REQUEST['search'])) $search = $_REQUEST['search'];

$sql = "
SELECT *

FROM root_pages

WHERE root_pages.pg_cat_id = '2'
AND root_pages.parent_id != root_pages.pg_id
AND root_pages.pg_hide != '1'
AND root_pages.pg_url != 'cms'
AND root_pages.pg_content_1 LIKE '%".$search."%'
OR root_pages.pg_content_2 LIKE '%".$search."%'

AND root_pages.pg_content_1 NOT LIKE '%http://%'
AND root_pages.pg_content_2 NOT LIKE '%http://%'

ORDER BY root_pages.pg_created DESC
";

$items = $connection->fetch_all($sql);
$total_item = $connection->num_rows($sql);

所以我认为,理论上我可以将此代码扩展为这样的类,

class search extends database
{

public $search = null;

public function __construct($keyword)
{
   $this->search = $keyword;    
}


public function get_result()
{
$sql = "
SELECT*

FROM root_pages

WHERE root_pages.pg_cat_id = '2'
AND root_pages.parent_id != root_pages.pg_id
AND root_pages.pg_hide != '1'
AND root_pages.pg_url != 'cms'
AND root_pages.pg_content_1 LIKE '%".$this->search."%'
OR root_pages.pg_content_2 LIKE '%".$this->search."%'

AND root_pages.pg_content_1 NOT LIKE '%http://%'
AND root_pages.pg_content_2 NOT LIKE '%http://%'

ORDER BY root_pages.pg_created DESC
";

$items = parent::fetch_all($sql);

return $items;
  }
}

然后我调用搜索的对象,

$output = new search('1');
print_r($output->get_result());

但我得到了很多错误,

警告:mysqli::query() [mysqli.query]:无法获取搜索 在 C:\wamp\www\xxx\class_database.php 在第 xx 行

警告:数据库::get_error() [database.get-error]:无法获取 搜索 C:\wamp\www\xxx\class_database.php 上 第 xx 行

警告:mysqli::close() [mysqli.close]:无法获取搜索 在 C:\wamp\www\xxx\class_database.php 在第 xx 行

我做错了什么?我该如何解决?

谢谢。

编辑:

当我尝试以这种方式从父类(数据库)调用子类(搜索)时,

$database = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME);
print_r(search::get_result());

然后我得到这个错误,

致命错误:非静态方法 mysqli::query() 不能被调用 静态地 C:\wamp\www\xxx\class_database.php 上 线

叹息...

有什么想法吗?

【问题讨论】:

    标签: php oop class mysqli


    【解决方案1】:

    因为search类中的search属性是非静态的,所以你必须先实例化一个对象:

    $database = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME);
    $search = new search("search term");
    print_r($search->get_result());
    

    也许已经阅读了关于 PHP 中 OOP 的基本教程,这是来自 Google 的第一篇:

    http://www.killerphp.com/tutorials/object-oriented-php/

    编辑:在您的 database 类中还有一些对 self::get_error(); 的调用,这些应该被重写为实例方法而不是类方法:

    $this->get_error()

    【讨论】:

      【解决方案2】:

      您在database 类中使用错误的方法调用mysqli 类的方法。

      您只想在访问静态方法、静态属性、常量或您正在覆盖的当前方法的父级时使用双冒号 ::。 mysqli 类中的所有方法都不是静态的,尽管 php 手册如何在方法列表中使用 :: 列出它们。

      您在__construct() 中使用parent::__construct() 的方式是正确的,因为您处于要覆盖的父级的当前方法中。

      但在您的其他方法中,您想使用$this-> 来引用其他父方法。

      fetch_all()fetch_assoc() 中使用$this->query() 而不是parent::query()

      __destruct() 中,请改用$this->close();

      当您使用self::get_error(); 时,您可能希望将其更改为$this-> 或修改您的函数定义以使其像public static function get_error() 那样静态化

      【讨论】:

      • 谢谢。我刚刚更改了它们并测试了课程,但这次我收到了这个错误:Fatal error: Maximum function nesting level of '100' reached, aborting! in C:\wamp\www\xx\class_database.php on line 385
      • 第 385 行引用此代码,位于 database 类:public function query($query) { $result = $this->query($query); if($result) { return $result; } else { return $this->get_error(); } }
      • 你会想在那里使用parent::query(),因为你覆盖父query()的函数。
      【解决方案3】:

      我认为从database 类扩展类可能是个坏主意...

      这是我的解决方案:

      class search
      {
      
          public $mysqli = null;
      
          public function __construct($mysqli)
          {
             $this->mysqli = $mysqli;
          }
      
          public function get_result($parameter)
          {
              $sql = "
              SELECT *
              FROM root_contacts_cfm
              WHERE root_contacts_cfm.cnt_id = '".$parameter."'
              ORDER BY cnt_id DESC
              ";
      
              $item = $this->mysqli->fetch_assoc($sql);
              return $item;
          }
      }
      

      将对象database 类传递给search 类,这样我就可以这样调用这个搜索类:

      $mysqli = new database(DB_HOST,DB_USER,DB_PASS,DB_NAME);
      $output = new search($mysqli);
      print_r($output->get_result('1'));
      

      我说的对吗...?

      【讨论】:

        猜你喜欢
        • 2010-12-21
        • 2013-08-30
        • 2013-07-18
        • 1970-01-01
        • 2011-01-29
        • 1970-01-01
        • 2017-03-26
        • 2017-03-28
        • 2020-02-06
        相关资源
        最近更新 更多