I have a big laravel project that contains a lot of deletion in that project, in all of those deletion didn't put alert before deleting, now I can't modify the project one by one and adding alert or confirm before deleting...
I was searching about a solution that we listen to DELETE query or override the \Illuminate\Database\Query\Builder delete method, but now I'm comfused about how to handle it so that works correctly, I really need your help.
I put all of my implementation up to now to do that:
namespace App\Extensions;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\Query\Grammars\Grammar;
use Illuminate\Database\Query\Processors\Processor;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Eloquent\Model;
class CustomQueryBuilder extends QueryBuilder
{
public function delete($id = null)
{
dd("...");
// You can add your confirmation logic here
if ($this->confirmDelete()) {
return parent::delete($id);
}
dd("Delete method called..!");
// If confirmation is not provided, return false or handle it accordingly.
return false;
}
private function confirmDelete()
{
return false;
// Implement your confirmation dialog with user interaction here
// You can use JavaScript for a client-side confirmation or a form for a server-side confirmation
}
In this way make a CustomQueryBuilder and bind it with the Builder in thev appServiceProvider boot(), then use CustomQueryBuilder in our Model instead of Builder
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Support\Facades\DB;
class ConfirmDeleteMiddleware
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
// Check if the request has a DELETE SQL query
$sql = DB::getQueryLog();
dd($sql);
foreach ($sql as $query) {
if (str_starts_with($query['query'], 'delete') || str_starts_with($query['query'], 'DELETE')) {
// Display a confirmation dialog to the user
return response()
->view('confirm_delete', ['deleteRoute' => url()->full()], 200)
->header('Content-Type', 'text/html');
}
}
return $next($request);
}
}
In this way we use DB::getQueryLog to get latest queries and after that check DELETE in the query to handle the delete logic.
test the addGlobalScope method:
Model::addGlobalScope(function (Builder $builder) {
return new CustomQueryBuilder($builder);
});
and use a lot of method like event listener, macro, etc but can't do it as well