PHP Classes
Icontem

File: DATA/MySQL5/Row.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Martin Alterisio  >  DATA  >  DATA/MySQL5/Row.php  
File: DATA/MySQL5/Row.php
Role: Class source
Content type: text/plain
Description: This class is the abstraction of a MySQL5 table row implementing the array access and iteration behavior.
Class: DATA
Access data stored in MySQL tables like arrays
 

Contents

Class file image Download
<?php
/**
 * @package DATA_MySQL5
 */

/**
 * This class is the abstraction of a MySQL5 table row implementing the
 * array access and iteration behavior.
 * 
 * Field modification will affect the real database row, unless the object
 * has been marked as read-only (example: when using integer index access
 * to the field), or unless the object has been detached (example: cloned
 * objects). Only the field modified will be affected.
 * 
 * When cloning a row the new object will become detached from database and
 * modifications won't be proxied to the database. The detached object will
 * become reattached once it is inserted again the in table array. This can
 * be used to bundle modifications to a row before commiting them, or
 * duplicating rows with small changes.
 * 
 * Data won't remain updated to external changes. Preferred use of row
 * objects is as volatile containers.
 * 
 * Field data returned will be inboxed into representative objects 
 * ({@link DATA_SQLChar}, {@link DATA_SQLVarchar}, {@link DATA_SQLDecimal},
 * {@link DATA_SQLInt}, {@link DATA_SQLSmallInt}
 * {@link DATA_SQLDate}, {@link DATA_SQLTime}, {@link DATA_SQLDatetime}).
 * 
 * Examples:
 * <code>
 * // Retrieve a field value
 * $fieldValue = $DB['table'][$rowOffset]['field'];
 * 
 * // Change a field value
 * $DB['table'][$rowOffset]['field'] = '...';
 * // or
 * $row = $DB['table'][$rowOffset];
 * $row['field'] = '...';
 * 
 * // Cloning
 * $row = clone $DB['table'][$rowOffset];
 * $row['field'] = '...';
 * $row['field2'] = '...';
 * $DB['table'][$rowOffset] = $row;
 * // or on a new row or offset
 * $DB['table'][] = $row;
 * </code>
 */
class DATA_MySQL5_Row implements ArrayAccessCountableIteratorAggregate {
    
/**
     * The table name.
     * @var string
     */
    
protected $table;
    
/**
     * The row data. It may be in raw or inboxed format.
     * @var array
     */
    
protected $data;
    
/**
     * Array for field checking purposes.
     * @var array
     */
    
protected $fields;
    
/**
     * Read only flag.
     * @var bool
     */
    
protected $readOnly;
    
/**
     * Detached from db flag
     * @var bool
     */
    
protected $detached;
    
/**
     * Disables inboxing in this object.
     * @var bool
     */
    
protected $inboxingDisabled;
    
    
/**
     * Default constructor.
     * 
     * @access protected
     * @param string $table The table.
     * @param array $data The fetched row data.
     * @param bool $readOnly The created object has read only access if set to true.
     *                       Optional, defaults to false.
     */
    
public function __construct($table$data$readOnly false) {
        
$this->table $table;
        
$this->setData($data);
        
$this->readOnly $readOnly;
        
$this->detached false;
        
$this->inboxingDisabled false;
    }
    
    
/**
     * isset(..) handler. Indicates if field exists.
     * 
     * @param string $field The field name.
     * @return bool True if field exists, false otherwise.
     */
    
public function offsetExists($field) {
        if (
is_int($field)) {
            return 
count($this->data) > $field && $field >= 0;
        } else {
            return isset(
$this->fields[$field]);
        }
    }
    
    
/**
     * [..] handler. Returns the value of the field requested.
     * 
     * Throws {@link DATA_FieldDoesntExist}.
     * 
     * @param string $field The field name.
     * @return string The field value.
     */
    
public function offsetGet($field) {
        if (!
$this->offsetExists($field)) {
            
throw new DATA_FieldDoesntExist($this->table$field);
        }
        if (
is_int($field)) {
            
$fields array_keys($this->data);
            
$field $fields[$field];
        }
        return 
$this->inboxField($field$this->data[$field]);
    }
    
    
/**
     * [..] = handler. Sets the value of a field.
     * 
     * Throws {@link DATA_ReadOnly}, {@link DATA_FieldDoesntExist},
     * {@link DATA_SQLTypeConstraintFailed}.
     * 
     * @param string $field The field name.
     * @param string $value The field value.
     */
    
public function offsetSet($field$value) {
        if (
$this->readOnly) {
            
throw new DATA_ReadOnly();
        }
        if (!
$this->offsetExists($field)) {
            
throw new DATA_FieldDoesntExist($this->table$field);
        }
        if (
is_int($field)) {
            
$fields array_keys($this->data);
            
$field $fields[$field];
        }
        
try {
            
$value $this->inboxField($field$value);
        } 
catch (DATA_SQLTypeConstraintFailed $exception) {
            
$exception->setTable($this->table);
            
$exception->setField($field);
            
throw $exception;
        }
        if (!
$this->detached) {
            
$keys DATA_MySQL5_Schema::getPrimaryKey($this->table);
            
DATA_MySQL5_Access::query("
                UPDATE `{$this->table}`
                   SET `{$field}` = " 
DATA_MySQL5_Access::prepareData($value) . "
                 WHERE `{$keys[0]}` = '" 
DATA_MySQL5_Access::escape($this->data[$keys[0]]) . "'
            "
);
        }
        
$this->data[$field] = $value;
    }
    
    
/**
     * unset(..) handler. Fields cannot be unset.
     * 
     * Will throw {@link DATA_CannotRemoveField DATA_CannotRemoveField exception}.
     */
    
public function offsetUnset($offset) {
        
throw new DATA_CannotRemoveField();
    }
    
    
/**
     * count(..) handler. Returns fields count.
     * 
     * @return int How many fields there are on this row.
     */
    
public function count() {
        return 
count($this->data);
    }
    
    
/**
     * Provides the iterator to be used on a foreach loop.
     * 
     * @return ArrayIterator The fields data iterator.
     */
    
public function getIterator() {
        if (
$this->inboxingDisabled) {
            return new 
ArrayIterator($this->data);
        }
        
$inboxedData = array();
        foreach (
$this->data as $field => $value) {
            
$inboxedData[$field] = DATA_MySQL5_Schema::getSQLTypeFactory($this->table$field)->inbox($value);
        }
        return new 
ArrayIterator($inboxedData);
    }
    
    
/**
     * clone handler. Detaches cloned object from the database.
     */
    
public function __clone() {
        
$this->readOnly false;
        
$this->detached true;
    }
    
    
/**
     * Reattaches the object to the database.
     * 
     * @param int $autoid Autogenerated numeric id. Optional, 0 if no id was generated.
     */
    
public function reattach($autoid 0) {
        if (
$autoid != 0) {
            
$autofield DATA_MySQL5_Schema::getAutoIncrementField($this->table);
            
$this->data[$autofield] = (int)$autoid;
        }
        
$sql "SELECT * FROM `{$this->table}` ";
        
$sql .= $this->buildWhereStatement();
        
$query DATA_MySQL5_Access::query($sql);
        
$this->setData(DATA_MySQL5_Access::fetchAssoc($query));
        
$this->readOnly false;
        
$this->detached false;
    }
    
    
/**
     * Builds a where statement to select this row.
     * 
     * @return string SQL where statement to select the requested row.
     */
    
protected function buildWhereStatement() {
        
$keys DATA_MySQL5_Schema::getPrimaryKey($this->table);
        
$sql 'WHERE';
        
$sep '';
        foreach (
$keys as $key) {
            
$sql .= "$sep `$key` = " DATA_MySQL5_Access::prepareData($this->data[$key]);
            
$sep ' AND';
        }
        return 
$sql;
    }
    
    
/**
     * Sets the fetched row data.
     * 
     * @param array $data The fetched row data.
     */
    
protected function setData($data) {
        
$this->data $data;
        
$this->fields = array();
        foreach (
array_keys($data) as $field) {
            
$this->fields[$field] = true;
        }
    }
    
    
/**
     * Returns inboxed version of the field provided.
     * 
     * Throws {@link DATA_SQLTypeConstraintFailed}.
     * 
     * @param string $field The field name.
     * @param null|int|string|DATA_SQLType $value The field value
     * @return DATA_SQLType Inboxed field.
     */
    
protected function inboxField($field$value) {
        if (
$this->inboxingDisabled) return $value;
        return 
DATA_MySQL5_Schema::getSQLTypeFactory($this->table$field)->inbox($value);
    }
    
    
/**
     * Member property overloading.
     * 
     * withoutInboxing property returns a db object with inboxing of
     * mysql types disabled.
     * 
     * @param string $propname Property name.
     * @return mixed Property value.
     */
    
public function __get($propname) {
        if (
$propname == 'withoutInboxing') {
            
$newRow clone $this;
            
$newRow->readOnly $this->readOnly;
            
$newRow->detached $this->detached;
            
$newRow->inboxingDisabled true;
            return 
$newRow;
        }
        
throw new Exception("Undefined property: {$propname}");
    }
}
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products