Archive for the ‘php’ Category

Using a CakePHP model to loop over database records

August 12, 2008

I was quite pleased to get this working so easily CakePHP 1.2.

Problem: I needed to iterate over records in a table, but there’s potentially too much data to fetch every record at once with findAll().

This isn’t a case of premature optimisation–using a CakePHP model to fetch records with complex associations can cause your script to be killed for using too much memory (the default allowance is 32MB, I think).

I only need a single record at a time, so rather than increase the memory limit (which won’t scale that well) I’d like to change how data is fetched.

Solution: Use a while loop with the “Model->find( ‘first’ )” method and a page variable, like so:

$page = 1;
while ( $record = $this->Model->find( 'first', array( 'page' => $page++ ) ) ) {
  print_r( $record );
}

And that’s all there is to it. We can now work with each record, having only one record in memory at a time. Eventually find() will return false when it has passed the last record, cleaning up the $record variable.

This is a similar approach to querying the database with SQL directly, then using a method such as mysql_fetch_array() to parse the results.

The only difference is the addition of the $page variable, which acts as a pointer and is incremented so it returns the next record each time. Otherwise we would get the first record returned over and over, creating an infinite loop. mysql_fetch_array() uses a pointer like this too (as far as I know), but it’s hidden inside the method.

You could easily do the same in CakePHP to create a findNext() function on your CakePHP model that then calls find(), along with any other conditions passed in. It would be used like so:

while ( $record = $this->Model->findNext( $conditions ) ) {
  print_r( $record );
}

But I haven’t tested that yet. :)

Dynamic CakePHP models without class definitions

July 25, 2008

Here’s a nifty CakePHP feature I stumbled across yesterday:

You can use a model without creating a file for it or defining a class for it.

Call a model from your controller or define relationships in other models as normal, and that model can be saved, fetched, recursed, etc, using normal “$this->ModelName->foo()” calls.

Without a model class you wont have any relationships or validation rules defined on the model, but this is still a useful feature.

I often have tables whose only purpose is to populate a drop-down list and/or keep the database normalised. A table of country names, for example.

In the past I would have created a bare-bones class for the model with nothing in it, but now I don’t even have to do that.

I’ve tested this using PHP5 and it works on the latest stable version of CakePHP (1.1) and the 1.2 beta.

I suspect this wouldn’t work for PHP4 though because of the comment that you should declare a model’s name inside its class when using PHP4.