问题
I was working with database, running dynamically generated query. Everything was just fine, when I noticed problems with encoding in couple of rows in one table, so I repopulated it from backup and rebuilt the table.
After this action, PDO returns empty result and doesn't throw any exceptions, however, the same query with the same parameters executes successfully (returns some rows) from the command line. I copy-pasted both query and parameters from var_dump()
output to run from command line.
The query:
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);
Things I've tried or checked:
- checked credentials, used by script;
- run same query with different parameters - same result;
- run other queries by both methods - same result;
- tried running without backquotes - same result;
- rebuilt tables from php script - didn't help;
- skimmed table dumps in html - they are up-to-date;
- compared html table dumps and cli dumps - they are similar;
- checked if php queries have effect on results, acquired by cli commands - yes, there is an effect (so, both use the same server/database)
I've run out of ideas where I made a mistake and what to fix, so I want borrow yours =) Even the craziest.
What is the problem?
Where am I mistaking?
Could be this server fault? I share nginx server and hosting with other sites and programmers and some of them may have access to my database.
MySQL version(): 5.6.29-76.2, PHP 5.5.9
Thank you in advance.
EDIT: PDO handling
PDO handling is encapsulated in the class
Creating PDO:
try
{
$this->handle = new PDO("mysql:dbname=" . $this->database . ";host=" . $this->server,
$this->user, $this->password);
// ensure that PDO::prepare returns false when passed invalid SQL
$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()
method is used to run queries. It has such parameters: $sql
- query string with '?', $parameters
- parameters array.
$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;
}
Method for changing $this->PDOFetchMode
public function SetPDOFetchMode($pdo_constant)
{
if (is_int($pdo_constant) && $pdo_constant >= 0)
$this->PDOFetchMode = $pdo_constant;
}
Other code is about parameters validation, singleton implementation etc.
EDIT:
Inspired by this post: PDO prepare statement and match against in boolean mode
I tried binding parameters, but this didn't help
I've tried Paul T.'s advice about using parameters in a query directly according to his comment, but this didn't help either. Nevertheless, the query I got still successfully runs in CLI.
回答1:
The problem was solved pretty unusually by this post best answer: PDO + MySQL and broken UTF-8 encoding
After forcing to use utf8 encoding to the whole base using in constructor, it worked fine and results did appear. But I don't quite understand, how this was done. CLI requests returned results in utf8 encoding properly by default.
It seems that my AGAINST
parameter was messed up with encoding.
Code to fix it:
$pdo = new PDO(
'mysql:host=hostname;dbname=defaultDbName',
'username',
'password',
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
);
Thanks Paul T. for inspiration
来源:https://stackoverflow.com/questions/45254166/pdo-returns-no-results-while-mysql-command-line-returns-expected-result