ActiveRecord PHP implementation Part I
This first implementation is very simple but will open doors for more advanced stuff, like foreign keys mapping(automatic or manually) or integration with Model, View and Controller components, in this case with the generation of PHP classes or objects.
Approach: A row in a database table or view is wrapped into a class, thus an object instance is tied to a single row in the database.
Imagine this table(person):
+-------------+---------------------+ | Field | Type | +-------------+---------------------+ | id | bigint(20) unsigned | | name | varchar(100) | | email | varchar(150) | | last_update | datetime | +-------------+---------------------+
With this records:
+----+----------+---------------+---------------------+ | id | name | email | last_update | +----+----------+---------------+---------------------+ | 1 | Nuno | nuno@xxx.xxx | 2005-11-06 20:39:08 | +----+----------+---------------+---------------------+ | 2 | Marta | marta@xxx.xxx | 2005-11-06 20:39:08 | +----+----------+---------------+---------------------+ | 3 | Pedro | joao@xxx.xxx | 2005-11-06 20:39:08 | +----+----------+---------------+---------------------+
You don’t have to define any table structure, just extend de ActiveRecord class and call the parent __construct() method with the table name :
<?php
include_once ‘class.ActiveRecord.php’;
class Person extends ActiveRecord {
public function __construct() {
parent::__construct(‘person’);
}
}
?>
To return all rows in the table:
<?php
$persons = new Person();
/**
* This will print all records
* $persons->findAll() will return a Recordset
*/
foreach($persons->findAll() as $person) {
echo ‘id: ‘.$person->id;
echo ‘name: ‘.$person->name;
echo ‘email: ‘.$person->email;
echo ‘last update: ‘.$person->last_update;
}
/**
* Alternatively you can ‘walk’ the Recordset
* with next(), prev(), etc. because Recordset
* implements the Iterator interface
*/
?>
Insert a record:
<?php
$person = new Person();
$person->name = ‘Julia’;
$person->email = ‘julia@xxx.xxx’;
$person->insert();
?>
Update a record:
<?php
$personId = $_POST[‘id’];
$person = new Person();
$person->id = $personId;
$person->name = ‘Nuno Mariz’;
$person->update();
?>
UPDATE:
With the Pádraic Brady tip for merging the insert() and update() methods to only one save() method, now is possible to:
<?php
// insert
$person = new Person();
$person->name = ‘Nuno Mariz’;
$person->save();
// or update
$personId = $_POST[‘id’];
$person = new Person();
$person->find($personId);
$person->name = ‘Nuno Mariz’;
$person->save();
?>
You can view the UML for the implementation.
See you in part II…



will you release your code for us…? :)
Yes, in part II(soon).
Maybe some method of merging insert() and update() into a single method? Make it easier if that decision was made internally - an insert assumes the record was read from database, which can be tracked, and if such a “read” flag were not set it would be inserted instead.
My 0.02c…
Yes, you are right.
I will implement the method save() instead of insert() and update().
Just like i said, this is the first approach, any sugestions are welcome.
Thanks
Hey!
Looks like you’ve been trying Ruby on Rails (as I did recently), you were already a PHP developer (as I am) and you got to the same conclusion as I did:
RoR is nice but it has a really weird syntax… it would be really nice if i just had some functionality of RoR in my PHP/Smarty apps.. well that ActiveRecord class in PHP would be just great!
well, i also found out that there is PHP on Trax, wich seems to be a clone of RoR and has most (all?) the base classes implemented, but as i was looking at the source code, some parts seem to really be integrated in Trax, but i think it might be worthy to have a look ;) (http://www.phpontrax.com)
Btw, I probably won’t be using Ruby on Rails or PHP on Trax, because I’m too used to PHP and Smarty… but I’ll definetly try to use some sort of standalone ActiveRecord in PHP.
My ActiveRecord implementation is 100% working(PHP4 and PHP5 versions) for one table without external keys.
Right now i’m trying to figure out the best way to fetch a Record(or a Recordset) with foreign keys data. Maybe the best way is to delegate this to another pattern, like “Foreign Key Mapping“. My concerns now is in the performance field.
In the second part II i will release some code, so stay tune.
no more part II ? did u gave up on Active Record ?
Hi,
Actually, i’ve already implemented the Active Record pattern just like Martin Fowler describes it. Right now i’m trying put together the foreigns tables relations, not that is difficult but i’m trying to figure out the best and the light way of doing it.
The ZActiveRecord has not convinced me. Too much rules about the table and field names, etc.
The second part will arrive soon as i have some free time.
This looks great - I’ve been looking at different ways of implementing ORM, and specifying the table name in the constructor follows my thinking entirely. Would you be kind enough to share your source?
Yes,
In an couple of weeks(it’s a promise), I’m very very busy right now.
Are you busy yet?
Yes, a lot. Read this.
But is not forgotten.
Congratulations about what you know ;)
We’re still waiting for the release of your code.
Hi, now I have some time to work on it.
Wait 1-2 weeks for the release.
..and, thanks ;)
Any news?
Maybe you should make the release of this code your resolution for next year.
Stay tuned this weekend ;)
Hey Nuno, looking forward for part II.
I think it’s pretty clear that Nuno is not going to release the code. Why don’t you try CakePHP (cakephp.org), which is so much better than his code will ever be.
No need to release the code than.