kernel panic

быдлокодю, дорого, интим не предлагать!

Проблемы c MySql signal при prepare statement в PHP

Вернуться

Начиная с Mysql версии 5.5 появилась замечательная возможность выбрасывать исключения с помощью команды signal. Это позволило нормально оформлять хранимые процедуры и обрабатывать ошибки как нативные Exception.

Проблемы всплыли при использовании этого функционала на PHP. Для PHP 2 варианта выполнить SQL код, это через mysqli::query и prepare statement.

В случае с query все отлично, signal из MySql обрабатывался как exception потому что для получения результата вы используете fetch. Но когда мы вызывали хранимую процедуру или функцию через prepare statement. Сам statement выполнялся и завершался успешно, никаких ошибок нигде не было. Связано это с типом вызова функции. Например:

При вызове

select mySignalCall();

функция не будет вызываться до тех пор, пока вы не начнете фетчить результат.

При вызове
call mySignalCall();

сигнал будет обработан сразу. Не зависимо от фетча результата.

Все написано правильно но в PHP нет никаких исключений? Потому что надо сделать несколько операций.

$driver = new mysqli_driver();
$driver->report_mode = MYSQLI_REPORT_ALL ^ MYSQLI_REPORT_INDEX;


Мы включили вывод всех ошибок и предупреждений, но чтобы не получать сообщение: No index used in query/prepared statement, мы исключили вывод предупреждений про индексы с помощью флага MYSQLI_REPORT_INDEX .

Теперь при вызове signal внутри mysql функции в PHP будет выбрасываться исключение mysqli_sql_exception.

А теперь ньюанс, который касается prepare statement в PHP, вы все сделали так как написано выше, prepare statement вы умеете использовать, но вот не задача signal не работает. Возможно это проблема документации,потому что все в основном используют mysqli::prepare для получения объекта statement, который после execute не будет содержать никакой информации о signal.

Связано это с неправильной инициализацией statement. Правильно делать так

$statement = mysqli::stmt_init();
$statement->prepare(your query here); // Важно!!!


Обратите внимание мы используем mysqli::stmt_init для создания объекта, и выполняем метод prepare у полученного объекта а не у mysqli!

Вот и все.