代码之家  ›  专栏  ›  技术社区  ›  Jesse Orange

拉氏移动控制器逻辑到模型

  •  -1
  • Jesse Orange  · 技术社区  · 6 年前

    我正处在重构代码的阶段,我遇到了一个有趣的难题。

    ArticleController 我有一个bog标准存储方法,用于将文章存储在我的文章数据库表中。

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(StoreArticle $request)
    {
        $article = new Article();
    
        $defauultPublished = "draft";
        $IntranetOnly = false;
        $isFeatured = false;
    
        $isFeatured = ($request->get('featuredArticle') == "1" ? true : false);
        $IntranetOnly = ($request->get('IntranetOnly') == "1" ? true : false);
    
        $article->title = $request->get('title');
        $article->slug = str_slug($request->get('title'));
        $article->author = $request->get('author');
        $article->category = $request->get('category');
        $article->excerpt = $request->get('excerpt');
        $article->content = clean($request->get('content'));
        $article->featuredImage = $request->get('featuredImage');
        $article->featuredVideo = $request->get('featuredVideo');
        $article->readingTime = $this->calculateReadTime($request);
        $article->featuredArticle = $isFeatured;
        $article->IntranetOnly = $IntranetOnly;
        $article->published = $defauultPublished;
    
        $article->save();
    
        $article->handleTags($request);
    
        return redirect('editable/news-and-updates')->with('success', 'Article has been added');
    }
    

    /**
     * Calculate a rough reading time for an articles by counting the words present
     * These words are then divided by a given reading time and rounded to the nearest whole number
     * Reading time average is roughly 267 words per minute, so this also accounts for relatively slow readers
     *
     * @param Request $request
     * @return void
     */
    public function calculateReadTime(Request $request)
    {
        $readingSpeed = 200;
    
        $title = str_word_count(strip_tags($request->get('title')));
        $excerpt = str_word_count(strip_tags($request->get('excerpt')));
        $content = str_word_count(strip_tags($request->get('content')));
    
        $words = ($title + $excerpt + $content);
    
        $minutes = round($words / $readingSpeed);
    
        return $minutes . ' minute' . ($minutes == 1 ? '' : 's');
    }
    

    我的问题是这些方法是否应该转移到 Article 模特儿?

    3 回复  |  直到 6 年前
        1
  •  2
  •   Martin Bean    6 年前

    控制器应尽可能薄。遵循一种足智多谋的方法(你似乎正在这样做) store() ArticleController 全班同学要尽量做到这样:

    class ArticleController extends Controller
    {
        public function store(CreateArticleRequest $request)
        {
            $article = Article::create($request->validated());
    
            // Redirect with success message
        }
    }
    

    在这里,请求数据在到达controller方法之前在form请求类中进行了验证;然后 Article 模型实例是从已验证的数据创建的。

    其他几个音符

    ($data['featuredArticle'] == "1" ? true : false) 过于冗长。你正在做一个条件检查 true false ;不需要手动返回三元运算符中的每个值。所以这个可以简化成 $data['featuedArticle'] == '1' . 此外,如果传递值 0 默认情况下,您可以完全取消支票。如果在刀片模板中,在复选框之前放置了隐藏的输入:

    <input type="hidden" name="featuredArticle" value="0" />
    
    <input type="checkbox" name="featuredArticle" value="1" />
    

    1 如果复选框被选中(因为它覆盖了隐藏的输入值,或者 0个

    另外,试着遵守拉威尔的惯例,让你的生活更轻松。如果对输入名使用snake_case,则只会使匹配到模型属性和表列名变得更容易。所以使用 featured_article ,在模型中具有同名的属性,该属性将再次映射到同名的数据库列。这样你就可以像 create() (根据我的控制器示例)和 update() .

    最后,像计算阅读时间这样的方法肯定属于你的模型。模型表示 某物 在你的申请中。因此,你可以 和你的模特们。计算读取 条款 因此,模型实例有助于 calculateReadingTime() 方法论 条款 模型。

        2
  •  1
  •   d3jn    6 年前

    你的控制器 store 项目很好,因为它基于请求数据填充您的项目实例。它可以使用一些重构,您可以将更多的逻辑封装到 Article slug 你的内心世界 条款

    但是这条线 $article->handleTags($request); 是可疑的,因为您的模型不应该对请求进行操作-它会很快用您不想要的非常特殊的依赖关系来处理您的模型代码(当您从缓存接收标记并且没有请求实例时会发生什么情况)?如果其他类型的请求包含不同的标记,会发生什么情况?等等)。您的模型不应该了解请求或应用程序的其他部分。你的控制器正在连接它们之间的点,所以请确保 handleTags 将一些基本的抽象类型/结构作为参数(例如,数组),并确保控制器在将数据提供给文章之前从请求中获取并相应地转换数据。

    至于你的 calculateReadTime 进退两难,它肯定在你的模型里。这样想-你的文章里面有计算阅读时间所需的一切吗 条款 模特儿?答案是肯定的,这是一个article对象的属性,不管您是将其存储在DB中还是从其他属性中计算出来。制造 getReadTime

    确保你读到了 has is 关于面向对象设计的概念,它将极大地帮助您。

        3
  •  0
  •   Chukwuemeka Inya    6 年前

    我认为你应该把这些作业转到服务班。您还可以继续创建一个存储库类。这将成为您的代码结构:

    这样做 $article = new Article();

    我建议你这样做:

        ArticleService.php
    
        use Article;
    
        class ArticleService {
    
            protected $article;
    
            public function __construct(Article $article){
                $this->article = $article;
            }
    
            public function store(array $data){
                $defauultPublished = "draft";
                $IntranetOnly = false;
                $isFeatured = false;
    
                $isFeatured = ($data['featuredArticle'] == "1" ? true : false);
                $IntranetOnly = ($data['IntranetOnly'] == "1" ? true : false);
                $this->article->title = $data['title'];
                $this->article->slug = str_slug($data['title']);
                $this->article->author = $data['author'];
                $this->article->category = $data['category'];
                $this->article->excerpt = $data['excerpt'];
                $this->article->content = clean($data['content']);
                $this->article->featuredImage = $data['featuredImage'];
                $this->article->featuredVideo = $data['featuredVideo'];
                $this->article->readingTime = $data['reading_time'];
                $this->article->featuredArticle = $isFeatured;
                //Capital letter I? You should be consistent with your naming convention                
                $this->article->IntranetOnly = $IntranetOnly;
                $this->article->published = $defauultPublished;
    
                if($this->article->save()){
                    $this->article->handleTags($request);
                    return true;
                }
                return false;
            }
        }
    

    你的控制器现在变成:

        class ArticleController{
    
            protected $articleService;
    
            public function __construct(ArticleService $articleService){
                $this->articleService = $articleService;
            }
    
            public function store(Request $request){
    
                //Some Validation Logic
                $readingTime = $this->calculateReadTime($request)
                $data = array_merge(['reading_time' => $readTime], $request->all());
                return $this->articleService->store($request->all());
            }
        }
    

    我还看到您没有验证传入的请求。您应该始终这样做,因为您可以/永远不应该信任您的用户总是提供/输入正确的数据。你有责任强迫他们这么做。e、 我作为你的用户可能决定在你的电子邮件栏中输入我的名字。如果不验证该数据,最终将得到错误的数据。

    另外还有一个问题,就是将请求参数单独分配给它们相应的模型属性。我决定不这样做,以免给你带来过多的信息。

    总之,只需查看以下资源以获得更多的信息。 https://laravel.com/docs/5.1/quickstart-intermediate https://laravel.com/docs/5.6/validation 简言之,请阅读整个拉勒维尔文件!祝你好运!