Skip to content

Instantly share code, notes, and snippets.

@jeremeamia
Created July 9, 2011 22:02
Show Gist options
  • Save jeremeamia/1073989 to your computer and use it in GitHub Desktop.
Save jeremeamia/1073989 to your computer and use it in GitHub Desktop.
View-Models for Kohana 3.2.x (ORM-specific)
<?php defined('SYSPATH') or die('No direct script access.');
class ORM extends Kohana_ORM {
protected $_as_object = NULL;
public function as_object($class)
{
$this->_as_object = $class;
return $this;
}
protected function _load_result($multiple = FALSE)
{
$this->_db_builder->from(array($this->_table_name, $this->_object_name));
if ($multiple === FALSE)
{
// Only fetch 1 record
$this->_db_builder->limit(1);
}
// Select all columns by default
$this->_db_builder->select($this->_object_name.'.*');
if ( ! isset($this->_db_applied['order_by']) AND ! empty($this->_sorting))
{
foreach ($this->_sorting as $column => $direction)
{
if (strpos($column, '.') === FALSE)
{
// Sorting column for use in JOINs
$column = $this->_object_name.'.'.$column;
}
$this->_db_builder->order_by($column, $direction);
}
}
// Make sure $_as_object is set
$this->_as_object = $this->_as_object ? $this->_as_object : get_class($this);
if ($multiple === TRUE)
{
// Return database iterator casting to this object type
$result = $this->_db_builder->as_object($this->_as_object)->execute($this->_db);
$this->reset();
return $result;
}
else
{
// Load the result as an associative array
$result = $this->_db_builder->as_assoc()->execute($this->_db);
$this->reset();
if ($result->count() === 1)
{
// Load object values
$this->_load_values($result->current());
}
else
{
// Clear the object, nothing was found
$this->clear();
}
// Make sure that an instance of the correct object is returned
if ($this->loaded() AND ! $this instanceof $this->_as_object)
return new $this->_as_object($this);
else
return $this;
}
}
}
<?php defined('SYSPATH') or die('No direct script access.');
/**
* The View-Model sits as a bridge between the View class and the Model, and
* serves as an abstraction layer for making sure data from the Model is
* formatted for presentation. It makes formatting code more DRY, because
* without the View-Model, the code is typically repeated in various View
* classes that need the same data. The View-Model is fundamentally different
* from the View class, because, whereas View-Models have a one-to-one
* correspondence with the Models (Domain layer), View classes have a
* one-to-one (roughly) correspondence with the Controller Actions
* (Application layer). A View class can utilize one or more View-Models to
* easily retrieve the data it needs to display without duplication of
* formatting code.
*
* This class is built for Kohana v3.2.x
*/
class View_Model
{
protected static $_unsafe_methods = array(
'update', 'save', 'create', 'values',
'set', 'delete', 'add', 'remove', 'clear',
);
public static function factory($model = '', $id = NULL)
{
$class = 'View_Model_'.$model;
return new $class($id);
}
protected $_model;
public function __construct($id = NULL)
{
$class = substr(get_class($this), 5); // 5 = strlen('View_')
$this->_model = ($id instanceof $class) ? $id : new $class($id);
}
public function __get($key)
{
$value = method_exists($this, $key) ? $this->{$key}() : $this->_model->{$key};
return $this->_encapsulate_model($value);
}
public function __set($key, $value)
{
throw new BadMethodCallException('You cannot set properties of a View-Model; they are readonly.');
}
public function __call($method, $args)
{
if (in_array($method, View_Model::$_unsafe_methods))
throw new BadMethodCallException('You cannot use the '.$method.' method; View-Models are readonly.');
$value = call_user_func_array(array($this->_model, $method), $args);
if ($value === $this->_model)
return $this;
else
return $this->_encapsulate_model($value);
}
public function __isset($column)
{
if ($this->_model->__isset($column))
return TRUE;
return (bool) (method_exists($this, $column) AND $this->{$column}() !== NULL);
}
public function find()
{
return $this->_model->as_object(get_class($this))->find();
}
public function find_all()
{
return $this->_model->as_object(get_class($this))->find_all();
}
protected function _encapsulate_model($value)
{
if ($value instanceof ORM)
return View_Model::factory($value->object_name(), $value);
else
return $value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment