不推荐使用旧函数的旧数据库连接类

时间:2013-09-27 09:33:39

标签: php dbconnection

在一个旧网站(PHP 3)上工作,我需要更新它的代码,特别是这个数据库连接类(mysql_db_query似乎已被弃用):

class db {
var $host; 
var $port;
var $login;
var $pass;
var $data_base;

function db(){
    $this->host = "";
    $this->port = ""; 
    $this->login = "";
    $this->pass = "";
    $this->data_base = "";
}

function connect() {
    return mysql_connect($this->host.':'.$this->port, $this->login, $this->pass);
}

function query( $query ){
    if ( $query )
        return mysql_db_query($this->data_base,$query);
        return mysql_query($query);
    return 0;
}

function close( $link ){
    mysql_close($link);
}
}

有人能告诉我如何更新吗?

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

更新该类的最佳方法是在其旁边创建一个新的IMHO。这将允许您逐步更改代码而不会破坏现有代码(或至少以更加受控的方式)。

您可以首先从现有类中提取接口,然后实现实现相同接口的新类。

使用像PHP Storm这样的IDE最容易做到这一点,但这不是必须的,你也可以手动完成。

首先,您从类db中提取界面,例如DbInterface(在PHPStorm中右键单击类名" db"然后选择Refactor - &gt ;提取 - >接口):

interface DbInterface {
    /**
     * @param $link
     * @return mixed
     */
    function close($link);

    /**
     * @param string $query
     * @return mixed
     */
    function query($query);

    function connect();
}

我还添加了一些缺少的docblock评论。我们还使用db类来实现接口:

class db implements DbInterface {

现在再次测试你的代码,一切都应该没有任何问题。

这个界面已经显示了一些值得注意的缺陷,所以我们以后不会错过它们:

  1. 该类的对象配置了一些代码,这些代码通过公共成员分配数据库配置和凭据,因此有一些其他代码(在您的问题中不可见)。随着数据库客户端库的更改,类的配置方式也可能会发生变化。配置代码也应该被封装,以便可以替换它(例如移动到类或配置对象中)。
  2. close方法需要来自外部的数据库链接。由于类本身控制着连接,因此该链接实际上应该是内部信息。
  3. 此时您可以决定如何继续。我建议你先从2.)开始,然后重构代码以将$link变量拉入其中,而不是将其外部化到类中。但是,也可以进行外部化,它只需要一个新类型,然后作为新接口引入:

    interface DbLinkInterface {
        /**
         * @return mixed
         */
        public function getLink();
    
        /**
         * @return DbInterface
         */
        public function getDatabase();
    
        public function close();
    }
    

    然后这个接口由一个新类实现,该类主要封装有关链接的详细信息:

    class DbLink implements DbLinkInterface
    {
        private $link;
        /**
         * @var DbInterface
         */
        private $db;
    
        public function __construct($link, DbInterface $db) {
            $this->link = $link;
            $this->db = $db;
        }
    
        /**
         * @return mixed
         */
        public function getLink() {
            return $this->link;
        }
    
        /**
         * @return DbInterface
         */
        public function getDatabase() {
            return $this->db;
        }
    
        public function close() {
            $this->db->close($this);
        }
    }
    

    现在进行测试时,您的代码仍应运行完美。每个小步骤后测试。

    接下来的步骤是将此类引入现有类,以便可以将数据库链接作为具体类型传递。此步骤有点危险,因为根据您在其他地方的代码中使用$link的方式,所以事情可能需要更多的更改才能像往常一样运行,因此您需要进行测试。例如,您可以替换

    mysql_something($link);
    

    至少

    mysql_something($link->getLink());
    

    但是你实际上必须从那里删除该功能。因此,更改$link的类型实际上会使所有这些地方都可见。然后将方法添加到DbInterface和/或DbLinkInterface,以便您可以更流利地执行操作:

    $link->something();
    

    但这很大程度上取决于您的代码以及您重构的程度(请参阅链接的重复问题,它建议以不同的方式扫描所有文件,并使用兼容的API自动替换,如果您认为的话)不值得抽象分支。)

    首先,DbLinkInterface引入了DbInterface

    interface DbInterface {
        /**
         * @param DbLinkInterface $link
         * @return void
         */
        function close(DbLinkInterface $link);
    
        ...
    

    这将使现有代码失败,因为db中的接口不满足,然后至少需要进行此更改:

    class db implements DbInterface {
        ...
    
        function close(DbLinkInterface $link) {
            if ($link->getDatabase() instanceof $this) {
                return mysql_close($link->getLink());
            }
    
            throw new InvalidArgumentException('Invalid Link given. Can only close link of my own type.');
        }
    
    }
    

    现在可以再次加载代码,但是在将链接传递到close的位置会出现致命错误。因此,当返回该链接时,类db需要另一个更改:

    class db implements DbInterface {
        ...
    
        function connect() {
            $link = mysql_connect($this->host . ':' . $this->port, $this->login, $this->pass);
            return new DbLink($link, $this);
        }
        ...
    

    当您仅使用链接关闭数据库连接时(因为它看起来有点像),您的整个代码应该再次运行。测试一下就可以了。

    所以现在终于将旧类抽象为两个接口,这将允许您更容易地替换它。这意味着您将添加其他代码,以便旧应用程序仍可以使用旧代码运行,您也可以使用新代码进行测试。您需要做的就是在您使用它的位置进行更改,通常是单个对象实例(变量)。

    现在,您将介绍使用新数据库客户端API的类:

    class db_mysqli extends db implements DbInterface {
        /**
         * @var mysqli
         */
        private $db;
    
        function connect() {
            $this->db = new mysqli($this->host, $this->login, $this->pass, $this->data_base, $this->port);
            return new DbLink($this->db, $this);
        }
    
        function query($query) {
            return $this->db->query($query);
        }
    
        function close(DbLinkInterface $link) {
            if ($link->getDatabase() instanceof $this) {
                return $link->getLink()->close();
            }
    
            throw new InvalidArgumentException('Invalid Link given. Can only close link of my own type.');
        }
    }
    

    您现在可以互换使用此类而不是另一个类,因此出于测试目的而您不需要在整个应用程序中使用它,或者您可以通过脚本或类似方式继续使用脚本。

    正如此示例所示,外部化链接确实会引入需要首先封装的差异。

    因为您不会更改数据库服务器,所以可以保留旧代码的配置和部分内容。

    将您的代码置于版本控制之下,以便您可以轻松地逐步执行此操作,并在您引入错误和/或此处概述的某个概念不适合您的情况下还原。

    我希望这会有所帮助。并记住要做一些小步骤,并考虑如何在不改变旧代码的情况下引入新代码。例如。就像我在这里做的一个新课而不是改变旧班。

    为了使此过程更加健壮,您还可以引入断言,有关详细信息,请参阅Should I be using assert in my PHP code?

答案 1 :(得分:0)

网上有很多关于如何迁移的文章,这是关于课堂的例子:

class db {
var $host; 
var $port;
var $login;
var $pass;
var $data_base;

function db(){
    $this->host = "";
    $this->port = ""; 
    $this->login = "";
    $this->pass = "";
    $this->data_base = "";
}

function connect() {
    $mysqli = new mysqli($this->host, $this->login, $this->pass, $this->data_base, $this->port);

    if( $mysqli->connect_errno )
        return 0;
    else
        return $mysqli;
}

function query( $query ){
    if ( $query )
        return mysqli_query($query);
    return 0;
}

function close( $link ){
    mysqli_close($link);
}
}

这里有一个很棒的源扫描工具,用于将mysql转换为mysqli:
Converting to MySQLi

答案 2 :(得分:-1)

您需要阅读mysqli的文档 - 请参阅http://php.net/manual/en/book.mysqli.php

此库也可以以功能方式使用。大多数对mysql_库的库调用都会在mysqli _

中有类似的调用