【问题标题】:Laravel - Collection::delete method does not existLaravel - Collection::delete 方法不存在
【发布时间】:2020-07-02 12:05:49
【问题描述】:

我正在尝试测试 boot() static::deleting 方法,该方法应在通过 Eloquent 删除模型时触发。

tinker App\User::find(6)->delete(); 中的命令返回“方法 [...]Collection::delete 不存在”。

如果我尝试使用App\User::where('id', 6)->delete();,那么由于未加载 Eloquent,因此不会触发 static::deleting 方法。如果我用->first() 加载 Eloquent,那么我会得到相同的错误,即 states 方法不存在。

这是整个用户模型

 <?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',
    ];
}

我现在已经花了几个小时在谷歌上寻找可能的解决方案,但还没有。

在触发启动删除方法时我应该如何正确删除用户模型?

【问题讨论】:

  • 如果你已经定义了监听器,你可以粘贴那个代码
  • 对不起,我不太清楚你的建议是什么,你能改写一下吗?
  • find 应该只返回一个集合,如果你向它传递一个数组.. 否则你应该得到一个模型实例或 null 并且应该能够在模型实例上调用 delete /跨度>
  • delete() 只能在QueryBuilder 实例See here 上调用
  • @user3647971 我应该使用什么方法来删除模型以触发删除方法?

标签: laravel


【解决方案1】:

在您的deleting 侦听器中,您正试图删除其他内容,这是导致错误的集合。

$user-&gt;posts 是与 Posts 的关系,它是复数,是 hasMany 关系(很可能),因此它返回一个 Collectionalways。集合没有delete 方法。您必须遍历集合并在每个帖子上调用 delete

// 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();
}

旁注:您不能对模型和查询批量执行任何操作并触发事件。所有模型事件都基于模型的单个实例。直接查询会绕过模型。

【讨论】:

  • 我认为这样做了,我必须退出修补程序并再次加载它才能应用更改!谢谢老兄!
【解决方案2】:

您可以优化lagbox's answer,只需使用一个查询即可删除所有帖子。在他的示例中,他正在为附加到用户的每个帖子执行delete 查询。

对于单个 delete 查询,可以直接使用关系的查询构建器:

$user->posts()->delete();

或使用集合的pluck method 和单独的查询:

Post::where('id', $user->posts->pluck('id'))->delete();

【讨论】:

  • 唯一的问题是他们是否想监听 Post 模型的事件,因为它们不会触发这些查询,因为它们是直接的
  • 谢谢老兄,这是一个添加()的问题,繁荣问题解决了!我明白我哪里做错了,这很重要,所以谢谢!
  • 这个问题是否属于拼写错误?由于代码使用固定语法?
  • 我使用的是“posts”属性,而不是调用“posts()”方法,所以我猜是这样。尽管这不会触发帖子的事件侦听器,但这是真的吗? $user-&gt;posts()-&gt;delete();
  • 不确定要调查的一件事。
【解决方案3】:

您也可以使用higher order messages

$user->posts->each->delete();

【讨论】:

    【解决方案4】:

    $user-&gt;posts-&gt;map-&gt;delete()

    【讨论】:

    • 对已得到很好回答的旧问题的新答案需要充分解释如何补充其他答案。
    • 只需要一行代码。我们可以利用我们在删除模型中定义的观察者的好处。它还利用了删除单个模型时提供的 eloquent 模型。
    • 所以请在你的回答中解释一下。它会改善所有其他答案吗?
    【解决方案5】:

    我在我的控制器文件中使用它来删除数据库条目:

    public function destroy(Item $id) {
            $id->destroy($id->id);
            //return view('inv.delete', compact('id'));
            return redirect('/inv');
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-27
      • 2021-09-27
      • 2021-03-26
      • 2021-10-25
      • 1970-01-01
      • 2021-05-30
      • 2020-03-25
      • 2019-12-06
      相关资源
      最近更新 更多