v5:userguide:active_record
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revisionNext revisionBoth sides next revision | ||
userguide:active_record [2015/08/30 18:06] – created mnewnham | v5:userguide:active_record [2016/01/13 01:51] – ↷ Page moved from userguide:active_record to v5:userguide:active_record mnewnham | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ADOdb Active Record | + | <WRAP todo> |
+ | Fix this | ||
+ | </ | ||
+ | ====== | ||
- | (c) 2000-2014 | + | <WRAP right box round> |
- | + | Author Credit: | |
- | This software is dual licensed using BSD-Style and LGPL. This means you can use it in compiled proprietary and commercial products. | + | </ |
- | + | ===== Introduction | |
- | Introduction | + | |
ADOdb_Active_Record is an Object Relation Mapping (ORM) implementation using PHP. In an ORM system, the tables and rows of the database are abstracted into native PHP objects. This allows the programmer to focus more on manipulating the data and less on writing SQL queries. | ADOdb_Active_Record is an Object Relation Mapping (ORM) implementation using PHP. In an ORM system, the tables and rows of the database are abstracted into native PHP objects. This allows the programmer to focus more on manipulating the data and less on writing SQL queries. | ||
Line 11: | Line 13: | ||
This implementation differs from Zend Framework' | This implementation differs from Zend Framework' | ||
- | Works with PHP4 and PHP5 and provides equivalent functionality in both versions of PHP. | + | * Works with PHP4 and PHP5 and provides equivalent functionality in both versions of PHP. |
- | ADOdb_Active_Record works when you are connected to multiple databases. Zend's only works when connected to a default database. | + | |
- | Support for $ADODB_ASSOC_CASE. The field names are upper-cased, | + | |
- | No field name conversion to camel-caps style, unlike Zend's implementation which will convert field names such as ' | + | |
- | NewADOConnection:: | + | |
- | Caching of table metadata so it is only queried once per table, no matter how many Active Records are created. | + | |
- | PHP5 version of ADOdb_Active_Record now supports one-to-many relationships. | + | |
- | New adodb-active-recordx.inc.php, | + | |
- | Lots of additional | + | |
+ | ===== Additional | ||
ADOdb_Active_Record is designed upon the principles of the " | ADOdb_Active_Record is designed upon the principles of the " | ||
ADOdb_Active_Record maps a database table to a PHP class, and each instance of that class represents a table row. Relations between tables can also be defined, allowing the ADOdb_Active_Record objects to be nested. | ADOdb_Active_Record maps a database table to a PHP class, and each instance of that class represents a table row. Relations between tables can also be defined, allowing the ADOdb_Active_Record objects to be nested. | ||
- | Setting the Database Connection | + | ===== Setting the Database Connection |
The first step to using ADOdb_Active_Record is to set the default connection that an ADOdb_Active_Record objects will use to connect to a database. | The first step to using ADOdb_Active_Record is to set the default connection that an ADOdb_Active_Record objects will use to connect to a database. | ||
+ | <code php> | ||
require_once(' | require_once(' | ||
- | $db = NewADOConnection(' | + | $db = NewADOConnection(' |
ADOdb_Active_Record:: | ADOdb_Active_Record:: | ||
- | Table Rows as Objects | + | |
+ | </ | ||
+ | |||
+ | ===== Table Rows as Objects | ||
First, let's create a temporary table in our MySQL database that we can use for demonstrative purposes throughout the rest of this tutorial. We can do this by sending a CREATE query: | First, let's create a temporary table in our MySQL database that we can use for demonstrative purposes throughout the rest of this tutorial. We can do this by sending a CREATE query: | ||
+ | <code php> | ||
$db-> | $db-> | ||
`id` int(10) unsigned NOT NULL auto_increment, | `id` int(10) unsigned NOT NULL auto_increment, | ||
Line 44: | Line 52: | ||
) ENGINE=MyISAM; | ) ENGINE=MyISAM; | ||
" | " | ||
+ | </ | ||
ADOdb_Active_Records are object representations of table rows. Each table in the database is represented by a class in PHP. To begin working with a table as a ADOdb_Active_Record, | ADOdb_Active_Records are object representations of table rows. Each table in the database is represented by a class in PHP. To begin working with a table as a ADOdb_Active_Record, | ||
+ | <code php> | ||
class person extends ADOdb_Active_Record{} | class person extends ADOdb_Active_Record{} | ||
$person = new person(); | $person = new person(); | ||
+ | </ | ||
+ | |||
In the above example, a new ADOdb_Active_Record object $person was created to access the " | In the above example, a new ADOdb_Active_Record object $person was created to access the " | ||
This kind of behavior is typical of ADOdb_Active_Record. It will assume as much as possible by convention rather than explicit configuration. In situations where it isn't possible to use the conventions that ADOdb_Active_Record expects, options can be overridden as we'll see later. | This kind of behavior is typical of ADOdb_Active_Record. It will assume as much as possible by convention rather than explicit configuration. In situations where it isn't possible to use the conventions that ADOdb_Active_Record expects, options can be overridden as we'll see later. | ||
- | Table Columns as Object Properties | + | ===== Table Columns as Object Properties |
When the $person object was instantiated, | When the $person object was instantiated, | ||
Line 59: | Line 71: | ||
Our " | Our " | ||
+ | <code php> | ||
var_dump($person-> | var_dump($person-> | ||
Line 74: | Line 87: | ||
| | ||
*/ | */ | ||
- | | + | </ |
One big difference between ADOdb and Zend's implementation is we do not automatically convert to camelCaps style. | One big difference between ADOdb and Zend's implementation is we do not automatically convert to camelCaps style. | ||
- | Inserting and Updating a Record | + | ===== Inserting and Updating a Record |
An ADOdb_Active_Record object is a representation of a single table row. However, when our $person object is instantiated, | An ADOdb_Active_Record object is a representation of a single table row. However, when our $person object is instantiated, | ||
Line 83: | Line 96: | ||
To insert a new record into the database, change the object' | To insert a new record into the database, change the object' | ||
+ | <code php> | ||
$person = new person(); | $person = new person(); | ||
$person-> | $person-> | ||
Line 88: | Line 102: | ||
$person-> | $person-> | ||
+ | </ | ||
+ | |||
Oh, no! The above code snippet does not insert a new record into the database. Instead, outputs an error: | Oh, no! The above code snippet does not insert a new record into the database. Instead, outputs an error: | ||
Line 98: | Line 114: | ||
To insert a new ADOdb_Active_Record in the database, populate all of ADOdb_Active_Record' | To insert a new ADOdb_Active_Record in the database, populate all of ADOdb_Active_Record' | ||
+ | <code php> | ||
/** | /** | ||
* Calling the save() method will successfully INSERT | * Calling the save() method will successfully INSERT | ||
Line 107: | Line 124: | ||
$person-> | $person-> | ||
$person-> | $person-> | ||
+ | |||
+ | </ | ||
Once this $person has been INSERTed into the database by calling save(), the primary key can now be read as a property. Since this is the first row inserted into our temporary table, its " | Once this $person has been INSERTed into the database by calling save(), the primary key can now be read as a property. Since this is the first row inserted into our temporary table, its " | ||
+ | <code php> | ||
var_dump($person-> | var_dump($person-> | ||
Line 115: | Line 135: | ||
* string(1) | * string(1) | ||
*/ | */ | ||
- | + | </ | |
From this point on, updating it is simply a matter of changing the object' | From this point on, updating it is simply a matter of changing the object' | ||
+ | <code php> | ||
$person-> | $person-> | ||
$person-> | $person-> | ||
- | + | </ | |
The code snippet above will change the favorite color to red, and then UPDATE the record in the database. | The code snippet above will change the favorite color to red, and then UPDATE the record in the database. | ||
- | ADOdb Specific Functionality | + | ===== ADOdb Specific Functionality |
- | Setting the Table Name | + | ==== Setting the Table Name ==== |
The default behaviour on creating an ADOdb_Active_Record is to " | The default behaviour on creating an ADOdb_Active_Record is to " | ||
Line 170: | Line 191: | ||
ADOdb supports replace functionality, | ADOdb supports replace functionality, | ||
+ | <code php> | ||
$rec = new ADOdb_Active_Record(" | $rec = new ADOdb_Active_Record(" | ||
$rec-> | $rec-> | ||
Line 176: | Line 197: | ||
$ok = $rec-> | $ok = $rec-> | ||
ADOdb_Active_Record:: | ADOdb_Active_Record:: | ||
+ | </ | ||
Sometimes, we want to load a single record into an Active Record. We can do so using: | Sometimes, we want to load a single record into an Active Record. We can do so using: | ||
+ | <code php> | ||
$person-> | $person-> | ||
Line 185: | Line 208: | ||
$person-> | $person-> | ||
Returns false if an error occurs. | Returns false if an error occurs. | ||
+ | </ | ||
ADOdb_Active_Record:: | ADOdb_Active_Record:: | ||
We want to retrieve an array of active records based on some search criteria. For example: | We want to retrieve an array of active records based on some search criteria. For example: | ||
+ | <code php> | ||
class person extends ADOdb_Active_Record { | class person extends ADOdb_Active_Record { | ||
var $_table = ' | var $_table = ' | ||
Line 196: | Line 220: | ||
$person = new person(); | $person = new person(); | ||
$peopleArray = $person-> | $peopleArray = $person-> | ||
- | Quoting Identifiers | + | </ |
+ | ===== Quoting Identifiers | ||
You can force column names to be quoted in INSERT and UPDATE statements, typically because you are using reserved words as column names by setting | You can force column names to be quoted in INSERT and UPDATE statements, typically because you are using reserved words as column names by setting | ||
- | ADODB_Active_Record:: | + | |
+ | | ||
Default is false. | Default is false. | ||
- | Error Handling and Debugging | + | ===== Error Handling and Debugging |
In PHP5, if adodb-exceptions.inc.php is included, then errors are thrown. Otherwise errors are handled by returning a value. False by default means an error has occurred. You can get the last error message using the ErrorMsg() function. | In PHP5, if adodb-exceptions.inc.php is included, then errors are thrown. Otherwise errors are handled by returning a value. False by default means an error has occurred. You can get the last error message using the ErrorMsg() function. | ||
To check for errors in ADOdb_Active_Record, | To check for errors in ADOdb_Active_Record, | ||
+ | <code php> | ||
# right! | # right! | ||
$ok = $rec-> | $ok = $rec-> | ||
Line 216: | Line 242: | ||
$rec-> | $rec-> | ||
if ($rec-> | if ($rec-> | ||
+ | |||
+ | </ | ||
The ADOConnection:: | The ADOConnection:: | ||
Line 222: | Line 250: | ||
You can convert an array to an ADOdb_Active_Record using Set(). The array must be numerically indexed, and have all fields of the table defined in the array. The elements of the array must be in the table' | You can convert an array to an ADOdb_Active_Record using Set(). The array must be numerically indexed, and have all fields of the table defined in the array. The elements of the array must be in the table' | ||
+ | <code php> | ||
$row = $db-> | $row = $db-> | ||
Line 241: | Line 270: | ||
echo $e-> | echo $e-> | ||
} | } | ||
- | Primary Keys | + | </ |
+ | |||
+ | ===== Primary Keys ===== | ||
ADOdb_Active_Record does not require the table to have a primary key. You can insert records for such a table, but you will not be able to update nor delete. | ADOdb_Active_Record does not require the table to have a primary key. You can insert records for such a table, but you will not be able to update nor delete. | ||
Line 247: | Line 278: | ||
Sometimes you are retrieving data from a view or table that has no primary key, but has a unique index. You can dynamically set the primary key of a table through the constructor: | Sometimes you are retrieving data from a view or table that has no primary key, but has a unique index. You can dynamically set the primary key of a table through the constructor: | ||
- | $pkeys = array(' | + | <code php> |
+ | $pkeys = array(' | ||
- | // set primary key using constructor | + | // set primary key using constructor |
- | $rec = new ADOdb_Active_Record(' | + | $rec = new ADOdb_Active_Record(' |
+ | // or define a new class | ||
+ | class Product extends ADOdb_Active_Record { | ||
+ | function __construct() | ||
+ | { | ||
+ | parent:: | ||
+ | } | ||
+ | } | ||
- | // or define a new class | + | $rec = new Product(); |
- | class Product extends ADOdb_Active_Record { | + | </ |
- | function __construct() | + | ===== Retrieval of Auto-incrementing ID ===== |
- | { | + | |
- | parent:: | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | $rec = new Product(); | + | |
- | Retrieval of Auto-incrementing ID | + | |
When creating a new record, the retrieval of the last auto-incrementing ID is not reliable for databases that do not support the Insert_ID() function call (check $connection-> | When creating a new record, the retrieval of the last auto-incrementing ID is not reliable for databases that do not support the Insert_ID() function call (check $connection-> | ||
Line 267: | Line 299: | ||
Sometimes we want to load data from one database and insert it into another using ActiveRecords. This can be done using the optional parameter of the ADOdb_Active_Record constructor. In the following example, we read data from db.table1 and store it in db2.table2: | Sometimes we want to load data from one database and insert it into another using ActiveRecords. This can be done using the optional parameter of the ADOdb_Active_Record constructor. In the following example, we read data from db.table1 and store it in db2.table2: | ||
+ | <code php> | ||
$db = NewADOConnection(...); | $db = NewADOConnection(...); | ||
$db2 = NewADOConnection(...); | $db2 = NewADOConnection(...); | ||
Line 276: | Line 308: | ||
foreach($activeRecs as $rec) { | foreach($activeRecs as $rec) { | ||
- | $rec2 = new ADOdb_Active_Record(' | + | $rec2 = new ADOdb_Active_Record(' |
- | $rec2-> | + | |
- | $rec2-> | + | |
- | $rec2-> | + | |
} | } | ||
+ | </ | ||
If you have to pass in a primary key called " | If you have to pass in a primary key called " | ||
$rec = new ADOdb_Active_Record(" | $rec = new ADOdb_Active_Record(" | ||
- | You can now give a named label in SetDatabaseAdapter, | ||
+ | You can now give a named label in SetDatabaseAdapter, | ||
+ | <code php> | ||
$db1 = NewADOConnection(...); | $db1 = NewADOConnection(...); | ||
ADOdb_Active_Record:: | ADOdb_Active_Record:: | ||
Line 297: | Line 331: | ||
... | ... | ||
} | } | ||
- | $ADODB_ACTIVE_CACHESECS | + | |
+ | </ | ||
+ | |||
+ | ===== $ADODB_ACTIVE_CACHESECS | ||
You can cache the table metadata (field names, types, and other info such primary keys) in $ADODB_CACHE_DIR (which defaults to /tmp) by setting the global variable $ADODB_ACTIVE_CACHESECS to a value greater than 0. This will be the number of seconds to cache. You should set this to a value of 30 seconds or greater for optimal performance. | You can cache the table metadata (field names, types, and other info such primary keys) in $ADODB_CACHE_DIR (which defaults to /tmp) by setting the global variable $ADODB_ACTIVE_CACHESECS to a value greater than 0. This will be the number of seconds to cache. You should set this to a value of 30 seconds or greater for optimal performance. | ||
- | Active Record Considered Bad? | + | ===== Active Record Considered Bad? ===== |
Although the Active Record concept is useful, you have to be aware of some pitfalls when using Active Record. The level of granularity of Active Record is individual records. It encourages code like the following, used to increase the price of all furniture products by 10%: | Although the Active Record concept is useful, you have to be aware of some pitfalls when using Active Record. The level of granularity of Active Record is individual records. It encourages code like the following, used to increase the price of all furniture products by 10%: | ||
- | $recs = $db-> | + | <code php> |
- | | + | $recs = $db-> |
+ | foreach($recs as $rec) { | ||
$rec-> | $rec-> | ||
$rec-> | $rec-> | ||
- | } | + | } |
+ | </ | ||
Of course an UPDATE statement is superior because it's simpler and much more efficient (probably by a factor of x10 or more): | Of course an UPDATE statement is superior because it's simpler and much more efficient (probably by a factor of x10 or more): | ||
- | $db-> | + | <code php> |
+ | $db-> | ||
+ | </ | ||
For performance sensitive code, using direct SQL will always be faster than using Active Records due to overhead and the fact that all fields in a row are retrieved (rather than only the subset you need) whenever an Active Record is loaded. | For performance sensitive code, using direct SQL will always be faster than using Active Records due to overhead and the fact that all fields in a row are retrieved (rather than only the subset you need) whenever an Active Record is loaded. | ||
- | Transactions | + | ===== Transactions |
The default transaction mode in ADOdb is autocommit. So that is the default with active record too. The general rules for managing transactions still apply. Active Record to the database is a set of insert/ | The default transaction mode in ADOdb is autocommit. So that is the default with active record too. The general rules for managing transactions still apply. Active Record to the database is a set of insert/ | ||
Line 320: | Line 363: | ||
Smart transactions, | Smart transactions, | ||
+ | <code php> | ||
$conn-> | $conn-> | ||
$parent-> | $parent-> | ||
$child-> | $child-> | ||
$conn-> | $conn-> | ||
- | One to Many Relations | + | </ |
+ | |||
+ | ===== One to Many Relations | ||
Since ADOdb 5.06, we support parent child relationships. This is done using the ClassBelongsTo() and ClassHasMany() functions. | Since ADOdb 5.06, we support parent child relationships. This is done using the ClassBelongsTo() and ClassHasMany() functions. | ||
- | ClassHasMany | + | ===== ClassHasMany |
- | To globally define a one-to-many relationship we use the static function ADODB_Active_Record:: | + | To globally define a one-to-many relationship we use the static function ADODB_Active_Record:: |
- | class person extends ADOdb_Active_Record{} | + | <code php> |
- | ADODB_Active_Record:: | + | class person extends ADOdb_Active_Record{} |
+ | ADODB_Active_Record:: | ||
- | $person = new person(); | + | $person = new person(); |
- | $person-> | + | $person-> |
- | foreach($person-> | + | foreach($person-> |
- | echo " $c-> | + | echo " $c-> |
- | $c-> | + | $c-> |
- | $c-> | + | $c-> |
- | } | + | } |
+ | </ | ||
If no data is loaded, then children is set to an empty array: | If no data is loaded, then children is set to an empty array: | ||
- | $person2 = new person(); | + | <code php> |
- | $p = $person2-> | + | $person2 = new person(); |
- | By default, data returned by HasMany() is unsorted. To define an order by clause (or define a SELECT LIMIT window), see LoadRelations() below. Another point is that all children are loaded only when the child member is accessed (in __get), and not when the Load() function of the parent object is called. This helps to conserve memory. | + | $p = $person2-> |
+ | </ | ||
+ | |||
+ | By default, data returned by HasMany() is unsorted. To define an order by clause (or define a SELECT LIMIT window), see LoadRelations() below. Another point is that all children are loaded only when the child member is accessed (in < | ||
To create and save new parent and child records: | To create and save new parent and child records: | ||
+ | <code php> | ||
+ | class person extends ADOdb_Active_Record{} | ||
+ | class children extends ADOdb_Active_Record{} | ||
+ | ADODB_Active_Record:: | ||
- | class | + | $person |
- | class children extends ADOdb_Active_Record{} | + | |
- | ADODB_Active_Record:: | + | |
- | $person = new person(); | + | for ($i=0; $i<10; $i++) |
+ | | ||
- | for ($i=0; $i<10; $i++) | + | // modify fields of $person, then... |
- | $person-> | + | $person-> |
- | // modify fields of $person, then... | + | foreach($person-> |
- | $person-> | + | // modify fields of $c then... |
- | + | $c-> | |
- | foreach($person-> | + | } |
- | // modify fields of $c then... | + | </ |
- | $c-> | + | |
- | } | + | |
You can have multiple relationships (warning: relations are case-sensitive, | You can have multiple relationships (warning: relations are case-sensitive, | ||
- | ADODB_Active_Record:: | + | <code php> |
- | ADODB_Active_Record:: | + | ADODB_Active_Record:: |
- | $person = new person(); | + | ADODB_Active_Record:: |
- | $person-> | + | $person = new person(); |
- | var_dump($person-> | + | $person-> |
- | var_dump($person-> | + | var_dump($person-> |
+ | var_dump($person-> | ||
+ | </ | ||
By default, the child class is ADOdb_Active_Record. Sometimes you might want the child class to be based on your own class which has additional functions. You can do so using the last parameter: | By default, the child class is ADOdb_Active_Record. Sometimes you might want the child class to be based on your own class which has additional functions. You can do so using the last parameter: | ||
- | + | <code php> | |
- | class person extends ADOdb_Active_Record{} | + | class person extends ADOdb_Active_Record{} |
- | class child extends ADOdb_Active_Record { .... some modifications here ... } | + | class child extends ADOdb_Active_Record { .... some modifications here ... } |
- | ADODB_Active_Record:: | + | ADODB_Active_Record:: |
- | Lastly some troubleshooting issues. We use the __get() method to set $p-> | + | </ |
- | + | Lastly some troubleshooting issues. We use the <code php>__get()</ | |
- | ADODB_Active_Record:: | + | <code php> |
- | $p = new person(); | + | ADODB_Active_Record:: |
- | $p-> | + | $p = new person(); |
- | # $p-> | + | $p-> |
- | var_dump($p-> | + | # $p-> |
- | + | var_dump($p-> | |
- | $p-> | + | $p-> |
- | # $p-> | + | # $p-> |
- | var_dump($p-> | + | var_dump($p-> |
+ | </ | ||
The solution to the above is to unset($p-> | The solution to the above is to unset($p-> | ||
- | TableHasMany | + | ===== TableHasMany |
For some classes, the mapping between class name and table name (which is the pluralised version) might not match. For example, the class name might be person, but the table name might be people. So we have 2 tables, people (parent table) and children (child table) linked by people.id = children.person_id. | For some classes, the mapping between class name and table name (which is the pluralised version) might not match. For example, the class name might be person, but the table name might be people. So we have 2 tables, people (parent table) and children (child table) linked by people.id = children.person_id. | ||
- | Then you use the following static function ADODB_Active_Record:: | + | Then you use the following static function ADODB_Active_Record:: |
ADODB_Active_Record:: | ADODB_Active_Record:: | ||
- | TableKeyHasMany | + | |
+ | ===== TableKeyHasMany | ||
For some classes, the mapping between class name and table name (which is the pluralised version) might not match or the primary key is not the default id. For example, the class name might be person, but the table name might be people. So we have 2 tables, people (parent table) and children (child table) linked by people.pid = children.person_id. | For some classes, the mapping between class name and table name (which is the pluralised version) might not match or the primary key is not the default id. For example, the class name might be person, but the table name might be people. So we have 2 tables, people (parent table) and children (child table) linked by people.pid = children.person_id. | ||
- | Then you use the following static function ADODB_Active_Record:: | + | |
+ | Then you use the following static function ADODB_Active_Record:: | ||
ADODB_Active_Record:: | ADODB_Active_Record:: | ||
Line 408: | Line 466: | ||
Here is sample usage using mysql: | Here is sample usage using mysql: | ||
+ | <code php> | ||
+ | include_once(' | ||
+ | include_once(' | ||
- | include_once('../adodb.inc.php'); | + | $db = NewADOConnection('mysql:// |
- | include_once(' | + | ADOdb_Active_Record:: |
- | $db = NewADOConnection('mysql:// | + | $db-> |
- | ADOdb_Active_Record:: | + | `id` int(10) unsigned NOT NULL auto_increment, |
+ | `name_first` varchar(100) NOT NULL default | ||
+ | `name_last` varchar(100) NOT NULL default '', | ||
+ | | ||
+ | PRIMARY KEY (`id`) | ||
+ | ) ENGINE=MyISAM; | ||
+ | " | ||
- | $db-> | + | $db-> |
- | | + | `id` int(10) unsigned NOT NULL auto_increment, |
- | | + | `person_id` int(10) unsigned NOT NULL, |
- | | + | `gender` varchar(10) default ' |
- | | + | |
- | | + | `name_last` varchar(100) NOT NULL default '', |
- | | + | `favorite_pet` varchar(100) NOT NULL default '', |
- | "); | + | PRIMARY KEY (`id`) |
+ | ) ENGINE=MyISAM; | ||
+ | | ||
- | $db-> | + | $db-> |
- | `id` int(10) unsigned NOT NULL auto_increment, | + | $db-> |
- | `person_id` int(10) unsigned NOT NULL, | + | $db-> |
- | `gender` varchar(10) default | + | |
- | `name_first` varchar(100) NOT NULL default | + | |
- | `name_last` varchar(100) NOT NULL default | + | |
- | `favorite_pet` varchar(100) NOT NULL default | + | |
- | PRIMARY KEY (`id`) | + | |
- | ) ENGINE=MyISAM; | + | |
- | "); | + | |
- | $db-> | + | class person extends ADOdb_Active_Record{} |
- | $db-> | + | ADODB_Active_Record:: |
- | $db-> | + | |
- | class | + | $person = new person(); |
- | ADODB_Active_Record:: | + | $person-> |
+ | $person-> | ||
+ | $person-> | ||
+ | $person-> | ||
- | $person | + | $person2 |
+ | $person2-> | ||
- | $person-> | + | $c = $person2-> |
- | $person->name_last | + | if (is_array($c) && sizeof($c) == 3 && $c[0]-> |
- | $person->favorite_color | + | && |
- | $person->save(); // this save will perform an INSERT successfully | + | else { |
+ | echo "Error loading hasMany should have 3 array elements Jill Joan Jamie<br>"; | ||
+ | } | ||
- | $person2 | + | ===== HasMany |
- | $person2-> | + | |
- | + | ||
- | $c = $person2-> | + | |
- | if (is_array($c) && sizeof($c) | + | |
- | && | + | |
- | else { | + | |
- | echo "Error loading hasMany should have 3 array elements Jill Joan Jamie< | + | |
- | } | + | |
- | HasMany | + | |
This older method is deprecated and ClassHasMany/ | This older method is deprecated and ClassHasMany/ | ||
- | The older way to define a one-to-many relationship is to use $parentobj-> | + | The older way to define a one-to-many relationship is to use $parentobj-> |
+ | <code php> | ||
+ | class person extends ADOdb_Active_Record{} | ||
- | class | + | $person |
+ | $person-> | ||
+ | $person-> | ||
+ | foreach($person-> | ||
+ | echo " $c-> | ||
+ | $c-> | ||
+ | $c-> | ||
+ | } | ||
+ | </ | ||
- | $person = new person(); | ||
- | $person-> | ||
- | $person-> | ||
- | foreach($person-> | ||
- | echo " $c-> | ||
- | $c-> | ||
- | $c-> | ||
- | } | ||
This HasMany() definition is global for the current script. This means that you only need to define it once. In the following example, $person2 knows about children. | This HasMany() definition is global for the current script. This means that you only need to define it once. In the following example, $person2 knows about children. | ||
+ | <code php> | ||
+ | $person = new person(); | ||
+ | $person-> | ||
- | $person = new person(); | + | $person2 = new person(); |
- | $person-> | + | $person-> |
- | + | $p = $person2-> | |
- | $person2 = new person(); | + | </ |
- | $person-> | + | ===== ClassBelongsTo |
- | $p = $person2-> | + | |
- | ClassBelongsTo | + | |
You can define the parent of the current object using ADODB_Active_Record:: | You can define the parent of the current object using ADODB_Active_Record:: | ||
Line 497: | Line 558: | ||
Also if no data is loaded into the child instance, then $p will return null; | Also if no data is loaded into the child instance, then $p will return null; | ||
+ | <code php> | ||
+ | ADODB_Active_Record:: | ||
- | ADODB_Active_Record:: | + | $ch = new kid(); |
- | + | $p = $ch-> | |
- | $ch = new kid(); | + | </ |
- | $p = $ch-> | + | |
Another way to define the class of the parent (which otherwise defaults to ADODB_Active_Record) as follows: | Another way to define the class of the parent (which otherwise defaults to ADODB_Active_Record) as follows: | ||
+ | <code php> | ||
+ | class kid extends ADOdb_Active_Record{}; | ||
+ | class person extends ADOdb_Active_Record{... your modifications ... }; | ||
+ | ADODB_Active_Record:: | ||
+ | </ | ||
- | class kid extends ADOdb_Active_Record{}; | + | ===== TableBelongsTo |
- | class person extends ADOdb_Active_Record{... your modifications ... }; | + | |
- | ADODB_Active_Record:: | + | |
- | TableBelongsTo | + | |
If the child table differs from the convention that the child table name is the plural of the child class name, use this function: ADODB_Active_Record:: | If the child table differs from the convention that the child table name is the plural of the child class name, use this function: ADODB_Active_Record:: | ||
Line 514: | Line 578: | ||
E.g. the class is child, but the table name is children, and the link between the two tables is children.person_id = person.id: | E.g. the class is child, but the table name is children, and the link between the two tables is children.person_id = person.id: | ||
- | ADODB_Active_Record:: | + | ADODB_Active_Record:: |
- | TableKeyBelongsTo | + | |
+ | ===== TableKeyBelongsTo | ||
If the child table differs from the convention that the child table name is the plural of the child class name or the primary key is not ' | If the child table differs from the convention that the child table name is the plural of the child class name or the primary key is not ' | ||
Line 521: | Line 586: | ||
E.g. the class is child, but the table name is children and primary key is ch_id, and the link between the two tables is children.person_id = person.id: | E.g. the class is child, but the table name is children and primary key is ch_id, and the link between the two tables is children.person_id = person.id: | ||
- | ADODB_Active_Record:: | + | ADODB_Active_Record:: |
- | BelongsTo | + | |
+ | ===== BelongsTo | ||
The following is deprecated. Use ClassBelongsTo/ | The following is deprecated. Use ClassBelongsTo/ | ||
The older way to define the parent of the current object is using BelongsTo($relationName, | The older way to define the parent of the current object is using BelongsTo($relationName, | ||
- | + | < | |
- | class Child extends ADOdb_Active_Record{}; | + | class Child extends ADOdb_Active_Record{}; |
- | $ch = new Child(' | + | $ch = new Child(' |
- | $ch-> | + | $ch-> |
- | | + | ## as foreign key defaults to $table.' |
- | | + | ## parent pkey defaults to ' |
- | $ch-> | + | $ch-> |
- | $p = $ch-> | + | $p = $ch-> |
- | if (!$p || $p-> | + | if (!$p || $p-> |
- | else echo "OK loading BelongTo< | + | else echo "OK loading BelongTo< |
+ | </ | ||
You only need to define BelongsTo() once in a script as it is global for all instances. | You only need to define BelongsTo() once in a script as it is global for all instances. | ||
- | LoadRelations | + | ===== LoadRelations |
- | Sometimes you want to load only a subset of data in a relationship. For example, you could load all female children sorted by children.name using LoadRelations($relation, | + | Sometimes you want to load only a subset of data in a relationship. For example, you could load all female children sorted by children.name using LoadRelations($relation, |
- | + | <code php> | |
- | # assume this has been called: | + | # assume this has been called: |
- | # | + | # |
- | $person = new person(); | + | $person = new person(); |
- | $person-> | + | $person-> |
- | # Load doesn' | + | # Load doesn' |
- | $person-> | + | $person-> |
+ | </ | ||
Lastly, if you have lots of child data, you can define a window of data of records to load. In the following example, we load a window of 100 records at a time: | Lastly, if you have lots of child data, you can define a window of data of records to load. In the following example, we load a window of 100 records at a time: | ||
+ | <code php> | ||
+ | # assume this has been called: | ||
+ | # ADODB_Active_Record:: | ||
+ | #acc = new Account(); | ||
+ | $acc-> | ||
- | # assume this has been called: | + | $start = 0; |
- | # ADODB_Active_Record:: | + | while(true) { |
- | $acc = new Account(); | + | $acc-> |
- | $acc->Load('id=23'); | + | if (!$acc-> |
+ | | ||
+ | ## process | ||
+ | $trx-> | ||
+ | $trx-> | ||
+ | } | ||
+ | $start += 100; | ||
+ | unset($acc-> | ||
- | $start = 0; | + | } |
- | while(true) { | + | </code> |
- | $acc-> | + | |
- | if (!$acc-> | + | |
- | foreach ($acc-> | + | |
- | ## process | + | |
- | $trx-> | + | |
- | $trx-> | + | |
- | } | + | |
- | $start += 100; | + | |
- | unset($acc->transactions); | + | |
- | + | ||
- | + | ||
- | } | + | |
The $offset is 0-based, and $limit is the number of records to retrieve. The default is to ignore $offset (-1) and $limit (-1). | The $offset is 0-based, and $limit is the number of records to retrieve. The default is to ignore $offset (-1) and $limit (-1). | ||
- | Acknowledgements | + | ===== Acknowledgements |
Thanks to Chris Ravenscroft for original one-to-many code (chris# | Thanks to Chris Ravenscroft for original one-to-many code (chris# | ||
- | ADOConnection Supplement | + | ===== ADOConnection Supplement |
- | ADOConnection:: | + | ==== ADOConnection:: |
This allows you to retrieve an array of ADOdb_Active_Records. Returns false if an error occurs. | This allows you to retrieve an array of ADOdb_Active_Records. Returns false if an error occurs. | ||
+ | <code php> | ||
$table = ' | $table = ' | ||
$whereOrderBy = "name LIKE ' | $whereOrderBy = "name LIKE ' | ||
Line 590: | Line 659: | ||
$rec-> | $rec-> | ||
} | } | ||
+ | </ | ||
And to retrieve all records ordered by specific fields: | And to retrieve all records ordered by specific fields: | ||
+ | <code php> | ||
$whereOrderBy = "1=1 ORDER BY Name"; | $whereOrderBy = "1=1 ORDER BY Name"; | ||
$activeRecArr = $db-> | $activeRecArr = $db-> | ||
- | To use bind variables (assuming ? is the place-holder for your database): | + | //To use bind variables (assuming ? is the place-holder for your database): |
$activeRecArr = $db-> | $activeRecArr = $db-> | ||
Line 603: | Line 673: | ||
array(' | array(' | ||
ADOConnection:: | ADOConnection:: | ||
+ | </ | ||
This allows you to retrieve an array of objects derived from ADOdb_Active_Records. Returns false if an error occurs. | This allows you to retrieve an array of objects derived from ADOdb_Active_Records. Returns false if an error occurs. | ||
+ | <code php> | ||
class Product extends ADOdb_Active_Record{}; | class Product extends ADOdb_Active_Record{}; | ||
$table = ' | $table = ' | ||
Line 616: | Line 687: | ||
$rec-> | $rec-> | ||
} | } | ||
+ | </ | ||
To use bind variables (assuming ? is the place-holder for your database): | To use bind variables (assuming ? is the place-holder for your database): | ||
+ | <code php> | ||
$activeRecArr = $db-> | $activeRecArr = $db-> | ||
array(' | array(' | ||
Line 624: | Line 696: | ||
$activeRecArr = $db-> | $activeRecArr = $db-> | ||
array(' | array(' | ||
+ | |||
+ | </ | ||
ADOConnection:: | ADOConnection:: | ||
Line 632: | Line 706: | ||
Returns last error number. | Returns last error number. | ||
- | ActiveRecord Code Sample | + | ===== ActiveRecord Code Sample |
- | + | ||
- | The following works with PHP4 and PHP5 | + | |
+ | <code php> | ||
include(' | include(' | ||
include(' | include(' | ||
Line 707: | Line 780: | ||
$person2 = $activeArr[0]; | $person2 = $activeArr[0]; | ||
echo "< | echo "< | ||
- | Active Record eXtended | + | </ |
+ | |||
+ | ===== Active Record eXtended | ||
This is the original one-to-many Active Record implementation submitted by Chris Ravenscroft (chris# | This is the original one-to-many Active Record implementation submitted by Chris Ravenscroft (chris# | ||
Line 715: | Line 790: | ||
It provides a new function called Find() that is quite intuitive to use as shown in the example below. It also supports loading all relationships using a single query (using joins). | It provides a new function called Find() that is quite intuitive to use as shown in the example below. It also supports loading all relationships using a single query (using joins). | ||
- | <?php | + | <code php> |
- | function ar_assert($obj, | + | function ar_assert($obj, |
- | { | + | { |
- | global $err_count; | + | |
- | $res = var_export($obj, | + | |
- | return (strpos($res, | + | |
- | } | + | } |
- | include_once(' | + | include_once(' |
- | include_once(' | + | include_once(' |
- | $db = NewADOConnection(' | + | $db = NewADOConnection(' |
- | $db-> | + | $db-> |
- | ADOdb_Active_Record:: | + | ADOdb_Active_Record:: |
- | echo "< | + | echo "< |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | $db-> | + | $db-> |
- | $db-> | + | $db-> |
- | $db-> | + | $db-> |
- | | + | `id` int(10) unsigned NOT NULL auto_increment, |
- | | + | `name_first` varchar(100) NOT NULL default '', |
- | | + | `name_last` varchar(100) NOT NULL default '', |
- | | + | `favorite_color` varchar(100) NOT NULL default '', |
- | | + | PRIMARY KEY (`id`) |
- | | + | ) ENGINE=MyISAM; |
- | "); | + | |
- | $db-> | + | $db-> |
- | | + | `id` int(10) unsigned NOT NULL auto_increment, |
- | `person_id` int(10) unsigned NOT NULL, | + | `person_id` int(10) unsigned NOT NULL, |
- | | + | `name_first` varchar(100) NOT NULL default '', |
- | | + | `name_last` varchar(100) NOT NULL default '', |
- | | + | `favorite_pet` varchar(100) NOT NULL default '', |
- | | + | PRIMARY KEY (`id`) |
- | | + | ) ENGINE=MyISAM; |
- | "); | + | |
+ | $db-> | ||
+ | $db-> | ||
+ | $db-> | ||
- | $db-> | + | // This class _implicitely_ relies on the 'people' |
- | $db->Execute(" | + | class Person extends ADOdb_Active_Record |
- | $db->Execute(" | + | { |
+ | function __construct() | ||
+ | { | ||
+ | parent:: | ||
+ | $this->hasMany('children'); | ||
+ | } | ||
+ | } | ||
+ | // This class _implicitely_ relies on the 'children' | ||
+ | class Child extends ADOdb_Active_Record | ||
+ | { | ||
+ | function __construct() | ||
+ | { | ||
+ | parent:: | ||
+ | $this->belongsTo('person'); | ||
+ | } | ||
+ | } | ||
- | // This class _implicitely_ relies on the ' | + | // This class _explicitely_ relies on the ' |
- | class Person extends ADOdb_Active_Record | + | class Kid extends ADOdb_Active_Record |
- | { | + | { |
- | function __construct() | + | function __construct() |
- | { | + | { |
- | parent:: | + | parent:: |
- | $this-> | + | $this-> |
- | } | + | } |
- | } | + | } |
- | // This class _implicitely_ relies on the ' | + | |
- | class Child extends ADOdb_Active_Record | + | |
- | { | + | |
- | function __construct() | + | |
- | { | + | |
- | parent:: | + | |
- | $this-> | + | |
- | } | + | |
- | } | + | |
- | // This class _explicitely_ relies on the ' | + | |
- | class Kid extends ADOdb_Active_Record | + | |
- | { | + | |
- | function __construct() | + | |
- | { | + | |
- | parent:: | + | |
- | $this-> | + | |
- | } | + | |
- | } | + | |
- | // This class _explicitely_ relies on the ' | + | |
- | class Rugrat extends ADOdb_Active_Record | + | |
- | { | + | |
- | function __construct() | + | |
- | { | + | |
- | parent:: | + | |
- | } | + | |
- | } | + | |
- | echo " | + | // This class _explicitely_ relies on the 'children' table but does not share its metadata |
- | echo " | + | class Rugrat extends ADOdb_Active_Record |
- | $person = new Person(); | + | { |
- | $person-> | + | function __construct() |
- | $person-> | + | { |
- | $person-> | + | parent:: |
- | $person->save(); // this save will perform an INSERT successfully | + | } |
+ | } | ||
- | $err_count | + | echo " |
+ | echo " | ||
+ | $person | ||
+ | $person-> | ||
+ | $person-> | ||
+ | $person-> | ||
+ | $person-> | ||
- | echo " | + | $err_count = 0; |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | $person5 = new Person(); | + | echo " |
- | $people5 = $person5-> | + | $person5 = new Person(); |
- | echo (ar_assert($people5, | + | $people5 = $person5-> |
- | echo (ar_assert($people5, | + | echo (ar_assert($people5, |
- | foreach($people5 as $person) | + | echo (ar_assert($people5, |
- | { | + | foreach($people5 as $person) |
- | foreach($person-> | + | { |
- | { | + | foreach($person-> |
- | if($child-> | + | { |
- | } | + | if($child-> |
- | } | + | } |
- | echo (ar_assert($people5, | + | } |
+ | echo (ar_assert($people5, | ||
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | $person6 = new Person(); | + | $person6 = new Person(); |
- | $people6 = $person6-> | + | $people6 = $person6-> |
- | echo (ar_assert($people6, | + | echo (ar_assert($people6, |
- | echo (ar_assert($people6, | + | echo (ar_assert($people6, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | $person7 = new Person(); | + | $person7 = new Person(); |
- | // When I specifically ask for a join, I have to specify which table id I am looking up | + | // When I specifically ask for a join, I have to specify which table id I am looking up |
- | // otherwise the SQL parser will wonder which table' | + | // otherwise the SQL parser will wonder which table' |
- | $people7 = $person7-> | + | $people7 = $person7-> |
- | echo (ar_assert($people7, | + | echo (ar_assert($people7, |
- | echo (ar_assert($people7, | + | echo (ar_assert($people7, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | $person2 = new Person(); | + | $person2 = new Person(); |
- | // Under the hood, Load(), since it returns only one row, always perform a join | + | // Under the hood, Load(), since it returns only one row, always perform a join |
- | // Therefore we need to clarify which id we are talking about. | + | // Therefore we need to clarify which id we are talking about. |
- | $person2-> | + | $person2-> |
- | echo (ar_assert($person2, | + | echo (ar_assert($person2, |
- | echo (ar_assert($person2, | + | echo (ar_assert($person2, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo "We are now loading from the ' | + | echo "We are now loading from the ' |
- | echo " | + | echo " |
- | $ch = new Child(); | + | $ch = new Child(); |
- | $ch-> | + | $ch-> |
- | echo (ar_assert($ch, | + | echo (ar_assert($ch, |
- | echo (ar_assert($ch, | + | echo (ar_assert($ch, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | $ch2 = new Child(); | + | $ch2 = new Child(); |
- | $ach2 = $ch2-> | + | $ach2 = $ch2-> |
- | echo (ar_assert($ach2, | + | echo (ar_assert($ach2, |
- | echo (ar_assert($ach2, | + | echo (ar_assert($ach2, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo "Where we see that kid shares relationships with child because they are stored\n"; | + | echo "Where we see that kid shares relationships with child because they are stored\n"; |
- | echo "in the common table' | + | echo "in the common table' |
- | echo " | + | echo " |
- | $ch3 = new Kid(' | + | $ch3 = new Kid(' |
- | $ach3 = $ch3-> | + | $ach3 = $ch3-> |
- | echo (ar_assert($ach3, | + | echo (ar_assert($ach3, |
- | echo (ar_assert($ach3, | + | echo (ar_assert($ach3, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo "Of course, lazy loading also retrieve medata information...\n"; | + | echo "Of course, lazy loading also retrieve medata information...\n"; |
- | echo " | + | echo " |
- | $ch32 = new Kid(' | + | $ch32 = new Kid(' |
- | $ach32 = $ch32-> | + | $ach32 = $ch32-> |
- | echo (ar_assert($ach32, | + | echo (ar_assert($ach32, |
- | echo (ar_assert($ach32, | + | echo (ar_assert($ach32, |
- | foreach($ach32 as $akid) | + | foreach($ach32 as $akid) |
- | { | + | { |
- | if($akid-> | + | if($akid-> |
- | } | + | } |
- | echo (ar_assert($ach32, | + | echo (ar_assert($ach32, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo "In rugrat' | + | echo "In rugrat' |
- | echo " | + | echo " |
- | $ch4 = new Rugrat(' | + | $ch4 = new Rugrat(' |
- | $ach4 = $ch4-> | + | $ach4 = $ch4-> |
- | echo (ar_assert($ach4, | + | echo (ar_assert($ach4, |
- | echo (ar_assert($ach4, | + | echo (ar_assert($ach4, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo "Note how only rugrat forgot its relations - kid is fine.\n"; | + | echo "Note how only rugrat forgot its relations - kid is fine.\n"; |
- | echo " | + | echo " |
- | $ch5 = new Kid(' | + | $ch5 = new Kid(' |
- | $ach5 = $ch5-> | + | $ach5 = $ch5-> |
- | echo (ar_assert($ach5, | + | echo (ar_assert($ach5, |
- | echo (ar_assert($ach5, | + | echo (ar_assert($ach5, |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | echo " | + | echo " |
- | $ch6 = new Rugrat(' | + | $ch6 = new Rugrat(' |
- | $ch6s = $ch6-> | + | $ch6s = $ch6-> |
- | $ach6 = $ch6s[0]; | + | $ach6 = $ch6s[0]; |
- | echo (ar_assert($ach6, | + | echo (ar_assert($ach6, |
- | echo (ar_assert($ach6, | + | echo (ar_assert($ach6, |
- | echo " | + | echo " |
- | $ach6-> | + | $ach6-> |
- | $ach6-> | + | $ach6-> |
- | echo (ar_assert($ach6, | + | echo (ar_assert($ach6, |
- | echo " | + | echo " |
- | echo "Test suite complete.\n"; | + | echo "Test suite complete.\n"; |
- | echo " | + | echo " |
- | ?> | + | </code> |
- | Todo (Code Contributions welcome) | + | |
+ | ====== | ||
Check _original and current field values before update, only update changes. Also if the primary key value is changed, then on update, we should save and use the original primary key values in the WHERE clause! | Check _original and current field values before update, only update changes. Also if the primary key value is changed, then on update, we should save and use the original primary key values in the WHERE clause! | ||
Line 936: | Line 1012: | ||
PHP5 specific: Make GetActiveRecords*() return an Iterator. | PHP5 specific: Make GetActiveRecords*() return an Iterator. | ||
- | PHP5 specific: Change PHP5 implementation of Active Record to use __get() and __set() for better performance. | + | PHP5 specific: Change PHP5 implementation of Active Record to use <code php>__get() and __set()</ |
- | + | ||
- | Change Log | + | |
- | + | ||
- | 0.93 | + | |
- | + | ||
- | You can force column names to be quoted in INSERT and UPDATE statements, typically because you are using reserved words as column names by setting ADODB_Active_Record:: | + | |
- | + | ||
- | 0.92 | + | |
- | + | ||
- | Fixed some issues with incompatible fetch modes (ADODB_FETCH_ASSOC) causing problems in UpdateActiveTable. | + | |
- | + | ||
- | Added support for functions that support predefining one-to-many relationships: | + | |
- | ClassHasMany ClassBelongsTo TableHasMany TableBelongsTo TableKeyHasMany TableKeyBelongsTo. | + | |
- | You can also define your child/ | + | |
- | + | ||
- | 0.91 | + | |
- | + | ||
- | HasMany hardcoded primary key field name to " | + | |
- | + | ||
- | 0.90 | + | |
- | + | ||
- | Support for belongsTo and hasMany. Thanks to Chris Ravenscroft (chris# | + | |
- | + | ||
- | Added LoadRelations(). | + | |
- | + | ||
- | 0.08 Added support for assoc arrays in Set(). | + | |
- | + | ||
- | 0.07 | + | |
- | + | ||
- | $ADODB_ASSOC_CASE=2 did not work properly. Fixed. | + | |
- | + | ||
- | Added === check in ADODB_SetDatabaseAdapter for $db, adodb-active-record.inc.php. Thx Christian Affolter. | + | |
- | + | ||
- | 0.06 | + | |
- | + | ||
- | Added ErrorNo(). | + | |
- | + | ||
- | Fixed php 5.2.0 compat issues. | + | |
- | + | ||
- | 0.05 | + | |
- | + | ||
- | If inserting a record and the value of a primary key field is null, then we do not insert that field in as we assume it is an auto-increment field. Needed by mssql. | + | |
- | + | ||
- | 0.04 5 June 2006 | + | |
- | Added support for declaring table name in $_table in class declaration. Thx Bill Dueber for idea. | + | |
- | + | ||
- | Added find($where, | + | |
- | + | ||
- | 0.03 | + | |
- | - Now we only update fields that have changed, using $this-> | + | |
- | - We do not include auto_increment fields in replace(). Thx Travis Cline | + | |
- | - Added ADODB_ACTIVE_CACHESECS. | + | |
- | 0.02 | + | |
- | - Much better error handling. ErrorMsg() implemented. Throw implemented if adodb-exceptions.inc.php detected. | + | |
- | - You can now define the primary keys of the view or table you are accessing manually. | + | |
- | - The Active Record allows you to create an object which does not have a primary key. You can INSERT but not UPDATE in this case. - Set() documented. | + | |
- | - Fixed _pluralize bug with y suffix. | + | |
- | + | ||
- | 0.01 6 Mar 2006 | + | |
- | - Fixed handling of nulls when saving (it didn't save nulls, saved them as '' | + | |
- | - Better error handling messages. | + | |
- | - Factored out a new method GetPrimaryKeys(). | + | |
- | 0.00 5 Mar 2006 | + | |
- | 1st release | + |
v5/userguide/active_record.txt · Last modified: 2019/05/08 16:32 by dregad