نحوه پیاده سازی بخشی از برنامه که به تعداد زیادی از تیبل ها نیاز دارد .

پرسیده شده
فعالیت 1035 روز پیش
دیده شده 360 بار
0

سلام وقت بخیر برای پیاده سازی بخشی از برنامه که با تیبل های زیادی سروکار دارد به چه صورت باید پیاده شود که     coupling به حداقل برسد و اصل ocp,srp نقض نشود.به عنوان مثال یه پست وبلاگ یا یک محصول فروشگاهی که تیبل کتگوری،لایک،هشتگ،ویو،کامنت و یوزر، پرمیشن،.. و را  شامل میشه ما برای اینکه یک پست را نشان دهیم نیاز به همه تیبل ها داریم و این باعث شده هم کلاس اصل ocp,srp را نقض کند و هم اینکه متد ها باد کنن و یا به اصطلاح bloat بشن. حالا باز میشه متد را تکه تکه کرد و کوچیک کرد ولی بقیه حالات رو نمیشه اصلاح کرد.با اینکه برنامه به خوبی کار میکنه ولی بشدت کلاس ها و متد ها به هم کاپل شدن برای این بخش و تغییر بخش از کد در این حالت باعث میشه متد ما عملکرد درستی نداشته باشد.چه راه حلی پیشنهاد میدید برای چنین بخش هایی که با تیبل های زیادی سر و کار داره به چه صورت باید پیاده بشه.

فایل پیوست

امیر
امیر

1 تیر 00

0
حذف شده

سلام و احترام

اگه توی پروژتون جدول های دارید که داره به صورت اشتراکی کار میکنه باید داخلش دو تا فیلد داشته باشید که مشخص باشه دقیقا چه کلاسی ازش استفاده کرده و با چه آیدی.

برای مثال میتونید برای جدول comments میتونید یه فیلد داخلش بزارید به اسم commentabletype و commentabl_id که داخل type همون typeی میشینه که داره ازش استفاده میکنه، برای مثال شما برای ویدیوهاتون بخش comment گذاشتید میتونید داخل این type بنویسید videos و داخل اون commentabl_id هم id همون ویدیویی رو بزارید که زیرش کامنت گذاشته

حالا همین ساختارو میتونید میتونید برای عکس ها، برای بخش پادکست ها و.. بزارید، لینک زیر لینک روابط polymorphic توی لاراوله که توضیحات و مثال زده که همین چیزی بود که من گفتم، حتما بهش یه سری بزنید اگه سوال داشتید مطرح کنید تا بهتون کمک کنیم

 

 

https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-polymorphic-relations

فایل پیوست

امیر صالحی

توسط

امیر صالحی

2 تیر 00

حذف شده
ممنون این موردی که گفتید بخشی از سوالمو جوابش رو گرفتم ولی بخش دیگه سوالم و مشکلی که برام پیش اومده رو ببخشید تو کامنت بعدی میگم چون اینجا طولانی میشه نمیشه فرستاد.
امیر

2 تیر 00

0
حذف شده

الان فرض کنید در نرم افزارمون یه بخشی داریم که پست های وبلاگ یا مقاله هارا نشان میدهد خب این پست ها خودشون شامل چند تیبل میشه که با کلاس اصلی پدر که همون پست ها هست رابطه composition دارد الان من برای اینکه این تیبل هارو به هم ربط بدم، ینی من باید مدل های تیبل رو در کلاس پدر فراخوانی کنم یا کنترولر هارو. 

من بخشی از کدمو اینجا قرار میدم 

<?php
namespace App\Controllers;
use App\Controllers\Uploader\UploadsController;

class PostsFeed{
    protected $postId;
    protected $posts;
    protected $comments;
    protected $tags;
    protected $category;
    protected $like;
    protected $view;
    protected $user;
    protected $uploader;
    public function __construct(int $postId)
    {
        $this->posts=new \App\Controllers\PostsController();
        $this->comments=new \App\Controllers\CommentController();
        $this->tags=new \App\Controllers\TagController();
        $this->category=new \App\Controllers\PostCategoryController();
        $this->like=new \App\Controllers\LikeController();
        $this->view=new \App\Controllers\PostReviewController();
        $this->user=new \App\Controllers\UserController();
        $this->uploader=new UploadsController();
        $this->postId=$postId;
    }

    public function getFeed():array
    {
        $post=$this->posts->find($this->postId);
        $image=$this->uploader->get($post->image_id);
        $tags=$this->tags->findBy('post_id',$this->postId);
        $category=$this->category->postCategory($this->postId);
        $like=$this->like->getPostLikeCount($this->postId);
        $comments=$this->comments->getAllCommentsBy([['comments.post_id','=',$this->postId],['comments.status','=','1']]);
        $commentsCount=count($comments);
        $view=$this->view->postViewCount($this->postId);
        $author=$this->user->find($post->author_id,'username,fullname,profile,user_id');
        $isUserLikeThisPost=$this->like->isUserLikeThisPost($this->postId);
        return ['posts'=>$post,'tags'=>$tags,'category'=>$category,'comments'=>$comments,
            'commentsCount'=>$commentsCount, 'likeCount'=>$like,'view'=>$view
            ,'isUserLikeThisPost'=>$isUserLikeThisPost,'author'=>$author,'image'=>$image];
    }
}

function clientCode(PostsFeed $posts){
    return $posts->getFeed();
}

 

اینم هوم کنترولر که صفحه اول همه پست ها نمایش داده میشه

 

<?php

namespace App\Controllers;

use App\Core\Request;
use App\Models\Post;
use App\Models\PostCategory;
use App\Models\Tag;
use App\Models\User;
use App\Utilities\ArrayTools;
use App\Utilities\Load;
use App\Utilities\Pagination;
use App\Utilities\Sorting;
use hisorange\BrowserDetect\Exceptions\Exception;
use Src\helpers\HttpClient;


class HomeController
{
    private $category;
    private $comment;
    private $postController;
    private $request;
    private $client;
    private $postsTags;

    public function __construct()
    {
        $this->request = new Request();
        $this->category = new CategoryController();
        $this->comment = new CommentController();
        $this->postController = new PostsController();
        $this->postsTags=new PostsTags();
        $this->client=new HttpClient();
    }

    public function index()
    {
        $search='%'.$this->request->search.'%';
        $data['page_index'] = $this->request->page_index ?? 1;
        $data['post_count'] = $this->postController->getPostsCount([['status','=','1']],$search);
        $data['page_size']  = $this->postController->getPageSize();
        $data['page_number'] = Pagination::pageNumber($data['post_count'],$data['page_size']);
        $posts=$this->postController->getAll($data['page_index'],[['posts.status','=','1']],$search,'posts.created_at',null);
        $result=[];
        if(empty($posts))
           $this->renderErrorPage('Sorry, no content was found!');

        $postsId=array_column($posts,'post_id');
        foreach ($postsId as $index => $postId) {
            $posts=new PostsFeed($postId);
            $result[$index]=clientCode($posts);
        }
        $data['feeds']=(object)$result;
        $data['postCategory']=$this->category->getPostsCategory();
        $data['postComments']= $this->comment->getPostsComment([['comments.status','=','1']]);
        $this->renderIndexPageInfo($data);
    }

    public function renderIndexPageInfo($data)
    {
        $data['title']='Blog | Main';
        Load::template('tpl-main')->view('home.index', $data);
    }

    public function renderErrorPage($message,$errorCode=404)
    {
        Load::template('tpl-main')->view('errors.ErrorNotification', ['message'=>$message,'ErrorCode'=>$errorCode]);
    }
    }

الان نگاه کنید متد ها خیلی حجمش زیاد شده و کنترولش سخت شده الان درون کنترولر هوم و متد ایندکس یسری  عملیات داره انجام میشه مثل پیدا کردن صفحه، گرفتن تعداد مطالب و گرفتن سرچ و.. آیا این جور کارها باید تو کنترولر انجام بشه یا باید تو کلاس دیگری انجام بشه و صرفا خروجی تو کنترولر فراخوانی بشه و به ویو پاس داده بشه و همچنین کلاس postsFeed که اطلاعات یه پست رو میگیره و کنارهم قرار میده آیا به این صورت که این کلاس نوشتم باید برای اینجور بخش ها که با چندین تیبل در ارتباط هستند باید عمل کنم؟ بهینه هست ؟ پیشنهاد شما چیه؟ممنون

فایل پیوست

امیر

توسط

امیر

2 تیر 00

0
حذف شده

سلام و احترام

اگه ارتباط از نوع تیبلی هستش بهتره که ارتباط درون کلاس مدل پیاده سازی بشه چون مدل ها با جداول دیتابیس در ارتباطن و به هم ربط دارن، اما اگه ارتباط بین کلاس ها قرار بشه که بهتره بین همون controller ها ارتباط بر قرار بشه.

امیدوارم که سوالتون رو درست متوجه شده باشم اگه جوابتون این نیست لطفا یه خورده واضع تر توضیح بدید

 

راجب متد getFeed میتونید مستقیم مقادیر ها رو آرایه بدید و داخل متغیر ذخیره نکنید که فضا بگیره

 public function getFeed():array
    {
        $comments=$this->comments->getAllCommentsBy([['comments.post_id','=',$this->postId],['comments.status','=','1']]);

        return [
            'posts' => $this->posts->find($this->postId),
            'tags' => $this->tags->findBy('post_id',$this->postId),
            'category' => $this->category->postCategory($this->postId),
            'comments' => $comments,
            'commentsCount' => count($comments), 
            'likeCount' => $this->like->getPostLikeCount($this->postId),
            'view' => $this->view->postViewCount($this->postId),
            'isUserLikeThisPost' => $this->like->isUserLikeThisPost($this->postId),
            'author' => $this->user->find($post->author_id,'username,fullname,profile,user_id'),
            'image' => $this->uploader->get($post->image_id),
        ];
    }

اما راه مناسب تر اینکه شما سعی کنید داخل مدل user یه متد بسازید به اسم tags که میتونید راحت تر از طریق posts متد tags رو صدا بزنید و تگ های اون post رو دریافت کنید به جای اینکه بیاید جدا صداش بزنید ببرید داخل مدل و از اون کوئری رو بزنید، به این شکل

$this->posts->find($this->postId)->tags();

به عنوان یه چالش داشته باشید و سعی کنید حلش کنید، اگه به این شکل صدا زدن متد سخته براتون میتونید به شکل زیر هم حلش کنید

 

$this->posts->find($this->postId, ['tags']);

میتونید به عنوان پارامتر دوم مثلا Relation اون پست رو بدید و داخل find طوری پیاده سازی کنید که بتونه بره از جدول tags تگ های مربوط به اون پست رو هم برگردونه

فایل پیوست

امیر صالحی

توسط

امیر صالحی

2 تیر 00

حذف شده
آها ممنون پس شما می گید ارتباط بین جداول توی مدل ها پیاده بشه ، آره بنظرم اینجوری ساده تر میشه . فقط یه نکته دیگه از سوالم اینه داده هایی که از ریکوئست کاربر میاد مثل sort کردن محصول یا سرچ کردن ، اینا باید کجا گرفته بشه تو همون متدی که ویو صدا زده میشه؟ یا تو متد جداگانه؟ چون تیبل ها جداست باید ینی بین همه تیبل ها یک جوین بزنم ؟ سمت مدل؟ یا اینکه برای هرکدام جوین جدا زده بشه؟
امیر

3 تیر 00

0
حذف شده

و ببخشید یه سوال دیگم اینه ما برای هر تیبل هم باید کنترولر داشته باشیم؟ یا برای تیبل هایی که ویو برای نمایش دارند فقط باید کنترولر داشته باشیم؟

فایل پیوست

امیر

توسط

امیر

3 تیر 00