Update 3: This problem from 9 months ago persists with Laravel 5.8 and Postgresql 11 on Windows 10 in a Laragon environment and Apache 2.4 on an Ubuntu machine. Does the Eloquent Model instance delete() method simply ignore foreign key constraints? It's baffling:
I have two tables in a Postgresql 9.3 database, companies and sites. There is a one-to-many relationship between them with companies on the one side. There is a foreign key constraint that prevents the deletion of a company if sites have been assigned to it. If I attempt to delete the company with the ID 'KSL' using an SQL query directly on the database, I get the expected error:
ERROR: update or delete on table "companies" violates foreign key constraint "sites_company_id_fkey" on table "sites" DETAIL: Key (company_id)=(KSL) is still referenced from table "sites".
I have defined an artisan command whose handler method has a simple try/catch block:
public function handle()
{
$company = Company::find('KSL');
try{
$company->delete();
}catch(\PDOException $e){
$this->info($e->getMessage());
}
}
When I run the command from the console, I get the expected error message:
SQLSTATE[23503]: Foreign key violation: 7 ERROR: update or delete on table "companies" violates foreign key constraint "sites_company_id_fkey" on table "sites" DETAIL: Key (company_id)=(KSL) is still referenced from table "sites". (SQL: delete from "companies" where "company_id" = KSL)
reflecting the native error message generated by Postgresql. However, when I call the delete method from a Controller using an Ajax call using a similar try/catch block, the exception is not caught and the call fails with no details of the error. I simplified the controller method to make it the same as the console handler:
public function deleteModel(Request $request) {
try {
$id = 'KSL';
$company = Company::find($id);
$result = $company->delete();
return 'success';
} catch (\PDOException $e) {
return $e->getMessage();
}
}
Normally I would get the value of $id from the request argument.
If I use a get request with a RESTful URL in the browser, I get a "The connection was reset" message in Firefox and a similar message in Chrome.
I have referred back to an old question of mine which I thought had the solution, but running composer dump-autoload
had no effect. I have cleared the cache, re-installed Laravel 5.5, updated my installation, and called composer dump-autoload
again several times but the absence of any exception or logged error message gives me no clue. Debug is set to true for this development app.
I passed a handler to the PHP native function register_shutdown_function like this in the autoload.php file in the bootstrap folder:
register_shutdown_function(function () {
$error = error_get_last();
file_put_contents(__DIR__.'/../storage/crash.log', var_export($error, true));
});
Only the word 'NULL' appears in the crash.log. I checked the Apache 2.4 error.log file and the specific error log for this Laravel app but there no relevant details recorded there.
Here is the Exception Handler:
<?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);
}
}
UPDATE 1: I got a clue from this question: Stack size for Apache under Windows. I quickly tested my online applications (all running on Linux machines) and there is no problem. The exception is thrown correctly and a nice clear message is displayed for the user. My local environment is Windows and it looks like Apache suffers from this connection reset error more than in a Linux environment. I've increased the stack size in Apache as suggested by the answer to that question but it still doesn't work. I still get a connection reset error. I've re-installed Apache with the latest binaries from Apache lounge I'm running PHP 7.3. Can anyone shed some light on this?
UPDATE 2:
An answer from Lucas to this question encouraged me to change server. When I ran php artisan serve
from the console and then call the ParentTable->delete()
method, I got the expected exception with no crashing. There is clearly something wrong with my Apache configuration. Unfortunately the accepted answer to that question doesn't solve my problem. I increased the stack size but the problem persists.
sites_company_id_fkey
value cannot exist on it's own without having a parent's reference. You may wish to haveonDeleteCascade()
or asoftDeletes()
on tables. – Wingspreadcrash.log
isNULL
, then that tells meerror_get_last()
returnedNULL
, which also tells me there was no last error. That suggests to me the error is handled, but is not being reported in a helpful way. Please post your controller code. – DenysedenzilPDOException
? Can you keep superclassException
for now and check? – Wingspreadapp\Exceptions\Handler.php
? – Lananna