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

yii2 中如何用 model 动态添加 attribute,并且添加新的 attribute 计算公式

  •  
  •   yantze · 2015-07-15 11:17:08 +08:00 · 8983 次点击
    这是一个创建于 3445 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如数据表B的数据里面记录的是这样:

    distribution.....分配.....NULL
    appoint..........人数.....NULL
    rate5............转化率...distribution/appoint

    数据表A现在要显示distribution和appoint这两个字段,并且现在需要动态的显示一个新的字段rate5,其值来自公式计算的值。

    当用户需要查看这个表的数据的时候,再动态的计算出这些值,这样可以不用写分页和排序,并且代码简洁。

    yii2有一个DynamicModel可以动态添加attribute,但是不支持数据库表。所以这个方法应该不行。

    18 条回复    2015-07-17 22:21:24 +08:00
    picasso250
        1
    picasso250  
       2015-07-15 12:54:39 +08:00   ❤️ 1
    为什么不创建view,然后裸写sql?
    yantze
        2
    yantze  
    OP
       2015-07-15 13:25:38 +08:00
    @picasso250 目前我用的就是这样的方法,但是随着项目的跟进,有可能代码会越来越难维护。
    所以我现在先使用拼接手写sql代码,以后打算重写一个基类,专门做这种model
    justfindu
        3
    justfindu  
       2015-07-15 13:25:59 +08:00   ❤️ 1
    model里面增加一个 function getRate5 ; return distribution/appoint.

    这样就可以用魔法函数 直接 $model->rate5 直接获取了
    yantze
        4
    yantze  
    OP
       2015-07-15 13:35:16 +08:00
    @justfindu 可是如果这样,getRate5函数我也必须动态添加,因为数据库表B的数据也是动态的
    yantze
        5
    yantze  
    OP
       2015-07-15 13:45:58 +08:00
    @justfindu 并且我按照你的方法去做完了,但是使用GridView后,不能自动排序。很可能是因为,AR model排序也是用sql排的,所以,目前最完美的解法,只能是写一个新的基类。
    AsterOcclu
        6
    AsterOcclu  
       2015-07-15 15:58:58 +08:00   ❤️ 1
    @yantze @justfindu 的方法是对的,至于GridView的排序和搜索功能,需要你自己去扩展对应的sort方法。http://www.yiiframework.com/doc-2.0/guide-output-sorting.html
    jarlyyn
        7
    jarlyyn  
       2015-07-15 17:45:58 +08:00
    2不熟。
    但从我的角度来看

    都要自定义表单功能了,还不如直接丢给前端js+api处理,别考虑 gridview了。
    yantze
        8
    yantze  
    OP
       2015-07-16 13:39:09 +08:00
    @jarlyyn 几十万条的数据全部取出来再排序! +_+
    jarlyyn
        9
    jarlyyn  
       2015-07-16 13:50:04 +08:00
    @yantze

    你能不能随便找几个api先看看别人是怎么实现的。
    加个 offset和limit不就能搞定了……
    jarlyyn
        10
    jarlyyn  
       2015-07-16 13:56:02 +08:00   ❤️ 1
    @yantze

    以Yii 1.x为例,我会这么做:

    创建一个api,用user/session认证。

    创建一个formModel,把offset/limit/排序/各种过滤选型都丢在里面,并负责验证。

    通过formModel生成合适的CdbCriteria,用于生成合适的数据。

    以json返回。

    前台用react/underscore来渲染。

    好处是不用动1里蛋疼的要死的gridview。

    稍微复杂点的东西就基本是通过eval来实现,各种排序也是,满蛋疼的。

    自己写前端舒服多了。
    yantze
        11
    yantze  
    OP
       2015-07-17 00:20:51 +08:00
    @jarlyyn 虽然说了这么多,但是还是没有说明Model里面如何动态的添加可排序的新字段。

    这种涉及底层的东西并不是修改model就可以实现的。

    因为yii当初设计model的时候,对于AR model只做了数据库的映射,对于非数据库字段的排序并没有定义SQL排序方法,所以,只能通过重写底层的model来实现的。

    有兴趣可以一起写一个这样的model出来。
    jarlyyn
        12
    jarlyyn  
       2015-07-17 10:25:54 +08:00
    @yantze

    至少在Yii 1.x里,排序不该找Model,

    应该找cdbcriteria.

    可以在model里新建一个scope,用于合并cdbcriteria.

    另外恕我不能 理解 ‘动态的添加可排序的新字段’ 的概念……

    排序一般不是数据库处理的事情吗……
    jarlyyn
        13
    jarlyyn  
       2015-07-17 10:29:58 +08:00
    @yantze

    大概的去看了下2的文档

    2里cdbcriteria对应的概念应该是activequery
    http://www.yiiframework.com/doc-2.0/yii-db-activequery.html
    jarlyyn
        14
    jarlyyn  
       2015-07-17 10:31:19 +08:00
    @yantze
    我觉得你需要的排序这一块的应该找这里:

    http://www.yiiframework.com/doc-2.0/yii-db-querytrait.html#orderBy()-detail
    yantze
        15
    yantze  
    OP
       2015-07-17 13:01:10 +08:00
    @jarlyyn ‘动态的添加可排序的新字段’,比如说,这个数据表里面没有字段rate5,但是现在我要通过model显示这个rate5,现在该怎么办呢?一般直接在model里面申明一个非动态的变量就可以了。

    但是这种变量并没有与数据库链接,所以并不能排序。关于activequery和orderby都是来自AR(activerecord)
    yantze
        16
    yantze  
    OP
       2015-07-17 13:02:32 +08:00
    @yantze ‘申明一个非动态的变量’ 改为 ‘申明一个非静态的变量’
    jarlyyn
        17
    jarlyyn  
       2015-07-17 14:00:18 +08:00
    @yantze

    哪家的model能实现你的这个需求呢?

    这个应该是自定义orderby的参数来做的吧?
    yantze
        18
    yantze  
    OP
       2015-07-17 22:21:24 +08:00
    @jarlyyn 是的,所以我已经先自己拼接sql完成了,不过我觉得应该可以用model实现,只是现在暂时没有这么多的时间。如果以后我能做出来,也许能发布出来。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1113 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:00 · PVG 03:00 · LAX 11:00 · JFK 14:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.