Why soft deleted entities appear in query results?

北城余情 提交于 2019-12-03 04:20:49
Rubens Mariuzzo

The soft deleting feature works when using Eloquent. If you are querying the results with query builder you will eventually see all the records trashed and not trashed.

It is not clear in the current docs of Laravel 4, but seeing that the concept of soft deleting just appears under Eloquent ORM - Soft Deleting and not under Query Builder, we can only assume that: soft delete only works with Eloquent ORM.

Sometimes, you will get the soft deleted table entries with get() even with eloquent and protected $softDelete = true;.

So to avoid this problem, use

...->whereNull('deleted_at')->get();

For example, this query will fetch all rows including soft deleted.

DB::table('pages')->select('id','title', 'slug')
                                   ->where('is_navigation','=','yes')
                                   ->where('parent_id','=',$parent_id)
                                   ->orderBy('page_order')
                                   ->get();

So the proper method is,

DB::table('pages')->select('id','title', 'slug')
                                   ->where('is_navigation','=','yes')
                                   ->where('parent_id','=',$parent_id)
                                   ->whereNull('deleted_at')
                                   ->orderBy('page_order')
                                   ->get();

There is a little trick using soft delete tables and queries in laravel:

When we create something like

$objCars = Car::where("color","blue");

The system executes something like that:

SELECT
  *
FROM
  cars
WHERE
  deleted_at IS NULL
AND
  "color" = 'blue'

So far, so good. But, when we apply the "orWhere" method, something funny happens

$objCars = Car::where("color","blue")->orWhere("color","red");

The system will execute something like that:

SELECT 
  * 
FROM
  cars
WHERE
  deleted_at IS NULL 
AND 
  "color" = 'blue'
OR
  "color" = 'red'

This new query will return all the car where deleted_at is null and the color is blue OR if the color is red, even if the deleted_at is not null. It is the same behavior of this other query, what show the problem more explicitly:

SELECT 
  * 
FROM
  cars
WHERE
  (
    deleted_at IS NULL 
  AND 
    "color" = 'blue'
  )
OR
  "color" = 'red'

To escape from this problem, you should change the "where" method passing a Closure. Like that:

$objCars = Car::where(
  function ( $query ) {
    $query->where("color","blue");
    $query->orWhere("color","red");
  }
);

Then, the system will execute something like that:

SELECT
  *
FROM
  cars
WHERE
  deleted_at IS NULL
AND
  (
    "color" = 'blue' 
  OR
    "color" = 'red'
  )

This last query, searches for all cars where deleted_at is null and where the color can be or red or blue, as we was want it to do.

I had the same problem and nothing here helped me.

My problem was in my construct, I forgot to call the parent constructor:

public function __construct()
{
   parent::__construct();

   //Rest of my code
}

Hope that help someone!

Tested it in Laravel 5.6, You need to use SoftDeletes Trait in your model

use Illuminate\Database\Eloquent\SoftDeletes;

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Banners extends Model
{
    use SoftDeletes;
    //no need of this below line
    //protected $softDelete = true;
}

and when you query

$banners = Banners::where('status', 1)->get();

it will not return soft deleted data.

Laravel 5.2.44 added withoutTrashed() method to SoftDeletingScope. For example you can use something like this:

Post::withoutTrashed()->get();

I use

Post::all()

I works fine, I mean it doesn't return soft deleted items (items flagged with deleted_at timestamps). I am using Laravel 4.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!