prevent query builder delete() method of laravel

68 Views Asked by At

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

0

There are 0 best solutions below