Laravel,雄辩和控制器中的foreach

时间:2019-11-02 19:39:01

标签: laravel eloquent

我是Laravel的新手,我对一件事感到好奇。我有3个数据库表:帖子,评论,回复。我想对每个对象进行简单的删除。但显然,帖子有很多评论,评论有很多回复。整个事情都与这些答复有关。好像我无法到达他们。

我在表之间有正常的工作关系。


<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;
use App\Comment;
use App\Reply;
use App\Traffic;
use Image;
use Illuminate\Support\Facades\Storage;

class PostsController extends Controller
{

  //few others things here...

  public function destroy($id) //$id is an id of post
    {
        // Select Post and comments of post
        $post = Post::find($id);
        $comments = Comment::where('post_id', $id);        

        //remove image (working fine)
        Storage::delete('public/img/' . $post->image);

        // delete all replies of post comments <<< Here is the issue. Can I even do like this?
            foreach ($comments as $comment) {
                $post_comment_reply = Reply::where('comment_id', $comment->id);
                $post_comment_reply->delete();
            }

            // delete post record (working fine)
            $post->delete();

            //delete comments of post (working fine)
            $comments->delete();

            // return to user profile (working fine)
            return redirect('/home')->with('success', 'Post has been deleted');
    }

4 个答案:

答案 0 :(得分:1)

还有一种更简单的方法..如果您只是将数据库约束添加到注释的回复表中的外键上。

$table->unsignedInteger('comment_id');

$table->foreign('comment_id')->references('id')->on('comments')
    ->onDelete('cascade');

最后一部分:onDelete('cascade')确保在删除评论后,所有回复都将被删除:),因此您不必在应用程序层中手动进行操作。

让我知道是否合理:)

答案 1 :(得分:0)

您可以一次删除所有答复,而不必循环删除所有答复:

$comments = Comment::where('post_id', $id);
$comment_ids = $comments->pluck('id');

Reply::whereIn('comment_id', $comment_ids)->delete();

答案 2 :(得分:0)

代码中的错误是您创建了一个数据库查询,但没有执行它:

// You forgot the ->get() following the where statement
foreach ($comments as $comment) 
    $post_comment_reply = Reply::where('comment_id', $comment->id)->get();
    $post_comment_reply->delete();
}

但是,代码的整体效果不是很理想,您可以使用onDelete('cascade')直接在数据库级别上进行编码,或者简单地创建一个删除答复的请求,而无需检索这些答复并减少对数据库的查询数量,像这样:

foreach ($comments as $comment) 
    Reply::where('comment_id', $comment->id)->delete();
}

进一步减少如上所述的数据库查询的一步:

Reply::whereIn('comment_id', $comments->pluck('id'))->delete();

答案 3 :(得分:0)

如果要通过Laravel删除关系,则必须重写boot函数。

之类的评论模型上覆盖boot()
protected static function boot()
    {
        static::deleting(function (Comment $model) {
            $model->replies()->delete();
        });

        parent::boot();
    }

通过雄辩删除评论时,这将删除与该评论相关的所有回复。