为每个方法调用处理声明文件中的 PHP 个对象
Handle PHP objects on declaration file for every method call
我正在寻找一种方法来构建处理程序或编辑 php 对象,以下是 mysqli 的示例
我的系统有很多文件,在变量中使用 mysqli 对象
$my_var=new mysqli($host, $user, $pass, $base);
Files 调用它进行查询并得到如下结果:
$q=$my_var->query("SELECT * FROM table");
$q->fetch_assoc();
如果查询出错,$my_var->error
将填充在第一行,并在第二行抛出错误 500。
我正在寻找一种方法来为 $my_var->error
构建处理程序并在调用任何 fetch_* 方法之前抛出错误,因此,
有什么方法可以为 $my_var->error
构建 handler/listener 吗?
如果这不可能,有什么方法可以覆盖 mysqli fetch_assoc()
、fetch_row() 和 fetch_array() 方法来检查 $my_var->error
是否为真并在继续之前显示错误?
我知道 try{}catch()
、throw new Exception
和 or die()
方法,但这些方法意味着要编辑系统中的每个 fetch_*,我只想编辑连接文件.
谢谢!
---编辑中---
我认为准备好的语句不是我要找的。
---编辑2---
不,我不是在寻找如何获取 mysqli 错误。
感谢fyrye的帮助!
---回答最终代码---
class mysqli2{
private $c;
function __construct(...$args){ // open connection
$this->c=new mysqli(...$args);
if(!empty($this->c->error)){ // check for errors
echo("<script>console.error(\"MySQL: ".$this->c->error."\");</script>");
}
}
function query($query, $resultmode = MYSQLI_STORE_RESULT){
$r=$this->c->query($query, $resultmode); // make query
if(!empty($this->c->error)){ // check for errors
echo("<script>console.error(\"MySQL: ".$this->c->error."\");</script>");
}
return $r; // returns query results
}
function __call($method, $args){ // calls others mysqli methods
return $this->c->$method(...$args);
}
function __get($name){ // get all the properties
return $this->c->$name;
}
function __set($name, $value){ // set all the properties
if (property_exists($this->c, $name))$this->c->$name = $value;
}
}
为了提出最佳实践,在使用 PDO 或 MySQLi 扩展时,建议始终检查任何可用方法的 return 结果,然后再继续使用依赖其结果的方法.
As mysqli::query
returns false
on an error,在使用fetch_assoc
之前应该检查它,而不是假设它不是false
。这同样适用于使用 fetch_assoc
,因为它可以 return NULL
;
if (!$q = $my_var->query($sql)) {
//something went wrong - handle the error here.
}
if ($data = $q->fetch_assoc()) {
echo $data['column'];
}
然而,正如我所建议的,您需要创建一个抽象层。
由于 $q
出错时会是 false
,因此您问题中代码的异常是:
Fatal error: Call to a member function fetch_assoc() on boolean
意味着您将无法重写 fetch_*
方法,而不重写 mysqli::query
以始终 return 一个对象。
请不要在生产代码中使用。
这只是一个示例,说明如何用您自己的方法覆盖 mysqli::query
方法。您还需要覆盖所有其他 mysqli::***
methods,例如 prepare
、commit
等
示例https://3v4l.org/PlZEs
class Conn
{
private $conn;
public function __construct(...$args)
{
$this->conn = new mysqli(...$args);
}
public function query($query, $resultmode = \MYSQLI_STORE_RESULT)
{
$d = $this->conn->query($query, $resultmode);
if (!empty($this->conn->error)) {
throw new \RuntimeException($this->conn->error);
}
return $d;
}
}
//Your connection code
$con = 'my_var';
$$con = new Conn('host', 'user', 'pass', 'base');
//example usage of valid query
$q = $my_var->query('Valid Query');
$q->fetch_assoc();
//example use of invalid query throwing an exception before `fetch_assoc`
$q = $my_var->query('This is not valid');
$q->fetch_assoc();
结果
I was successful
-----
Fatal error: Uncaught exception 'RuntimeException' with message 'Expected "Valid Query"' in /in/PlZEs:51
Stack trace:
#0 /in/PlZEs(70): Conn->query('This is not val...')
#1 {main}
thrown in /in/PlZEs on line 51
此方法使用 PHP 5.6 argument packing and unpacking 来匹配函数调用参数,以避免必须手动定义它们。
可以对此进行扩展以将消息写入日志文件、发送电子邮件、触发事件或显示友好的错误消息而不是抛出异常。以及用您自己的 Statement
对象覆盖 mysqli_stmt
响应。
我正在寻找一种方法来构建处理程序或编辑 php 对象,以下是 mysqli 的示例
我的系统有很多文件,在变量中使用 mysqli 对象
$my_var=new mysqli($host, $user, $pass, $base);
Files 调用它进行查询并得到如下结果:
$q=$my_var->query("SELECT * FROM table");
$q->fetch_assoc();
如果查询出错,$my_var->error
将填充在第一行,并在第二行抛出错误 500。
我正在寻找一种方法来为 $my_var->error
构建处理程序并在调用任何 fetch_* 方法之前抛出错误,因此,
有什么方法可以为 $my_var->error
构建 handler/listener 吗?
如果这不可能,有什么方法可以覆盖 mysqli fetch_assoc()
、fetch_row() 和 fetch_array() 方法来检查 $my_var->error
是否为真并在继续之前显示错误?
我知道 try{}catch()
、throw new Exception
和 or die()
方法,但这些方法意味着要编辑系统中的每个 fetch_*,我只想编辑连接文件.
谢谢!
---编辑中---
我认为准备好的语句不是我要找的。
---编辑2---
不,我不是在寻找如何获取 mysqli 错误。
感谢fyrye的帮助!
---回答最终代码---
class mysqli2{
private $c;
function __construct(...$args){ // open connection
$this->c=new mysqli(...$args);
if(!empty($this->c->error)){ // check for errors
echo("<script>console.error(\"MySQL: ".$this->c->error."\");</script>");
}
}
function query($query, $resultmode = MYSQLI_STORE_RESULT){
$r=$this->c->query($query, $resultmode); // make query
if(!empty($this->c->error)){ // check for errors
echo("<script>console.error(\"MySQL: ".$this->c->error."\");</script>");
}
return $r; // returns query results
}
function __call($method, $args){ // calls others mysqli methods
return $this->c->$method(...$args);
}
function __get($name){ // get all the properties
return $this->c->$name;
}
function __set($name, $value){ // set all the properties
if (property_exists($this->c, $name))$this->c->$name = $value;
}
}
为了提出最佳实践,在使用 PDO 或 MySQLi 扩展时,建议始终检查任何可用方法的 return 结果,然后再继续使用依赖其结果的方法.
As mysqli::query
returns false
on an error,在使用fetch_assoc
之前应该检查它,而不是假设它不是false
。这同样适用于使用 fetch_assoc
,因为它可以 return NULL
;
if (!$q = $my_var->query($sql)) {
//something went wrong - handle the error here.
}
if ($data = $q->fetch_assoc()) {
echo $data['column'];
}
然而,正如我所建议的,您需要创建一个抽象层。
由于 $q
出错时会是 false
,因此您问题中代码的异常是:
Fatal error: Call to a member function fetch_assoc() on boolean
意味着您将无法重写 fetch_*
方法,而不重写 mysqli::query
以始终 return 一个对象。
请不要在生产代码中使用。
这只是一个示例,说明如何用您自己的方法覆盖 mysqli::query
方法。您还需要覆盖所有其他 mysqli::***
methods,例如 prepare
、commit
等
示例https://3v4l.org/PlZEs
class Conn
{
private $conn;
public function __construct(...$args)
{
$this->conn = new mysqli(...$args);
}
public function query($query, $resultmode = \MYSQLI_STORE_RESULT)
{
$d = $this->conn->query($query, $resultmode);
if (!empty($this->conn->error)) {
throw new \RuntimeException($this->conn->error);
}
return $d;
}
}
//Your connection code
$con = 'my_var';
$$con = new Conn('host', 'user', 'pass', 'base');
//example usage of valid query
$q = $my_var->query('Valid Query');
$q->fetch_assoc();
//example use of invalid query throwing an exception before `fetch_assoc`
$q = $my_var->query('This is not valid');
$q->fetch_assoc();
结果
I was successful
-----
Fatal error: Uncaught exception 'RuntimeException' with message 'Expected "Valid Query"' in /in/PlZEs:51
Stack trace:
#0 /in/PlZEs(70): Conn->query('This is not val...')
#1 {main}
thrown in /in/PlZEs on line 51
此方法使用 PHP 5.6 argument packing and unpacking 来匹配函数调用参数,以避免必须手动定义它们。
可以对此进行扩展以将消息写入日志文件、发送电子邮件、触发事件或显示友好的错误消息而不是抛出异常。以及用您自己的 Statement
对象覆盖 mysqli_stmt
响应。