Subversion Repositories PHPX

Rev

Rev 62 | Rev 65 | Go to most recent revision | 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 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 search for by its current ID.
   * @see Table::find(Model)
   * @return Model|null
   *   This object filled with missing data, or <code>null</code>
   *   if there is no data for this object
   */

  public function find ($id = null)
  {
        $class = \get_class($this);
    if ($id !== null)
    {
      $this->{$class::$_persistentId} = $id;
    }

    $result = $this->persistentTable->find($this->{$class::$_persistentId});
    if ($result)
    {
        return $this->map($result);
    }

    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});
  }
}