ActiveRecord PHP implementation Part I

By Nuno Mariz, on 6 January 2006 @ 18:09
ActiveRecord UML
This is the first part of an attempt to implement the ActiveRecord design pattern in PHP. 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 :
include_once 'class.ActiveRecord.php';

class Person extends ActiveRecord {
    public function __construct() {
        parent::__construct('person');
    }
}
To return all rows in the table:
$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:
$person = new Person();
$person->name = 'Julia';
$person->email = 'julia@xxx.xxx';
$person->insert();
Update a record:
$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:
// 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...

Comments

  • #1 By orixilus on 7 January 2006 @ 01:58
    will you release your code for us...? :)
  • #2 By Pádraic Brady on 11 January 2006 @ 15:55
    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...
  • #3 By Joaquim Rendeiro on 19 January 2006 @ 13:07
    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:

    <b>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!</b>

    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.
  • #4 By B. Remy on 19 March 2006 @ 21:23
    no more part II ? did u gave up on Active Record ?
  • #5 By Ronald on 8 May 2006 @ 11:59
    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?
  • #6 By Sam on 13 September 2006 @ 16:09
    Are you busy yet?
  • #7 By dodik on 31 October 2006 @ 16:04
    Congratulations about what you know ;)

    We're still waiting for the release of your code.
  • #8 By Solid on 26 November 2006 @ 23:54
    Any news?
  • #9 By Jesse on 31 December 2006 @ 07:31
    Maybe you should make the release of this code your resolution for next year.
  • #10 By Nuno Mariz on 2 January 2007 @ 19:44
    Stay tuned this weekend ;)
  • #11 By Leonel on 6 February 2007 @ 17:00
    Hey Nuno, looking forward for part II.
  • #12 By Siemen Paulsen on 18 February 2007 @ 15:57
    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.
Comments are closed.