几乎所有的 Yii 的应用程序都是建立在数据库之上,虽然 Yii 可以非常灵活的操作数据库,但有些时候一些设计的选择可以使它更便于使用.
首先 Yii 应用程序广泛使用了 CActiveRecord, 设计的考虑主要围绕优化使用而不是组成复杂的 SQL 语句. 实际上大多的设计是使用友好的 SQL 模式来解决实践中的问题.
最常用的方式是创建易于被人阅读和理解的代码,例如使用命名来传达意思,但是这很难做到.
特别当你在论坛或 '#yii' 频道寻求帮助时,使用奇怪的名字意味着你会有一堆麻烦:解释代码是干什么的。你的问题有时就不会得到有效解决.
一堆一致性问题.
然而这些只是准测而不是规则,你的代码不遵循这些准则也照样会工作,但是如果你遵循这些准则你的代码将更加简单.
我们认为 SQL 表 包含很多记录,一个模型(model) 只是其中的一个,在任何地方使用$model = new Comments()来表示再次定义关系时感觉非常奇怪.
命名您的表名为comment而不是comments,invoice而不是invoices等等。对于的模型(model)类名也是一样(Comment,Invoice等等).
如果你不可以改变数据库的模式,但至少在适当的情况下你可以改变 Yii 模型类(model class)的名称,在这种不匹配的情况下你应该在代码中添加一个额外的注释//COMMENT来提醒用户.
下面的做法是在传统 SQL 设计模式上非常常见的,但是它在于 ActiveRecord 结合时时冗长复杂的。在category表中:
-- 不可取 -- 可取 create table category ( create table category( category_id INTEGER ..., id INTEGER ..., category_name VARCHAR ..., name VARCHAR ..., category_value INTEGER value INTEGER ); ); // 不友好的 // 友好的$model->category_id $model->id $model->category_name $model->name $model->category_value $model->value
虽然使用这种long方式生称的 SQL 语句容易理解一些,但是在 ActiveRecord 中使用就不太方便了.
Yii 支持表前缀,表前缀被用在 所有 应用放到共享的主机并且共享一个数据库的环境中. 你的博客表前缀为blog_,计时应用的表前缀为time_等等. 它们存在于同一个数据库中而互相不起冲突.
前缀tbl_在很多教程和例子中经常看到。
但是类不需要包含这些前缀,因为没有必要避免冲突:你的博客应用和你的计时应用时两个不同的应用.
class TblComment extends CActiveRecord { // 不可取 class Comment extends CActiveRecord { // 可取
在代码中看到无处不见的前缀使人们非常反感.
大多数表都有一个唯一主机,命名主键为id(而不是commentid、postid) 会使你的工作更加顺手.
虽然无论你是否访问数据库 Yii 都可以通过读取数据结构来得到它的主键,但是系统的其他部分可能不会这样做,并且它们依赖的主键为id.
例子: 默认的主键为id, 虽然你可以重写它的属性 'keyField', 但是把这放到第一位是很不方便的.
显而易见,当使用复合主键时这将不能工作,但是这毕竟是少数.
一个经典的设计错误是创建的表的主键有实际意义. 在下面的列子中 用户(user)表使用的用户名(name)作为主键:
-- 不要这么做! CREATE TABLE user ( name VARCHAR(16) PRIMARY KEY, -- bad idea email VARCHAR... ... )
这样做引发了两个问题:This presents two difficulties:
当在其他地方 引用 时,它的效率大大降低,因为它包含16个字符而不是4个字节的整数.当大量的 引用 时性能大大降低。
当系统中存在外键约束时用户想 修改用户名 是很困难的:表中的字段和引用都必须在同一时间改变,这样做的代价时昂贵的。
最好的解决办法时创建一个整型字段作为主键,并设置name字段为 unique:
-- much better CREATE TABLE user ( id INTEGER PRIMARY KEY AUTO_INCREMENT, name VARCHAR(32) NOT NULL UNIQUE, email ... ... );
这种方式在用户更新用户名时只修改了一条记录.
大多数的数据支持定义表之间的关系,一个表中的字段指向另一个表的主键。这些外键帮助保证了数据的完整性当有记录执行某条记录时不允许你删除它.
MySQL的InnoDB 强制使用外键约束,而 MyISAM 允许你 定义 它们,但不会 强制 使用. Yii 知道怎么处理这些关系,并且可以使用 Gii或Giix 自动生成关系.
抛开 Yii ,外键是维护数据库完整性的重要部分,在网络上有许多学习它的教程.
通过以上的说明,如果你有一个字段指向一个用户(user),命名这个字段为userid而不是user. 原因是你肯定要为表中的每一个外键定义一个 关系.
在 Yii、类变量、数据字段、虚拟属性、关系共享一个命名空间(namespace), 所以不可能通过$model->user的方式来 同时 访问表的外键 和 关系.
通过外键userid,$model->user形式的 BELONGS_TO 关系可以轻松自然的使用:
class Post extends CActiveRecord { public function relations() { return array( 'user' => array(self::BELONGS_TO, 'User', 'userid') ); }
注意: 有很多人喜欢用Id或_id来代替id.这只是个人爱好问题,意义是一样的.
继续我们的主题一致性和代码易于阅读,关系应当在名称上体现它们代表的为单数还是复数.
注意: 对于返回一个数组的关系,它们可能只包含一个模型,但事实上它们是通过复数名称方式认证来的 数组
你只需要通过看关系的名称就会知道它返回的是一个数组还是一个模型:
$model->post$model->comments$model->author$model->members
如果你必须通过查看代码才会知道,那这将会让你的代码更加难以阅读和维护.