如果使用给定的查询条件在数据库中没有找到任何东西, find 方法将返回null。

不同于AR在其他框架的执行, Yii在其 AR 中支持多个主键.
一个复合主键由两个或更多字段构成。相应地,主键值在Yii中表现为一个数组。primaryKey属性给出了一个
AR 实例的主键值。

// 更新符合指定条件的行Post::model()->updateAll($attributes,$condition,$params);// 更新符合指定条件和主键的行Post::model()->updateByPk($pk,$attributes,$condition,$params);// 更新满足指定条件的行的计数列Post::model()->updateCounters($counters,$condition,$params);

AR类之间的关联直接反映着数据库中这个类所代表的数据表之间的关联。从关系数据库的角度来说,两个数据表A,B之间可能的关联有三种:一对多,一对一,多对多。而在AR中,关联有以下四种:

现在若我们访问 $author->posts, 我们将得到用户的根据发表时间降序排列的
posts. 每个post 实例也载入了它的分类。

$post=new Post;$post->title='sample post';$post->content='post body content';$post->save();

上面的代码将取回所有的 posts
以及它们的作者和分类。它也将取出每个作者的profile和 posts.

正如我们可以看到的,我们使用同样的 save()
方法执行插入和更新操作。如果一个 AR 实例是使用 new
操作符创建的,调用save()

condition: WHERE 子语句。默认为空。注意, 列要使用别名引用。

数据表行中列的值可以作为相应AR实例的属性访问。例如,如下代码设置了 title
列 :

将更新表中现有的行。实际上,我们是使用 CActiveRecord::isNewRecord
说明一个 AR 实例是不是新的。

如果表的主键是自增的,在插入完成后,AR实例将包含一个更新的主键。在上面的例子中,id属性将反映出新插入帖子的主键值,即使我们从未显式地改变它。

之前我们提到额外的参数可以被指定在关联声明中。这些选项,指定为
name-value 对,被用来定制关联查询。它们被概述如下:

在AR中声明关联,是通过覆盖父类CActiveRecord中的relations()方法来实现的。这个方法返回一个包含了关系定义的数组,数组中的每一组键值代表一个关联:

$rowCount=$command->execute(); // 执行无查询SQL$dataReader=$command->query(); // 执行一个SQL查询$rows=$command->queryAll(); // 查询并返回结果中的所有行$row=$command->queryRow(); // 查询并返回结果中的第一行$column=$command->queryColumn(); // 查询并返回结果中的第一列$value=$command->queryScalar(); // 查询并返回结果中第一行的第一个字段

User 实例填充。不是为每个post 执行一个连接查询,
急切加载方法在一个单独的连接查询中取出所有的 post 以及它们的author!

$criteria=new CDbCriteria;$criteria->with=array('author.profile','author.posts','categories',);$posts=Post::model;或$posts=Post::model()->findAll(array('with'=>array('author.profile','author.posts','categories',));

4、使用事务

2、关联查询

DAO 基于 PHP Data Objects
构建。它是一个为众多流行的DBMS提供统一数据访问的扩展,这些 DBMS 包括

要建立一个数据库连接,创建一个 CDbConnection

$contents=Content::model;

aliasToken:列前缀占位符。默认是“??.”。

9、自定义

class Post extends CActiveRecord {public function relations() {return array('author'=>array(self::BELONGS_TO,'User','authorID'),'categories'=>array(self::MANY_MANY,'Category','PostCategory,);}}class User extends CActiveRecord {public function relations() {return array('posts'=>array(self::HAS_MANY,'Post','authorID'),'profile'=>array(self::HAS_ONE,'Profile','ownerID'),);}}
$sql="SELECT username, email FROM tbl_user";$dataReader=$connection->createCommand;// 使用 $username 变量绑定第一列 $dataReader->bindColumn;// 使用 $email 变量绑定第二列 $dataReader->bindColumn;while!==false){// $username 和 $email 含有当前行中的 username 和 email}

1、建立数据库连接

* Oracle: oci:dbname=//localhost:1521/testdb

然后我们就可以通过 Yii::app()->db
访问数据库连接了。它已经被自动激活了,除非我们特意配置了
CDbConnection::autoConnect 为
false。通过这种方式,这个单独的DB连接就可以在我们代码中的很多地方共享。

将会向数据表中插入一行新数据;如果 AR 实例是某个 find 或 findAll
方法的结果,调用 save()

进行关联查询最简单的方式就是访问一个关联AR对象的某个关联属性。如果这个属性之前没有被访问过,这时就会启动一个关联查询,通过当前AR对象的主键连接

我们也可以在应用配置中设置CDbConnection::enableParamLogging为true,这样绑定在SQL语句中的参数值也会被记录。

提示:
由于AR允许我们无需写一大堆SQL语句就能执行数据库操作,我们经常会想知道AR在背后到底执行了什么SQL语句。这可以通过开启Yii的日志功能实现。例如,我们在应用配置中开启了CWebLogRoute,我们将会在每个网页的最后看到执行过的SQL语句。

一并写在这里。对于多对多的关系,关联表必须在外键中注明,例如在Post类的categories

* 如果查询中的一个失败,整个事务回滚。

要读取数据表中的数据,我们可以通过如下方式调用 find 系列方法中的一种:

together:
是否关联的数据表被强制与主表和其他表连接。此选项只对于HAS_MANY 和
MANY_MANY 关联有意义。若此选项被设置为 false,
…….默认为空。此选项中的字段名以被消除歧义。

如果有很多列,我们可以看到一个用于这种复制的很长的列表。这可以通过使用如下所示的
attributes 属性简化操作。更多信息可以在 安全的特性赋值 一节和 创建动作
一节找到。

参数是一个以列名做索引的值的数组。在一些框架中,此任务可以通过调用类似
findByNameAndTitle

3、获取查询结果

Active Record技术。每个 AR

在使用AR进行关联查询之前,我们需要告诉AR各个AR类之间有怎样的关联。

除了上面讲述的 find 和 findAll 方法,为了方便,还提供了如下方法:

7、数据验证

注意,默认的命名范围只会应用于 SELECT 查询。INSERT, UPDATE 和 DELETE
查询将被忽略。

要访问一个数据表,我们首先需要通过集成CActiveRecord定义一个AR类。每个AR类代表一个单独的数据表,一个AR实例则代表那个表中的一行。

CActiveRecord
提供了几个占位符方法,它们可以在子类中被覆盖以自定义其工作流。

一条 SQL 语句会通过 CDbCommand 以如下两种方式被执行:

query(): 执行一条会返回若干行数据的 SQL 语句,例如
SELECT。如果成功,它将返回一个 CDbDataReader
实例,通过此实例可以遍历数据的结果行。为简便起见,还实现了一系列
queryXXX() 方法以直接返回查询结果。

命名范围多用作 find
方法调用的修改器。几个命名范围可以链到一起形成一个更有约束性的查询结果集。例如,要找到最近发布的帖子,我们可以使用如下代码:

要使用表前缀功能,AR类的 tableName() 方法可以通过如下方式覆盖

上面的代码中,如果我们没有提供参数 3,我们将默认获取 5
条最近发布的帖子。

如果一个 AR 实例被一行数据填充,我们也可以删除此行数据。

2、定义AR类

‘VarName’=>array(‘RelationType’, ‘ClassName’, ‘ForeignKey’,
…additional options)

$post=new Post;$post->title='sample post';$post->content='content for the sample post';$post->create_time=time;

* SQLite: sqlite:/path/to/dbfile

// 查找 postID=10 的那一行$post=Post::model()->find('postID=:postID', array;

说明:
有时外键可能由两个或更多字段组成,在这里可以将多个字段名由逗号或空格分隔,

在AR类中声明关联时,每个关联会作为一个属性添加到AR类中,属性名就是关联的名称。在进行关联查询时,这些属性就会被设置为关联到的AR类的实例,例如在查询取得一个Post实例时,它的$author属性就是代表Post作者的一个User类的实例。

每个 AR 实例都含有一个属性名叫 dbConnection ,是一个 CDbConnection
的实例,这样我们可以在需要时配合 AR 使用由 Yii DAO 提供的 事务 功能:

调用find时,我们使用 $condition 和 $params 指定查询条件。此处 $condition
可以是 SQL 语句中的 WHERE 字符串,$params
则是一个参数数组,其中的值应绑定到 $condation 中的占位符。例如:

CDbCommand::bindValue()

$posts=Post::model()->with('author.profile','author.posts','categories')->findAll();
$connection=new CDbConnection($dsn,$username,$password);// 建立连接。你可以使用 try...catch 捕获可能抛出的异常$connection->active=true;......$connection->active=false; // 关闭连接
class Content extends CActiveRecord{public function defaultScope(){return array('condition'=>"language='".Yii::app;}}

急切加载也可以通过指定 CDbCriteria::with 属性被执行, 如下:

6、删除记录

3、关联查询选项

CDbDataReader 一行行检索数据。

现在,如果下面的方法被调用,将会自动使用上面定义的查询规则:

8、对比记录

如果你想使用一个不是db的应用组件,或者如果你想使用AR处理多个数据库,你应该覆盖CActiveRecord::getDbConnection()。CActiveRecord类是所有AR类的基类。

CDbDataReader::read() 获取结果中的行。你也可以在 PHP 的 foreach
语言结构中使用

5、更新记录

return array('import'=>array('application.models.*',),);

使用下面的类级别代码,可以无需首先加载行就可以删除它。

CDbDataReader: 代表一个只向前移动的,来自一个查询结果集中的行的流。

1、建立数据库连接

afterConstruct: 这个将在每个使用 new 操作符创建 AR 实例后被调用。

6、绑定列

三、Relational Active Record

// 一条带有两个占位符 ":username" 和 ":email"的 SQL$sql="INSERT INTO tbl_user  VALUES";$command=$connection->createCommand;// 用实际的用户名替换占位符 ":username"$command->bindParam(":username",$username,PDO::PARAM_STR);// 用实际的 Email 替换占位符 ":email"$command->bindParam(":email",$email,PDO::PARAM_STR);$command->execute();// 使用新的参数集插入另一行$command->bindParam(":username",$username2,PDO::PARAM_STR);$command->bindParam(":email",$email2,PDO::PARAM_STR);$command->execute();

以使用实际参数替换这些占位符。这些参数不需要使用引号引起来:底层的数据库驱动会为你搞定这个。参数绑定必须在
SQL 语句执行之前完成。

注意: 在上面的例子中,我们可能需要在特定的 DBMS 中将 postID
列的引用进行转义。 例如,如果我们使用 PostgreSQL,我们必须将此表达式写为
“postID”=:postID,因为 PostgreSQL 在默认情况下对列名大小写不敏感。

关联中,外键就需要写成PostCategory。

beforeSave 和 afterSave: 这两个将在保存 AR 实例之前和之后被调用。

一种替代 CDbCriteria 的方法是给 find
方法传递一个数组。数组的键和值各自对应标准的属性名和值,上面的例子可以重写为如下:

* 一个个执行查询。任何对数据库的更新对外界不可见。

多的关系。用AR的方式去理解的话,我们可以认为
MANY_MANY关系是由BELONGS_TO和HAS_MANY组成的。

要向数据表中插入新行,我们要创建一个相应 AR
类的实例,设置其与表的列相关的属性,然后调用 save() 方法完成插入:

二、Active Record

CDbCommand: 代表一条通过数据库执行的 SQL 语句。

return array('components'=>array('db'=>array('class'=>'system.db.CDbConnection','connectionString'=>'sqlite:path/to/dbfile',// 开启表结构缓存提高性能// 'schemaCachingDuration'=>3600,),),);
$posts=Post::model->findAll();

params: 被绑定到 SQL 语句的参数. 应当为一个由 name-value
对组成的数组()。

// 查找满足指定条件的所有行$posts=Post::model()->findAll;// 查找带有指定主键的所有行$posts=Post::model()->findAllByPk($postIDs,$condition,$params);// 查找带有指定属性值的所有行$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);// 通过指定的SQL语句查找所有行$posts=Post::model()->findAllBySql;

执行 SQL 语句时如果发生错误,将会抛出一个异常。

{{TableName}} 代表表的名字,其中的 TableName
是指不带前缀的表名。例如,如果数据库含有一个名为 tbl_user

BELONGS_TO: 如果数据表A和B的关系是一对多,那我们就说B属于A。

beforeFind: 这个将在一个 AR 查找器被用于执行查询之前被调用。

类似于表记录,AR实例由其主键值来识别。因此,要对比两个AR实例,假设它们属于相同的AR类,
我们只需要对比它们的主键值。然而,一个更简单的方式是调用
CActiveRecord::equals()。

on: ON 子语句. 这里指定的条件将使用 and
操作符被追加到连接条件中。此选项中的字段名应被消除歧义。此选项不适用于
MANY_MANY 关联。

$posts=Post::model->recently;

7、使用表前缀

* SQL Server: mssql:host=localhost;dbname=testdb

注意: 命名范围只能用于类级别方法。也就是说,此方法必须使用
ClassName::model() 调用。

select: 为关联 AR 类查询的字段列表。默认是 ‘*’,
意味着所有字段。查询的字段名字可用别名表达式来消除歧义(例如:COUNT AS
nameCount)。

update 和
delete)操作的SQL语句。而且我们的代码中混杂了SQL语句时也会变得难以维护。要解决这些问题,我们可以使用Active
Record。

HAS_MANY: 如果数据表A和B的关系是多对一,那我们就说B有多个A。

$post->title=$_POST['title'];$post->content=$_POST['content'];$post->save();

2、执行SQL语句

下面的代码演示了如何定义User和Post之间的关联。

在不同的关联情况下,如果没有查询到结果,其返回的值也不同:BELONGS_TO 和
HAS_ONE 关联,无结果时返回null; HAS_MANY 和 MANY_MANY,
无结果时返回空数组。

13、默认的命名范围

数据库连接建立后,SQL 语句就可以通过使用 CDbCommand
执行了。你可以通过使用指定的SQL语句作为参数调用
CDbConnection::createCommand() 创建一个 CDbCommand 实例。

// 查找满足指定条件的结果中的第一行$post=Post::model()->find;// 查找具有指定主键值的那一行$post=Post::model()->findByPk($postID,$condition,$params);// 查找具有指定属性值的行$post=Post::model()->findByAttributes($attributes,$condition,$params);// 通过指定的SQL语句查找结果中的第一行$post=Post::model()->findBySql;

要避免 SQL 注入攻击 并提高重复执行的 SQL 语句的效率,你可以
“准备”一条含有可选参数占位符的 SQL
语句,在参数绑定时,这些占位符将被替换为实际的参数。

直接更新数据表中的一行或多行而不首先载入也是可行的。 AR
提供了如下方便的类级别方法实现此目的:

由于 CDbConnection 继承自 CApplicationComponent,我们也可以将其作为一个
应用组件 使用。要这样做的话,请在 应用配置 中配置一个 db 应用组件如下:

public function tableName(){return '{{post}}';}

在CDbCommand::query() 生成 CDbDataReader 实例之后,你可以通过重复调用

// 假设 $_POST['Post'] 是一个以列名索引列值为值的数组$post->attributes=$_POST['Post'];$post->save();

1、如何声明关联

参数占位符可以是命名的 或未命名的 。调用 CDbCommand::bindParam() 或

offset: 偏移。本选项不能用于BELONGS_TO关联。

的方法实现。虽然此方法看起来很诱人,
但它常常引起混淆,冲突和比如列名大小写敏感的问题。

上述工作流可以通过如下代码实现:

当有多行数据匹配指定的查询条件时,我们可以通过下面的 findAll
方法将他们全部带回。每个都有其各自的 find 方法,就像我们已经讲过的那样。

$post=Post::model;$post->title='new post title';$post->save(); // 将更改保存到数据库

CDbTransaction: 代表一个数据库事务。

些关联的数据取出来。下面的例子描述了延迟加载的过程:

$criteria=new CDbCriteria;$criteria->select='title'; // 只选择 'title' 列$criteria->condition='postID=:postID';$criteria->params=array;$post=Post::model; // $params 不需要了

with: 应当和此对象一同载入的子关联对象列表. 注意,
不恰当的使用可能会形成一个无穷的关联循环。

* 提交事务。如果事务成功,更新变为可见。

模型类可以有一个默认命名范围,它将应用于所有

DSN 的格式取决于所使用的 PDO 数据库驱动。总体来说, DSN 要含有 PDO
驱动的名字,跟上一个冒号,再跟上驱动特定的连接语法。可查阅 PDO 文档
获取更多信息。下面是一个常用DSN格式的列表。

beforeDelete 和 afterDelete: 这两个将在一个 AR
实例被删除之前和之后被调用。

ClassName是这个关系关联到的AR类的类名;ForeignKey指定了这个关联是通过哪个外键联系起来的。后面的additional

然后,我们就可以使用如下语句获取3条最近发布的帖子。

虽然我们从未在Post类中显式定义属性title,我们还是可以通过上述代码访问。这是因为title是tbl_post表中的一个

注意,当使用 CDbCriteria 作为查询条件时,$params
参数不再需要了,因为它可以在 CDbCriteria 中指定,就像上面那样。

order: ORDER BY 子语句。默认为空。注意, 列要使用别名引用(例如:??.age
DESC)。

* PostgreSQL: pgsql:host=localhost;port=5432;dbname=testdb

public function recently{$this->getDbCriteria()->mergeWith(array('order'=>'create_time DESC','limit'=>$limit,));return $this;}

关于此模型的查询。例如,一个支持多种语言的网站可能只想显示当前用户所指定的语言的内容。因为可能会有很多关于此网站内容的查询,我们可以定义一个默认

注意,删除之后, AR 实例仍然不变,但数据表中相应的行已经没了。

实例并将其激活。连接到数据库需要一个数据源的名字以指定连接信息。用户名和密码也可能会用到。当连接到数据库的过程中发生错误时

命名范围主要是在 CActiveRecord::scopes()
方法中以名字-规则对的方式声明。如下代码在Post模型类中声明了两个命名范围,
published 和 recently。

$sql='SELECT * FROM {{user}}';$users=$connection->createCommand;

options可以加入一些额外的设置,后面会做介绍。

public function primaryKey(){return 'id';// 对于复合主键,要返回一个类似如下的数组// return array;}

11、命名范围

$posts=Post::model()->with(‘author’,’categories’)->findAll();

总体来说,命名范围必须出现在一个 find
方法调用的左边。它们中的每一个都提供一个查询规则,并联合到其他规则,包括传递给
find 方法调用的那一个。最终结果就像给一个查询添加了一系列过滤器。

的命名范围以解决此问题。为实现此目的,我们覆盖
CActiveRecord::defaultScope 方法如下:

我们可以在with()方法中指定多个关联名字。例如, 下面的代码将取回 posts
以及它们的作者和分类:

// 删除符合指定条件的行Post::model()->deleteAll;// 删除符合指定条件和主键的行Post::model()->deleteByPk($pk,$condition,$params);

延迟加载方法使用非常方便,但在某些情况下并不高效。例如,若我们要取得N个post的作者信息,使用延迟方法将执行N次连接查询。此时我们应当使用所谓的急切加载方法。

如果没有任何东西符合查询条件,findAll 将返回一个空数组。这跟 find
不同,find 会在没有找到什么东西时返回 null。

HAS_ONE:
这是‘HAS_MANY’关系中的一个特例,当A最多有一个的时候,我们说B有一个A 。

$transaction=$connection->beginTransaction();try{$connection->createCommand;$connection->createCommand;//.... other SQL executions$transaction->commit();}catch // 如果有一条查询失败,则会抛出异常{$transaction->rollBack();}

beforeva lidate 和
afterValidate:这两个将在验证数据有效性之前和之后被调用。

* MySQL: mysql:host=localhost;dbname=testdb

如上所示,我们通过 Post::model() 调用 find 方法。请记住,静态方法
model()
是每个AR类所必须的。此方法返回在对象上下文中的一个用于访问类级别方法的AR实例。

array(......'components'=>array(......'db'=>array('class'=>'CDbConnection','connectionString'=>'mysql:host=localhost;dbname=testdb','username'=>'root','password'=>'password','emulatePrepare'=>true, // needed by some MySQL installations),),)

5、绑定参数

提示: 由于Active
Record依靠表的元数据测定列的信息,读取元数据并解析需要时间。

此外, 下面的选项在延迟加载中对特定关联是可用的:

class Post extends CActiveRecord{......public function scopes(){return array('published'=>array('condition'=>'status=1',),'recently'=>array('order'=>'create_time DESC','limit'=>5,),);}}
$post=new Post;$post->title='a sample post';

我们也可以使用 $condition 指定更复杂的查询条件。不使用字符串,我们可以让
$condition 成为一个 CDbCriteria 的实例,它允许我们指定不限于 WHERE
的条件。例如:

execute(): 执行一个无查询 SQL语句,例如 INSERT, UPDATE 和 DELETE
。如果成功,它将返回此执行所影响的行数。

// retrieve the post whose ID is 10$post=Post::model;// retrieve the post's author: a relational query will be performed here$author=$post->author;
class User extends CActiveRecord{public function relations(){return array('posts'=>array(self::HAS_MANY, 'Post', 'author_id','order'=>'posts.create_time DESC','with'=>'categories'),'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'),);}}

每个命名范围声明为一个可用于初始化 CDbCriteria
实例的数组。例如,recently 命名范围指定 order 属性为 create_time DESC
, limit 属性为 5。他们翻译为查询规则后就会返回最近的5篇帖子。

当插入或更新一行时,我们常常需要检查列的值是否符合相应的规则。如果列的值是由最终用户提供的,这一点就更加重要。总体来说,我们永远不能相信任何来自客户端的数据。

当获取查询结果时,你也可以使用PHP变量绑定列。这样在每次获取查询结果中的一行时就会自动使用最新的值填充。

4、读取记录

(例如,错误的 DSN 或无效的用户名/密码),将会抛出一个异常。

要使用表前缀,配置 CDbConnection::tablePrefix
属性为所希望的表前缀。然后,在 SQL 语句中使用

虽然Yii DAO可以处理几乎任何数据库相关的任务,但很可能我们会花费 90%
的时间以编写一些执行普通 CRUD(create, read,

我们已经知道如何通过Active
Record从单个数据表中取得数据了,在这一节中,我们将要介绍如何使用AR来连接关联的数据表获取数据。

记录在保存到数据库之前,其属性可以赋值为 CDbExpression
类型。例如,为保存一个由MySQL的 NOW()
函数返回的时间戳,我们可以使用如下代码:

$connection=Yii::app()->db; // 假设你已经建立了一个 "db" 连接// 如果没有,你可能需要显式建立一个连接:// $connection=new CDbConnection($dsn,$username,$password);$command=$connection->createCommand;// 如果需要,此 SQL 语句可通过如下方式修改:// $command->text=$newSQL;
$posts=Post::model->recently;
class Post extends CActiveRecord{public $title='please enter a title';......}$post=new Post;echo $post->title; // 这儿将显示: please enter a title

having: HAVING子句。默认为空。注意,
列要使用别名引用。本选项仅应用于HAS_MANY 和 MANY_MANY 关联。

index:
返回的数组索引类型。确定返回的数组是关键字索引数组还是数字索引数组。不设置此选项,
将使用数字索引数组。此选项只对于HAS_MANY 和 MANY_MANY 有意义

group: GROUP BY子句。默认为空。注意, 列要使用别名引用。
本选项仅应用于HAS_MANY 和 MANY_MANY 关联。

$post=Post::model()->find(array('select'=>'title','condition'=>'postID=:postID','params'=>array;
$post=new Post;$post->create_time=new CDbExpression; //CDbExpression类就是计算数据库表达式的值// $post->create_time='NOW' 将会被作为一个字符串处理。$post->save();

列,CActiveRecord通过PHP的__get()魔术方法使其成为一个可访问的属性。如果我们尝试以同样的方式访问一个不存在的列,将会抛出一个异常。

afterFind: 这个将在每个 AR 实例作为一个查询结果创建时被调用。

事务,在 Yii 中表现为 CDbTransaction 实例,可能会在下面的情况中启动:

limit: 限制查询的行数。本选项不能用于BELONGS_TO关联。

相关的表,来取得关联对象的值,然后将这些数据保存在对象的属性中。这种方式叫做“延迟加载”,也就是只有等到访问到某个属性时,才会真正到数据库中把这

上面的代码将返回一个由 Post 实例组成的数组. 不同于延迟加载方法,每个Post
实例中的author 属性在我们访问此属性之前已经被关联的

这个相当于关系数据库中的多对多关系。因为绝大多数关系数据库并不直接支持多对多的关系,这时通常都需要一个单独的关联表,把多对多的关系分解为两个一对

如果你数据库的表结构很少改动,你应该通过配置CDbConnection::schemaCachingDuration属性的值为一个大于零的值开启表结构缓存。

joinType: 此关联的连接类型。默认是 LEFT OUTER JOIN。

注意:
不同于query方法会直接返回数据。例如,queryRow()会返回代表查询结果第一行的一个数组。

在 AR 实例填充了列的值之后,我们可以改变它们并把它们存回数据表。

$post=Post::model; // 假设有一个帖子,其 ID 为 10$post->delete(); // 从数据表中删除此行
// 获取满足指定条件的行数$n=Post::model()->count;// 通过指定的 SQL 获取结果行数$n=Post::model()->countBySql;// 检查是否至少有一行复合指定的条件$exists=Post::model()->exists;
if{// 数据有效且成功插入/更新}else{// 数据无效,调用 getErrors() 提取错误信息}

这里的VarName是这个关联的名称;RelationType指定了这个关联的类型,有四个常量代表了四种关联的类型:

$model=Post::model();$transaction=$model->dbConnection->beginTransaction();try{// 查找和保存是可能由另一个请求干预的两个步骤// 这样我们使用一个事务以确保其一致性和完整性$post=$model->findByPk;$post->title='new post title';$post->save();$transaction->commit();}catch{$transaction->rollBack();}

alias: 关联的数据表的别名。默认是 null, 意味着表的别名和关联的名字相同。

提示: 由于 AR 类经常在多处被引用,我们可以导入包含 AR
类的整个目录,而不是一个个导入。 例如,如果我们所有的 AR 类文件都在
protected/models 目录中,我们可以配置应用如下:

注意:
AR并非要解决所有数据库相关的任务。它的最佳应用是模型化数据表为PHP结构和执行不包含复杂SQL语句的查询。
对于复杂查询的场景,应使用Yii DAO。

命名范围表示一个命名的查询规则,它可以和其他命名范围联合使用并应用于Active
Record查询。

在上面的代码中, $attributes 是一个含有以 列名作索引的列值的数组;
$counters 是一个由列名索引的可增加的值的数组;$condition 和 $params
在前面的段落中已有描述。

如果find方法找到了一个满足查询条件的行,它将返回一个Post实例,实例的属性含有数据表行中相应列的值。然后我们就可以像读取普通对象的属性那样读取载入的值,例如
echo $post->title;。

如果一个表没有主键,则必须在相应的AR类中通过如下方式覆盖 primaryKey()
方法指定哪一列或哪几列作为主键。

10、使用AR处理事务

self::BELONGS_TO,self::HAS_ONE,self::HAS_MANY和self::MANY_MANY;

命名范围可以参数化。例如,我们想自定义 recently
命名范围中指定的帖子数量,要实现此目的,不是在CActiveRecord::scopes
方法中声明命名范围,而是需要定义一个名字和此命名范围的名字相同的方法:

MySQL, PostgreSQL 等等。因此,要使用 Yii DAO,PDO 扩展和特定的 PDO
数据库驱动

急切加载方法检索主要的 AR 实例及其相关的 AR 实例. 这通过使用 with()
方法加上 find 或 findAll 方法完

默认情况下,AR类的名字和数据表的名字相同。如果不同,请覆盖tableName()方法。

我们也可以使用嵌套的急切加载。不使用一个关联名字列表,
我们将关联名字以分层的方式传递到 with() 方法, 如下,

这就是说,我们将没有前缀的表名用双大括号括起来,这样Yii就能自动添加前缀,从而返回完整的表名。

方法 bindParam
非常相似。唯一的区别就是前者使用一个PHP变量绑定参数,而后者使用一个值。对于那些内存中的大数据块参数,处于性能的考虑,应优先使用前者。

class Post extends CActiveRecord{public static function model{return parent::model;}public function tableName(){return 'tbl_post';}}

如果一个列在表结构中使用了静态默认值定义。则AR实例中相应的属性将在此实例创建时自动含有此默认值。改变此默认值的一个方式就是在AR类中显示定义此属性:

3、创建记录

下面我们改变在 User 中的 posts 关联声明,通过使用上面的一些选项:

Yii DAO 主要包含如下四个类:

的表,而 tbl_
被配置为表前缀,那我们就可以使用如下代码执行用户相关的查询:

提示:
通过AR使用多个数据库有两种方式。如果数据库的结构不同,你可以创建不同的AR基类实现不同的getDbConnection()。否则,动态改变静态变量CActiveRecord::db是一个好主意。

当要插入或更新的数据由最终用户在一个 HTML
表单中提交时,我们需要将其赋给相应的 AR
属性。我们可以通过类似如下的方式实现:

Post::model->recently;

having: HAVING 子语句。默认是空。注意, 列要使用别名引用。

当调用 save() 时, AR 会自动执行数据验证。验证是基于在 AR 类的 rules()
方法中指定的规则进行的。关于验证规则的更多详情,请参考 声明验证规则
一节。下面是保存记录时所需的典型的工作流。

命名范围也可用于 update 和 delete
方法。例如,如下代码将删除所有最近发布的帖子:

类代表一个数据表的列在 AR
类中体现为类的属性,一个AR实例则表示表中的一行。常见的 CRUD 操作作为 AR

AR依靠一个数据库连接以执行数据库相关的操作。默认情况下,它假定db应用组件提供了所需的CDbConnection数据库连接实例。如下应用配置提供了一个例子:

在使用关联AR之前,首先要在数据库中建立关联的数据表之间的主键-外键关联,AR需要通过分析数据库中的定义数据表关联的元信息,来决定如何连接数据。

当一个查询条件是关于按指定的值匹配几个列时,我们可以使用
findByAttributes()。我们使 $attributes

CDbConnection: 代表一个数据库连接。

如下例子演示了代表tbl_post表的AR类的最简代码:

的方法实现。因此,我们可以以一种更加面向对象的方式访问数据。例如,我们可以使用以下代码向tbl_post表中插入一个新行。

$dataReader=$command->query 直到它返回 falsewhile(($row=$dataReader->read { ... }// 使用 foreach 遍历数据中的每一行foreach { ... }// 一次性提取所有行到一个数组$rows=$dataReader->readAll();

12、参数化的命名范围

发表评论

电子邮件地址不会被公开。 必填项已用*标注