Reputation: 393
I am trying to test the boot() static::deleting method, which should fire when a model is deleted through Eloquent.
The command in tinker App\User::find(6)->delete();
returns a 'method [...]Collection::delete does not exist'.
If I try to use App\User::where('id', 6)->delete();
then the static::deleting method does not get triggered since Eloquent is not loaded. If I load Eloquent with ->first()
then I get the same error that states method does not exist.
Here is the entire user model
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
public function profile() {
return $this->hasOne(Profile::class);
}
public function posts() {
return $this->hasMany(Post::class);
}
public function tempUploads() {
return $this->hasMany(TempUploads::class);
}
protected static function boot() {
parent::boot();
static::created(function ($user) {
$user->profile()->create(['id' => $user->username, 'avatar' => '/storage/avatars/edit-profile.png']);
mkdir(public_path() . "/storage/images/" . $user->username , 0755);
// $data = [
// 'user_id' => $user->username
// ];
// Mail::to($user->email)->send(new WelcomeMail($data));
});
static::deleting(function ($user) {
$user->posts->delete();
if ($user->profile->avatar != '/storage/avatars/edit-profile.png') {
if ($user->profile->cover != NULL && $user->profile->cover != '') {
$oldAvatar = $_SERVER['DOCUMENT_ROOT'] . $user->profile->avatar;
$oldCover = $_SERVER['DOCUMENT_ROOT'] . $user->profile->cover;
if (is_file($oldAvatar) && is_file($oldCover)) {
unlink($oldAvatar);
unlink($oldCover);
} else {
die("Грешка при изтриване на стария файл. File does not exist in profile deleting method.");
}
}
}
$user->profile->delete();
});
}
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'username', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
I have spent hours now looking through google for possible solutions but nothing has yet.
How should I properly delete a User model while triggering the boot deleting method ?
Upvotes: 4
Views: 10189
Reputation: 486
$user->posts()->delete() will work
$user->posts->delete() will not work
Because if you not put '()' then it becomes collection instead of query. delete() works on query
Upvotes: 1
Reputation: 149
You can use higher order messages as well:
$user->posts->each->delete();
Upvotes: 2
Reputation: 148
I used this in my Controller File to delete the Database Entry:
public function destroy(Item $id) {
$id->destroy($id->id);
//return view('inv.delete', compact('id'));
return redirect('/inv');
}
Upvotes: 0
Reputation: 50491
In your deleting
listener you are trying to delete something else, which is a Collection which is causing the error.
$user->posts
is a relationship to Posts which is a plural which is a hasMany relationship (most likely) so it returns a Collection always. Collections do not have a delete
method. You will have to iterate through the collection and call delete
on each Post
// calling `delete()` on a Collection not a Model
// will throw the error you see
$user->posts->delete();
// iterate through the Collection
foreach ($user->posts as $post) {
$post->delete();
}
Side Note: you can not do any action in bulk with Models and queries and have the events be fired. All Model events are based on single instances of the Models. A direct query bypasses the Model.
Upvotes: 7
Reputation: 5358
You can optimise lagbox's answer by using only one query to delete all of the posts. In his example he's executing a delete
query for every post attached to the user.
For a single delete
query either use the query builder of the relationship directly:
$user->posts()->delete();
or use the pluck
method of the collection and a separate query:
Post::where('id', $user->posts->pluck('id'))->delete();
Upvotes: 6