При вызове DB::select почему я получаю сообщение "Соединение было сброшено"?

В моем приложении Laravel 5.5 вызовы DB::select, которые запускают запрос на выборку для базы данных Postgresql, не отображаются без ошибок в журналах ошибок Apache или Laravel и вызывают сообщение "Соединение было сброшено". Этот пример кода работает как ожидалось, потому что функция get_users_with_roles существует.

public function missing_function(Request $request) {
        try{
           $all = DB::select('SELECT * from get_users_with_roles()', []);
        }catch(Illuminate\Database\QueryException $qe){
            return json_encode($qe->getMessage());
        }
        return json_encode($all);
}

Однако, если я заменю эту строку SQL на функцию, которая не существует:

public function missing_function(Request $request) {
        try{
           $all = DB::select('SELECT * from test()', []);
        }catch(Illuminate\Database\QueryException $qe){
            return json_encode($qe->getMessage());
        }
        return json_encode($all);
}

Соединение сброшено, и я не вижу ошибок в журналах. Если я выполню этот ошибочный запрос в собственной среде Postgresql:

SELECT * from test();

Я получаю четкое сообщение об ошибке:

    ERROR:  function test() does not exist
LINE 1: select * from test()
                      ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

Это особенно странно, потому что эта проблема не является последовательной. Блок try иногда перехватывает QueryException и отображает сообщение об ошибке Postgresql как исключенное.

Я пробовал добавлять

php_flag xcache.cacher Off 
php_flag xcache.size 0 
php_flag xcache.stat Off

в файл.htaccess, но безрезультатно.

Мне нужна возможность использовать метод DB::select, потому что я сильно полагаюсь на пользовательские SQL-функции Postgresql и функции plpgsql в приложении. У меня есть функция, которая создает соответствующий SQL и передает ему метод DB::select программно, поэтому мне нужно иметь возможность отлавливать исключения, возникающие при возникновении ошибки в SQL, например, когда функция отсутствует.

ОБНОВИТЬ

Эта проблема, похоже, связана с тем, как DB::select обрабатывает любую ошибку SQL. Я только что попробовал это с функцией, которая существует, но которая выдает ошибку SQL. Опять же, вместо того, чтобы позволить мне перехватить это в PHP с помощью блока try/catch, он просто сбрасывает соединение и не регистрирует ошибку ни в журнале Laravel, ни в журнале Apache.

Этот вопрос не проливает свет. Принятый ответ там относится к ожидаемому поведению. В моей среде QueryException не генерируется и не перехватывается.

2 ответа

Решение

Сложной частью этого является упрямый отказ браузера выявить любую форму сообщения об ошибке. Когда это происходит, мне нравится идти в командную строку и пробовать это, таким образом исключая веб-сервер как переменную.

Из чата мы узнали, что командная строка показала ошибку, как и ожидалось, но не сделали это изящно: ошибка была выведена, и сценарий был остановлен. Это серьезный сбой, не связанный с веб-сервером.

С введением \ThrowableСценарии, в которых PHP умирает, становятся все меньше и меньше. Итак, чтобы перевести дыхание PHP, мы реализовали register_shutdown_function что вытащил error_get_last в попытке выяснить, что, если вообще что-то, было сказано перед взрывом.

Это показало, кратко, сообщение об ошибке в браузере (на этот раз с использованием другого браузера). Однако это не повторилось. Понимание в этом пункте было кэшированием: composer dump-autoload исправил проблему!

Я подозреваю, что случилось так:

  • Eloquent бросил исключение
  • PHP перепутал это с помощью классов обработки исключений Laravel
  • В какой-то момент PHP попытался загрузить класс, которого не было в автозагрузчике
  • PHP сильно рухнул (это один из тех случаев, когда PHP 7.0 дает сбой)

Запустив composer dump-autoloadвсе "отсутствующие" классы были перенесены в область автозагрузчика, и при повторной попытке произошла правильная последовательность кода.

Я думаю, что это ошибка запроса SQL

 `SELECT * from test()` 

Так как () скобка указывает на функцию, поэтому попробуйте использовать как

 `SELECT * from test` in your query 

Лучший способ в Laravel

Создайте модель с помощью php artisan make: Test Model

Тогда используйте в контроллере как

     `use App\Test;'

а затем получить записи Test::all(); он принесет все записи из базы данных, как ваше требование SELECT * из теста

Другие вопросы по тегам