+1 571-297-6383 | info@sonjara.com

Chapter 3. More Data Model Shenanigans

In the last chapter we learned how to define the objects in our data model, and many ways to query them. In this chapter we will learn how to store objects in the database, how to user filters to mask fields for database access, and how to output the data in our objects in a variety of ways.

Existence Tests

One of the primitives defined by the DataItem base class that we did not discuss in the previous chapter is the exists() method. This is fairly self explanatory–it checks to see if an object exists in the database. It can be used in two ways:

Checking existence by primary key
$task = new Task();
$task->task_id = 3;
echo ($task->exists()) ? "I am" : "Sadly, I am not";
Checking existence by constraint
$person = new Person();
$descartes = $person->exists("WHERE first_name='Andy' AND last_name='Green' ");

echo $descartes ? "I am" : "Sadly, I am not";

Saving to the database

Saving to the database is handled via the DataItem::insert(), DataItem::update() and DataItem::save() methods. The insert() and update() methods implement the equivalently named SQL operations for the DataItem. The save() method checks whether the item has previously been saved, and call insert() or update() as appropriate. Unless you are really in need of a performance tweak it is generally considered best practice to use the save() method as it simplifies application code significantly.

An example using the save() method
$person = new Person();
$person->first_name = "Andy";
$person->last_name = "Green";
$person->role = "Evil Genius";
$person->save();

Deleting objects from the database

The interface for deleting objects follows the same pattern as for exists().

Deleting an object by Primary Key
$doomed = new Person();
$doomed->person_id = 3;
$doomed->delete();
Deleting objects by constraint
$doomed = new Person();
$doomed->delete("WHERE last_name='Green'");
Just delete everything!
$doomed = new Person();
$doomed->deleteAll();

DataItem Filters

By default, Fakoli loads or saves all the fields in a given DataItem whenever a call is made to query or update the database. Filters provide a mechanism to control this and limit which fields are included in a given database operation. This can be useful when you want to optimize a database query by excluding a large data field, or if you need to update only a sub-set of the fields in an object.

There are two types of Filter objects: InclusionFilters and ExclusionFilters. They achieve the same goal, but work in opposite ways. If you know the subset of fields that you want, you can use an InclusionFilter:

// Only interested in names!

$people = Query::create(Person)
               ->filter(new InclusionFilter("first_name", "last_name"))
               ->execute();

If you know the fields you want to exclude, use an ExclusionFilter:

// Don't include the biography!

$people = Query::create(Person)
               ->filter(new ExclusionFilter("biography"))
               ->execute();

You can apply filters to DataItems at any point, to affect the subsequent database operations. To remove a filter, assign null to the DataItem's filter property:

// done with that filter
$person->filter = null;

Database Transactions

Sometimes you need to update multiple tables in the database within a single transaction. Assuming your database supports a transactional model, Fakoli supplies the DataTransaction object to make this simple to implement.

$tx = new DataTransaction();

$task = new Task($task_id);
$person = $task->Person();

try
{
    $task->joinTransaction($tx);
    $person->joinTransaction($tx);

    $person->status = 'Terminated';
    $person->save();
 
    $task->status = 'Cancelled';
    $task->save();

    $tx->commit();
}
catch(Exception $e)
{
    echo "Something is amiss - rolling back transaction";
    $tx->rollback();
}

It is important to always commit the transaction upon completion and ensure that the transaction operations fall within a try ... catch block so that the transaction is correctly rolled back if an error occurs.

Fakoli creates a new connection to the database for every DataTransaction object, so you can have more than one transaction in progress within the same script if necessary.


Chapter 4: Data Formatting » « Chapter 2. The Data Model