V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
taaaang
V2EX  ›  PHP

PHP 的 sql 到底该写在哪儿?

  •  
  •   taaaang · 2020-04-13 18:17:18 +08:00 · 7700 次点击
    这是一个创建于 1445 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近刚接触 PHP,过了一遍 PHP 官方文档和 thinphp 的官方文档就开干。然后用到原生 sql,不知道正常情况应该写在哪儿更合适,controller ? 还是单独整一层? 或者一起放在 model 里面? 求大佬们指点下,怎么搞看起来专业一点。。。

    66 条回复    2020-05-25 11:38:41 +08:00
    zooo
        1
    zooo  
       2020-04-13 18:20:13 +08:00
    controller
    service
    dao

    dao 层里面写

    data access object
    taaaang
        2
    taaaang  
    OP
       2020-04-13 18:24:27 +08:00
    @zooo
    我一直是搞 java 方面的,最近因为做兼职项目所以搞 PHP 。 根据 thinkphp 文档来看,就提供了 controller 和 model,然后 model 主要是封装了模型的基本操作。看了一个叫 apiadmin(基于 thinkphp)的开源项目,一些数据库操作它直接就在 controller 里面写了, 很迷
    chotow
        3
    chotow  
       2020-04-13 18:33:23 +08:00 via iPhone
    Controller 注入 Service,Service 注入 Repository 。
    我个人不喜欢 DAO,所以用 Repository 。
    如果项目不大,直接在 Service 操作 DB 。
    zooo
        4
    zooo  
       2020-04-13 19:44:08 +08:00
    Repository 和 dao 差不多吧? 换个名字
    m939594960
        5
    m939594960  
       2020-04-13 19:55:48 +08:00
    @zooo #1 搞 PHP 就搞 PHP 用啥 dao 命名? 这个词除了在 java 里有意义之外还有什么实际意义么?
    emeab
        6
    emeab  
       2020-04-13 19:59:17 +08:00
    我个人做法是用 trait 封装一些常用的方法。 然后在 model 层写。php 没那么严谨 写在那层都可以
    m939594960
        7
    m939594960  
       2020-04-13 19:59:49 +08:00
    @zooo #1 搞 PHP 就搞 PHP 用啥 dao 命名? 这个词除了在 java 里有意义之外还有什么实际意义么?
    AngryPanda
        8
    AngryPanda  
       2020-04-13 20:02:24 +08:00
    @m939594960 微软也用呢。
    emeab
        9
    emeab  
       2020-04-13 20:06:21 +08:00
    tp 的 model 层类似 Java 里面的 service 层+dao 层的合体。
    sagaxu
        10
    sagaxu  
       2020-04-13 20:18:24 +08:00 via Android
    tp 用户,写哪都行,就是混在 html 里问题也不大
    yxwzaxns
        11
    yxwzaxns  
       2020-04-13 20:20:22 +08:00 via iPhone
    都是老千层饼啊
    zooo
        12
    zooo  
       2020-04-13 20:20:28 +08:00
    @m939594960 赞同 你
    Takamine
        13
    Takamine  
       2020-04-14 00:11:59 +08:00 via Android
    写在 model 吧,然后自己在 model 和 controller 之间加个 service 层。
    heyjei
        14
    heyjei  
       2020-04-14 00:23:01 +08:00
    写在 controller 里,不然就对不起 Quick And Dirty 这个称号,复杂且会存在共用的逻辑才抽取出来放 Service 里。Model 负责定义数据模型,不要把逻辑放里面了。
    guolaopi
        15
    guolaopi  
       2020-04-14 00:23:17 +08:00
    楼上说的写到 model 里是要把 model 做成 DDD 里的充血模型(滑稽
    hbolive
        16
    hbolive  
       2020-04-14 00:51:37 +08:00
    既然兼职的,controller 里干就是了,讲究那么多干啥。。
    emeab
        17
    emeab  
       2020-04-14 01:34:25 +08:00 via iPhone
    @guolaopi 学习了 之前写的小项目都是写在 model 里面的 确实有点不合理 还是抽离出一个 service 层比较好管理 和解耦
    kaiki
        18
    kaiki  
       2020-04-14 04:48:56 +08:00
    看给多少钱,钱少我就哪里需要写哪里,钱多就规范点。
    专不专业得看谁来看的,如果对方啥都不懂,那你写啥都专业。
    avenger
        19
    avenger  
       2020-04-14 07:16:02 +08:00 via iPhone
    model 里面用 orm,不写 sql 🐶
    815979670
        20
    815979670  
       2020-04-14 07:36:09 +08:00 via Android
    有 orm,调用对象就行了
    tabris17
        21
    tabris17  
       2020-04-14 08:52:26 +08:00 via iPhone
    没必要抽象出 dal,事实上项目是不可能切换数据库的
    taaaang
        22
    taaaang  
    OP
       2020-04-14 09:05:15 +08:00
    @chotow @m939594960 @sagaxu @Takamine @heyjei @hbolive
    首先感谢大佬们的围观。
    如果用 service 来封装共用逻辑,你们怎么命名文件的呢? 类似于 java 的 xxxService ? 我想既然干 php 就得像 php 。 大部分时候 model 够用,主要是有一些原生 sql 写在 controller 里面,代码文件显得很长了,也确实有一些逻辑需要抽取出来。

    我居然因为一个代码组织的问题来专门提个问题,也真是心累了。。。
    AlanLeung2018
        23
    AlanLeung2018  
       2020-04-14 09:11:08 +08:00
    tp 框架,建议写在 model 层
    jfhy0901
        24
    jfhy0901  
       2020-04-14 09:18:25 +08:00 via Android
    一般都是写在 C 里面,M 里面做一些关联模型等。兼职不要讲究那么多,我接手的一个项目,一个 C 里面写了一万行你敢信?
    zjsxwc
        25
    zjsxwc  
       2020-04-14 09:19:15 +08:00
    有 ORM 就按照 ORM 推荐的用法来写,sql 写在 Repository 和 Entity 里都可以,一般都是类 sql 的方言比如 linq 、dql 等,反正都是 Entity 实体对象处理,entity manager 会自动搞定。

    如果是类似 mybatis 的框架 sql 就写到 mapper xml 文件里,花点时间自己手动构造每个 DAO 。

    其他比如 PDO 这种全局变量的,哪里都能写,你安自己项目需求写呗,只要合理就行。
    guolaopi
        26
    guolaopi  
       2020-04-14 09:19:17 +08:00
    @emeab
    我瞎说的啊,我不做 PHP,只是给我的感觉像充血模型一样
    edk24
        27
    edk24  
       2020-04-14 09:19:31 +08:00
    用 sql 少, 我觉得可以写在 controller 里, 但这个 sql 常用到可以写在 model 方便复用
    handsomehaitao
        28
    handsomehaitao  
       2020-04-14 09:19:57 +08:00
    service 与 response 里
    encro
        29
    encro  
       2020-04-14 09:24:55 +08:00
    一般不用写 sql 了吧,复杂查询用 orm 自动关联出来。

    如果需要对一些操作进行封装,比如对多个批量操作采用事务,可以写在 model,便于复用。

    其实不用太在乎写在哪里,而应该在乎是否好用好用,便于用即可,实际写写看。

    比如用户充值,需要修改余额和生成充值记录,那么直接用$user->recharge($money)我觉得是比较方便和复用的,那么对我来说就是适合的,
    因为如果写在控制器里面,那么不能复用,
    如果单独抽取 service 层,你用的时候就得 UserService::Recharge($user_id,$money),UserService 里面你得再次实例化 User,当然你也可以直接传$user 进去,但是我懒。
    代码怎么简单明了够用就怎么写吧,大部分时候代码行数越少就越容易维护。
    m939594960
        30
    m939594960  
       2020-04-14 09:39:50 +08:00
    一般的项目,一般我就写到 controller 或者 service 里了
    absolutelynull
        31
    absolutelynull  
       2020-04-14 09:40:31 +08:00
    数据处理的话 可以写在 model 层,单纯的 crud 的话 实例化模型在 controller 写入
    Varobjs
        32
    Varobjs  
       2020-04-14 09:50:10 +08:00 via Android
    写在哪里都可以,
    如果简单的, 写 c 里也行吧,如果多处用,就写 service 里,如果很多 service 用,那就再单独一层
    brader
        33
    brader  
       2020-04-14 09:50:58 +08:00
    用 php 框架就尽量不要写原生 sql 了,php 框架的数据库操作非常完善和好用,如果某些特殊的需要写原生 sql,直接写就是了,一点都不要担心,我保证,这样的特例,是极少数的,并不会对后期造成太大的困扰
    skys215
        34
    skys215  
       2020-04-14 10:00:07 +08:00
    在只有 controller 和 model 的情况下
    有重 controller 轻 model,重 model 轻 controller 两种方式。
    重 controller 的话,前端在做某些操作的时候要调用同一个 api
    重 model 的话,就没有这个问题,但也有一些问题。例如,相似的操作会在方法里多次定义。
    所以才会引入中间层 repository/service (怎么叫都无所谓了)。model 就只写相关定义,例如表名、主键名、枚举值之类的。
    ben1024
        35
    ben1024  
       2020-04-14 10:04:24 +08:00
    新建一个 Repository 层,写在 Repository 里
    0x663
        36
    0x663  
       2020-04-14 10:25:27 +08:00
    写 html 里边
    Takamine
        37
    Takamine  
       2020-04-14 11:30:09 +08:00 via Android
    @taaaang Service 可以直接和 Controller 同名服务于 Controller,把 Controller 的复杂逻辑抽出来到 Service 。
    PHP 框架的 orm 和楼上说的一样都比较完善了,model 做映射之后直接给 service 层提供服务,你 sql 也这样写在 model 里面给 Service 提供服务,感觉合理一点。
    james122333
        38
    james122333  
       2020-04-14 11:34:04 +08:00 via Android
    我之前替公司弄的小型框架写在 service controller 负责回应 只是写个类
    每次都
    $mysql->connect();
    $data = $mysql->query("
    select...
    ", array(
    参数替换
    ));
    这样就可以了 用 orm 只是增加複杂度
    Dao model 通通省了
    php 字串里可加变量 "$abc" 动态性已经足够了
    完成一样的事情 java 就啰唆非常多
    又简单又动态的感觉是爽度
    MonoLogueChi
        39
    MonoLogueChi  
       2020-04-14 11:34:49 +08:00
    @m939594960 dao 不是 java 专属的呢
    james122333
        40
    james122333  
       2020-04-14 11:40:14 +08:00 via Android
    connect()里面还可以加入 ip 使用者 选项类
    顶多再弄个 enum 解决回家睡觉
    dobelee
        41
    dobelee  
       2020-04-14 13:10:18 +08:00 via iPhone
    只是临时简单用到的话不用特意抽一层,简单写到 html 里...哦不 controller 里就 ok 了。🐶
    airflybusoren
        42
    airflybusoren  
       2020-04-14 13:14:16 +08:00
    一直写 model 那,跟 java 不一样
    m939594960
        43
    m939594960  
       2020-04-14 13:30:34 +08:00
    @MonoLogueChi #39 哪 dao 什么意思?是什么的简写?有什么含义?我以后管 model 叫 Eloquent 管 view 叫 blade 管 route 叫 fasterouter 可以么?
    shenjia
        44
    shenjia  
       2020-04-14 13:35:52 +08:00
    只用过 Yii 框架的 ActiveRecord,一开始感觉链式调用还挺爽的……后来发现还是用 sprintf 手拼 sql 最实在,性能可控,线上有慢查询了好定位,一搜一个准。
    iyaozhen
        45
    iyaozhen  
       2020-04-14 13:40:41 +08:00
    其实你会 java 的话按 java 一模一样来就行
    james122333
        46
    james122333  
       2020-04-14 13:44:56 +08:00 via Android
    @dobelee
    这不如直接写一个脚本就好...
    "超文本预处理器"...
    yogogo
        47
    yogogo  
       2020-04-14 13:50:44 +08:00
    我是再加了一层 logic 层,就是类似 service
    hantsy
        48
    hantsy  
       2020-04-14 13:52:10 +08:00
    你们写 php 不用 Doctrine 吗?
    james122333
        49
    james122333  
       2020-04-14 13:55:49 +08:00 via Android
    @shenjia
    手拼外加封装"一个"类 会更爽
    那些写设定的不知道在想什么
    设定再动态也不会比语言动态
    只要不要写成$xxx->select()->from()类似的就可以了
    hantsy
        50
    hantsy  
       2020-04-14 14:07:40 +08:00
    @shenjia ActiveRecord 模式最成功是 CakePHP,还进行很多封装,简单易用。
    lzj307077687
        51
    lzj307077687  
       2020-04-14 14:26:51 +08:00
    一般开一层 Repository 或者 Service
    要快的话直接 Controller
    predator
        52
    predator  
       2020-04-14 15:29:07 +08:00   ❤️ 6
    不是说 DAO 专不专于什么的问题,也不是说 PHP 要怎么写显得“专业”一些的问题
    ThinkPHP 或者类似的框架,本来就有文档去规范要把可重用的数据库操作写在 model 里面

    有些人接手公司的项目,连框架规范都不愿意看,model 里面套 service,service 里面再套 dao,自己觉得在 IDE 里面爽得不行,完全大傻逼

    dao 你妈逼 dao
    HUALIAN
        53
    HUALIAN  
       2020-04-14 16:07:23 +08:00
    dao 哈哈 笑死我了🐎的
    Heartbleed
        54
    Heartbleed  
       2020-04-14 16:11:04 +08:00
    常用的 SQL 写在 model 好一点,逻辑清晰
    G4vin
        55
    G4vin  
       2020-04-14 16:37:29 +08:00
    要不是学过两个月的 java 我真没听过 dao 是什么鬼。。。。
    james122333
        56
    james122333  
       2020-04-14 16:52:24 +08:00 via Android
    @Heartbleed
    是阿 是"常用" model 不一定必须
    yoshiyuki
        57
    yoshiyuki  
       2020-04-14 17:01:14 +08:00
    model 层
    lepig
        58
    lepig  
       2020-04-14 17:09:47 +08:00
    能不能别整天在那 dao 比 dao

    ![c9sA.png]( https://u.vmpic.cn/2020/04/14/c9sA.png)
    Heartbleed
        59
    Heartbleed  
       2020-04-14 17:38:31 +08:00
    “dao 你妈逼” 的那位笑死我了 hhhh
    dvaknheo
        60
    dvaknheo  
       2020-04-14 18:13:16 +08:00   ❤️ 1
    Service/Logic 跟业务走。
    Model/Repository 跟表走 如果是附属表也可以不那么严格。

    比如用户充值,需要修改余额和生成充值记录,那么直接用$user->recharge($money)我觉得是比较方便和复用的,那么对我来说就是适合的,

    按业务来分的话
    UserService::Recharge($user_id,$money)
    这个走 RechargeModel 还可能要用到 LogModel 还看看用户是否有钱 UserInfoModel
    UserService::GetProfile($user_id)
    用 UserInfoModel
    tokyo2020
        61
    tokyo2020  
       2020-04-14 20:46:57 +08:00
    Infrastructure
    baobao1270
        62
    baobao1270  
       2020-04-15 01:31:47 +08:00 via Android
    model 里 或者 orm
    couashi
        63
    couashi  
       2020-04-15 09:32:20 +08:00
    @zooo 直接让他学 spring 算了
    hiColin
        64
    hiColin  
       2020-04-15 14:47:34 +08:00
    sql 写在 model 层,一般使用 orm 操作数据库,不推荐直接使用原生 sql 语句,除非 orm 无法完成的查询。
    kylesean
        65
    kylesean  
       2020-05-07 17:20:18 +08:00
    拆分 Service 里用 ORM 写,一般的项目够了。扯什么 Dao 层 Repository 层,PHP 项目有个要这样拆分?不要跟我扯以后换什么数据库,什么单元测试方便。没有以这一层,代码可读性,扩展维护性都很方便。PHP 就要有 PHP 的样子,听到别人扯 Dao 层就来火,框架的 ORM 或者 ActiveRecord 设计模式本身就是轻量级的 Dao 层。PHP 分个 4 、5 层就是脱裤子放屁。
    QlanQ
        66
    QlanQ  
       2020-05-25 11:38:41 +08:00
    php 要什么 dao ? model 不够用?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3157 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 12:35 · PVG 20:35 · LAX 05:35 · JFK 08:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.