NYCPHP Meetup

NYPHP.org

[nycphp-talk] Cake PHP and "Active Records"

Baer, Jon jbaer at VillageVoice.com
Fri Sep 29 14:21:16 EDT 2006


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This already works in CakePHP ...

The DESCRIBE TABLE is performed and cached under /tmp/models (describing
the table structure only once)

You can also optimize your cascades by specifically telling the model
what you want from the join, ie:

$this->Model->findAll(null, array("Model.col1","OtherModel.col3"));

On your view use pr($this->_viewVars) and you will see the object
layout.

So in a nutshell, its pretty identical to RoR.

- - Jon 

- -----Original Message-----
From: talk-bounces at lists.nyphp.org [mailto:talk-bounces at lists.nyphp.org]
On Behalf Of Derek DeVries
Sent: Friday, September 29, 2006 12:31 PM
To: NYPHP Talk
Subject: Re: [nycphp-talk] Cake PHP and "Active Records"

<snip>
   One of the interesting questions is early loading versus lazy
loading.  The Active Record from Ruby on Rails,  for instance,  lazy
loads everything and caches nothing.  When you ask for 'User.name', Ruby
immediately does something like

SELECT name from user where id=66;
</snip>


Actually, in Rails the following occurs:

>> User.name
NoMethodError: undefined method `name' for User:Class
        from
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/
base.rb:1129:in
`method_missing'
        from (irb):1

FYI, you can't do this. User is a class, so you need to first find an
user object whose attributes you want to get the records for.

>> user = User.find(1)

This will execute the SQL query:
SELECT * FROM users WHERE (users.id = 1) LIMIT 1

>> puts user.name
=> derek

This will execute the SQL query:
SHOW FIELDS FROM users

BUT... Only in development mode. On production it caches this info and
no sql is executed

>> puts user.email
=> devrieda at gmail.com

now, no SQL query is executed. We've already introspected the db.


As far as eager loading sql queries, Rails has a method of doing this.
The sql for finding all comments could be written as

>> user = User.find(1, :include => :comments)

This would generate a single sql query to retrieve the user and all
associated comments so that you can now do:

>> for comment in user.comments
>>   puts comment.body
>> end

This can also cascade as much as you want and continues to only perform
one db query.

>> user = User.find(1, :include=>{:posts=>[:comments, 
>> :categorizations]})

a better explanation of how it works can be found here:
http://blog.caboo.se/articles/2006/02/21/eager-loading-with-cascaded-ass
ociations

This is very possible in php, and I've written an implementation of
ActiveRecord in PHP that uses the following syntax:

>> $user = User::find(1, array('include' => array('posts' =>
array('comments', 'categorizations'))));

which can do something like this with the resulting data:
>> foreach ($user->posts as $post) {
>>     print $post->title;
>>
>>     foreach ($post->comments as $comment) {
>>         print $comment->body;
>>     }
>>     foreach ($post->categorizations as $comment) {
>>         print $categorizations->name;
>>     }
>> }

not terribly pretty with all the array(array(array())), but it's what we
have to work with in PHP. this can get slow when there are many
associations for the active record objects, and many records are being
loaded from the db. Our own application however doesn't seem to have any
problems because we tend to use paging on any items that tend to appear
in sets greater than 250 records in the interface.
_______________________________________________
New York PHP Community Talk Mailing List
http://lists.nyphp.org/mailman/listinfo/talk

NYPHPCon 2006 Presentations Online
http://www.nyphpcon.com

Show Your Participation in New York PHP
http://www.nyphp.org/show_participation.php
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (MingW32)

iD8DBQFFHWQc99e5DI8C/rsRArC6AJ0S4Fo5MXHljCuQC8tFmrlTj6KNtQCeKzIL
xGCn13LnBzsYX8XI/PmK0jA=
=mRn2
-----END PGP SIGNATURE-----



More information about the talk mailing list