【问题标题】:Lines of code duplicated in Controller, where to create a method with them?Controller中重复的代码行,在哪里用它们创建方法?
【发布时间】:2015-11-10 17:28:25
【问题描述】:

Aloha,我的 Controller 中有两种方法,一种用于设置头像,另一种用于更新头像。我在这两种方法中都使用了这行代码:

    $user = Auth::user();

    if (Input::file('image')) {
        $image = Image::make(Input::file('image'));
        $fullName = Input::file('image')->getClientOriginalName();
        $extension = Input::file('image')->getClientOriginalExtension();

        $pathToCreate = public_path() .'/images/'. $user->email . '/';
        $fullPath = $pathToCreate . $user->email . '.' . $extension;
        $pathDatabase = 'images/' . $user->email . '/' . $user->email . '.' .$extension;

        // Creating directory if it does not exists
        File::exists($pathToCreate) or File::makeDirectory($pathToCreate);
        $image->resize(null, 145, function ($constraint) { $constraint->aspectRatio(); })
            ->crop(130,130)
            ->save($fullPath);
        $user->picture = $pathDatabase;

我想用这行代码创建一个方法,但我觉得控制器不是一个好地方。我应该把这个方法放在哪里?

【问题讨论】:

    标签: php laravel design-patterns model-view-controller laravel-5


    【解决方案1】:

    一般来说,这取决于代码的用途。如果这是您网站上唯一会使用该代码的地方,那么将代码作为私有方法包含在 Controller 类中是完全可以接受的。

    如果此代码将在其他控制器中使用,您可能需要创建一个服务类来处理此问题。在您的控制器中使用时,这将等同于以下内容:

    $user->picture = $this->fileUploadService->process( Input::file('image') );
    

    非常简短的回答是:把它放在最有意义的地方。通用解决方案应作为服务广泛使用。一个特定的解决方案应该去任何需要特定性的地方(控制器、存储库、模型等)。

    【讨论】:

    • 谢谢Trip,这是我需要知道的。
    • @javipedrera 为了使设计更简单(KISS 模式),在您真正需要控制器之外的类中的代码之前,不要创建单独的类。就设计的 GRASP 模式而言,将函数提取到单独的类称为Pure Fabrication。如果只是将重复代码提取到同一个类中的一个方法中,则称为Extract Method refactoring
    【解决方案2】:

    你应该看看 Laravel-Stapler。对于在 Laravel 中处理图像上传非常有用。 https://github.com/CodeSleeve/laravel-stapler

    而不是保存图像并检查它是否存在,您可以将图像附加(或“装订”)到模型。

    以下是从文档中获取的有关如何设置表单的示例。

     <?= Form::open(['url' => action('UsersController@store'), 'method' => 'POST', 'files' => true]) ?>
        <?= Form::input('first_name') ?>
        <?= Form::input('last_name') ?>
        <?= Form::file('picture') ?>
        <?= Form::submit('save') ?>
     <?= Form::close() ?>
    

    模型在控制器中会有这样的东西:

     $this->hasAttachedFile('picture', [
            'styles' => [
                'thumbnail' => '100x100',
                'large' => '300x300',
                'pictureCropped' => '75x75#'
            ],
            'url' => '/system/:attachment/:id_partition/:style/:filename',
            'default_url' => '/:attachment/:style/missing.jpg'
        ]);
    

    那么你在控制器中所做的就是User::create(Input::all());

    检查“附件”是否存在就像if ($user-&gt;picture) ... 一样简单

    因此,Stapler 已经处理了文件的保存,并且通过'pictureCropped' =&gt; '75x75#' 配置自动完成了裁剪。这应该会删除足够多的代码,您不需要创建其他方法。

    希望这会有所帮助!

    【讨论】:

    • 感谢 Helliax,非常有用,但仍然需要知道哪里是创建方法的最佳位置,这不是我第一次向自己提出这样的问题。
    • 我编辑了我的答案以更具体地针对您的情况。大多数事情都将由 Stapler 完成或在模型级别处理,因此控制器中的代码非常小,我认为您不需要在其他地方重构它。
    • 再次感谢您尝试帮助我以另一种方式处理图像 Helliax,但我来到这里质疑在类似情况下我能做什么,当我有很多行代码重复多次时。我应该在哪里实现方法,在自己的控制器中,在服务中,在模型中?
    • 这真的取决于用例。每种情况都不同。如果你有具体的例子,我可以给你我的意见。
    • 我个人赞同单一责任学派,所以如果你想研究一下,你可能会看到我的答案。 en.m.wikipedia.org/wiki/Single_responsibility_principle
    猜你喜欢
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    • 2019-06-03
    • 2016-03-03
    相关资源
    最近更新 更多