讨论 Web 开发中 PHP 项目的合理分层

有时候写着写着代码,就会觉得自己写的一团糟。觉得这儿也不合理,那儿也不合理。强迫症更是为了很小的一些东西纠结半天。

在此只是讨论一下代码整体目录结构的分层合理性,并不是什么标准,也只是说一些自己的见解和大家一起讨论。

controller

 当我们收到一个请求的时候,会先进入controller,那么这层应该做什么事情呢?我个人认为controller层应该做3件事情

1. 接收并验证参数的基本类型正确性和参数的必须性
2. 调用logic,可以调用多个logic
3. 返回响应

我们应该在这一层验证参数的基本正确性,而且只允许调用logic,可以调用多个logic进行配合完成最终的业务处理。至多写个if else调用不做其它处理。

logic

logic层,分发控制逻辑层,只能被controller调用,这层应该做3件事情

1. 进一步验证参数的正确性,比如是否存在数据,或者其他复杂逻辑的验证
2. 调用service层,可以调用多个service实现具体业务,比如调用serviceA得到结果,再传入serviceB获取数据。
3. 返回结果

每个controller都应该对应一个logic,而且方法一一对应,这层我们用来进一步验证参数的合法性,以及控制service层,使得彼此配合完成业务。这层只能调用service。而不能相互调用。

service

service层,具体的业务层,这层应该书写详细的逻辑处理,

1. 书写具体逻辑,一般可以是被多次调用的。这层需要灵活的解耦,以便于logic调用。
2. 调用model层,model层应该只能被service调用。
3. 返回结果

service只能被logic调用,不能彼此调用

lib

现在还有一个问题就是,service层可能会相互依赖,比如serviceA依赖serviceB,或者同时logicA也依赖serviceB,那么service是不应该互相调用的。我个人想法是在service层建一个lib。我们可以把serviceA依赖serviceB的方法提取出来,写一个Trait亦或者是一个类。总之service的共用方法提取到lib里面。这样完成解耦。

model

model我觉得没有争议,就是和数据库打交道。
最终目录结构
Controller
Logic
Service
    --Lib
Models

总体流程就是 controller调用logic,logic调用service,service的彼此依赖提取到lib中,service调用model。这样配合完成最终的处理。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 12
Summer

我来抛砖引玉哈。

不建议分层太多,整太复杂。

KISS —— keep it simple and stupid.

一个优秀的项目结构就是你写的时候很舒服、方便,一两年过去了,需要修改代码,还可以轻松定位到。

分层太多,真正写代码时,一些简单的逻辑会让你无法决定放在哪里。

之前有个同事,觉得 Model 里不该写业务逻辑,就弄了个 Repository 模式。几个月后过去了,发现他还是在 Model 层里还是写业务逻辑,询问的结果是:他用了一段时间的 Repository 模式后,后面觉得 Repository 太费劲,没有直接 Model 来着方便,就又回到 Model 层写逻辑。可是项目推进很快,原有代码没写测试不敢轻易重构,导致整个项目陷入混乱。

不要过多设计,保持简单是最佳实践。

3年前 评论
Jiangqh 3年前
lyxxxh 3年前
欧皇降临 3年前

开发思路应当这样

  1. 先使用最简单的 mvc 写下去
  2. 遇到 或 预判 到 重复逻辑 , 则提取到 service 或 logic 层
  3. 不要为了分层而分层 , 每层应该在它最需要的时候出现
  4. service 或 logic 应该只专注业务 , 数据验证和过滤不应在此层进行 , controller 传递过来的数据必须是可靠地
3年前 评论
Summer

我来抛砖引玉哈。

不建议分层太多,整太复杂。

KISS —— keep it simple and stupid.

一个优秀的项目结构就是你写的时候很舒服、方便,一两年过去了,需要修改代码,还可以轻松定位到。

分层太多,真正写代码时,一些简单的逻辑会让你无法决定放在哪里。

之前有个同事,觉得 Model 里不该写业务逻辑,就弄了个 Repository 模式。几个月后过去了,发现他还是在 Model 层里还是写业务逻辑,询问的结果是:他用了一段时间的 Repository 模式后,后面觉得 Repository 太费劲,没有直接 Model 来着方便,就又回到 Model 层写逻辑。可是项目推进很快,原有代码没写测试不敢轻易重构,导致整个项目陷入混乱。

不要过多设计,保持简单是最佳实践。

3年前 评论
Jiangqh 3年前
lyxxxh 3年前
欧皇降临 3年前
aodaobi

controller=> service=> model,多了确实就很烦躁

3年前 评论
kis龍 3年前
Colorado 3年前

c->s->m就够了吧 其他的感觉多余

3年前 评论

c->s->m 或者,c->m ,或者 c。
如果只是一个数据的创建,一个c就够了,稍微复杂点的 c->m,有各种复杂情况的 c->s->m

3年前 评论

c->s->m,最佳体验 :kissing_heart: :kissing_heart:

3年前 评论
congcong (楼主) 3年前

Logic+Service 典型tp3.2项目

3年前 评论

controller=> service=> model
我感觉这个就够了

  • controller 业务+逻辑

  • service 提供数据,比如 UserService::user(1); 获取用户ID 1 的用户信息, 可以添加自定义字段

  • model 模型,访问数据库

PS: 同一个逻辑会在多个地方使用吗? 大多数逻辑只用1次吧?

3年前 评论

开发思路应当这样

  1. 先使用最简单的 mvc 写下去
  2. 遇到 或 预判 到 重复逻辑 , 则提取到 service 或 logic 层
  3. 不要为了分层而分层 , 每层应该在它最需要的时候出现
  4. service 或 logic 应该只专注业务 , 数据验证和过滤不应在此层进行 , controller 传递过来的数据必须是可靠地
3年前 评论

@liu126 同意

基本和你一样。mvc ,有重复的编写lib公共类,供其它类调用。
如果逻辑太长,也提取出来。

3年前 评论

原来还有lib,我一般都是直接依赖注入解耦(违背你说的service不能相互调用)

3年前 评论
congcong (楼主) 3年前

c-s-m,…………我见过有的项目在service中,直接调用request()拿参数,然后实例化model 保存。个人感觉又点别扭,但又不敢说,希望楼主点评一下 :grin:

2年前 评论
ZJalen 2年前

c-s-m 传参的方式? 假如业务是新建人员,参数有5个,分别是编号No性别sex年龄age身高height体重weight,。。。
service中,是接收5个参数function create(No,sex,age,height,weight),还是接收一个array参数function create(array data) ?

2年前 评论
ZJalen 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!