当前位置: 首页 > 面试题库 >

如何用PDO代替MySQL函数?

阎晗日
2023-03-14
问题内容

在php.net上阅读有关 MySQL函数的信息时 。我遇到了这个消息

警告此扩展自PHP5.5.0起不推荐使用,以后将被删除。相反,应使用MySQLi或PDO_MySQL扩展。另请参见MySQL:选择API指南和相关的FAQ,以获取更多信息。此功能的替代方法包括:

  • mysqli_connect()

  • PDO :: __ construct()

我已经了解了PDO。如何使用MySQL或MSSQL将代码更新为PDO?


问题答案:

我看到在实现 my_sql函数的 SO上张贴了很多代码。以及其他人(包括我自己)的评论迫使提问者放弃 MySQL功能
并开始使用PDO或MySQLI。这篇文章对您有所帮助。您可以参考它,因为它提供了为什么不推荐使用它们以及什么是 PDO的
解释,以及实现PDO的最少代码示例。

首先:

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

为什么不推荐使用 mysql函数

mysql扩展很古老,自15年前发布(PHP)以来一直存在(!!);与现代PHP试图摆脱过去的不良做法相比,它绝对是另一种野兽。mysql扩展是MySQL的非常原始的低级连接器,它缺少许多便利功能,因此很难以安全的方式正确应用。因此对菜鸟不利。许多开发人员不了解SQL注入,并且mysql
API十分脆弱,即使您知道它,也很难阻止它。它充满了全局状态(例如,通过了隐式连接),这使得编写难以维护的代码变得容易。由于它已经很旧了,因此在PHP核心级别上可能难以合理地维护。

mysqli扩展很新,可以解决上述所有问题。PDO还是相当新的,并且还解决了所有这些问题,以及更多其他问题。

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

如何实施PDO

PDO提供了一种用于连接多个数据库的解决方案。该答案仅涵盖 MySQLMSSQL 服务器。

连接到 MySQL 数据库,先决条件

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

该模块是 php_pdo_mysql.dll

连接到 MSSQL 数据库,先决条件

这是一个更高级的设置。您需要php_pdo_sqlsrv_##_ts.dllphp_pdo_sqlsrv_##_nts.dll drivers。它们是特定于版本的,因此##。在撰写本文时,Microsoft已经发布了PHP
5.5.x的官方驱动程序。5.6驱动程序尚未正式通过微软发布的,但可作为非官方建立由他人。

该模块php_pdo_sqlsrv_##_ts.dll用于线程安全变体该模块php_pdo_sqlsrv_##_nts.dll用于非线程安全变体

使用PDO 连接到数据库要连接到数据库,您需要从 PDO构造中 创建一个 新的PDO实例 。 __

$connection = new PDO(arguments);

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

  1. DSN或 数据源名称 ,通常是一个字符串,其中包含有关驱动程序,主机和数据库名称的信息。从PHP 7.4开始,它还可以包含用户名和密码。
  2. 用户名
  3. 密码
  4. 选件

连接到 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脚本期间执行一次此操作。

您需要在 try-catch子句中
包装PDO实例创建。如果创建失败,将显示向后跟踪,显示有关您的应用程序的重要信息,例如用户名和密码。为了避免这种情况,请捕获错误。

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

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

执行查询

PDO使用 准备好的语句 。这是 PDO的 方法和 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(),使用变量use
prepare()query()会在调用后立即执行。请注意调用(->)的面向对象方式。

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

准备方法

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

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

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

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是一种最多可以包含三个可选参数的方法。它从结果集中获取一行。默认情况下,它返回一个包含列名称作为键和索引结果的 数组
。我们的示例查询可能返回类似

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
获取单个数组中的所有行。使用与相同的默认选项fetch

$rows = $result->fetchAll();

如果您使用的查询未返回诸如插入或更新查询之类的结果,则可以使用该方法rowCount来检索受影响的行数。

一个简单的类:

class pdoConnection {
    public $isConnected;

    protected $connection;

    public function __construct($dsn, $username, $password, $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 PDOException($e->getMessage());
        }
    }

    public function prepare($SQL, $params = array()) {
        try {
            $result = $this->connection->prepare($SQL);
            $result->execute($params);
            return $result;
        } catch (PDOException $e) {
            throw new PDOException($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'];
}


 类似资料:
  • null 我读过PDO的书。如何使用MySQL或MSSQL将代码更新为PDO?

  • 问题内容: 现在,我有一个PHP文件,该文件执行MYSQL查询,然后计算像这样的行: 这可以正常工作,但是我试图将所有PHP文件更改为使用PDO。那么如何用PDO做到这一点呢? 问题答案: 要么 您也可以使用它来询问数据是否存在或被选择: 或使用您的变量:

  • 问题内容: 在这个查询中 我正在尝试将变量与PDO 绑定。不确定最后如何处理。 可不可能是 绑定到哪里 还是会 绑定到哪里 还是会完全不同? 问题答案: 您还可以说: 在MySQL末尾进行字符串连接,并不是在这种情况下有任何特殊原因。 如果要查找的部分本身可以包含百分比或下划线字符(因为这些字符对LIKE运算符具有特殊含义)或反斜杠(MySQL用作LIKE运算符的另一种转义层),则事情会变得更加棘

  • 问题内容: 这是我到目前为止阅读的内容: 由于MySQL的本机准备绕过了查询缓存,因此PDO的准备仿真在性能上更好。 MySQL的本机准备更好地提高了安全性(防止SQL注入)。 MySQL的本机准备更好地用于错误报告。 我不知道这些陈述的真实性。在选择MySQL接口时,我最大的担心是防止SQL注入。第二个问题是性能。 我的应用程序当前使用过程MySQLi(没有准备好的语句),并且大量利用了查询缓存

  • 这是我到目前为止读到的关于的内容: PDO的prepare仿真性能更好,因为MySQL的本机prepare绕过查询缓存。 MySQL的本机prepare在安全性方面更好(防止SQL注入)。 MySQL的本机prepare更适合错误报告。 我不知道这些说法有多真实了。我在选择MySQL接口时最关心的是防止SQL注入。第二个关注点是业绩。 我的应用程序目前使用过程式MySQLi(没有准备好的语句),并

  • 问题内容: 我一直在做的简单连接,: 虽然使用这个我一直使用的简单的方法,使查询之前逃脱的任何数据,不管是,,或者通过使用 现在我知道这在一定程度上是安全的! 它逃脱了危险人物;但是,它仍然容易受到其他攻击的攻击,这些攻击可能包含安全字符,但可能有害于显示数据或在某些情况下恶意修改或删除数据。 因此,我进行了一些搜索,以了解有关PDO,MySQLi和准备好的语句的信息。是的,我可能迟到了游戏,但是