PHP PDO 关闭连接设置为 null 但 return 语句
PHP PDO close connection set to null but return statement
我创建了一个连接到数据库的 class。然后,所有其他 classes 都可以使用此 class 中的连接函数打开与数据库的连接。在函数的最后,我 return 结果。那么在 return 编辑结果后如何关闭连接?
<?php
class DbhPdo {
private $servername;
private $username;
private $pwd;
private $dbname;
protected function connect() {
$this->servername = "localhost";
$this->username = "someUser";
$this->pwd = "somePswd";
$this->dbname = "someDB";
$this->charset = "utf8mb4";
try{
$dsn = "mysql:host=" . $this->servername . ";dbname=" . $this->dbname . ";charset=" . $this->charset;
$pdo = new PDO($dsn, $this->username, $this->pwd);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
} catch(PDOException $e) {
echo "Message: " . $e->getMessage();
}
}
}
如果我在 return 之后设置以下内容,则永远不会调用它来关闭连接:
$pdo = null;
或者 PDO 是否自动关闭此连接,因为它在 - return $pdo 之后执行完命令?
或者我是否必须关闭扩展连接的 class 中的连接?
下面是扩展前面提到的class的class,但是我return也在这个class中计算结果,所以我无法设置stmt 在此处为空:
<?php
require_once('dbh.pdo.inc.php');
class LoginPdo extends DbhPdo {
public $name;
public $pass1;
public $hashed;
public $salted;
protected function getSomething($name) {
try{
$stmt = $this->connect()->query("select something from table where name ='" . $name . "'");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}catch (PDOException $e){
echo 'Message: ' . $e->getMessage();
}
}
}
这还剩下开始这个的原始 class:
try{
$this->result = $this->getSomething($this->name);
echo json_encode($this->result);
$this->result = null;
}catch (PDOException $e){
echo 'Message: ' . $e->getMessage();
}
设置 $this->result = null 是否要关闭连接?如果是这样,那我就不明白了。有人可以向我解释吗?或者我在设置 $pdo = null 时是否正确理解它是我需要关闭连接的地方?
如果是这样,那么在执行 return $pdo 后如何将其设置为空?
提前致谢
更新:
以防万一其他人希望能够验证连接是否已关闭,这些是我为确认@Don'tPanic 评论以跟踪一般日志文件而采取的步骤:
mysql -u root -p
show variables like '%log%';
set global general_log=ON;
tail -f /usr/local/mysql/data/<your log file's name>.log
然后显示连接,因为我使用 PostMan post 以下查询立即打开和关闭:
190130 11:00:17 2581 Query show variables like '%log%'
190130 11:02:14 2582 Connect root@localhost on <table name>
2582 Query select * from something where name ='whatever'
2582 Quit
这是通过按照@Don'tPanic 的回答在 DbhPdo class 中添加一个新函数来完成的:
protected function disconnect() {
$this->pdo = null;
}
然后我添加了$this->pdo = null;在 echo json_encode($this->result);
之后
谢谢大家的评论
您的 PDO API 实例是 return 从 $this->connect()
编辑而来的。这是您使用的唯一实例。如果你想保存状态供以后使用或关闭它,你可以使用:
$stmt = ($con =& $this->connect())->query(...);
$con = null; # Or use the instance else where
return $stmt->fetchAll(PDO::FETCH_ASSOC);
如果 PDOPrepareStatement
通过引用使用 PDO
实例,您可以使用 clone
复制实例而不是写入实例。
$stmt = ($con =& clone $this->connect())->query(...);
你的 $stmt
变量是一个 PDOPrepareStatement
因为 PDO::query
不是 return PDO
实例所以你已经设置了它为空。
注意事项:如果要构建模型,您应该考虑设计单例方法。你可以看看example I made for Laravel
trait Singleton
{
private static $instance;
public static function getInstance()
{
return self::$instance ?? (self::$instance = new self());
}
//
}
然后你就可以创建你的超级模特了:
class Model
{
use Singleton;
protected $pdo;
public function __construct()
{
// instance your PDO
}
public function select()
{
// super method all models can use
}
}
然后创建您的模型!
class UserModel extends Model
{
public function find($id)
{
return $this->select(...)->fetch();
}
}
你可以这样使用它:
UserModel::getInstance()
->find(1);
将结果设置为空不会将连接设置为空。
可能确实没有必要显式关闭连接,但如果您希望能够做到这一点,则需要有一些可以设置为 null 的东西。您必须对连接有一些引用,并且您当前的方法不会将该引用存储在任何地方。将连接定义为 class 的 属性 将为您处理。
我修改了你的连接函数来展示一个例子。
基本上不只是 return 建立连接,而是检查现有连接和 return 连接,如果尚未建立连接,则建立新连接,但重要的部分是您设置 属性 $this->pdo
而不是使用仅存在于连接函数范围内的 $pdo
变量。
// ...
private $pdo;
protected function connect() {
// I suggest setting these in the constructor rather than hard coding them here
// $this->servername = "localhost";
// $this->username = "someUser";
// $this->pwd = "somePswd";
// $this->dbname = "someDB";
// $this->charset = "utf8mb4";
if ($this->pdo) {
return $this->pdo;
else {
try{
$dsn = "mysql:host=" . $this->servername . ";dbname=" . $this->dbname . ";charset=" . $this->charset;
$this->pdo = new PDO($dsn, $this->username, $this->pwd);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->pdo;
} catch(PDOException $e) {
echo "Message: " . $e->getMessage();
}
}
}
设置 $this->pdo
而不是仅在连接函数中使用局部变量将为您提供一些可以设置为 null 以断开连接的内容。
protected function disconnect() {
$this->pdo = null;
}
您可以在执行完请求所需的所有查询后调用disconnect()
。如果在此之前断开连接,则必须重新连接到 运行 个额外的查询,这是不必要的,并且会损害应用程序的性能。
我创建了一个连接到数据库的 class。然后,所有其他 classes 都可以使用此 class 中的连接函数打开与数据库的连接。在函数的最后,我 return 结果。那么在 return 编辑结果后如何关闭连接?
<?php
class DbhPdo {
private $servername;
private $username;
private $pwd;
private $dbname;
protected function connect() {
$this->servername = "localhost";
$this->username = "someUser";
$this->pwd = "somePswd";
$this->dbname = "someDB";
$this->charset = "utf8mb4";
try{
$dsn = "mysql:host=" . $this->servername . ";dbname=" . $this->dbname . ";charset=" . $this->charset;
$pdo = new PDO($dsn, $this->username, $this->pwd);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
} catch(PDOException $e) {
echo "Message: " . $e->getMessage();
}
}
}
如果我在 return 之后设置以下内容,则永远不会调用它来关闭连接:
$pdo = null;
或者 PDO 是否自动关闭此连接,因为它在 - return $pdo 之后执行完命令?
或者我是否必须关闭扩展连接的 class 中的连接?
下面是扩展前面提到的class的class,但是我return也在这个class中计算结果,所以我无法设置stmt 在此处为空:
<?php
require_once('dbh.pdo.inc.php');
class LoginPdo extends DbhPdo {
public $name;
public $pass1;
public $hashed;
public $salted;
protected function getSomething($name) {
try{
$stmt = $this->connect()->query("select something from table where name ='" . $name . "'");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}catch (PDOException $e){
echo 'Message: ' . $e->getMessage();
}
}
}
这还剩下开始这个的原始 class:
try{
$this->result = $this->getSomething($this->name);
echo json_encode($this->result);
$this->result = null;
}catch (PDOException $e){
echo 'Message: ' . $e->getMessage();
}
设置 $this->result = null 是否要关闭连接?如果是这样,那我就不明白了。有人可以向我解释吗?或者我在设置 $pdo = null 时是否正确理解它是我需要关闭连接的地方?
如果是这样,那么在执行 return $pdo 后如何将其设置为空?
提前致谢
更新: 以防万一其他人希望能够验证连接是否已关闭,这些是我为确认@Don'tPanic 评论以跟踪一般日志文件而采取的步骤:
mysql -u root -p
show variables like '%log%';
set global general_log=ON;
tail -f /usr/local/mysql/data/<your log file's name>.log
然后显示连接,因为我使用 PostMan post 以下查询立即打开和关闭:
190130 11:00:17 2581 Query show variables like '%log%'
190130 11:02:14 2582 Connect root@localhost on <table name>
2582 Query select * from something where name ='whatever'
2582 Quit
这是通过按照@Don'tPanic 的回答在 DbhPdo class 中添加一个新函数来完成的:
protected function disconnect() {
$this->pdo = null;
}
然后我添加了$this->pdo = null;在 echo json_encode($this->result);
之后谢谢大家的评论
您的 PDO API 实例是 return 从 $this->connect()
编辑而来的。这是您使用的唯一实例。如果你想保存状态供以后使用或关闭它,你可以使用:
$stmt = ($con =& $this->connect())->query(...);
$con = null; # Or use the instance else where
return $stmt->fetchAll(PDO::FETCH_ASSOC);
如果 PDOPrepareStatement
通过引用使用 PDO
实例,您可以使用 clone
复制实例而不是写入实例。
$stmt = ($con =& clone $this->connect())->query(...);
你的 $stmt
变量是一个 PDOPrepareStatement
因为 PDO::query
不是 return PDO
实例所以你已经设置了它为空。
注意事项:如果要构建模型,您应该考虑设计单例方法。你可以看看example I made for Laravel
trait Singleton
{
private static $instance;
public static function getInstance()
{
return self::$instance ?? (self::$instance = new self());
}
//
}
然后你就可以创建你的超级模特了:
class Model
{
use Singleton;
protected $pdo;
public function __construct()
{
// instance your PDO
}
public function select()
{
// super method all models can use
}
}
然后创建您的模型!
class UserModel extends Model
{
public function find($id)
{
return $this->select(...)->fetch();
}
}
你可以这样使用它:
UserModel::getInstance()
->find(1);
将结果设置为空不会将连接设置为空。
可能确实没有必要显式关闭连接,但如果您希望能够做到这一点,则需要有一些可以设置为 null 的东西。您必须对连接有一些引用,并且您当前的方法不会将该引用存储在任何地方。将连接定义为 class 的 属性 将为您处理。
我修改了你的连接函数来展示一个例子。
基本上不只是 return 建立连接,而是检查现有连接和 return 连接,如果尚未建立连接,则建立新连接,但重要的部分是您设置 属性 $this->pdo
而不是使用仅存在于连接函数范围内的 $pdo
变量。
// ...
private $pdo;
protected function connect() {
// I suggest setting these in the constructor rather than hard coding them here
// $this->servername = "localhost";
// $this->username = "someUser";
// $this->pwd = "somePswd";
// $this->dbname = "someDB";
// $this->charset = "utf8mb4";
if ($this->pdo) {
return $this->pdo;
else {
try{
$dsn = "mysql:host=" . $this->servername . ";dbname=" . $this->dbname . ";charset=" . $this->charset;
$this->pdo = new PDO($dsn, $this->username, $this->pwd);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->pdo;
} catch(PDOException $e) {
echo "Message: " . $e->getMessage();
}
}
}
设置 $this->pdo
而不是仅在连接函数中使用局部变量将为您提供一些可以设置为 null 以断开连接的内容。
protected function disconnect() {
$this->pdo = null;
}
您可以在执行完请求所需的所有查询后调用disconnect()
。如果在此之前断开连接,则必须重新连接到 运行 个额外的查询,这是不必要的,并且会损害应用程序的性能。