【问题标题】:Correct way of implementing a service layer in CodeIgniter applications在 CodeIgniter 应用程序中实现服务层的正确方法
【发布时间】:2017-03-20 00:47:37
【问题描述】:

以下是在 CodeIgniter 应用程序中实现服务层的两种方式。

第一种方法

1.send request to the controller 
2.calling service layer methods from controller
3.return processed result data set(D1) from service layer to controller 
4.then according to that data set controller demand data from model
5.model return data set(D2) to the controller
6.then controller send second data set(D2) to view.

第二种方法

1.send request to the controller
2.calling service layer methods from controller
3.service layer demand data from model
4.model send requested data set(d1) to the service layer
5.after some processing return generated data(d2) to controller from service layer
6.then controller send data set(d2) to view. 

在 CodeIgniter 中实现服务层的正确方法是什么?除了这两种方法,还有什么好的方法吗?

如果你能在代码中提供一个例子,那就太好了

【问题讨论】:

  • 这个问题似乎没有必要用 Codeigniter 进行标记。 Cz codeigniter 不会在没有控制器命令的情况下加载任何外部视图。

标签: php codeigniter oop service-layer


【解决方案1】:

您应该使用第一个。因为在 MVC Web 应用程序中,控制器用于将您的业务逻辑与视图分离,它类似于网关。您需要开始使用控制器处理您的信息,您应该从控制器调用模型或服务层或您需要的任何东西,最后您应该从这里将数据返回到任何其他来源。您的视图或服务层不应直接访问模型。

【讨论】:

  • 服务层不应该直接访问模型?
【解决方案2】:

恕我直言,这里没有对错:

选项 #1 - 如果你想在多个控制器/动作中重用服务层 并根据请求为它提供来自不同模型的数据,这对第一个是有意义的。

选项 2# - 但是,如果您的数据模型更复杂,第一个选项可能会出现问题。如果需要根据第一次调用的数据对模型进行第二次调用怎么办?将控制器用于此业务逻辑违背了服务层的全部目的。在这种情况下,最好选择第二个。

我觉得第二种比较常见。

【讨论】:

  • 但是,如果我使用选项 2,然后以某种方式想要摆脱控制器怎么办?那我应该怎么处理那个控制器的行李呢?
【解决方案3】:

请注意,这不一定是正确的方法,但我将解释类似框架通常如何做到这一点,然后您可以了解其他方法并确定最适合您的方法用例。因此,我不希望这个答案是正确的,但我希望它至少能在真正知道他们在说什么的人出现并附和(也对那些人- 请随时编辑/否决这个答案:D)。最后,这也与 CodeIgniter 无关,而是与一般框架有关。您的问题不仅应与框架无关,还应与语言无关。

所以我要在这里提供一个观点,那就是所有现代框架,特别是 PHP,不做 MVC。为什么这很重要?因为我们都需要说同一种语言,而 PHP 中不存在“mvc”。这是事实。接受这一点,然后我们就可以继续对框架使用的概念进行混蛋; CodeIgnitor 是“MVC”混蛋的一个特别好的例子;此后称为带引号的“mvc”。

有利的一面是,像 Symfony 这样的框架,例如,提供了一个初始的固执己见的架构,该架构至少包含某种形式的跨应用程序的一致性,它是这样的:

  1. 一个标准的 HTTP 请求进入并到达前端控制器,通常是 app.phpapp_dev.php,具体取决于您是处于开发还是生产环境;一种涉及大量缓存,需要在每次更改时运行,而另一种则不需要 - 这非常适合开发。

  2. 路由器将当前 url 与控制器类和该类中的“动作”(方法)相匹配。

  3. 框架的依赖注入部分计算出从控制器向前到模型层再返回的所有内容都需要哪些对象,并在需要时实例化或准备实例化它们。

  4. 使用任何所需的依赖项实例化控制器并执行相关方法。这通常是您开始开发并将代码“挂钩”到框架的地方。

  5. 这是您决定架构的地方,但是,无论从开发人员角度还是业务角度(为了降低未来维护成本),最重要的是一致性

  6. 我个人更喜欢确保我的代码与框架分离。我将从请求中获取的标量传递给应用层服务,该服务使用来自模型层的对象(通过 DI 传入)来使用域对象。这里的重点是域对象不是直接传递到控制器,它们是通过应用层介质代理的,所以理论上你可以替换围绕它的整个框架,你需要做的就是将这些标量传递到这一层在他们到达模型层之前,它仍然可以工作(想想 CLI 调用,没有更多的控制器)。

  7. 1234563日常使用),然后将该数据返回到应用程序级服务。
  8. 然后服务将数据返回给控制器,你猜怎么着?这就是框架容易搞砸的地方!因为在今天的框架中没有“视图”的概念。只有一个模板,然后你将这些数据传递给一个模板,然后就可以了。所以在你的图表中,绝对没有视图的概念,因为事情不是这样完成的。老实说,我仍然在使用模板,因为它们是最快的做事方式,但是在现代框架整合它们并真正开始使用视图之前,我们运气不好,必须在面对时保持坚定一些(如 Laravel)将自己称为“mvc”框架的事实。

注意,Fabien Potencier 明确指出 Symfony 不是 MVC 框架——至少他知道他在说什么。同样,这不是纯粹主义者,重要的是我们在计算中都使用相同的、事实上正确的语言。

所以,因为您非常喜欢图表,所以有些人可能会用今天的框架来做这件事...

这适用于每个 Review 具有 ReviewCriteria 概念的应用程序。甚至不要让我开始研究 Symfony 表单,它们是如此耦合到所有东西,它们不是任何架构的重要组成部分。

你需要多少层效果?我们已经有了“MVC”,在 DDD 中我们有“应用程序”、“域”和“基础设施”分离的概念,所以先让这两者一起工作,然后是这个“服务层”?你真的需要另一层,还是上面的就足够了?需要考虑的事情...

你看,由于这种分离,你并没有被框架/http请求所困,让应用程序运行

看到上图中的“服务”了吗?它们与控制器分离,因此您可以从任何地方抛出标量,并且应用程序仍然可以工作。 我认为这将为您提供所需的分离。以正确的方式做事,学习如何去做,然后学习如何控制自己并在涉及到业务和需求时务实地做事是很棒的,但是框架需要整理它们的东西——你当然不会用 CodeIgniter 编写可爱的代码;)

【讨论】:

  • @teresko 来找我兄弟
  • 没什么可找你的。我不做 DDD,这意味着,虽然我不喜欢周围的结构,但在服务方面我没有什么实质性的分歧。如果我有时间的话,我可能会尝试在这里写下我自己的答案。
  • @Jimbo 如果问题与 Symfony 相关,您的解释会非常好。但在 Codeigniter 中,很少有行是正确的。 Cz 它是 PHP 中的一个小框架。
  • @AbdullaNilam CodeIgniter 仍然使用前端控制器、路由、控制器和操作方法的概念。我剩下的答案就是将你的类放在哪里,在应用程序级服务层中,与框架分开。重新阅读我的问题的顶部 - 此架构可在 任何 框架中使用,您可以在其中创建自己的类,CodeIgniter 也不例外。
  • 我的投票。答案解释了它背后的整个想法。
【解决方案4】:

依赖注入和适配器模式将是一个很好的起点。 CodeIgniter 支持既不是开箱即用的,所以你需要编写一个包装器或者一个钩子。

您的视图只能支持 xml|html,因为 json 需要预渲染为 .json 文件,然后作为输出返回,但这需要通过代码完成,在这种情况下返回对象更容易并在前端进行了更改。 PHP 是一种嵌入式语言,适用于 (xml|html)

服务模型在注入时效果最好(依赖注入) 到控制器/模型中,并作为该控制器/模型的属性列出。

然后将服务绑定到接口

例如脸书/推特 它们都具有请求和响应功能,但都遵循相似的模式,但具有不同的端点。

interface SocialMediaAdapter{
  public request(url);
  public response();
}

public class FaceBookProvider implements SocialMediaAdapter
{
     public request(url){

     }
     public response(){

     }

}

public class TwitterProvider implements SocialMediaAdapter
    {
         public request(url){

         }
         public response(){

         }
    }

public class SocialMediaServiceProvider{

    protected $provider = null;

    public function constructor(SocialMediaAdapter $provider){
       $this->provider = $provider;
    }

    public function fetch($url){
       return $this->provider->request($url);
    }
}

此处需要依赖注入

new MyController( new SocialMediaServiceProvider ( new FacebookService ) )

【讨论】:

    猜你喜欢
    • 2019-08-11
    • 2012-06-15
    • 1970-01-01
    • 2017-01-04
    • 2012-09-21
    • 1970-01-01
    • 2023-03-12
    • 2020-02-29
    • 2010-10-24
    相关资源
    最近更新 更多