مهرداد
3 سال پیش توسط مهرداد مطرح شد
12 پاسخ

نمایش نظرات تو در تو در لاراول

سلام دوسان من با استفاده از تابع بازگشتی کامنت های والد و فرزنهاشو نمایش دادم ولی نمایشش به دلم نیست میخام کامنت پدر اصلی همون رنگ خاکستری داشته باشه کامنت های فرزندش همشون width یه اندازه سفید رنگ رو داشته باشن و به این صورت تو در تو ظاهر نشن با استفاده از توابع بازگشتی به این شکل نمایش میده
توضیح تصویر رو وارد کنید

اینم کدهاشه

                @foreach ($article->comments->where('status' , \App\Comment::STATUS_ACCEPT)->where('parent_id' , null) as $comment)
                <div class="comment-1">
                    <div class="comment-photo">
                        <img class="img-fluid" src="{{$comment->user->userAvatar}}" width="100%" alt="">
                    </div>
                    <div class="comment-info" style="width: 80%">
                        <h4 class="theme-color text-info">{{$comment->user->fullName}}</h4>
                        @auth
                        <div class="port-post-social float-right">
                            <a href="#mytextarea" class="replyComment" data-commentID="{{ $comment->id }}">
                            <i class="fa fa-reply"></i>
                            </a>
                        </div>
                        @endauth
                        <p class="badge badge-danger ml-10 mr-10">{{$comment->JalaliCreatedAT}}</p>
                        <p style="white-space: pre-wrap; margin-top: 10px " >{!! $comment->body !!}</p>
                    </div>
                </div>
                    @include('front.comments.comment-child' , ['comment' => $comment])
                @endforeach

اینم کدهای بخش تابع بازگشتی

@if (count($comment->child))
<div class="comment-1 comment-2">
    @foreach ($comment->child as $child)
    <div class="comment-photo">
        <img class="img-fluid" src="{{$child->user->userAvatar}}" alt="">
    </div>

    <div class="comment-info mb-10" style="width: 80%;">

        <h4 class="theme-color">{{$child->user->fullName}}</h4>
        @auth
        <div class="port-post-social float-right">
            <a href="#mytextarea" class="replyComment" data-commentID="{{ $child->id }}">
                <i class="fa fa-reply"></i>
            </a>
        </div>
        @endauth
        <p class="badge badge-danger ml-10 mr-10">{{$child->JalaliCreatedAT}}</p>
        <p>{{$child->body}}</p>
    </div>
    @endforeach
    @include('front.comments.comment-child' , ['comment' => $child])
</div>
@endif

میخام به این صورت کامنت والد و فرزندهای رو نشون بده یعنی همه فرزندها به این شکل نمایش بده که width هم اندازه داشته باشن
توضیح تصویر رو وارد کنید


ثبت پرسش جدید
بهزاد عزیزان
@behzad.azizan 3 سال پیش مطرح شد
0

مشکلتون رو متوجه نشدم. خودتون کد سی اس اس رو نوشتید و برای کلاس replyComment استایلی تعریف کردید که تو رفتگی داره . خب این استایل رو تغییر بدید ظاهرتون درست میشه

یه موردی که توی کدتون هست اینه که اصلا بهینه نیست و باید روی بهینه بودن کدنون کار کنید. مشکلی که هست اینه که برای هر کامنت از طریق ریلیشن ها یه کوئری میخوره تو جدول کامنت. در صورتی که اکثر کامنت ها اصلا reply ندارن !
معمولا جداول نظرات توی هر سیستمی میتونه سنگین باشه و این برناه بعد از یه مدت میتونه بار زیادی رو به سرور و منابع فیزیکی وارد کنه.
میتونه یه راهکار این باشه که یه فیلد tinyint(1) توی جدول کامنت بزارید که مشخص میکنه این کامنت ریپلای (یا به قول شما child) داره یا نه. در صورتی که این فیلد ۱ بود فقط برای گرفتن ریپلای ها کوئری بزنید.
و هر بار که یک کامنت ریپلای ایجاد میشه شما شناسه ی کامنت اصلی رو که دارید ، این فیلد رو هم آپدیت کنید و اون رو ۱ کنید.
این یه مثال هست و اگه بازم فکر کنید روش شاید روش بهینه تری هم پیدا کنید


علی بیات
تخصص : توسعه دهنده ارشد وب
@ali.bayat 3 سال پیش مطرح شد
0

۲ حالت کلی برای رفع این موضوع هست

  • تغییر کوئری
  • تغییر فایل بلید

که من روش اول رو پیشنهاد میکنم. یه کوئری بنویس که از Level 1 به بعد، تمام کامنت ها رو زیر مجموعه کامنت اصلی بدونه..
به این ترتیب فایل بلید هم خیلی تر و تمیز در میاد . باید هر یک کامنت رو نشون بدی + کامنت های فرزندش رو


مهرداد
@mehrdadroshanraee69 3 سال پیش مطرح شد
0

@behzad.azizan1991
سلام حرف شما کاملا این پروژه برا رزومه ست و کسب تجربه تو پیاده سازی و نمایش کامنت های تو در تو توی وبسایت هم هست فقط یه سوال من متوجه این قسمت از صحبتتون نشدم

مشکلی که هست اینه که برای هر کامنت از طریق ریلیشن ها یه کوئری میخوره تو جدول کامنت. در صورتی که اکثر کامنت ها اصلا reply ندارن !

مگه تو بخش نظرات وبسایت اموزشی نظرات بصورت n تعداد فرزند منطقی نیس؟


بهزاد عزیزان
@behzad.azizan 3 سال پیش مطرح شد
0

@mehrdadroshanraee69 ببینید فرض کنید سایت شما دارای 10 هزار کامنت هست.
حالا فرضا برای یک پست ، 70 کامنت ارسال شده. ازین 70 کامنت 2 کامنت دارای پاسخ هستن (منظورم کامنتی هست که در پاسخ به کامنت دیگه ای ارسال شده)
خب با کدی که شما نوشتید برای تمام 70 کامنت یک بار یک کوئری به دیتابیس میخوره که ببینه کامنت مورد نظر child داره یا نداره . 70 کوئری در جدولی با تعداد 10 هزار رکورد! در صورتی که طبق این مثالی که من زدم فقط دو کامنت دارای ریپلای هست پس اگه الگوریتمتون درست باشه به جای 70 کوئری فقط دو کوئری دریافت میشه.


مهرداد
@mehrdadroshanraee69 3 سال پیش مطرح شد
0

@behzad.azizan1991
الان این ساختار دیتابیس منهو روابط اشتباهه؟

    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('parent_id')->nullable();

            $table->longText('body');
            $table->enum('status' , ['accept' , 'reject' , 'pending'])->default('pending');
            $table->integer('commentable_id');
            $table->string('commentable_type');

            $table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE');
            $table->foreign('parent_id')->references('id')->on('comments')->onDelete('CASCADE');
            $table->timestamps();
        });
    }
    public function commentable()
    {
        return $this->morphTo();
    }

    public function child()
    {
        return $this->hasMany(Comment::class , 'parent_id');
    }

بهزاد عزیزان
@behzad.azizan 3 سال پیش مطرح شد
0

@mehrdadroshanraee69 نه روابطتون درسته
فقط یک فیلد به نام has_child توی جدول comments بزارید که پیش فرض 0 هست. در صورتی که یک ریپلای برای یک کامنت ارسال شد این فیلد رو توی رکورد پدر یک کنید. با اینکار کامنت هایی که child دارن مشخص میشن . بعد به جای کد

@if (count($comment->child))

از این کد استفاده کنید :‌

@if($comment->has_child)

ببینید شرطی که شما گذاشتید برای هر کامنت کوئری زیر رو اجرا میکنه . یعنی به ازای هر کامنت یکبار این کوئری اجرا میشه :‌

select * from comments where parent_id = X

اما با اصلاحی که توی کد بدید اینکه یک کامنت childداره یا نداره از طریق یک فیلد به نام has_child مشخص میشه و نیازی به کوئری زدن دوباره توی دیتابیس نیست.


مهرداد
@mehrdadroshanraee69 3 سال پیش مطرح شد
0

@behzad.azizan1991
دیگه با اضافه کردن این فیلد boolean نیازی به تغییرات توی ریلیشن هایی که تعریف کردم نیس؟


بهزاد عزیزان
@behzad.azizan 3 سال پیش مطرح شد
0

@mehrdadroshanraee69 نه نیازی به تغییر ریلیشن ها نیست
فقط باید موقعی که یک ریپلای برای کامنت با شناسه مثلا 2 میاد، شما باید مقدار فیلد has_child این رکورد (کامنت با آیدی 2) رو 1 کنید.


مهرداد
@mehrdadroshanraee69 3 سال پیش مطرح شد
0

ببخشید نمونه کدی مینویسید برا این توضیحتون has_child این رکورد (کامنت با آیدی ۲) رو ۱ کنید
@behzad.azizan


بهزاد عزیزان
@behzad.azizan 3 سال پیش مطرح شد
0

@mehrdadroshanraee69 کد مربوط به ذخیره ی کامنت در دیتابیس رو بفرستید


مهرداد
@mehrdadroshanraee69 3 سال پیش مطرح شد
0

@behzad.azizan

    public function courseComment(Course $course , Request $request)
    {

        $course->comments()->create([
            'body' => $request->body,
            'user_id' => auth()->id(),
            'parent_id' =>$request->parent_id,
        ]);

        return response()->json(['success' => 'عملیات با موفقیت انجام شد']);
    }

بهزاد عزیزان
@behzad.azizan 3 سال پیش مطرح شد
0
public function courseComment(Course $course , Request $request)
    {

        $course->comments()->create([
            'body' => $request->body,
            'user_id' => auth()->id(),
            'parent_id' =>$request->parent_id,
        ]);

Comment::where('id', $request->parent_id)
      ->update(['has_child' => 1]);

        return response()->json(['success' => 'عملیات با موفقیت انجام شد']);
    }

این کدو بزارید


برای ارسال پاسخ لازم است وارد شده یا ثبت‌نام کنید

ورود یا ثبت‌نام