Reference Documentation

From Outlet

Jump to: navigation, search

{{#hierarchy-top:}}

Contents

Overview

Outlet provides database persistence for PHP objects in a transparent, unobtrusive way. It let's you define and instantiate entity classes that are completely independent of the code that saves them to the database. The data is persisted through the use of proxies. Whenever you 'save' an object, Outlet decorates the object with a sub-class that performs the database operations behind the scenes.

Let's say we start out with an entity object such as: <source lang="php"> class Bug {

 public $Title;
 public $ProjectID;
 private $project;
 function getProject () {
   return $this->project;
 }
 function setProject (Project $p) {
   $this->project = $p;
 }

} </source>

Whenever you instantiate, populate, and save it to the database with code like: <source lang="php"> $con = Outlet::getInstance();

$bug = new Bug; $bug->Title = "error on page"; $bug->ProjectID = 1;

$con->save( $bug ); //performs an insert </source>

Outlet is replacing your $bug variable of type Bug with a proxy called Bug_OutletProxy: <source lang="php"> print_r($bug); // after it's been saved </source>

outputs:

Bug_OutletProxy Object
(
    [Title] => error on page
    [ProjectID] => 1
    [project:private] =>
)

Since the proxy is a subclass of the entity (Bug_OutletProxy extends Bug), you can use the proxy wherever you would have used the original entity. Even the following code evaluates to true:

<source lang="php"> // since the bug has been saved it is now an instance of Bug_OutletProxy if ($bug instanceof Bug) echo "It seems to be a Bug too"; </source>

Now here's where the magic happens, when you call a method such a $bug->getProject(), the proxy automatically populates the $project property with data from the database behind the scenes: <source lang="php"> $project = $bug->getProject();

print_r($bug); </source>

outputs:

Bug_OutletProxy Object
(
    [Title] => error on page
    [ProjectID] => 1
    [project:private] => Project_OutletProxy Object
        (
            [ID] => 1
            [Name] => My Project
        )

)

Configuration

The configuration consists of an associative array with the elements: <source lang="php"> <?php return array(

 'connection' => array(...), // connection config
 'classes' => array(...)     // class mappings config

); </source>

connection
Database connection settings
classes
Mapping configuration for each of the entity classes


Database Connection

<source lang="php"> array(

 'dsn' => 'mysql:hostname=myhost.com;dbname=testdb',
 'username' => 'testdbuser',
 'password' => 'testdbpass'

) </source>

dsn
A PDO connection string
username
A username if the database driver requires it
password
A password if the database driver requires it

Classes

<source lang="php"> array(

 'User' => array(
   'props' => array(...),        // properties mappings
   'associations' => array(...)  // relationships mappings
 ),
 'Project' =>
 ...

) </source>

An array of class mappings indexed by the name of the entity class. Each class mapping is an associative array with the elements:

props
An array of property mappings
associations
An array of association mappings

Properties

<source lang="php"> array(

 'ID'        => array('user_id', 'int', array('pk'=>true, 'autoIncrement'=>true)),
 'FirstName' => array('first_name', 'varchar'),
 ...

) </source>

  • The indexes are the properties of the class being mapped.
  • The first element of each mapping is the name of the column.
  • The second is the column type, which can be either int or varchar.
  • The third element is an array of optional settings:
    pk
    Whether this field is (part of) the primary key. Defaults to false.
    autoIncrement
    Whether this field is automatically incremented by the database. Defaults to false.

Associations

<source lang="php"> array(

 array('one-to-many', 'Bug', array('key'=>'BugID')),
 array('many-to-one', 'Project', array('key'=>'ProjectID')),
 ...

) </source>

  • The first element of an association mapping is the type, it can be either one-to-many or many-to-one.
  • The second element is the entity class that this relation refers to (related entity).
  • The third element is a set of options which differ depending on the type of association.
    one-to-many
    key
    The name of the property on the related entity that contains the primary key of this entity.
    name
    Optional. Defaults to the name of the related entity.
    The name to give the relationship. If this association defines the relationship between a bug and the people who are assigned to it (one-to-many from Bug to User), and you set the name to 'Assignee', the method names on the bug object will be 'getAssignees', 'setAssignees', and 'addAssignee'.
    many-to-one
    key
    The name of the property on this entity that contains the primary key of the related entity.
    name
    Optional. Defaults to the name of the related entity.
    The name to give the relationship. If this association defines the relationship between a bug and the user who reported it (many-to-one from Bug to User), and you set the name to 'Reporter', the method names on the bug object will be 'getReporter' and 'setReporter'.
    optional
    Optional. Defaults to false.
    Whether to allow this relationship to be optional (allow null).

Usage

Selecting

A query with outlet is just a regular SQL statement except for the ability to refer to columns by their class member names. Simply wrap the identifier in curly braces and outlet will automatically replace it with the corresponding table or column name. You can even add aliases: <source lang="php"> $bugs = $outlet->select("Bug", "INNER JOIN {Project p} ON {Bug.ProjectID} = {p.ProjectID}"); // this code will be transformed to // SELECT bugs.* // FROM bugs // INNER JOIN projects p // ON bugs.project_id = p.project_id </source>

Although referring to the columns by their class member name is recommended, you're always free to simple use straight sql.

select

<source lang="php"> <?php $outlet = Outlet::getInstance(); // retrieve an array of Bug objects by using a prepared statement $bugs = $outlet->select("Bug", "WHERE {Bug.StatusID} = ?", array(1)); </source>

load

<source lang="php"> <?php $outlet = Outlet::getInstance(); // retrieve a Bug by primary key $bug = $outlet->load("Bug", 1); </source>

Inserting and Updating

<source lang="php"> <?php $outlet = Outlet::getInstance(); // insert a bug $bug = new Bug; $bug->Title = 'This is a test bug'; $bug->ProjectID = 1;

$outlet->save( $bug ); // executes an insert statement

// now that the bug is saved and we're dealing with a proxy, // any subsequent calls to $outlet->save() will execute an update statement $bug->Title = 'New Title';

$outlet->save( $bug ); // executes an update statement </source>

Relationships

You can also use the query syntax to filter what's returned through a relationship method: <source lang="php"> <?php $outlet = Outlet::getInstance(); $project = $outlet->load('Project', 1);

$bugs = $project->getBugs('WHERE {Bug.StatusID} = 1'); </source>

{{#hierarchy-bottom:}}