Rev 65 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
1
<?php
namespace PointedEars\PHPX
;
/**
* Abstract model class for Object-Relational Mapping
*
* Provides simple mapping of a model object to records of
* a table of a relational database.
*
* @property Db\Table $persistentTable
* @author Thomas Lahn
*/
abstract class Model
extends \PointedEars\PHPX\AbstractModel
{
/**
* The <code>Table</code> for instances of this model
*
* @type Table|string
*/
protected static
$_persistentTable;
/**
* The name(s) of the property or properties whose value(s)
* identify this object in the <code>Table</code>. They are
* used for comparing against the primary key column(s) of
* the <code>Table</code>.
*
* @type string|array[string]
*/
protected static
$_persistentId = 'id';
/**
* The names of the properties that should be used in database
* queries, and their mapping to the columns of
* the <code>Table</code>, if specified (keys are property names,
* values are column names, or both if the key is numeric).
*
* NOTE: It should not be necessary to include the
* <code>persistentId</code> property value here. If an object
* is not in the database, it should be assigned an ID
* automatically when saved; if it is in the database,
* you already have its ID as you searched by it.
*
* @type array
*/
protected static
$_persistentProperties = array();
/**
* Creates a new model object
*
* @see AbstractModel::__construct()
*/
public function __construct
(
array $data = null, array $mapping = null, $exclusiveMapping = false)
{
parent
::__construct
($data, $mapping, $exclusiveMapping);
}
public function getPersistentTable
()
{
$class = \
get_class($this);
if (\
is_string($class::$_persistentTable))
{
/* Call setter to convert to Table */
$this->setPersistentTable($class::$_persistentTable);
}
return $class::$_persistentTable;
}
public function setPersistentTable
($value)
{
$class = \
get_class($this);
if ($value instanceof Table
)
{
$class::$_persistentTable = $value;
}
else
{
$table = new $value();
if (!($table instanceof Db\Table
))
{
throw new \InvalidArgumentException
(
'Parameter does not specify a subclass of \\PointedEars\\PHPX\\Table: '
. $value
);
}
$class::$_persistentTable = $table;
}
}
/**
* Returns an array containing the property-column mapping.
*
* @param array $propertyNames = null
* Names of the properties that should be included.
* The default is to include all persistent properties.
* @return array
*/
public static
function getPersistentMapping
(array $propertyNames = null)
{
$a = array();
$persistent_properties = static
::$_persistentProperties;
if ($propertyNames === null)
{
$propertyNames = $persistent_properties;
}
foreach ($propertyNames as $property_name)
{
if (!array_key_exists($property_name, $persistent_properties))
{
$column_name = $property_name;
}
else
{
$column_name = $persistent_properties[$property_name];
}
$a[$property_name] = $column_name;
}
return $a;
}
/**
* Returns an array for database queries containing the
* property values of this object, using the specified
* property-to-column mapping.
*
* @param array $propertyNames = null
* Names of the properties that should be included.
* The default is to include all persistent properties.
* @return array
*/
public function getPropertyArray
(array $propertyNames = null)
{
$a = array();
if ($propertyNames === null)
{
$class = \
get_class($this);
$propertyNames = $class::$_persistentProperties;
}
foreach ($propertyNames as $propertyName => $columnName)
{
if (is_numeric($propertyName))
{
$propertyName = $columnName;
}
$a[$columnName] = $this->$propertyName;
}
return $a;
}
/**
* Finds the record for the model object in the table, fills
* the object with missing data, and returns the result.
*
* @param mixed $id = null
* The ID of the object to find. If <code>null</code> (default),
* the object is searched for by its current ID.
* @return Model|null
* This object filled with missing data, or <code>null</code>
* if there is no data for this object
* @see Table::find(int)
*/
public function find
($id = null)
{
$class = \
get_class($this);
if ($id === null)
{
$id = $this->{$class::$_persistentId};
}
$result = $this->persistentTable->find($id);
if ($id !== null)
{
$this->{$class::$_persistentId} = $id;
}
$result = $this->persistentTable->find($this->{$class::$_persistentId});
if ($result)
{
return $this->map($result);
}
return null;
}
/**
* Finds the records for model objects in the table by value,
* and returns the result.
*
* @param string $name
* Name of the property to search for.
* @param mixed $value = null
* The property value to find. If <code>null</code>,
* the current value of the specified property is used.
* (To search for null, you need to make sure that the
* current property value is <code>null</code>, which is
* the PHP default.)
* @return array[Model]|null
* Model objects, or <code>null</code> if there is no data
* for this property and value
* @see Table::select(Model)
*/
public function findByProperty
($name, $value = null)
{
$class = \
get_class($this);
$mapping = $class::getPersistentMapping(array($name));
if ($value === null)
{
$value = $this->$name;
}
$results = $this->persistentTable->select(null,
array($mapping[$name] => $value));
if ($results)
{
return array_map(array($this, 'map'), $results);
}
return null;
}
/**
* Saves the model object in the table
*
* @param array $propertyNames = null
* Names of the properties whose values should be saved
* in the database. The default is to save the values
* of all persistent properties.
* @return boolean
* The return value of
* <code>$this->persistentTable->updateOrInsert()</code>.
* @see Model::getPropertyArray()
* @see Table::updateOrInsert()
*/
public function save
(array $propertyNames = null)
{
$table = $this->persistentTable;
$class = \
get_class($this);
$idPropertyName = $class::$_persistentId;
$result = $table->updateOrInsert(
$this->getPropertyArray($propertyNames),
array(
$table->id => $this->$idPropertyName
)
);
if ($result && ($lastInsertId = $table->lastInsertId))
{
$this->$idPropertyName = $lastInsertId;
}
return $result;
}
/**
* Inserts the model object into the table
*
* @param array $propertyNames = null
* Names of the properties whose values should be insert
* in the database. The default is to insert the values
* of all persistent properties.
* @return boolean
* @see Model::getPropertyArray()
* @see Table::insert()
*/
public function insert
(array $propertyNames = null)
{
$table = $this->persistentTable;
$class = \
get_class($this);
$idPropertyName = $class::$_persistentId;
$result = $table->insert($this->getPropertyArray($propertyNames));
if ($result && ($lastInsertId = $table->lastInsertId))
{
$this->$idPropertyName = $lastInsertId;
}
return $result;
}
/**
* Deletes a model object from the <code>Table</code>
*
* @return bool
* @see Table::delete()
*/
public function delete
()
{
$class = \
get_class($this);
return $this->persistentTable->delete($this->{$class::$_persistentId});
}
}