PHP 的 sql 到底该写在哪儿? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
taaaang
V2EX    PHP

PHP 的 sql 到底该写在哪儿?

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

    最近刚接触 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 里有意义之外还有什么实际意义么?
    2kCS5c0b0ITXE5k2
        6
    2kCS5c0b0ITXE5k2  
       2020-04-13 19:59:17 +08:00
    我个人做法是用 trait 封装一些常用的方法。 然后在 model 层写。php 没那么严谨 写在那层都可以
    /table>
    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 微软也用呢。
    2kCS5c0b0ITXE5k2
        9
    2kCS5c0b0ITXE5k2  
       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 里干就是了,讲究那么多干啥。。
    2kCS5c0b0ITXE5k2
        17
    2kCS5c0b0ITXE5k2  
       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  
    PRO
       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     Solana     1162 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 17:50 PVG 01:50 LAX 09:50 JFK 12:50
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86