更新 3:9 个月前的这个问题在 Laragon 环境中的 Windows 10 上的 Laravel 5.8 和 Postgresql 11 以及 Ubuntu 机器上的 Apache 2.4 上仍然存在。Eloquent Model 实例 delete() 方法是否只是忽略外键约束?莫名其妙:
我在 Postgresql 9.3 数据库、公司和站点中有两个表。一方面,它们与公司之间存在一对多的关系。如果已将站点分配给公司,则有一个外键约束可防止删除公司。如果我尝试直接在数据库上使用 SQL 查询删除 ID 为“KSL”的公司,则会收到预期的错误:
错误:表“companies”上的更新或删除违反了表“sites”上的外键约束“sites_company_id_fkey” 详细信息:键(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”上的外键约束“sites_company_id_fkey”详细信息:键(company_id)=(KSL)仍然从表“sites”中引用. (SQL:从“company_id”= KSL 的“companies”中删除)
反映 Postgresql 生成的本机错误消息。但是,当我使用 Ajax 调用使用类似的 try/catch 块从 Controller 调用 delete 方法时,没有捕获到异常并且调用失败并且没有错误的详细信息。我简化了控制器方法,使其与控制台处理程序相同:
public function deleteModel(Request $request) {
try {
$id = 'KSL';
$company = Company::find($id);
$result = $company->delete();
return 'success';
} catch (\PDOException $e) {
return $e->getMessage();
}
}
通常我会从请求参数中获取 $id 的值。如果我在浏览器中使用带有 RESTful URL 的 get 请求,我会在 Firefox 中收到“连接已重置”消息,在 Chrome 中收到类似消息。我已经提到了我的一个老问题,我认为它有解决方案,但运行composer dump-autoload
没有效果。我已经清除了缓存,重新安装了 Laravel 5.5,更新了我的安装,并再次调用composer dump-autoload
了几次,但没有任何异常或记录的错误消息让我没有任何线索。此开发应用程序的 Debug 设置为 true。
我在 bootstrap 文件夹的 autoload.php 文件中向 PHP 原生函数 register_shutdown_function 传递了一个处理程序:
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:我从这个问题中得到了一个线索:Stack size for Apache under Windows。我很快测试了我的在线应用程序(都在 Linux 机器上运行),没有任何问题。异常被正确抛出,并为用户显示一条清晰的消息。我的本地环境是 Windows,看起来 Apache 比 Linux 环境更容易受到这种连接重置错误的影响。正如该问题的答案所建议的那样,我已经增加了 Apache 中的堆栈大小,但它仍然不起作用。我仍然收到连接重置错误。我已经使用 Apache 休息室的最新二进制文件重新安装了 Apache,我正在运行 PHP 7.3。任何人都可以对此有所了解吗?
更新2:卢卡斯对这个问题的回答鼓励我改变服务器。当我php artisan serve
从控制台运行然后调用该ParentTable->delete()
方法时,我得到了预期的异常而没有崩溃。我的 Apache 配置显然有问题。不幸的是,该问题的公认答案并不能解决我的问题。我增加了堆栈大小,但问题仍然存在。