Data access objects (dao)


dao is built on php data objects (pdo). It is an extension that provides unified data access for many popular dbms,These dbms include

mysql, postgresql, etc. Therefore, to use Yii Dao, pdo extension and specific pdo database driver (such as pdo_mysql)

Must be installed.

Yii Dao mainly includes the following four categories:

cdbconnection:represents a database connection.

cdbcommand:represents a sql statement executed through the database.

cdbdatareader:represents a forward-only one,A stream of rows from a query result set.

cdbtransaction:represents a database transaction.

1. Establish a database connection

To establish a database connection,Create a cdbconnection

Instance and activate it.Connecting to a database requires a data source name (dsn) to specify the connection information.A username and password may also be used.When an error occurs while connecting to the database

(For example, wrong dsn or invalid username/password), an exception will be thrown.

$connection=new cdbconnection ($dsn, $username, $password);
//establish connection.
You can use try ... catch to catch possible exceptions
$connection->active=false;//close the connection

The format of dsn depends on the pdo database driver used.In general, dsn contains the name of the pdo driver,Keep up with a colon,Then keep up with the drive-specific connection syntax.See the pdo documentation for more information.Below is a list of commonly used dsn formats.

* sqlite:sqlite:/path/to/dbfile

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

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

* sql server:mssql:host=localhost;dbname=testdb

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

Since cdbconnection inherits from capplicationcomponent, we can also use it as an application component. To do this,Please configure a db (or other name) application component in the application configuration as follows:

array (
"components" =>array (
"db" =>array (
"class" =>"cdbconnection","connectionstring" =>"mysql:host=localhost;dbname=testdb","username" =>"root","password" =>"password","emulateprepare" =>true, //needed by some mysql installations

Then we can access the database connection through yii ::app ()->db.It has been activated automatically,Unless we specifically configured cdbconnection ::autoconnect to false. This way,This single db connection can be shared in many places in our code.

2, execute the SQL statement

After the database connection is established,The sql statement can be executed by using cdbcommand. You can create a cdbcommand instance by calling cdbconnection ::createcommand () with the specified sql statement as a parameter.

$connection=yii ::app ()->db;//Assuming you have already established a "db" connection
//if there is not,You may need to explicitly establish a connection:
//$connection=new cdbconnection ($dsn, $username, $password);
$command=$connection->createcommand ($sql);
//If needed,This sql statement can be modified as follows:

A sql statement is executed by cdbcommand in two ways:

execute ():Execute a non-query SQL statement, such as insert, update, and delete. If successful,It will return the number of rows affected by this execution.

query ():Execute a sql statement that returns several rows of data, such as select. If successful,It will return a cdbdatareader instance through which the result rows of the data can be traversed.For simplicity,(Yii) also implements a series of queryxxx () methods to return query results directly.

If an error occurs while executing the sql statement,An exception will be thrown.

$rowcount=$command->execute ();//execute without query sql
$datareader=$command->query ();//execute a sql query
$rows=$command->queryall ();//Query and return all rows in the result
$row=$command->queryrow ();//Query and return the first row in the result
$column=$command->querycolumn ();//query and return the first column in the result
$value=$command->queryscalar ();//Query and return the first field of the first row in the result

3. Get query results

After cdbcommand ::query () generates a cdbdatareader instance,You can call

cdbdatareader ::read () gets the rows in the result.You can also use it in php's foreach language structure

cdbdatareader retrieves data line by line.

$datareader=$command->query ();
//call read () repeatedly until it returns false
while (($row=$datareader->read ())! == false) {...}
//use foreach to iterate through each row in the data
foreach ($datareader as $row) {...}
//extract all rows into an array at once
$rows=$datareader->readall ();

Note:Unlike query (), all queryxxx () methods return data directly.For example, queryrow () returns an array representing the first row of the query result.

4. Use transactions

A transaction, represented as a cdbtransaction instance in Yii, may be initiated in the following cases:

* Start transaction.

* Perform queries one by one.Any updates to the database are not visible to the outside world.

* Commit transaction.If the transaction is successful,The update becomes visible.

* If one of the queries fails,The entire transaction is rolled back.

The above workflow can be implemented by the following code:

$transaction=$connection->begintransaction ();
$connection->createcommand ($sql1)->execute ();
$connection->createcommand ($sql2)->execute ();
//.... other sql executions
$transaction->commit ();
catch (exception $e) //if a query fails,Will throw an exception
$transaction->rollback ();

5.Binding parameters

To avoid SQL injection attacks and improve the efficiency of repeated SQL statements,You can "prepare" an sql statement with optional parameter placeholders. When the parameters are bound,These placeholders will be replaced with the actual parameters.

Parameter placeholders can be named (represented as a unique token) or unnamed (represented as a question mark). Call cdbcommand ::bindparam () or

cdbcommand ::bindvalue ()

Replace these placeholders with actual parameters.These parameters don't need to be quoted:the underlying database driver will do this for you.Parameter binding must be completed before the sql statement is executed.

//a sql with two placeholders ":username" and ":email"
$sql="insert into tbl_user (username, email) values ​​(:username,:email)";
$command=$connection->createcommand ($sql);
//Replace the placeholder ":username" with the actual username
$command->bindparam (":username", $username, pdo ::param_str);
//Replace the placeholder ":email" with the actual email
$command->bindparam (":email", $email, pdo ::param_str);
$command->execute ();
//insert another row with new parameter set
$command->bindparam (":username", $username2, pdo ::param_str);
$command->bindparam (":email", $email2, pdo ::param_str);
$command->execute ();

The methods bindparam () and bindvalue () are very similar.The only difference is that the former uses a php variable to bind the parameters,The latter uses a value.For those large data block parameters in memory,For performance reasons,The former should be used in preference.

6.Binding columns

When getting query results,You can also bind columns using php variables.This will automatically populate with the latest value each time a row in the query result is fetched.

$sql="select username, email from tbl_user";
$datareader=$connection->createcommand ($sql)->query ();
//bind the first column (username) with the $username variable
$datareader->bindcolumn (1, $username);
//bind the second column (email) using the $email variable
$datareader->bindcolumn (2, $email);
while ($datareader->read ()! == false)
//$username and $email contain username and email in the current line

7.Use table prefixes

To use a table prefix,Configure the cdbconnection ::tableprefix property to the desired table prefix.Then, use in sql statement

{{tablename}} represents the name of the table,Where tablename is the name of the table without a prefix.For example, if the database contains a file named tbl_user

, And tbl_ is configured as a table prefix,Then we can use the following code to execute user-related queries:

$sql="select * from {{user}}";
$users=$connection->createcommand ($sql)->queryall ();

Second, active record

Although Yii Dao can handle almost any database related task,But most likely we will spend 90%of our time writing some common crud (create, read,

update and delete) SQL statements. And our code will become difficult to maintain when mixed with SQL statements.To solve these problems,We can use active records.

Active record (ar) is a popular object-relational mapping (orm) technology. Each ar

A class represents a data table (or view), and the columns of the data table (or view) are reflected as attributes of the class in the ar classAn ar instance represents a row in the table.Common crud operations as ar

Method to achieve.Therefore, we can access the data in a more object-oriented way.For example, we can use the following code to insert a new row into the tbl_post table.

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

Note:ar is not intended to solve all database related tasks.Its best application is to model data tables for PHP structures and execute queries that do not contain complex SQL statements. For complex query scenarios,Yii dao should be used.

1. Establish a database connection

ar relies on a database connection to perform database-related operations.by default,It assumes that the db application component provides the required cdbconnection database connection instance.The following application configuration provides an example:

return array (
"components" =>array (
"db" =>array (
"class" =>"system.db.cdbconnection","connectionstring" =>"sqlite:path/to/dbfile",//Turn on table structure caching to improve performance
//"schemacachingduration" =>3600,),),);

Tip:Because the active record relies on the metadata of the table to determine the information of the columnReading metadata and parsing takes time.

If your database table structure rarely changes,You should enable the table structure cache by configuring the cdbconnection ::schemacachingduration property to a value greater than zero.

If i want to use an application component that is not db,Or if i want to handle multiple databases with ar,You should override cactiverecord ::getdbconnection (). The cactiverecord class is the base class for all ar classes.

Tip:There are two ways to use multiple databases with ar.If the database structure is different,You can create different ar base classes to implement different getdbconnection (). Otherwise, dynamically changing the static variable cactiverecord ::db is a good idea.

2.Define ar class

To access a data table,We first need to define an ar class by integrating cactiverecord. Each ar class represents a separate data table,An ar instance represents a row in that table.

The following example shows the simplest code of the ar class representing the tbl_post table:

class post extends cactiverecord
public static function model ($classname=__ class__)
return parent ::model ($classname);
public function tablename ()
return "tbl_post";

Tip:Since the ar class is often referenced in multiple places,We can import the entire directory containing the ar class,Instead of importing one by one. For example, if all our ar class files are in the protected/models directory, we can configure the application as follows:

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

by default,The ar class has the same name as the data table.If different,Please override the tablename () method.

To use the table prefix feature,The tablename () method of the ar class can be overridden as follows

public function tablename ()
return "{{post}}";

This means that,We enclose table names without prefixes in double curly brackets,This allows Yii to automatically add prefixes,This returns the full table name.

The value of a column in a data table row can be accessed as a property of the corresponding ar instance.For example, the following code sets the title column (attribute):

$post=new post;
$post->title="a sample post";

Although we never explicitly define the property title in the post class, we can still access it through the above code.This is because title is one of the tbl_post tables

Column, cactiverecord makes it an accessible property via PHP's __get () magic method.If we try to access a non-existing column in the same way,An exception will be thrown.

If a table has no primary key,You must override the primarykey () method in the corresponding ar class to specify which column or columns to use as the primary key.

public function primarykey ()
return "id";
//For composite primary keys,To return an array similar to the following
//return array ("pk1", "pk2");

3. Create a record

To insert a new row into a data table,We want to create an instance of the corresponding ar class,Set its properties related to the columns of the table,Then call the save () method to complete the insert:

$post=new post;
$post->title="sample post";
$post->content="content for the sample post";
$post->create_time=time ();
$post->save ();

If the primary key of the table is self-incrementing,After the insertion is complete,The ar instance will contain an updated primary key.In the example above,The id attribute will reflect the primary key value of the newly inserted post,Even if we never change it explicitly.

If a column uses a static default value in the table structure (such as a string,A number) definition. The corresponding attribute in the ar instance will automatically include this default value when the instance is created.One way to change this default is to explicitly define this property in the ar class:

class post extends cactiverecord
public $title="please enter a title";
$post=new post;
echo $post->title;//here will show:please enter a title

Before the record is saved (inserted or updated) into the database,Its attributes can be assigned the type cdbexpression. For example, to save a timestamp returned by mysql's now () function,We can use the following code:

$post=new post;
$post->create_time=new cdbexpression ("now ()");//cdbexpression class is to calculate the value of the database expression
//$post->create_time="now ()";will not work,because
//"now ()" will be treated as a string.
$post->save ();

Tip:Since ar allows us to perform database operations without writing a lot of SQL statements,We often want to know what SQL statements are executed behind ar. This can be achieved by enabling Yii's logging function.For example, we enable cweblogroute in the application configuration, and we will see the executed SQL statements at the end of each web page.

We can also set cdbconnection ::enableparamlogging to true in the application configuration, so that the parameter values ​​bound in the sql statement will also be recorded.

4.Read records

To read data from a data table,We can call one of the find series methods as follows:

//Find the first row in the results that meet the specified conditions
$post=post ::model ()->find ($condition, $params);
//find the row with the specified primary key value
$post=post ::model ()->findbypk ($postid, $condition, $params);
//find rows with specified attribute value
$post=post ::model ()->findbyattributes ($attributes, $condition, $params);
//Find the first line in the result by the specified SQL statement
$post=post ::model ()->findbysql ($sql, $params);

As shown above,We call the find method via post ::model (). Remember that the static method model () is required for every ar class.This method returns an ar instance in the object context for accessing class-level methods (something similar to static class methods).

If the find method finds a row that meets the query conditions,It will return a post instance whose properties contain the value of the corresponding column in the data table row.Then we can read the loaded value like the properties of ordinary objects,For example echo $post->title ;.

If nothing is found in the database using the given query criteria, The find method will return null.

When calling find, we use $condition and $params to specify query conditions.Here $condition can be a where string in the sql statement, and $params is an array of parameters.The value should be bound to a placeholder in $condation.E.g:

//find the line with postid=10
$post=post ::model ()->find ("postid =:postid", array (":postid" =>10));

Note:In the above example,We may need to escape references to the postid column in a particular dbms. For example, if we use postgresql, we must write this expression as "postid" =:postid because postgresql is not case sensitive by default for column names.

We can also use $condition to specify more complex query conditions.Without using strings,We can make $condition an instance of cdbcriteria, which allows us to specify conditions that are not limited to where. E.g:

$criteria=new cdbcriteria;
$criteria->select="title";//Select only the "title" column
$criteria->condition="postid =:postid";
$criteria->params=array (":postid" =>10);
$post=post ::model ()->find ($criteria);//$params is no longer needed

Note that when using cdbcriteria as the query criteria,The $params parameter is no longer needed,Because it can be specified in cdbcriteria, just like above.

An alternative to cdbcriteria is to pass an array to the find method.The keys and values ​​of the array correspond to the attribute names and values ​​of the criterion.The above example can be rewritten as follows:

$post=post ::model ()->find (array (
"select" =>"title","condition" =>"postid =:postid","params" =>array (":postid" =>10),));

When a query condition is about matching several columns by a specified value,We can use findbyattributes (). We make $attributes

The argument is an array of values ​​indexed by the column names.In some frameworks,This task can be done by calling something like findbynameandtitle

Method to achieve.Although this method seems tempting, But it often causes confusion,Conflicts and issues such as case sensitivity of column names.

When multiple rows of data match the specified query criteria,We can bring them all back with the findall method below.Each has its own find method, as we have already said.

//find all rows that meet the specified criteria
$posts=post ::model ()->findall ($condition, $params);
//find all rows with the specified primary key
$posts=post ::model ()->findallbypk ($postids, $condition, $params);
//find all rows with the specified attribute value
$posts=post ::model ()->findallbyattributes ($attributes, $condition, $params);
//find all rows by the specified sql statement
$posts=post ::model ()->findallbysql ($sql, $params);

If nothing matches the query,findall will return an empty array.This is different from find, which returns null if nothing is found.

In addition to the find and findall methods described above, for convenience,(Yii) The following methods are also provided:

//Get the number of rows that meet the specified conditions
$n=post ::model ()->count ($condition, $params);
//Get the number of result rows by the specified sql
$n=post ::model ()->countbysql ($sql, $params);
//check if there is at least one line compounding the specified condition
$exists=post ::model ()->exists ($condition, $params);

5, update records

After the ar instance is populated with column values,We can change them and save them back to the data table.

$post=post ::model ()->findbypk (10);
$post->title="new post title";
$post->save ();//save changes to the database

As we can see,We use the same save () method to perform insert and update operations.If an ar instance was created using the new operator,Call save ()

A new row of data will be inserted into the data table;If the ar instance is the result of a find or findall method,Call save ()

The existing rows in the table will be updated.In fact, we use cactiverecord ::isnewrecord to indicate if an ar instance is new.

It is also possible to directly update one or more rows in the data table without loading it first. ar provides the following convenient class-level methods for this purpose:

//Update the rows that meet the specified conditions
post ::model ()->updateall ($attributes, $condition, $params);
//Update the rows that meet the specified conditions and primary key
post ::model ()->updatebypk ($pk, $attributes, $condition, $params);
//Update the count column of the rows that meet the specified conditions
post ::model ()->updatecounters ($counters, $condition, $params);

In the above code, $attributes is an array containing column values ​​indexed by column names; $counters is an array of incrementable values ​​indexed by column names;$condition and $params were described in the previous paragraph.

6.Delete records

If an ar instance is populated with a row of data,We can also delete this row of data.

$post=post ::model ()->findbypk (10);//Suppose there is a post,Its id is 10
$post->delete ();//delete this row from the data table

Note that after deletion, The ar instance remains unchanged,But the corresponding row in the data table is gone.

Use the following class-level code,You can delete a row without first loading it.

//delete rows that meet the specified conditions
post ::model ()->deleteall ($condition, $params);
//delete rows that meet the specified conditions and primary key
post ::model ()->deletebypk ($pk, $condition, $params);

Data verification

When inserting or updating a row,We often need to check whether the values ​​of a column comply with the corresponding rules.If the value of the column is provided by the end user,This is even more important.In general,We can never trust any data from the client.

When save () is called, ar automatically performs data validation.Validation is based on the rules specified in the rules () method of the ar class.For more details on validation rules,Please refer to the Claim Verification Rules section. The following is a typical workflow required when saving records.

if ($post->save ())
//data is valid and successfully inserted/updated
//data is invalid,Call geterrors () to extract error information

When the data to be inserted or updated is submitted by an end user in an html form,We need to assign it to the corresponding ar attribute. We can achieve it in a way similar to the following:

$post->title=$_ post ["title"];
$post->content=$_ post ["content"];
$post->save ();

If there are many columns,We can see a long list for this kind of replication.This can be simplified by using the attributes attribute shown below.More information can be found in the section Security Property Assignments and Creating Actions.

//Suppose $_post ["post"] is an array whose values ​​are indexed by column names
$post->attributes=$_ post ["post"];
$post->save ();

8. Contrast records

Similar to table records,The ar instance is identified by its primary key value.So to compare two ar instances, assuming they belong to the same ar class, we only need to compare their primary key values.However, an easier way is to call cactiverecord ::equals ().

Unlike the implementation of ar in other frameworks, Yii supports multiple primary keys in its ar. A composite primary key consists of two or more fields.Accordingly, the primary key value appears as an array in Yii.The primarykey attribute gives the primary key value of an ar instance.


cactiverecord provides several placeholder methods,They can be overridden in subclasses to customize their workflow.

beforeva lidate and aftervalidate:these two will be called before and after validating the data.

beforesave and aftersave:these will be called before and after saving the ar instance.

beforedelete and afterdelete:these will be called before and after an ar instance is deleted.

afterconstruct:This will be called after each ar instance is created using the new operator.

beforefind:This will be called before an ar finder is used to execute the query (eg find (), findall ()).

afterfind:This will be called when each ar instance is created as a query result.

10.Using ar to process transactions

Each ar instance contains a property called dbconnection, which is an instance of cdbconnection, so that we can use the transaction function provided by yii dao with ar when needed:

$model=post ::model ();
$transaction=$model->dbconnection->begintransaction ();
//Find and save are two steps that may be intervened by another request
//This way we use a transaction to ensure its consistency and integrity
$post=$model->findbypk (10);
$post->title="new post title";
$post->save ();
$transaction->commit ();
catch (exception $e)
$transaction->rollback ();

11, named range

A named scope represents a named query rule,It can be used in conjunction with other named ranges and applied to active record queries.

Named scopes are mainly declared as name-rule pairs in the cactiverecord ::scopes () method.The following code declares two named ranges in the post model class. published and recently.

class post extends cactiverecord
public function scopes ()
return array (
"published" =>array (
"condition" =>"status=1",),"recently" =>array (
"order" =>"create_time desc","limit" =>5,),);

Each named range is declared as an array that can be used to initialize cdbcriteria instances.For example, the recently named range specifies that the order attribute is create_time desc and the limit attribute is 5. After they translate into query rules, they will return the last 5 posts.

Named ranges are mostly used as modifiers for find method calls.Several named ranges can be chained together to form a more restrictive query result set.For example, to find recent posts,We can use the following code:

$posts=post ::model ()->published ()->recently ()->findall ();

In general,The named range must appear to the left of a find method call.Each of them provides a query rule,And federated to other rules,Including the one passed to the find method call.The end result is like adding a series of filters to a query.

Named ranges can also be used in the update and delete methods. For example, the following code will delete all recently posted posts:

post ::model ()->published ()->recently ()->delete ();

Note:Named scopes can only be used for class-level methods.That is,This method must be called with classname ::model ().

12.Parameterized named ranges

Named ranges can be parameterized.For example, we want to customize the number of posts specified in the recently named range,To achieve this,Instead of declaring named scopes in the cactiverecord ::scopes method,Instead, you need to define a method with the same name as this named range:

public function recently ($limit=5)
$this->getdbcriteria ()->mergewith (array (
"order" =>"create_time desc","limit" =>$limit,));
return $this;

Then, we can use the following statement to get the 3 most recently posted posts.

$posts=post ::model ()->published ()->recently (3)->findall ();

In the above code,If we don't provide parameter 3, we will get the 5 most recent posts by default.

13.Default named range

Model classes can have a default named scope,It will apply to all (including those related)

Queries about this model.For example, a website that supports multiple languages ​​may only want to display content in the language specified by the current user.Because there may be many queries about the content of this site,We can define a default

Named range to resolve this issue.To achieve this,We override the cactiverecord ::defaultscope method as follows:

class content extends cactiverecord
public function defaultscope ()
return array (
"condition" =>"language =" ". yii ::app ()->language." "",);

Now, if the following method is called,The query rules defined above will be used automatically:

$contents=content ::model ()->findall ();

Note that the default named range applies only to select queries. The insert, update and delete queries will be ignored.

Third, the relational active record (relational query)

We already know how to get data from a single data table through active record (ar),In this section,We will introduce how to use ar to connect to the associated data table to obtain data.

Before using association ar, you must first establish a primary key-foreign key association between the associated tables in the database.ar needs to analyze the meta information associated with the data table in the analysis database,To decide how to connect the data.

1.How to declare an association

Before using ar for related queries,We need to tell ar how the ar classes are related.

The association between ar classes directly reflects the association between the data tables represented by this class in the database.From a relational database perspective,There are three possible associations between the two data tables a and b:one-to-many, one-to-one, and many-to-many. In ar, there are four types of associations:

belongs_to:If the relationship between data tables a and b is one-to-many,Then we say that b belongs to a.

has_many:If the relationship between data tables a and b is many-to-one,Then we say that b has many a.

has_one:This is a special case of the "has_many" relationship,When a has at most one,We say that b has one a.


This is equivalent to a many-to-many relationship in a relational database.Because most relational databases do not directly support many-to-many relationships,A separate association table is usually required at this time,Break up a many-to-many relationship into two one-to-one relationships

Many relationships.If you use ar to understand,We can think of the many_many relationship as consisting of belongs_to and has_many.

Declare the association in ar,This is achieved by overriding the relationships () method in the parent class cactiverecord.This method returns an array containing relation definitions.Each set of key values ​​in the array represents an association:

"varname" =>array ("relationtype", "classname", "foreignkey", ... additional options)

Where varname is the name of the association;relationtype specifies the type of this relation,There are four constants that represent the four associated types:

self ::belongs_to, self ::has_one, self ::has_many and self ::many_many;

classname is the class name of the ar class to which this relationship is associated;foreignkey specifies the foreign key through which this association is related.Additional

options can add some additional settings,Will be introduced later.

The following code shows how to define the association between user and post.

class post extends cactiverecord {
public function relations () {
return array (
"author" =>array (
self ::belongs_to,"user","authorid"
),"categories" =>array (
self ::many_many,"category","postcategory (postid, categoryid)"
class user extends cactiverecord {
public function relations () {
return array (
"posts" =>array (
self ::has_many,"post","authorid"
),"profile" =>array (
self ::has_one,"profile","ownerid"

Explanation:Sometimes a foreign key may consist of two or more fields,Multiple field names can be separated by commas or spaces here.

Written here together.For many-to-many relationships,The association table must be noted in the foreign key,For example categories in the post class

In the association, the foreign key needs to be written as postcategory (postid, categoryid).

When declaring an association in the ar class,Each association is added to the ar class as an attribute, and the attribute name is the name of the association.When performing a correlated query,These properties will be set to the instance of the ar class associated with it,For example, when a query obtains a post instance, its $author attribute is an instance of the user class representing the post author.

2.Related query

The simplest way to perform a related query is to access a related attribute of a related ar object.If this property has not been accessed before,A relational query is started,Connect through the primary key of the current ar object

Related tables,To get the value of the associated object,This data is then saved in the properties of the object.This method is called "lazy loading", that is, only when a property is accessed,To actually put this into the database

Relevant data is retrieved.The following example describes the process of lazy loading:

//retrieve the post whose id is 10
$post=post ::model ()->findbypk (10);
//retrieve the post "s author:a relational query will be performed here

In different contexts,If no results are found,The returned values ​​are also different:belongs_to is associated with has_one and returns null if there is no result;has_many and many_many, returns an empty array when there is no result.

The lazy loading method is very convenient to use,But in some cases it is not efficient.For example, if we want to get the author information of n posts,Using the deferred method will execute n join queries.At this point we should use the so-called eager loading method.

The eager loading method retrieves the main ar instance and its related ar instance. This is done by using the with () method plus the find or findall methods

to make. E.g,

$posts=post ::model ()->with ("author")->findall ();

The above code will return an array of post instances. Unlike the lazy loading method,The author attribute in each post instance has been associated before we access this attribute

user instance population.Instead of performing a join query for each post, Eager loading method takes all posts and their authors in a single join query!

We can specify multiple association names in the with () method.For example, the following code will retrieve posts and their authors and categories:

$posts=post ::model ()->with ("author", "categories")->findall ();

We can also use nested eager loading.Not using a list of associated names, We pass the association name to the with () method in a hierarchical manner, as follows,

$posts=post ::model ()->with (
"author.profile","author.posts","categories")->findall ();

The above code will retrieve all posts and their authors and categories.It will also take out the profile and posts of each author.

Eager loading can also be performed by specifying the cdbcriteria ::with attribute, as follows:

$criteria=new cdbcriteria;
$criteria->with=array (
$posts=post ::model ()->findall ($criteria);
$posts=post ::model ()->findall (array (
"with" =>array (

3.Related query options

Earlier we mentioned that additional parameters can be specified in the association declaration.These options,Specified as a name-value pair, used to customize the correlation query.They are outlined as follows:

select:A list of fields to query for the associated ar class.

The default is empty.

The default is empty.

The default is empty.

The default is empty.

class user extends cactiverecord
public function relations ()
return array (

  • Previous Android code to achieve top and bottom layout of pictures and text
  • Next Access, creation, modification, deletion of DOM nodes in JavaScript