PDO在返回结果时没有返回任何结果,而MySQL命令行则返回了预期的结果。

4 浏览
0 Comments

PDO在返回结果时没有返回任何结果,而MySQL命令行则返回了预期的结果。

我正在使用数据库,并运行动态生成的查询。一切都很好,但我注意到一个表中有几行编码问题,所以我从备份重新填充了表并重建了表格。

在这个操作之后,PDO返回空结果并且没有抛出任何异常,然而,相同的查询在命令行中执行成功(返回一些行)。我从var_dump()输出中复制粘贴了查询和参数,以便在命令行中运行。

查询语句:

SELECT `contracts_info`.`contract_number` AS `Номер контракта`, `contracts_info`.`balance` AS `Остаток`, `contracts_info`.`conclusion_date` AS `Дата заключения`, `contracts_info`.`activation_date` AS `Активация аккаунта`, `contracts_info`.`deactivation_date` AS `Деактивация аккаунта`,
`parents`.`mother_fullname` AS `ФИО матери`, `parents`.`mother_email` AS `E-mail матери`, `parents`.`mother_phone` AS `Телефон матери`, `parents`.`father_fullname` AS `ФИО отца`, `parents`.`father_email` AS `E-mail отца`, `parents`.`father_phone` AS `Телефон отца`, `parents`.`postal_office` AS `Отделение Новой почты`,
`students`.`name` AS `Имя`, `students`.`second_name` AS `Отчество`, `students`.`surname` AS `Фамилия`, `students`.`form_number` AS `Класс`, `students`.`form_letter` AS `Буква класса`, `students_info`.`medical_features` AS `Медицинские особенности`, `students_info`.`psychological_features` AS `Психологические особенности`
FROM contracts_info
JOIN `parents` USING(`contract_number`)
JOIN `students` USING(`contract_number`)
JOIN `students_info` USING(`contract_number`)
WHERE MATCH (`contracts_info`.`contract_number`) AGAINST (? IN BOOLEAN MODE)
OR MATCH (`parents`.`contract_number`, `parents`.`mother_fullname`, `parents`.`mother_email`, `parents`.`father_fullname`, `parents`.`father_email`) AGAINST (? IN BOOLEAN MODE)
OR MATCH (`students`.`name`, `students`.`second_name`, `students`.`surname`, `students`.`contract_number`) AGAINST (? IN BOOLEAN MODE)
OR MATCH (`students_info`.`medical_features`, `students_info`.`psychological_features`, `students_info`.`contract_number`) AGAINST (? IN BOOLEAN MODE);

我尝试过或检查过的事项:

  • 检查脚本使用的凭据;
  • 使用不同的参数运行相同的查询-相同的结果;
  • 通过两种方法运行其他查询-相同的结果;
  • 尝试不带反引号运行-相同的结果;
  • 从php脚本中重建表格-没有帮助;
  • 浏览html中的表格转储-它们是最新的;
  • 比较html表格转储和cli转储-它们是相似的;
  • 检查php查询是否对cli命令获取的结果有影响-是的,有影响(所以,两者都使用相同的服务器/数据库)

我已经无法想到自己犯了什么错误和需要修复什么,所以我想借用你们的想法=)

即使是最疯狂的想法。

问题出在哪里?

我哪里错了?

可能是服务器的问题吗?我与其他网站和程序员共享nginx服务器和主机,其中一些人可能可以访问我的数据库。

MySQL版本:5.6.29-76.2,PHP 5.5.9

提前谢谢你的帮助。

编辑:PDO处理

PDO处理封装在类中

创建PDO:

try
{
    $this->handle = new PDO("mysql:dbname=" . $this->database . ";host=" . $this->server,
        $this->user, $this->password);
    // 确保PDO::prepare在传递无效的SQL时返回false
    $this->handle->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $this->handle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
    trigger_error($e->getMessage(), E_USER_ERROR);
    exit;
}

Query()方法用于运行查询。它有以下参数:$sql - 带有'?'的查询字符串,$parameters - 参数数组。

$statement = $this->handle->prepare($sql);
if ($statement === false)
{
    trigger_error($this->handle->errorInfo()[2], E_USER_ERROR);
    exit;
}
$results = $statement->execute($parameters);
if ($results !== false)
{
    return $statement->fetchAll($this->PDOFetchMode);
}
else
{
    return false;
}

更改$this->PDOFetchMode的方法

public function SetPDOFetchMode($pdo_constant)
{
if (is_int($pdo_constant) && $pdo_constant >= 0)
    $this->PDOFetchMode = $pdo_constant;
}

其他代码涉及参数验证、单例实现等。

编辑:

受到此帖子的启发:PDO prepare statement and match against in boolean mode

我尝试了绑定参数,但这没有帮助。

我尝试了Paul T.在他的评论中关于直接在查询中使用参数的建议,但这也没有帮助。尽管如此,我得到的查询仍然可以成功在CLI中运行。

0
0 Comments

问题的原因是PDO返回了空结果,而MySQL命令行返回了预期的结果。解决方法是在构造函数中强制使用utf8编码来使用整个数据库。但是我不太理解是如何实现的。命令行请求默认以utf8编码正确返回结果。似乎我的AGAINST参数与编码混淆了。

修复的代码如下:

$pdo = new PDO(
'mysql:host=hostname;dbname=defaultDbName',
'username',
'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
);

感谢Paul T.的灵感。这是一个很好的发现。感谢您发布了发现的结果!

0