Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 构建一个mysqli数据库连接类,其他类使用它_Php_Oop_Mysqli - Fatal编程技术网

Php 构建一个mysqli数据库连接类,其他类使用它

Php 构建一个mysqli数据库连接类,其他类使用它,php,oop,mysqli,Php,Oop,Mysqli,对于这个愚蠢的问题很抱歉,我是php中oop的新手……我有一个问题,编写一个mysqli类时会返回一个连接处理程序,使我能够在其他类/方法中使用连接处理程序。我运行了一个小程序博客,希望将其转换为oop。 下面是我的工作代码示例。请在必要时为我重构。先谢谢你 $db_link = mysqli_connect(DB,HOST,DB_USER,DB,PASS,DB_NAME) or die(mysql_error()); class myDB extends mysqli { public f

对于这个愚蠢的问题很抱歉,我是php中oop的新手……我有一个问题,编写一个mysqli类时会返回一个连接处理程序,使我能够在其他类/方法中使用连接处理程序。我运行了一个小程序博客,希望将其转换为oop。 下面是我的工作代码示例。请在必要时为我重构。先谢谢你

$db_link = mysqli_connect(DB,HOST,DB_USER,DB,PASS,DB_NAME) or die(mysql_error());
class myDB extends mysqli
{
  public function getConfig($id, $db_link) // thanks cbuckley
 {
   $db_link = $this->db_link;
   $res = mysqli_query($this->db_link,"SELECT * from config where id='1'");
   $row = mysqli_fetch_array($res);
   return $row['option'];
  }    
}
我已经定义了常量,连接成功,但选择不起作用。在索引页上,这是

include('inc/dbc.php'); 
$db = new MyDB(); 
echo $db->getConfig(1, $db_link);  

非常感谢您的帮助

我建议将“连接到数据库”也移动到类中:

class myDB extends mysqli
{
  private $link;

  public function Connect()
  {
    $this->link = mysqli_connect(DB,HOST,DB_USER,DB,PASS,DB_NAME) or die(mysql_error());
  }

  public function getConfig($id) // thanks cbuckley
  {
     $res = mysqli_query($this->link,"SELECT * from config where id='$id'");
     $row = mysqli_fetch_array($res);
     return $row['option'];
   }    
}
然后像这样使用它:

include('inc/dbc.php'); 
$db = new MyDB();
$db->Connect(); 
echo $db->getConfig(1);
$mysqli = new mysqli('localhost', 'root', 'pw', 'my_db');
$config = new Configuration($mysqli);

var_dump($config->get(0));
class DatabaseConnection extends Mysqli
{
    ...

    public function getOption($id) {
        $statement = $this->prepare('SELECT `option` FROM config WHERE id=?');
        $statement->bind_param('i', $id);
        $statement->execute();
        $statement->bind_result($option);
        $statement->fetch();
        $statement->close();
        return $option;
    }

我建议您将mysqli类包装在一个新类中,而不是扩展它: 对于那些需要配置的类,只需包含带有依赖项注入的配置。这给您带来了好处,您需要配置的代码不需要知道配置获取其值的方式。 如果以后决定从INI文件解析配置,只需更改配置类,或者编写一个实现ConfigurationInterface的新类并注入新的ConfigurationClass

class Configuration implements ConfigurationInterface{
        private $mysqli;

        public function construct(mysqli $mysqli) {
            $this->mysqli = $mysqli;
        }

        public function get($key) 
        {
            // You should escape this query to prevent SQL-injection
            $res = $this->mysqli->query("SELECT * from config where id='$key'");
            $row = $res>fetch_array();
            return $row['option'];
        }
    }

interface ConfigurationInterface {
    public get($key);
}
像这样使用它:

include('inc/dbc.php'); 
$db = new MyDB();
$db->Connect(); 
echo $db->getConfig(1);
$mysqli = new mysqli('localhost', 'root', 'pw', 'my_db');
$config = new Configuration($mysqli);

var_dump($config->get(0));
class DatabaseConnection extends Mysqli
{
    ...

    public function getOption($id) {
        $statement = $this->prepare('SELECT `option` FROM config WHERE id=?');
        $statement->bind_param('i', $id);
        $statement->execute();
        $statement->bind_result($option);
        $statement->fetch();
        $statement->close();
        return $option;
    }

你的问题不是很具体,我感觉你还没有真正意识到你的具体问题是什么。您已经接受了一个答案,该答案为您提供了一些代码,但将您带入了错误的方向,因为它无法解决您的根本问题,并且浪费了代码

如果您想利用PHP的mysqli扩展的面向对象接口并从中获益,首先应该知道的是,mysqli类表示数据库连接和链接,因为它已经以过程方法命名:

require('inc/dbc.php');

$dbConnection = new Mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
已经是这样了。确实,您可能希望在此处使用一些错误处理:

if ($dbConnection->connect_error)
{
    throw new Exception(
       sprintf('(#%d) %s', $dbConnection->connect_errorno,
                $dbConnection->connect_error)
    );
}
抛出异常,而不是说die'message'已经完成,因为您可以轻松创建异常处理程序,这样您就可以从一个中心位置向用户显示更有用的响应,而不是处理每个异常错误情况,因为它实际上出现在die所在的位置

您还可以记录并邮寄回溯,以便更轻松地修复问题。当然,您不需要使用异常,但是经验法则是,仅在您在一周内丢弃的脚本中使用die,并且它不适用于面向对象设计

由于您在需要数据库连接的所有地方都需要此代码,因此您可以创建自己的连接对象,将这些部分合并在一起,因为它们属于一起:

class DatabaseException extends Exception
{
}

class DatabaseConnection extends Mysqli
{
    public function __construct($host, $user, $password, $database = "", $port = NULL, $socket = NULL) {

        parent::__construct($host, $user, $password, $database, $port, $socket);

        $this->throwConnectionExceptionOnConnectionError();
    }

    private function throwConnectionExceptionOnConnectionError() {

        if (!$this->connect_error) return;

        $message = sprintf('(%s) %s', $this->connect_errno, $this->connect_error);

        throw new DatabaseException($message);
    }
}
其用法实际上非常简单,非常相似,只是类的名称不同,需要加载其定义:

require('inc/dbc.php');
require('inc/database.php');

$dbConnection = new DatabaseConnection(DB_HOST, DB_USER, DB_PASS, DB_NAME);
如前所述,connection对象已表示您的数据库连接。因此,应用程序中需要它的每个部分都必须请求它。让我们回顾一下您的示例函数:

function getOption($id, $db_link)
{
   // $db_link = $this->db_link;
   $res = mysqli_query($this->db_link,"SELECT * from config where id='1'");
   $row = mysqli_fetch_array($res);
   return $row['option'];
}
我重命名了函数,并对第一行进行了注释,即使这可能是您想要的。实际上,如果该函数是DatabaseConnection对象的一部分,它可以如下工作:

include('inc/dbc.php'); 
$db = new MyDB();
$db->Connect(); 
echo $db->getConfig(1);
$mysqli = new mysqli('localhost', 'root', 'pw', 'my_db');
$config = new Configuration($mysqli);

var_dump($config->get(0));
class DatabaseConnection extends Mysqli
{
    ...

    public function getOption($id) {
        $statement = $this->prepare('SELECT `option` FROM config WHERE id=?');
        $statement->bind_param('i', $id);
        $statement->execute();
        $statement->bind_result($option);
        $statement->fetch();
        $statement->close();
        return $option;
    }
如本例所示,数据库连接已经存在。然而,这是不可取的。想象一下,你不仅有选择,而且还有这个、那个、什么等等等等。您可以在一个类中一个接一个地创建函数。对于一个可能工作正常的小应用程序来说,这很好,但是想象的越来越多。你会得到一个非常大的类,负责很多事情。因此,这样做是不好的,即使您已经可以使用$this来准备语句

还要注意的是,你应该准备陈述。这个问题在这里已经被回答了很多次,如果你不习惯,读一读,这是值得的。有更好的方法可以避免重复代码枯燥:在进入面向对象时不要重复自己,甚至应该已经使用过程化方法来完成

因此,如果要将所有这些都放在一个类中,这将是一个问题,您可以将其放在它自己的类中:

class DatabaseModelBase
{
    protected $connection;

    public function __construct(Connection $connection) {
        $this->connection = $connection;
    }

    protected function prepare($query) {
        $connection = $this->connection;
        $statement = $connection->prepare($query);
        if (!$statement) {
            throw new DatabaseException(
                sprintf('(%s) %s', $connection->error, $connection->errno)
            );
        }
        return $statement;
    }
}

class Option extends DatabaseModelBase
{
    public function find($id) {
        $statement = $this->prepare('SELECT `option` FROM config WHERE id=?');
        $statement->bind_param('i', $id);
        $statement->execute();
        $statement->bind_result($option);
        $statement->fetch();
        $statement->close();

        return $option;
    }
}
这又有一些扩展的错误处理,因为大多数错误都是在SQL查询中发生的。正如您所看到的,获取特定数据的单个函数被放置在它自己的类中。您可以使用这些类对特定数据类型的获取和更新进行分组

使用全文:

$dbConnection = new Connection(DB_HOST, DB_USER, DB_PASS, DB_NAME);

$option = new Option($dbConnection);

$optionValue = $option->find(1);

echo $optionValue; # value for option with ID1
选项对象的名称可能不太好,我试图保持示例的轻量级,但也提供了一些分离。对于其他场景,您可能希望选择某种不同的方式来访问db连接,因为它是通过其构造函数注入Option的,Option不再处理如何创建数据库连接的细节

例如,只有在第一次实际使用准备或查询时才连接到数据库,才能使数据库连接对象更智能。因此 对不需要数据库连接的网站的请求不会不必要地连接到数据库

您可以在其他问题中找到更多示例,您可能希望了解依赖项注入。此外,您总是希望将事物彼此分开,因此您有一些对象彼此之间仅轻轻连接


呜呜……谢谢兄弟,我欠你一个……它工作得很好!!!。。。hpe如果你不介意我们成为朋友,因为我在oop过程中遇到了很多麻烦…非常感谢。这有点复杂,显然没有理由从mysqli扩展myDB类。那你为什么这么做?你不认为这对提出问题的开发人员有误导性吗?阅读OO、搜索封装、关注点分离、可测试代码等。编程是一项严肃的职业。@JvdBerg:当然,但你在这里做的完全相反。这就是我问的真正原因。你的理由是什么?专业精神并非如此。首先,使用Mysqli的过程接口是程序化的,而不是面向对象的。你可以说你把它封装起来了,但是这完全是多余的,因为你从mysqli扩展,使用父级的ctor和$this就可以了,不是吗?然后是可测试代码。数据库配置为全局静态常量,怎么能不发出警告呢?这个名单可以一直列下去。那么你的理由是什么呢?我正试图帮助那些在OO编程中迈出第一步的人!如果你想讨论这个问题,你可以随时提出问题。谢谢你的建议,但我真的不明白你的逻辑。请注意,这是一个php编程范例的新手。请简化您的代码。谢谢,我希望现在更清楚了。。。关于转义,我相信你会在API中找到,我不太了解mysqli,因为我使用PDO而不是headis,你为什么不使用PDO呢?许多PHP用户都在谈论PDO对他们来说更容易使用,它提供了与mysqli和其他类似的功能?只是问一下,我很想知道。嗯……哈克拉,这是对我问题的广泛回答。。非常感谢,我将使用这段代码,并就结果和我可能遇到的任何问题返回给您…谢谢,是的,这有点广泛,我想第二部分有点模糊。这一部分也主要影响了你将如何做/你的风格,我认为第一部分对于了解Mysli OO的基础知识更为重要。它有点广泛,因为我认为你把多个东西放在一起,你认为是问题,甚至可能是一个问题。尽量将问题隔离一点,这通常有助于更容易地找到解决方案。这是伴随实践而来的东西,在编程中永远不会停止,无论你的练习时间长短。再次感谢你,请你给我一个完整的工作班。加入所有必要的函数及其对相应对象的调用…感谢你在下面的示例中创建你自己的连接对象,以将这些部分合并在一起,因为它们属于一起:-这就是整个数据库连接类。而且它也应该起作用,用法示例是最后一个示例。另外请注意,您的常量名称有点误导,我更改了它们。使用起来仍然很混乱..很抱歉我的错误。枯燥的交互非常糟糕,在oop中没有经验..创建自己的连接线后的代码?.我是否在编辑器上复制该代码和paset,使用示例和配置值将返回?