Laravel 5.5, почему исключение не вызывается нарушением внешнего ключа из метода удаления?
У меня есть две таблицы в базе данных Postgresql 9.3, компании и сайты. Между ними существуют отношения один-ко-многим с компаниями с одной стороны. Существует ограничение внешнего ключа, которое препятствует удалению компании, если ей назначены сайты. Если я пытаюсь удалить компанию с идентификатором KSL, используя SQL-запрос непосредственно в базе данных, я получаю ожидаемую ошибку:
ОШИБКА: обновление или удаление в таблице "companies" нарушает ограничение внешнего ключа "sites_company_id_fkey" для таблицы "sites". ПОДРОБНЕЕ: Ключ (company_id)=(KSL) все еще ссылается на таблицу "sites".
Я определил команду ремесленника, чей метод-обработчик имеет простой блок try/catch:
public function handle()
{
$company = Company::find('KSL');
try{
$company->delete();
}catch(\PDOException $e){
$this->info($e->getMessage());
}
}
Когда я запускаю команду из консоли, я получаю ожидаемое сообщение об ошибке:
SQLSTATE [23503]: Нарушение внешнего ключа: 7 ОШИБКА: обновление или удаление в таблице "companies" нарушает ограничение внешнего ключа "sites_company_id_fkey" для таблицы "sites" ДЕТАЛИ: На ключ (company_id)=(KSL) все еще ссылаются из таблицы "sites", (SQL: удалить из "companies", где "company_id" = KSL)
отражающий собственное сообщение об ошибке, сгенерированное Postgresql. Однако, когда я вызываю метод delete из контроллера, используя Ajax-вызов с использованием аналогичного блока try/catch, исключение не перехватывается, и вызов завершается неудачно без подробных сведений об ошибке. Я упростил метод контроллера, чтобы сделать его таким же, как обработчик консоли:
public function deleteModel(Request $request) {
try {
$id = 'KSL';
$company = Company::find($id);
$result = $company->delete();
return 'success';
} catch (\PDOException $e) {
return $e->getMessage();
}
}
Обычно я получаю значение $id из аргумента запроса. Если я использую запрос get с URL-адресом RESTful в браузере, я получаю сообщение "Соединение было сброшено" в Firefox и аналогичное сообщение в Chrome. Я сослался на мой старый вопрос, который, я думал, имел решение, но работает composer dump-autoload
не имел никакого эффекта. Я очистил кеш, переустановил Laravel 5.5, обновил мою установку и вызвал composer dump-autoload
снова несколько раз, но отсутствие каких-либо исключений или зарегистрированных сообщений об ошибках не дает мне никакой подсказки. Отладка имеет значение true для этого приложения для разработки.
Я передал обработчик в собственную функцию PHP register_shutdown_function, например, в файле autoload.php в папке начальной загрузки:
register_shutdown_function(function () {
$error = error_get_last();
file_put_contents(__DIR__.'/../storage/crash.log', var_export($error, true));
});
В файле crash.log отображается только слово "NULL". Я проверил файл Apache 2.4 error.log и журнал ошибок для этого приложения Laravel, но там не было записано соответствующих подробностей.
Вот обработчик исключений:
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
return parent::render($request, $exception);
}
}
ОБНОВЛЕНИЕ 1: я получил ключ от этого вопроса: размер стека для Apache под Windows. Я быстро проверил свои онлайн-приложения (все они работают на компьютерах с Linux), и проблем нет. Исключение выдается правильно, и пользователю отображается хорошее четкое сообщение. Моя локальная среда - Windows, и похоже, что Apache страдает от этой ошибки сброса соединения больше, чем в среде Linux. Я увеличил размер стека в Apache, как подсказывает ответ на этот вопрос, но он все еще не работает. Я все еще получаю ошибку сброса соединения. Я переустановил Apache с последними двоичными файлами из Apache lounge, я использую PHP 7.3. Может кто-нибудь пролить некоторый свет на это?
ОБНОВЛЕНИЕ 2: Ответ от Лукаса на этот вопрос побудил меня сменить сервер. Когда я побежал php artisan serve
с консоли, а затем вызвать ParentTable->delete()
Метод, я получил ожидаемое исключение без сбоев. Очевидно, что-то не так с моей конфигурацией Apache. К сожалению, принятый ответ на этот вопрос не решает мою проблему. Я увеличил размер стека, но проблема сохраняется.