From Habari Project
A single instance of QueryRecord represents a single query result row. QueryRecord also serves as the base class for derivative classes that provide row-level data access. QueryRecord is, in many ways, the fundamental building block of Habari.
QueryRecord provides basic functions that allow Habari to interact with the single row of data. The properties of a QueryRecord object represent the field values of the row.
To obtain an instance of QueryRecord with data, call one of these static methods on the DB class:
- Returns a single QueryRecord instance for the single row retrieved
- Returns an array of QueryRecord instances, one per row returned in the query
$record = DB::get_row('SELECT id, bar FROM foo WHERE id = 1'); echo $record->bar;
The code above firsts queries the database for a record containing the fields id and bar from the table 'foo' where the 'id' field is equal to 1. The single record (only one is returned by DB::get_row()) is stored in $record as an instance of the QueryRecord class. The property bar referenced as $record->bar contains the value of the 'bar' field returned by the query. Similarly, although this is not shown, the 'id' field is assigned to $record->id.
By echoing the value of $record->bar, the value of that field is output.
Updating a Record
By changing the values of these properties and calling the update() method on the object, the QueryRow can commit that data back to the database. For example:
$record = DB::get_row('SELECT id, bar FROM foo WHERE id = 1'); $record->bar = 'hello'; $record->update('foo', array('id'));
As with the prior example, the values of the fields 'id' and 'bar' have been queried into an instance of QueryRecord.
The $record->bar is then assigned the value 'hello'. This prepares the new data for update in the database. The value of $record->bar will contain 'hello' after this assignment.
To update the record in the database, the update() method is called. In QueryRecord, update() accepts two parameters. The first is the table to which the data will be written and the second is an array of fields that will be used to match the data in the object to the correct row in the database.
In this case, the table updated is 'foo', and the value of $record->id will be matched against the field 'id' in the database. Any record in the database with a matching id value will have its fields updated to the other property values of $record
Inserting a Record
QueryRecord can also be used to insert new records into a table. For example:
$record = new QueryRecord( array('bar'=>'hello') ); $record->insert('foo');
In the above example, a new instance of QueryRecord is created and asigned to $record. The values of the properties in the new QueryRecord are built from the associative array that is passed to the QueryRecord constructor. The keys of the array become the object's properties, and the values of the array become those properties' values. After creating $record as above, the value of $record->bar would be set to 'hello'.
Calling $record->insert() inserts the property values into the specified table, in this case, 'foo'.
In order for this to work correctly, all of the values required to insert a row into a table must have been set as properties of the QueryRecord object. Note that in this example, the 'id' field is omitted with the assumption that it is an auto_increment primary key in the 'foo' table.
After the row is inserted, the value of 'id' *will not* be set in $record->id. This must be done manually using DB::last_insert_id(), which is often handled from a subclass, as described in the Extending QueryRecord section below.
Deleting a Record
This is fundamentally the same as updating a row, except it deletes the row from the table that has fields with the matching values.
As part of Habari's Object-Oriented approach, other classes can extend the QueryRecord class to provide additional methods that interact with QueryRecords that contain a specific type of data. For example, the Post class extends QueryRecord to provide additional methods that are post-specific. The class that extends QueryRecord inherits all of the methods of QueryRecord in addition to any that it provides on its own.
In most cases, a QueryRecord is not the class of a row. A row is usually requested as one of QueryRecord's descendant classes.
Many classes extend the QueryRecord class. The following classes all inherit from QueryRecord:
- Represents a single post
- Represents a single comment
- Represents a single entry in the event log
- Represents a single periodically executed task
- Represents a single rewrite rule
- Represents a single user
The classes above represent wildly different functionality and and data representations; yet they each extend the base QueryRecord class. By providing this core functionality for descendant classes, extended classes don't need to duplicate code.
QueryRecord descendants map to database tables of the same name, and most of the properties of the descendants map the columns of that table. For example, the Post table is used to store Post object data. The Post object has fields 'id', 'title', and 'content', among others. These fields are also columns in the 'posts' table in the database.
The Post class also provides special functionality that is associated only to posts. For example, every post has a status value. In the database, this status value is stored as an integer. Because it's often easier to work with the names of these status, the Post class provides the ability to accept either the integer or the string as the value of the poperty, but always stores the value in the database as an integer. This is just one example of what additional functionality a subclass of QueryRecord can provide.
One of the more significant additions a subclass can make is to override the update() and insert() methods of QueryRecord. By creating having its own update() method, a class can identify the correct table and key fields that are used to update that row in the database. This allows a subclass instance to omit the table and keyfields parameters in the call to update. So when updating a post, instead of this:
You would simply call this:
Using a subclass, you can transparently assign the value of DB::last_insert_id() to the keyfield property of the object. This will allow you to update the object after it is inserted without having to manually retrieve the key values each time. So when inserting a post, instead of this, where the id property must be set manually:
$record = new QueryRecord(/* post field data */); $record->insert('posts'); $record->id = DB::last_insert_id(); $record->title = 'new title'; $record->update('post', array('id'));
You would simply call this:
$post = new Post(/* post field data*/); $post->insert(); $post->title = 'new title'; $post->update();
It's not that the assignment doesn't need to be made at all, but that it takes place in the Post class (which extends QueryRecord) so that you need not repeat it whenever you insert a new post.
Please review the documentation for the classes that extend QueryRecord for the details of functionality that they provide beyond QueryRecord itself.
QueryRecord provides the following:
- overloaded __get(), __set() and __isset()
- exclude_fields() and list_excluded_fields(), for identifying properties handled exclusively by the database
- insert(), for adding data to the database
- to_array(), to permit array operations on the object (like
- get_url_args(), which returns an array of the values represented by the object
- update(), for recording modified values to the database
- delete(), for deleting an item from the database