Skip to content
This repository has been archived by the owner on Oct 31, 2021. It is now read-only.

Commit

Permalink
Modified unmarshalling to use a Closure.
Browse files Browse the repository at this point in the history
  • Loading branch information
tenorviol committed Apr 27, 2010
1 parent af05d2b commit 65a4d14
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 22 deletions.
209 changes: 209 additions & 0 deletions src/AbstractRecord.php
@@ -0,0 +1,209 @@
<?php

abstract class AbstractRecord implements IteratorAggregate {

// does this record exist on the permanent media?
private $exists = false;

// has this record already been loaded from the permanent media?
private $loaded = false;

// the data in this record
private $data = array();

// modified fields that have not yet been stored to the permanent media
private $dirty = null;

public abstract function id();

/**
* Load this record's data from the data source.
* @return success/failure
*/
public function load() {
$data = $this->readData();
if ($data === false) {
$this->loaded = false;
$this->exists = false;
} elseif ($data === null) {
$this->loaded = true;
$this->exists = false;
} else {
foreach ($data as $key => $value) {
if (!isset($this->dirty[$key])) {
$this->data[$key] = $value;
}
}
}
return $this->loaded;
}

/**
* Save all dirty data to the permanent record.
* @return success/failure
*/
public function save() {
if (empty($this->dirty)) {
return false;
}
if ($return = $this->writeData($this->dirty)) {
$this->exists = true;
$this->dirty = null;
}
return $return;
}

/**
* Delete from the permanent record.
*/
//public abstract function delete();

public function exists() {
$this->loadOnce();
return $this->exists;
}

/**
* Read from the permanent record.
*
* Return the associative array on success.
* Return null if the record doesn't exist.
* Return false if the read fails.
* @param mixed $fields null|false=easy fields, true=all fields, array=selected fields (+easies)
* @param array $exclude_fields unneeded fields
* @return array|null|false
*/
protected abstract function readData($require_fields = null, array $exclude_fields = null);

/**
* Write to the permanent record.
*
* @param array $dirty_fields those that need saving
* @return boolean success/failure
*/
protected abstract function writeData(array $dirty_fields);

/**
* For use by external functions instantiating records in bulk.
* I.e. run sql query, fetch rows, instantiate records, setData().
*/
public function setData(array $data, $loaded = true, $clean = true) {
$this->exists = true;
if ($this->loaded) {
$this->loaded = true;
}
$this->data = $data;
if ($clean) {
$this->dirty = null;
}
}

/**
* Load this record's data, but only once.
*/
public function loadOnce() {
if (!$this->loaded) {
$this->load();
}
}

/**
* Write a record property.
*/
public function __set($name, $value) {
$this->data[$name] = $value;
$this->dirty[$name] = true;
}

/**
* Read a record property.
*/
public function __get($name) {
return $this->data[$name];
}

/**
* Check on a record property.
*/
public function __isset($name) {
$this->loadOnce();
return isset($this->data[$name]);
}

/**
* Remove a record property.
*/
public function __unset($name) {
unset($this->data[$name]);
$this->dirty[$name] = true;
}

/**
* Making this record usable in foreach statements.
*
* @return Iterator
*/
public function getIterator() {
$fields = array_fields($this->data);
return new AbstractRecord_Iterator($this, $fields);
}

/**
* Convert this record to an array.
*
* @return array
*/
public function toArray() {
$this->loadOnce();
return $this->data;
}
}

class AbstractRecord_Iterator {
private $record;
private $fields;
private $field_count;
private $marker = 0;

public function __construct($record, $fields) {
$this->record = $record;
$this->fields = $fields;
$this->field_count = count($fields);
}

/**
* @return mixed
*/
public function current() {
$field = $this->fields[$this->marker];
return $this->record[$field];
}

/**
* @return scalar
*/
public function key() {
return $this->fields[$this->marker];
}

/**
*
*/
public function next() {
$this->marker++;
}

/**
*
*/
public function rewind() {
$this->marker = 0;
}

/**
* @return boolean
*/
public function valid() {
return $this->marker < $this->field_count;
}
}
6 changes: 2 additions & 4 deletions src/Grubby/DB/Recordset.php
Expand Up @@ -40,10 +40,8 @@ public function fetchAll() {
while ($row = $this->recordset->fetchRow(DB_FETCHMODE_ASSOC)) {
$all[] = $row;
}
if ($this->object_type) {
foreach ($all as $key => $row) {
$all[$key] = $this->unmarshal($row);
}
foreach ($all as $key => $row) {
$all[$key] = $this->unmarshal($row);
}
return $all;
}
Expand Down
6 changes: 2 additions & 4 deletions src/Grubby/MDB2/Recordset.php
Expand Up @@ -36,10 +36,8 @@ public function fetch() {
*/
public function fetchAll() {
$all = $this->recordset->fetchAll(MDB2_FETCHMODE_ASSOC);
if ($this->object_type) {
foreach ($all as $key => $row) {
$all[$key] = $this->unmarshal($row);
}
foreach ($all as $key => $row) {
$all[$key] = $this->unmarshal($row);
}
return $all;
}
Expand Down
6 changes: 2 additions & 4 deletions src/Grubby/Mysql/Recordset.php
Expand Up @@ -36,10 +36,8 @@ public function fetchAll() {
while ($row = mysql_fetch_assoc($this->recordset)) {
$all[] = $row;
}
if ($this->object_type) {
foreach ($all as $key => $row) {
$all[$key] = $this->unmarshal($row);
}
foreach ($all as $key => $row) {
$all[$key] = $this->unmarshal($row);
}
return $all;
}
Expand Down
6 changes: 2 additions & 4 deletions src/Grubby/PDO/Recordset.php
Expand Up @@ -32,10 +32,8 @@ public function fetch() {
*/
public function fetchAll() {
$all = $this->recordset->fetchAll(PDO::FETCH_ASSOC);
if ($this->object_type) {
foreach ($all as $key => $row) {
$all[$key] = $this->unmarshal($row);
}
foreach ($all as $key => $row) {
$all[$key] = $this->unmarshal($row);
}
return $all;
}
Expand Down
6 changes: 6 additions & 0 deletions src/Grubby/Record.php
Expand Up @@ -10,6 +10,12 @@
* Licensed under the MIT license (see LICENSE file).
*/

/**
* TODO: 4 spaces to tabs
* TODO: change set object to a factory
* TODO: integrate bug fixes in "my" project
*/

abstract class Grubby_Record {

/**
Expand Down
13 changes: 8 additions & 5 deletions src/Grubby/Recordset.php
Expand Up @@ -5,6 +5,7 @@
*/
abstract class Grubby_Recordset {
protected $object_type;
private $factory = null;

/**
*
Expand All @@ -15,17 +16,19 @@ public function setObjectType($object_type) {
$this->object_type = $object_type;
}

public function setRecordFactory($factory) {
$this->factory = $factory;
}

/**
*
* @param $result
* @return unknown_type
*/
protected function unmarshal($result) {
if ($this->object_type) {
$object = new $this->object_type;
foreach ($result as $key => $value) {
$object->$key = $value;
}
if ($this->factory) {
$factory = $this->factory;
$object = $factory($result);
return $object;
} else {
return $result;
Expand Down
10 changes: 9 additions & 1 deletion src/Grubby/Table.php
Expand Up @@ -167,7 +167,15 @@ private function readImpl($query) {
$sql = 'SELECT '.$fields.' FROM '.$this->info['name'].$join.$where.$group.$order.$limit;
$result = $this->info['database']->query($sql);
if (!empty($this->info['class'])) {
$result->setObjectType($this->info['class']);
// $result->setObjectType($this->info['class']);
$class = $this->info['class'];
$result->setRecordFactory(function ($row) use ($class) {
$object = new $class();
foreach ($row as $key => $value) {
$object->$key = $value;
}
return $object;
});
}
if ($first) {
return $result->fetch(); // Return the first result of the iterator
Expand Down

0 comments on commit 65a4d14

Please sign in to comment.