#php #oop #inheritance #pdo
#php #ооп #наследование #pdo
Вопрос:
Я хотел бы получить последний запрос (для целей отладки) из PDOStatement. Но я не могу переопределить методы bindParam и bindValue. Когда я попробовал приведенный ниже код, я получил:
Неустранимая ошибка: значение по умолчанию для параметров с подсказкой типа класса может быть только NULL
Затем я заменил PDO::PARAM_STR
на null
в списке параметров bindParam/bindValue, так что я получил:
Строгие стандарты: объявление DBStatement::bindParam() должно быть совместимо с объявлением PDOStatement::bindParam()
Затем я удалил int
предшествующий $data_type
параметр и установил значение по умолчанию на PDO::PARAM_STR
. Затем я получил:
Строгие стандарты: объявление DBStatement::bindParam() должно быть совместимо с объявлением PDOStatement::bindParam() в D:wwwpdotest.php в строке 73
(интересно, что значение bindValue теперь в порядке).
Итак, что я могу теперь сделать?
class DBConnection extends PDO
{
public function __construct($dsn, $username = null, $password = null, $driver_options = array())
{
parent::__construct($dsn, $username, $password, $driver_options);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DBStatement', array($this)));
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
}
class DBException extends PDOException
{
private $query_string;
private $parameters;
public function __construct($message = '', $code = 0, $previous = null, $query_string = '', $parameters = array())
{
parent::__construct($message, $code, $previous);
$this->query_string = $query_string;
$this->parameters = $parameters;
}
public function getQueryString()
{
return $this->query_string;
}
public function getParameters()
{
return $this->parameters;
}
}
class DBStatement extends PDOStatement
{
private $conn;
private $parameters = array();
protected function __construct($conn)
{
$this->conn = $conn;
}
public function bindParam($parameter, amp;$variable, int $data_type = PDO::PARAM_STR, int $length = null, $driver_options = null)
{
$this->parameters[$parameter] = $variable;
parent::bindParam($parameter, $variable, $data_type, $length, $driver_options);
}
public function bindValue($parameter, $value, int $data_type = PDO::PARAM_STR)
{
$this->parameters[$parameter] = $value;
parent::bindValue($parameter, $value, $data_type);
}
public function execute($input_parameters = null)
{
try
{
parent::execute($input_parameters);
}
catch (PDOException $e)
{
throw new DBException($e->getMessage(), $e->getCode(), $e->getPrevious(), $this->queryString, $this->parameters);
}
}
}
$id = 1;
try
{
$conn = new DBConnection('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $conn->prepare('select * from foo where id = :id');
$stmt->bindParam(':id', $id);
$stmt->execute();
}
catch (DBException $e)
{
echo "Query string was: ".$e->getQueryString()."n";
echo "Parameters was: ".print_r($e->getParameters(), true);
}
Я также получаю следующее, когда я создаю исключение DBException (из-за параметра $code):
Обратите внимание: неправильно сформированное числовое значение, встречающееся в D:wwwpdotest.php в строке 21
Комментарии:
1. Да, вы можете проголосовать против этого вопроса, но где ответ? Вы знаете? Пожалуйста, поделитесь этим!
Ответ №1:
Не нужно использовать тип «int» переменной $data_type, тогда это работает.
public function bindParam($parameter, amp;$variable, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null)
{
$this->parameters[$parameter] = $variable;
parent::bindParam($parameter, $variable, $data_type, $length, $driver_options);
}
public function bindValue($parameter, $value, $data_type = PDO::PARAM_STR)
{
$this->parameters[$parameter] = $value;
parent::bindValue($parameter, $value, $data_type);
}
Ответ №2:
Уведомление, которое вы получаете, похоже, связано с этой неразрешенной ошибкой в php. Я бы изменил переопределенные bindParam и bindValue так, чтобы они были совместимы с объявлением родительского элемента. Если вы хотите установить свои собственные значения параметров по умолчанию, вы можете сделать это с помощью переопределенных методов. Наконец, я бы просто изменил конструкцию исключения, чтобы опустить код:
throw new DBException($e->getMessage(), NULL, $e->getPrevious(), $this->queryString, $this->parameters);