Laravel, красноречивый и foreach в контроллере - PullRequest
0 голосов
/ 02 ноября 2019

Я новичок в 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 ]

1 голос
/ 02 ноября 2019

Есть еще более простой способ сделать это ... если вы просто добавите ограничение комментария к внешнему ключу в таблице ответов к комментарию ..

$table->unsignedInteger('comment_id');

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

Последняя часть: onDelete('cascade')гарантирует, что все ответы будут удалены после удаления комментария :), поэтому вам не придется делать это вручную на прикладном уровне.

Дайте мне знать, если это имеет смысл:)

0 голосов
/ 02 ноября 2019

Если вы хотите удалить отношения через Laravel, вам необходимо переопределить функцию boot.

Переопределить boot() в вашей модели комментариев, например

protected static function boot()
    {
        static::deleting(function (Comment $model) {
            $model->replies()->delete();
        });

        parent::boot();
    }

Это будетудалить все ответы, связанные с комментарием, когда этот комментарий удален с помощью eloquent.

0 голосов
/ 02 ноября 2019

Что плохо в вашем коде, так это то, что вы создаете запрос базы данных, но не выполняете его:

// 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();
0 голосов
/ 02 ноября 2019

Вместо удаления ответов в цикле, вы можете удалить их все сразу:

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

Reply::whereIn('comment_id', $comment_ids)->delete();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...