49

I'm having a minor issue with Laravel 4. I'd like to use the delete() method on a record but for some reason it doesn't actually delete the record. destroy() does, though, so my code is good. Also, if I pass Teetime::where('date', '=', $formattedDate)->count() to my view I get one which is correct. What's the problem?

        if($action=="delete") {
            $teetime = Teetime::where('date', '=', $formattedDate)->firstOrFail();
            // for some reason $teetime->delete() doesn't work
            Teetime::destroy($teetime->id);
        }
Rishabh
  • 3,752
  • 4
  • 47
  • 74

3 Answers3

70
  • destroy is correct method for removing an entity directly (via object or model).

Example:

$teetime = Teetime::where('date', '=', $formattedDate)->firstOrFail();
$teetime->destroy();
  • delete can only be called in query builder

Example:

$teetime = Teetime::where('date', '=', $formattedDate)->delete();

From documentation:

Deleting An Existing Model By Key

User::destroy(1);

User::destroy(array(1, 2, 3));

User::destroy(1, 2, 3);

Of course, you may also run a delete query on a set of models:

$affectedRows = User::where('votes', '>', 100)->delete();

More info: http://laravel.com/docs/eloquent

ek9
  • 3,392
  • 5
  • 23
  • 34
  • 9
    Thanks but why does the documentation also provide this example: `$user = User::find(1); $user->delete();`? I've used `delete()` elsewhere in my code and it has been working fine. –  Mar 25 '14 at 08:33
  • 1
    I have updated my answer, please check it :) It explains it in detail. – ek9 Mar 25 '14 at 08:34
  • Oh, I get it. I think it's `firstOrFail()` that gets me out of Query Builder. –  Mar 25 '14 at 08:36
  • Yes, as it returns an object (model). – ek9 Mar 25 '14 at 08:36
  • When I use `User::destroy(1);` Laravel is throwing error, saying `Method [delete] does not exist.` – Brent Connor May 18 '15 at 20:28
  • when I do: `self::delete();` **Laravel 5.1** says `Non-static method Illuminate\Database\Eloquent\Model::delete() should not be called statically` – Yevgeniy Afanasyev Jun 01 '16 at 03:36
  • So I used `self::truncate();` I don't know how can you do `$affectedRows = User::where('votes', '>', 100)->delete();` because it is still **static** method call. – Yevgeniy Afanasyev Jun 01 '16 at 03:48
  • 3
    whats up with this answer? this answer is wrong. 66 upvotes? you mislead a lot of people. Destroy calls the model method delete() as well. And you should almost NEVER call delete on queries, as it will not trigger delete events. – Toskan Nov 10 '21 at 19:22
  • @Toskan it is a 7.5 year old answer, it's possible things have changed since it was posted. I've added an answer for modern versions of Laravel. – miken32 Dec 17 '21 at 17:25
6

The accepted answer may have been true in 2014, I'm not sure. It is certainly not correct now.

The delete() method is called against an instance of a model class. Using the original question's code:

$teetime = Teetime::where('date', '=', $formattedDate)->firstOrFail();
// $teetime is a model instance
$teetime->delete();

The destroy() method is a static method of the model class. It accepts one or multiple primary keys:

$teetime_ids = Teetime::where('date', '=', $formattedDate)->pluck('id');
// $teetime_ids is a collection of 1 or more primary keys
Teetime::destroy($teetime_ids);

From the documentation:

Deleting Models

To delete a model, you may call the delete method on the model instance:

use App\Models\Flight;
$flight = Flight::find(1);
$flight->delete();

Deleting An Existing Model By Its Primary Key

In the example above, we are retrieving the model from the database before calling the delete method. However, if you know the primary key of the model, you may delete the model without explicitly retrieving it by calling the destroy method. In addition to accepting the single primary key, the destroy method will accept multiple primary keys, an array of primary keys, or a collection of primary keys:

Flight::destroy(1);
Flight::destroy(1, 2, 3);
Flight::destroy([1, 2, 3]);
Flight::destroy(collect([1, 2, 3]));

There is also a delete() query builder method that allows you to directly delete records from the database table. There are important caveats for using this method, and it's important to understand that Eloquent implements its own query builder class, much as it does its own collection class.

When called against an Eloquent query builder, certain behaviour such as support for soft deletes is preserved. However, Eloquent events deleting and deleted are not fired, as a model is never created.

delete() can also be called against the base query builder class, which has no knowledge of Eloquent at all.

Compare the generated queries, assuming that Teetime imports the SoftDeletes trait:

Teetime::where('date', '=', $formattedDate)->delete();
// UPDATE teetimes SET deleted_at = NOW(), updated_at = NOW() WHERE `date` = ?
DB::table('teetimes')->where('date', '=', $formattedDate)->delete();
// DELETE FROM teetimes WHERE `date` = ?
miken32
  • 42,008
  • 16
  • 111
  • 154
  • imho add forceDelete and how to properly delete multiple models with events e.g. `->each(function($element){$element->delete()}` – Toskan Dec 20 '21 at 13:04
  • `Model::destroy()` does fire events so you can pass it an array of ids. (Also check out higher order proxies – no need for anonymous functions. `$collection->each->delete()`) – miken32 Dec 20 '21 at 16:02
6

Status 2022

I wonder how many explanations there are. The difference is actually quite easy to explain.

You have two ways to delete an entity:

  1. $model->delete() and
  2. Model::destroy($model->id).

delete()

The first option refers directly to the model. This means you must already have it. For example, with a RouteModelBinding it would be the case and you can delete the entity directly in the controller.

public function destroy(SomeModel $model)
{
  return $model->delete();
}

The return value from delete() here is a boolean.

destroy()

The second option does not presuppose the entity. You only need the model. Then you pass the id of the desired entity as a parameter.

public function destroy($id)
{
  return SomeModel::destroy($id);
}

The return value from destroy()here is an integer. The number tells you how many entities were deleted. In the example, it would logically be only 1.

Maik Lowrey
  • 15,957
  • 6
  • 40
  • 79