【问题标题】:Is it bad practice to use the same method for SAVE and UPDATE?对 SAVE 和 UPDATE 使用相同的方法是不好的做法吗?
【发布时间】:2019-10-04 15:18:49
【问题描述】:

我使用的是 laravel,但这并不重要,当您使用 laravel 命令行工具创建控制器时,它会在其中放置 4 个默认函数用于创建和更新。

createstore 对应 save

editupdate update!

这是 laravel 对 Shop 控制器的建议。

class ShopController extends Controller
{

    public function create()
    {
       // return create view
    }

    public function store(Request $request)
    {
      // save a shop
    }

    public function edit($id)
    {
        // find a shop , return edit view
    }

    public function update(Request $request, $id)
    {
        // find the shop with id , update the shop
    }

}

但我喜欢使用相同的方法来显示视图和存储/更新我的行,避免编写大量额外代码。

class ShopController extends Controller
{

    public function create($id  = 0)
    {
        return view('shop-create' , ['edit'=> Shop::find($id)]);
    }

    public function store(Request $request , $id = 0 )
    {
        $whitelist = [
            'title'=>'required',
            'phone'=>'present|numeric' ,
            'address'=>'present' ,
        ];
        $this->validate($request, $whitelist );
        $shop = Shop::findOrNew($id) ;
        // find a shop with given id or create a new shop instance
        foreach($whitelist as $k=>$v)
        $shop->$k = $request[$k];

        $shop->save();
     }

}

我自然会选择我喜欢的方式(第二种选择),但是由于 laravel 建议第一种方式,出于好奇,我有什么理由不这样做吗?这在任何方面都被认为是不好的做法吗?

【问题讨论】:

  • 显示你的视图源代码。
  • 最好不要违背框架的约定,以后可能会混淆你和其他人。拥抱 Laravel 的做事方式,您将获得更容易遵循的文档,并且更容易利用框架功能。

标签: php laravel eloquent


【解决方案1】:

没有错,但是你的代码会更难理解,恕我直言。

例如

  • 这个方法有什么作用?它叫create,但它也可以编辑?
  • 视图名为shop-create,但它也可以编辑?
  • 没有必要每次都将0 参数作为id 的默认值传递并尝试find

public function create($id  = 0)
{
    return view('shop-create' , ['edit'=> Shop::find($id)]);
}

尽管您认为自己正在简化代码,但由于您违反了 SOLID 中的 Single Responsibility 原则,因此您将其变得更加复杂。

如果你有类似 Laravel 的建议的话会更容易理解。

您还保留了一个任何 Laravel 开发人员都会理解的非常常见的模式,因此您可以聘请某人来处理您的代码,不用担心他是否会理解。

【讨论】:

  • thanx ,如果id 大于0,我总是可以重命名方法/视图和find ...但我明白你的意思,你是对的,我会使用单独的方法跨度>
【解决方案2】:

按照自己的方式做事没有错。您提到的“laravel”方式是当您创建 Restful resource controller 时,这只是解决它的一种方法。

我猜这些控制器方法之所以被选中是因为它们很好地符合“安静”类型的控制器。如果你要构建一个真正的 rest api,那么从标准的角度来看,你如何做到这一点会变得更加严格(不是 laravel 强加的,而是更符合 laravel 的方式)。

如果您不创建面向公众的 api,或将被外部实体使用的东西,那么我建议您设计最适合您和您的团队的控制器

【讨论】:

    【解决方案3】:

    这就是我通常的做法,这样您仍然可以通过使用请求进行不同的验证,并且仍然清楚 (imo) 函数的作用。

    public function store(AdminPartnerRequest $request)
    {
        return $this->handleCreateOrUpdate($request);
    }
    
    public function update(AdminPartnerRequest $request, $id)
    {
        return $this->handleCreateOrUpdate($request,true, $id);
    }
    
    
    private function handleCreateOrUpdate($request, $edit = false, $id = null)
    {
       if ($edit){
           $partner = Partner::find($id);
       } else{
           $partner = new Partner();
       }
    
            $partner->name = $request->input('name');
            $partner->picture = $request->input('image');         
            $partner->save();
    
            return \Redirect::route('admin.partners.index');
    }
    

    【讨论】:

      【解决方案4】:

      对 save() 和 update() 使用相同的函数是个好主意,但同时它会增加复杂性.. 一点是,如果将来您想更改任何内容,您只需要在一个地方进行更改。 但与此同时,您需要格外小心。

      因为你的功能应该更加动态。

      1) 多条记录操作:您可能需要同时更新多个原始数据,因此您的函数应该足够灵活,可以通过同一函数插入/更新单个/多个值。意思是,在这两种情况下都应该针对多条记录触发单个查询。

      2) 验证值是否已存在:当您要检查某些验证时... 在插入情况下,您只需要检查数据库中是否存在该值 在更新情况下,您需要检查排除当前 ID 例如

      用于插入盒

       $this->validate($request, [
              'email' => 'required|string|email|unique:tablename,email'
          ]);
      

      更新案例

        $this->validate($request, [
              'email' => 'required|string|email|unique:tablename,email,'.$id.',id'
          ]);
      

      最后是很小的一点,但需要考虑..

      3) 成功消息: 插入消息时应“添加成功”,更新时记录“更新成功”

      【讨论】:

        【解决方案5】:

        小项目,随心所欲。与其他开发人员大,遵守约定。

        编码约定是针对特定编程语言的一组指导方针,为用该语言编写的程序的各个方面推荐编程风格、实践和方法。这些约定通常涵盖文件组织、缩进、cmets、声明、语句、空格、命名约定、编程实践、编程原则、编程经验法则、架构最佳实践等。这些是软件结构质量的指导方针。强烈建议软件程序员遵循这些准则,以帮助提高其源代码的可读性并使软件维护更容易。编码约定仅适用于软件项目的人工维护者和同行评审者。约定可以在整个团队或公司遵循的一组书面规则中正式化,或者可以像个人的习惯性编码实践一样非正式。编译器不强制执行编码约定。 -- https://en.wikipedia.org/wiki/Coding_conventions

        【讨论】:

          【解决方案6】:

          我在我的最后一个项目中使用了这种方法,我们调用了store()update() 函数manage(),并有一个getManage(),它将使用相同的视图进行创建和编辑。我非常喜欢这种方法,但遇到了一些值得注意的事情。可悲的是,如果您不得不面对这些问题,则缺点会超过优点:(

          优点:

          • 更小的代码 - 您的 store()update() 函数中不再有重复的代码行。
          • 更快地重复使用基本模型 - ctrl+c ctrl+v ctrl+f ctrl+r 如果你明白我的意思。
          • 更容易添加/更改输入值 - 额外的值并不意味着必须更改 store()update() 以确保它们都使用额外的输入。
          • 一个函数统统统统 - 只要您不做任何特别的事情,您甚至可以为所有事情定义一个函数。需要改变一些东西吗?您只有一个功能,不用担心。

          缺点:

          • 对于其他人(或年长的您)来说,代码更难理解 - 如果有人不熟悉此方法或有一段时间没有使用它,那么理解您的函数中发生的事情比拥有两个单独的函数要困难一些。
          • 验证很麻烦 - 如this answer 中所述,创建和更新的验证可能不同。这意味着您有时可能必须编写两个验证,这最终会导致代码混乱,我们不希望这样!
          • 值插入并不像我想象的那么酷 - 如果您想使用相同的预定义数组来创建或更新,那么您可能会遇到想要在创建时插入值但又不想更新它们的问题。这最终导致了丑陋的 if 语句或两个预定义的数组。

          最终,这取决于你要做什么以及你想做什么。如果您有一个可以管理博客文章和页面的基本网站,那么不用担心共享store()update() 功能。但是,如果您要创建一个包含许多模型、关系以及不同的创建和更新输入值(这可能意味着不同的验证)的大型 CMS,那么我会采用 Laravel 的建议。从长远来看,它会更容易维护,并且您不必处理令人头疼的问题、hacky 修复和不干净的代码。

          无论您做什么,都不要在不同的控制器中同时进行!那会令人困惑。

          顺便说一句,如果您想知道我有什么样的项目 - 那是一个巨大的 CMS。因此,尽管它在某些情况下非常有用且简单,但遗憾的是不值得。

          【讨论】:

          • thanx ,非常有见地......我正在为客户编写一个团购网站......它不小但相当简单,至少在 CRUD 方法中没有任何复杂的事情发生,但我仍然想我会用不同的方法去
          • @max 不用担心。在这种情况下,最好坚持使用 Laravel 提供的内容,因为当您自己无法找出问题所在时,其他人更容易修复错误。遗憾的是,这种方式有时很无聊,并且可能感觉您在输入两次相同的内容。但从长远来看,无聊比头痛更值得:P
          【解决方案7】:

          没有错,但在这种情况下,您必须维护适当的 cmets,以指定您的函数执行添加/编辑,并为此使用 $id 之类的变量或其他东西。如果它可用,则可以更新记录,否则插入它。

          【讨论】:

            猜你喜欢
            • 2011-11-16
            • 1970-01-01
            • 2020-01-16
            • 2010-11-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-04
            • 2021-08-30
            相关资源
            最近更新 更多