当您没有指定功能模型时,应将业务逻辑放在何处?Laravel

4

我正在尝试改进我的代码,使其更符合面向对象的编程原则。

我有将一些业务逻辑放在控制器(Controller)中的倾向。

有些人告诉我这是不可取的。

我知道当你处理像“帖子”这样的东西时,可以简单地将业务逻辑放在Post.php模型中。

现在我有一个功能,我需要上传一个 .xlsx 文件,并检查和验证它是否符合正确的格式。

它目前在 ScheduleController@storeDeliveryXlsx 中。

但是我没有指定用于存储验证的模型?

这是需要使用仓库设计模式吗?还是可以创建一个不与数据库通信的模型,例如: DeliveryFile.php,在其中放置我稍后可以在整个应用程序中使用的逻辑,如:DeliveryFile::validate($file);DeliveryFile::upload(file);

我认为我可能会在多个实例上重复使用相同的 .xlsx 验证。所以我想做类似于 Model::validate($file); 的事情。但我不知道该把代码放在哪里。


你想检查 CSV 文件的标题列是否有效吗? - kunal
3个回答

5
在这种情况下,我个人建议使用一个Service。Service类本质上是为您可能在多个控制器中重复使用的常见功能而设计的。Service层是一种设计模式,它将帮助您将共享逻辑抽象到一个共同的服务中,即我们的新Service类。
因此,在您的情况下,您可以拥有一个名为ExcelValidator的Service类,然后使用以下内容来构建您的方法。
<?php

namespace App/Services;

class ExcelValidatorService
{

  public function validate($file) 
  {
    // our validate logic
  }

}

然后在您的控制器或模型中,您可以调用ExcelValidator服务来实现您的重复验证逻辑。


我认为这类似于使用存储库?您知道使用服务而不是存储库的优缺点吗? - Rubberduck1337106092
3
仓库是持久性的外观,提供访问数据/对象的方式,它用于将存储数据/对象的方式与应用程序的其余部分解耦。例如,可以实现仓库模式来抽象我们在 Redis 中存储对象的事实,以便在以后决定将数据持久化到 MySQL 时,可以更换仓库。另一方面,服务提供常见功能,通常限于控制器/模型的业务逻辑。例如,我们将 Excel 验证逻辑移动到 ExcelValidator 服务中,以便其他控制器可以使用它。 - liamjnorman
我使用服务而不是仓库来修复它,因为我从未计划更改数据供应。感谢您的回答。 - Rubberduck1337106092
仓库不是门面模式。它们是两种不同的模式。 - tereško
这里并不是在提到外观模式。只是在解释仓储模式。 - liamjnorman

1
在您编写代码的过程中,“I now have a feature”这个短语会不断重复。拥有单独的控制器、服务、模型类、面向对象的设计和模块化代码无疑会有所帮助。现在可能会更容易,但随着时间的推移,它会变得越来越困难。

1

最近我遇到了一个类似的问题,我的情况是需要使用一个Restful API作为模型。

在composer.json文件中,我在autoload下添加了以下内容:

"psr-4": {
    "App\\": "app/",
    "MYCOMP\\": "app/MYCOMP/"
},

在应用文件夹下,我添加了名为MYCOMP的文件夹,其中包含两个子文件夹Providers和Restmodels。

在config/app.php文件中的提供者数组中,我仅添加了:

MYCOMP\Providers\RestModelServiceProvider::class,

在 app/MYCOMP/Providers/RestModelServiceProvider.php 中,我注册了所有 rest 模型的提供者和门面:
public function register()
{
    $loader = \Illuminate\Foundation\AliasLoader::getInstance();

    $models = glob( realpath(__DIR__."/../") ."/RestModels/*/*RestModel.php");
    foreach($models as $model){
        $bnmodel = basename($model);

        if($bnmodel !== "BaseRestModel.php" && $bnmodel !== "BaseFacadeRestModel.php"){
            list($n, $niente) = explode("RestModel.php", $bnmodel);
            list($bnnoext, $niente) = explode(".php", $bnmodel);
            $res = $n.'Repository';
            $fold = basename(dirname($model));
            $nc = "\\MYCOMP\\RestModels\\".$fold."\\".$bnnoext;  
            $this->app->bind($res, function($app) use ($nc) {     
                return new $nc;
            });               
            $loader->alias($res, $nc."Facade");
        }
    }
}

这段代码是特定于我的项目,以及我如何构建文件夹。 对于所有其他模型,我有两个文件:
  • app/MYCOMP/RestModels/{ModelName}/{ModelName}RestModel.php
  • app/MYCOMP/RestModels/{ModelName}/{ModelName}RestModelFacade.php
唯一的例外是:BaseRestModel和BaseFacadeRestModel,这些类被所有的RestModel和RestModelFacade继承。因此,我会在BaseRestModel下实现类似validate的功能。
BaseFacadeRestModel只包含:
<?php

namespace MYCOMP\RestModels\Base;
use Illuminate\Support\Facades\Facade;

class BaseFacadeRestModel extends Facade{
    private $facadeName;

    protected static function getFacadeName(){
        list($senzasuffisso, $niente) = explode("RestModelFacade", static::class);

        $nc = last(explode("\\", $senzasuffisso));
        return $nc;
    }

    protected static function getFacadeAccessor() {
        return static::getFacadeName().'Repository'; 
    }
}

所以所有其他外观都是通过扩展BaseFacadeRestModel来工作的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接