gpt4 book ai didi

php - PDO 连接和抽象类

转载 作者:可可西里 更新时间:2023-11-01 00:58:56 25 4
gpt4 key购买 nike

我在 PDO 中使用抽象类。我想知道是否有必要每次都清空 $conn 变量,或者它是否在脚本结束时自行清空?

您能否也告诉我,对于这种类型的结构,使 $conn 无效的最佳方法是什么?

abstract class DB_Connection
{
protected static $tbl_admin = "prof_admin";
//protected static $tbl_admin = "prof_admin";

protected static function obj_db()
{
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "salmanshahid";
$conn = null;

try
{
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $conn;
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
}
protected static function select($query)
{
try
{
$conn = self::obj_db();
$stmt = $conn->prepare($query);
$stmt->execute();

// set the resulting array to associative
$stmt->setFetchMode(PDO::FETCH_ASSOC);
return $stmt->fetchAll();
}
catch(PDOException $e)
{
throw new Exception("Error In SELECT STATMENT: " . $e->getMessage());
}
}
protected static function insert($query)
{
try
{
$conn = self::obj_db();
$stmt = $conn->prepare($query);
$stmt->execute();
}
catch(PDOException $e)
{
throw new Exception("Error In INSERT STATMENT: " . $e->getMessage());
}
}

}

最佳答案

or if it does so itself when the scripts ends?

是的,当然,PHP 会自动关闭并清理所有在脚本执行期间打开的资源,所以,不用担心手动关闭它。

无论如何,要使 conn 无效,只需将其无效:$this->conn = NULL;

但是与你类(class)的其他问题相比,所有这些东西都是完全可以忽略不计的,这些问题是不安全的、低效的和不可用的。

  • 首先,我不知道您为什么要将此类抽象化。抽象类是原型(prototype)类,曾经是其他类的来源。但是数据库包装器是一个随时可用的最终类。我认为将其抽象化没有意义。
  • 错误报告也是多余且不一致的。在错误消息中添加“Error In SELECT STATMENT”是毫无用处的。虽然连接错误处理显然是错误的。相反,让 PDO 抛出异常并让它过去。它的处理方式与您网站中的任何其他错误相同。
  • 下一个问题是安全性。由于某些原因,select()insert() 函数都不支持准备好的语句,这使它们变得毫无用处:您可以使用 PDO::query () 相反,结果完全相同。但是您真正需要的是正确使用准备/执行,方法是在查询中使用占位符,同时将实际变量发送到 execute();
  • 另一个问题是重复代码:两个函数几乎相同。
  • 同时这两个函数都非常不可靠:select() 函数仅限于一种类型的结果集,而 insert() 不返回任何东西。相反,您可以只使用一个函数来运行所有查询,并让它返回语句,这将非常有用。它可以让您获得 PDO 支持的几十种不同格式的返回数据,甚至可以让您从 DML 查询中获得受影响的行数

让我建议您另一种方法,一个简单的 PDO 包装器,可以让您以最简单和安全的方式使用 PDO:

<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_CHAR', 'utf8');

class DB
{
protected static $instance = null;

public function __construct() {}
public function __clone() {}

public static function instance()
{
if (self::$instance === null)
{
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => TRUE,
);
$dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHAR;
self::$instance = new PDO($dsn, DB_USER, DB_PASS, $opt);
}
return self::$instance;
}

public static function __callStatic($method, $args)
{
return call_user_func_array(array(self::instance(), $method), $args);
}

public static function run($sql, $args = [])
{
$stmt = self::instance()->prepare($sql);
$stmt->execute($args);
return $stmt;
}
}

它非常强大、安全且易于使用。

您可以使用任何 PDO 函数,只需在 DB:: 前缀之后添加它的调用即可:

$stmt = DB::query("SELECT * FROM table WHERE foo='bar'");

因此,首先,它是一个PDO 包装器,它能够通过使用神奇的__call() 方法运行任何PDO 方法。我添加的唯一函数是 run()

我建议您使用一个通用的 run() 方法,而不是您自己的不安全和不可靠的 select()insert() 方法方法,无非是这三行的简写:

$stmt = DB::prepare($query);
$stmt->execute($params);
$data = $stmt->fetch();

因此,您可以将其写成简洁的单行代码:

$data = DB::run($query, $params)->fetch();

请注意,它可以运行任何 类型的查询并以 PDO 支持的任何格式返回结果。

我写了一篇关于这个简单包装器的文章,您可以在其中找到一些使用示例。所有示例代码都可以按原样运行,只需将其复制并粘贴到您的脚本中并设置凭据:http://phpdelusions.net/pdo/pdo_wrapper#samples

关于php - PDO 连接和抽象类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33067214/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com