如何用PDO替换MySQL函数?

时间:2015-01-22 18:24:39

标签: php sql pdo

php.net上阅读有关 MySQL功能的内容时。我遇到了这条消息

  

警告   自PHP 5.5.0起,此扩展已弃用,将来将被删除。相反,应该使用MySQLi或PDO_MySQL扩展。另请参阅MySQL:选择API指南和相关的常见问题解答以获取更多信息。该功能的替代方案包括:

     

我读过PDO。如何使用MySQL或MSSQL将代码更新为PDO?

1 个答案:

答案 0 :(得分:15)

我在SO上发布了很多代码来实现 my_sql函数。其他人(包括我自己)的评论迫使提问者放弃 MySQL函数并开始使用PDO或MySQLI。这篇文章是为了帮助。您可以参考它,因为它提供了解释它们被弃用的原因以及 PDO 的内容,以及实现PDO的最小代码示例。

首先:

mysql函数 PDO 的转换不是一个简单的搜索和替换案例。 PDO是一种面向对象的编程,用于PHP语言。 这意味着编写代码的另一种方法与 mysql函数一样。首先转换为什么?

为什么 mysql函数已弃用?

mysql扩展很古老,自从15年前发布的PHP 2.0以来就已存在(!!);这是一个与现代PHP完全不同的野兽,试图摆脱过去的不良做法。 mysql扩展是一个非常原始的,低级别的MySQL连接器,缺少许多便利功能,因此很难以安全的方式正确应用;因此对新手不利。许多开发人员都不了解SQL注入,并且mysql API很脆弱,即使您已经意识到它,也很难阻止它。它充满了全局状态(例如,隐式连接传递),这使得编写难以维护的代码变得容易。由于它已经老了,在PHP核心级别维护可能是不合理的。

mysqli扩展程序更新,修复了上述所有问题。 PDO也是新的,并且解决了所有这些问题,还有更多。

由于这些原因*将来某个时候将删除mysql扩展名。

来源Deceze

如何实施PDO

PDO提供了一种连接多个数据库的解决方案。这个答案仅涵盖 MySQL MSSQL 服务器。

连接 MySQL 数据库,先决条件

这非常简单,并且不需要任何预先设置的PHP。现代PHP安装标准附带一个模块,允许PDO连接到MySQL服务器。

  

模块为php_pdo_mysql.dll

连接 MSSQL 数据库,先决条件

这是一个更高级的设置。您需要php_pdo_sqlsrv_##_ts.dllphp_pdo_sqlsrv_##_nts.dll drivers。它们是版本特定的##。在撰写本文时,微软已经发布了 PHP 5.5.x的官方驱动程序。 5.6的驱动程序尚未由Microsoft正式发布,但可由others以非官方版本的形式提供。

  

对于线程安全变体,模块为php_pdo_sqlsrv_##_ts.dll   对于非线程安全变体

,模块为php_pdo_sqlsrv_##_nts.dll

使用PDO连接到数据库 要连接到数据库,您需要从 PDO构造创建新PDO实例

$connection = new PDO(arguments);

PDO构造函数需要3个必需参数和1个可选参数。

  1. DSN或数据源名称,主要是包含有关驱动程序,主机和数据库名称信息的字符串。
  2. 用户名
  3. 密码
  4. 选项
  5. 连接 MySQL

    $dsn = 'mysql:dbname=databasename;host=127.0.0.1';
    $user = 'dbuser';
    $password = 'dbpass';
    
    $dbh = new PDO($dsn, $user, $password);
    

    让我们看一下$dsn:首先定义驱动程序(mysql)。然后是数据库名称,最后是主机。

    连接 MSSQL

    $dsn = 'sqlsrv:Server=127.0.0.1;Database=databasename';
    $user = 'dbuser';
    $password = 'dbpass';
    
    $dbh = new PDO($dsn, $user, $password);
    

    让我们看一下$dsn:首先定义驱动程序(sqlsrv)。然后是主机,最后是数据库名称。

    创建实例时,将建立与数据库的连接。您只需在执行PHP脚本期间执行一次此操作。

      

    您需要将PDO实例创建包装在 try-catch子句中。如果创建失败,则会显示返回跟踪,显示有关应用程序的关键信息,如用户名和密码。为了避免这种错误。

    try 
    {
        $connection = new PDO($dsn, $user, $password);
    }
    catch( PDOException $Exception ) 
    {   
         echo "Unable to connect to database.";
         exit;
    }
    
      

    要抛出SQL服务器返回的错误,请使用setAttribute将此选项添加到PDO实例:$connection->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

    执行查询

    PDO使用预备语句。这是 PDO&#39> 方法和 mysql函数之间的真正区别。后者非常容易受到 SQL-INJECTION 的影响。一个人会建立一个这样的查询:

    $SQL = 'SELECT ID FROM users WHERE user = '.$username ;
    

    当恶意网站或个人发布用户名injector; DROP TABLE users时。结果将是毁灭性的。您需要通过使用引号转义和封装字符串和变量来证明您的代码。必须这样做 对于每个查询。在较大的网站或维护不良的代码上,拥有允许SQL注入的表单的风险可能会变得非常高。准备好的语句消除了第一层SQL注入的可能性,如上例所示。

    PDO驱动程序充当PHP服务器和数据库服务器之间的中间人,称为数据访问抽象层。它不会重写您的SQL查询,但确实提供了连接到多种数据库类型的通用方法 并为您处理将变量插入查询的过程。 Mysql函数构造了执行PHP代码的查询。使用PDO,查询实际上是在数据库服务器上构建的。

    准备好的SQL示例:

    $SQL = 'SELECT ID, EMAIL FROM users WHERE user = :username';
    

    注意区别;我们在字符串外使用$而不是PHP变量,而是在字符串中使用:引入变量。另一种方式是:

    $SQL = 'SELECT ID, EMAIL FROM users WHERE user = ?';
    

    如何执行实际查询

    您的PDO实例提供了两种执行查询的方法。如果没有变量,则可以使用query(),变量使用prepare()query()会在通话时立即执行。请注意面向对象的通话方式(->)。

    $result = $connection->query($SQL);
    

    准备方法

    prepare方法有两个参数。第一个是SQL字符串,第二个是Array形式的选项。一个基本的例子

    $connection->prepare($SQL, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
    

    在我们的SQL字符串示例中,我们使用了一个名为:username的命名变量。我们仍然需要将PHP变量,整数或字符串绑定到它。我们可以通过两种方式做到这一点。构建包含命名变量key的Array或使用方法bindParambindValue。 为简单起见,我将解释数组变体和方法bindValue

    Array
    您可以对命名变量执行类似的操作,将变量作为数组键提供:

    $queryArguments = Array(':username' => $username);
    

    这对于索引变量(?):

    $queryArguments = Array($username);
    

    添加了所需的所有变量后,可以调用方法execute()来执行查询。从而将数组作为参数传递给函数execute

    $result = $connection->execute($queryArguments);
    

    bindValue
    bindValue 方法允许您将值绑定到 PDO实例。该方法需要两个必需参数和一个可选参数。可选参数设置值的数据类型。

    对于命名变量:

    $connection->bindValue(':username', $username);
    

    对于索引变量:

    $connection->bindValue(1, $username);
    

    将值绑定到实例后,可以调用execute而不传递任何参数。

    $result = $connection->execute();
    
      

    注意:您只能使用一次命名变量!使用它们两次将导致无法执行查询。根据您的设置,这将会或不会引发错误。

    获取结果

    同样,我将仅介绍从返回集中获取结果的基础知识。 PDO是一个相当高级的补充。

    使用fetchfetchAll

    如果您执行选择查询或执行了返回结果集的存储过程

    fetch
    fetch是一种最多可以使用三个可选参数的方法。它从结果集中获取单行。默认情况下,它返回一个 Array ,其中包含列名作为键和索引结果。 我们的示例查询可以返回类似

    的内容
    ID      EMAIL
    1       someone@example.com
    

    fetch会将此返回为:

    Array
    (
        [ID] => 1
        [0] => 1
        [EMAIL] => someone@example.com
        [1] => someone@example.com
    )
    

    回显结果集的所有输出:

    while($row = $result->fetch())
    {
        echo $row['ID'];
        echo $row['EMAIL'];
    }
    

    您可以在此处找到其他选项:fetch_style;

    fetchAll
    获取一个Array对象中的所有行。使用与fetch相同的默认选项。

    $rows = $result->fetchAll();
    

    如果您使用的查询没有像插入或更新查询那样返回结果,则可以使用rowCount方法检索受影响的行数。

    一个简单的课程:

    class pdoConnection
    {
        public $isConnected;
        protected $connection;
        public function __construct($dsn, $username, $password, $host, $dbname, $options=array())
        {
            $this->isConnected = true;
            try { 
                $this->connection = new PDO($dsn, $username, $password, $options); 
                $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                $this->connection->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); //sets the default to return 'named' properties in array.
            } 
            catch(PDOException $e) { 
                $this->isConnected = false;
                throw new Exception($e->getMessage());
            }
        }
    
        public function Disconnect(){
            $this->connection = null;
            $this->isConnected = false;
        }
    
        public function query($SQL)
        {
            try
            { 
                $result = $this->connection->query($SQL); 
                return $result;  
            }
            catch(PDOException $e)
            {
                throw new Exception($e->getMessage());
            }
        }
        public function prepare($SQL, $params=array())
        {
            try
            { 
                $result = $this->connection->prepare($SQL); 
                $result->execute($params);
                return $result;     
            }
            catch(PDOException $e)
            {
                throw new Exception($e->getMessage());
            }       
        }
    }
    

    使用方法:

    $dsn = 'mysql:dbname=databasename;host=127.0.0.1';
    $user = 'dbuser';
    $password = 'dbpass';
    
    $db = new pdoConnection($dsn, $user, $password);
    
    $SQL = 'SELECT ID, EMAIL FROM users WHERE user = :username';
    $result = $db->prepare($SQL, array(":username" => 'someone'));
    
    while($row = $result->fetch())
    {
        echo $row['ID'];
        echo $row['EMAIL'];
    }