From 03f362a40a8dd39f8c8b4bf816334922b7b264e4 Mon Sep 17 00:00:00 2001 From: wei <> Date: Tue, 9 Jan 2007 10:42:06 +0000 Subject: add TActiveRecord::findAllByPks() --- .../protected/pages/Database/ActiveRecord.page | 280 ++++++++++++--------- 1 file changed, 158 insertions(+), 122 deletions(-) (limited to 'demos/quickstart/protected/pages/Database/ActiveRecord.page') diff --git a/demos/quickstart/protected/pages/Database/ActiveRecord.page b/demos/quickstart/protected/pages/Database/ActiveRecord.page index e3da53c0..a1337ba3 100644 --- a/demos/quickstart/protected/pages/Database/ActiveRecord.page +++ b/demos/quickstart/protected/pages/Database/ActiveRecord.page @@ -2,53 +2,53 @@

Active Record

Active Records are objects that wrap a row in a database table or view, - encapsulates the database access and adds domain logic on that data. - The basics of an Active Record is a business object class, e.g., a - Products class, that match very closely the record structure - of an underlying database table. Each Active Record will be responsible for - saving and loading data to and from the database.

+ encapsulates the database access and adds domain logic on that data. + The basics of an Active Record is a business object class, e.g., a + Products class, that match very closely the record structure + of an underlying database table. Each Active Record will be responsible for + saving and loading data to and from the database.

Info: - The data structure of an Active Record should match exactly that of a table - in the database. - Each field in the class must correspond to one column in the table. + The data structure of an Active Record should match exactly that of a table + in the database. + Each field in the class must correspond to one column in the table.

When to Use It

Active Record is a good choice for domain logic that isn't too complex, - such as creates, reads, updates, and deletes. Derivations and validations - based on a single record work well in this structure. Active Record has the - primary advantage of simplicity. It's easy to build - Active Records, and they are easy to understand.

+ such as creates, reads, updates, and deletes. Derivations and validations + based on a single record work well in this structure. Active Record has the + primary advantage of simplicity. It's easy to build + Active Records, and they are easy to understand.

-

However, as your business logic grows in complexity, you'll soon want - to use your object's direct relationships, collections, inheritance, and so +

However, as your business logic grows in complexity, you'll soon want + to use your object's direct relationships, collections, inheritance, and so forth. These don't map easily onto Active Record, and adding them piecemeal - gets very messy. - Another argument against Active Record is the fact that it couples the object - design to the database design. This makes it more difficult to refactor as a project goes forward.

- -

The alternative is to use a Data Mapper that separates the roles of the - business object and how these objects are stored. - Prado provides a complimentary choice between Active Record and - SqlMap Data Mapper. - A SqlMap Data Mapper can be used to load Active Record objects, in turn, these - Active Record objects can be used to update the database. - The "relationship" between Active Records and SqlMap is illustrated in the - following diagram. More details regarding the SqlMap Data Mapper can be found in - the SqlMap Manual. - alt="Active Records and SqlMap DataMapper" id="fig:diagram.png" class="figure"/> -

- -

- The Active Record class has methods that do the following: -

-

-The Active Record implementation utilizes the Prado DAO classes for data access. + gets very messy. + Another argument against Active Record is the fact that it couples the object + design to the database design. This makes it more difficult to refactor as a project goes forward.

+ +

The alternative is to use a Data Mapper that separates the roles of the + business object and how these objects are stored. + Prado provides a complimentary choice between Active Record and + SqlMap Data Mapper. + A SqlMap Data Mapper can be used to load Active Record objects, in turn, these + Active Record objects can be used to update the database. + The "relationship" between Active Records and SqlMap is illustrated in the + following diagram. More details regarding the SqlMap Data Mapper can be found in + the SqlMap Manual. + alt="Active Records and SqlMap DataMapper" id="fig:diagram.png" class="figure"/> +

+ +

+ The Active Record class has methods that do the following: +

+

+The Active Record implementation utilizes the Prado DAO classes for data access. The current Active Record implementation supports MySQL, Postgres SQL and @@ -56,14 +56,14 @@ The current Active Record implementation supports Support for other databases can be provided when there are sufficient demand.

Defining an Active Record

Let us - consider the following "users" table that contains two columns named "username" and "email", - where "username" is also the primary key. + consider the following "users" table that contains two columns named "username" and "email", + where "username" is also the primary key. CREATE TABLE users ( - username VARCHAR( 20 ) NOT NULL , - email VARCHAR( 200 ) , - PRIMARY KEY ( username ) + username VARCHAR( 20 ) NOT NULL , + email VARCHAR( 200 ) , + PRIMARY KEY ( username ) );

@@ -71,91 +71,98 @@ CREATE TABLE users class UserRecord extends TActiveRecord { - public $username; //the column named "username" in the "users" table - public $email; - - public static $_tablename='users'; //table name - - /** - * @return TActiveRecord active record finder instance - */ - public static function finder() - { - return self::getRecordFinder('UserRecord'); - } + public $username; //the column named "username" in the "users" table + public $email; + + public static $_tablename='users'; //table name + + /** + * @return TActiveRecord active record finder instance + */ + public static function finder() + { + return self::getRecordFinder('UserRecord'); + } }

Each property of the UserRecord class must correspond to a - column with the same name in the "users" table. The static class variable - $_tablename (must be public) is optional when the class name is the same as - the table name in the database, otherwise $_tablename must - specify the table name that corresponds to your Active Record class. + column with the same name in the "users" table. The static class variable + $_tablename (must be public) is optional when the class name is the same as + the table name in the database, otherwise $_tablename must + specify the table name that corresponds to your Active Record class.

Tip: - Since TActiveRecord extends TComponent, setter and - getter methods can be defined to allow control over how variables - are set and returned. For example, adding a $level property to the UserRecord class: + Since TActiveRecord extends TComponent, setter and + getter methods can be defined to allow control over how variables + are set and returned. For example, adding a $level property to the UserRecord class: class UserRecord extends TActiveRecord { - ... //existing definitions as above - - private $_level; - public function setLevel($value) { - $this->_level=TPropertyValue::ensureInteger($value,0); - } - public function getLevel($value){ - return $this->_level; - } + ... //existing definitions as above + + private $_level; + public function setLevel($value) { + $this->_level=TPropertyValue::ensureInteger($value,0); + } + public function getLevel($value){ + return $this->_level; + } }
+
Note: +TActiveRecord can also work with database views by specifying the value $_tablename +corresponding to the view name. However, objects returned +from views are read-only, calling the save() or delete() method +will raise an exception. +
+

- The static method finder() returns an UserRecord instance - that can be used to load records from the database. The loading of records - using the finer methods is discuss a little later. The TActiveRecord::getRecordFinder() - static method takes the name of the current Active Record class as parameter. + The static method finder() returns an UserRecord instance + that can be used to load records from the database. The loading of records + using the finer methods is discuss a little later. The TActiveRecord::getRecordFinder() + static method takes the name of the current Active Record class as parameter.

Setting up a database connection

- A default database connection for Active Record can be set as follows. - See Establishing Database Connection for - futher details regarding creation of database connection in general. + A default database connection for Active Record can be set as follows. + See Establishing Database Connection for + futher details regarding creation of database connection in general. //create a connection and give it to the ActiveRecord manager. $dsn = 'pgsql:host=localhost;dbname=test'; //Postgres SQL $conn = new TDbConnection($dsn, 'dbuser','dbpass'); TActiveRecordManager::getInstance()->setDbConnection($conn); - +

- The default database connection can also be configured using a <module> - tag in the application.xml - or config.xml as follows. + The default database connection can also be configured using a <module> + tag in the application.xml + or config.xml as follows. - - + +

Tip: - The EnableCache attribute when set to "true" will cache the table - meta data, that is, the table columns names, indexes and constraints are - saved in the cache and reused. You must clear or disable the cache if you - wish to see chanages made to your table definitions. A cache - module must also be defined for the cache to function. + The EnableCache attribute when set to "true" will cache the table + meta data, that is, the table columns names, indexes and constraints are + saved in the cache and reused. You must clear or disable the cache if you + wish to see chanages made to your table definitions. A cache + module must also be defined for the cache to function.

A ConnectionID property can be specified with value corresponding - to another TDataSourceConfig module configuration's ID value. This allows - the same database connection to be used in other modules such as SqlMap. + to another TDataSourceConfig module configuration's ID value. This allows + the same database connection to be used in other modules such as SqlMap. @@ -168,32 +175,52 @@ TActiveRecordManager::getInstance()->setDbConnection($conn); - - + +

Loading data from the database

- The TActiveRecord class provides many convenient methods to find - records from the database. The simplest is finding records by matching primary keys. - See the for - more details. + The TActiveRecord class provides many convenient methods to find + records from the database. The simplest is finding records by matching primary keys. + See the for + more details.

-

findByPk()

-

Finds one record using only the primary key or composite primary keys. +

findByPk()

+

Finds one record using only the primary key or composite primary keys. $finder = UserRecord::finder(); $user = $finder->findByPk($primaryKey); //when the table uses composite keys -$record = $finder->findByPk($key1, $key2, ...); //for composite keys -$record = $finder->findByPk(array($key1, $key2,...)); //same as above +$record = $finder->findByPk($key1, $key2, ...); +$record = $finder->findByPk(array($key1, $key2,...));

+

findAllByPks()

+

Finds multiple records using a list of primary keys or composite primary keys. +The following are equivalent for scalar primary keys (primary key consisting of only one column/field). + +$finder = UserRecord::finder(); +$users = $finder->findAllByPk($key1, $key2, ...); +$users = $finder->findAllByPk(array($key1, $key2, ...)); + +The following are equivalent for composite keys. + +//when the table uses composite keys +$record = $finder->findAllByPks(array($key1, $key2), array($key3, $key4), ...); + +$keys = array( array($key1, $key2), array($key3, $key4), ... ); +$record = $finder->findAllByPks($keys); + + +

+ +

find()

Finds one single record that matches the criteria. The criteria - can be a partial SQL string or a TActiveRecordCriteria object. + can be a partial SQL string or a TActiveRecordCriteria object. $finder = UserRecord::finder(); @@ -212,13 +239,13 @@ $finder->find($criteria); //the 2nd parameter for find() is ignored.

The TActiveRecordCriteria class has the following properties: -

+

@@ -258,8 +285,8 @@ $finder->find('Username = ? AND Password = ?', $name, $pass); $finder->findAllByAge($age); $finder->findAll('Age = ?', $age); -

- +

+

findBySql()

Finds records using full SQL, returns corresponding array of record objects.

@@ -291,7 +318,7 @@ incremented values.

To update a record in the database, just change one or more properties of the Active Record object that has been loaded from the database and then -call the save() method. +call the save() method. $user = UserRecord::finder()->findByName('admin'); @@ -303,14 +330,23 @@ $user->save(); //update it.

Active Record objects have a simple life-cycle illustrated in the following diagram. alt="Active Records Life Cycle" id="fig:cycle.png" class="figure"/> +We see that new ActiveRecord objects are created by either using one of the find*() +methods or using creating a new instance by using PHP's new keyword. Objects +created by a find*() method starts with clean state. New instance of +ActiveRecords created other than by a find*() method starts with new state. +When ever you +call the save() method on the ActiveRecord object, the object enters the clean +state. Objects in the clean becomes dirty whenever one of more of its +internal states are changed. Calling the delete() method on the object +ends the object life-cycle, no futher actions can be performed on the object.

Deleting existing records

- To delete an existing record that is already loaded, just call the delete() method. - You can also delete records in the database by primary keys without - loading any records using the deleteByPk() method. - For example, to delete one or records with tables having a scalar primary key. + To delete an existing record that is already loaded, just call the delete() method. + You can also delete records in the database by primary keys without + loading any records using the deleteByPk() method. + For example, to delete one or records with tables having a scalar primary key. $finder->deleteByPk($primaryKey); //delete 1 record $finder->deleteByPk($key1,$key2,...); //delete multiple records @@ -333,7 +369,7 @@ $finder->deleteByPk(array( array($key1,$key2), array($key3,$key4), .. ));

Transactions

All Active Record objects contains the property DbConnection - that can be used to obtain a transaction object. + that can be used to obtain a transaction object. $finder = UserRecord::finder(); @@ -345,7 +381,7 @@ try $user->save(); $transaction->commit(); } -catch(Exception $e) // an exception is raised if a query fails will be raised +catch(Exception $e) // an exception is raised if a query fails { $transaction->rollBack(); } @@ -353,8 +389,8 @@ catch(Exception $e) // an exception is raised if a query fails will be raised

References

\ No newline at end of file -- cgit v1.2.3