Help cleanly integrating three classes
Posted: Mon Nov 22, 2010 3:33 pm
So currently I'm stuck trying to integrate dynamic finders into my Domain models with Lazy Loading. The lazy loading works just fine if I use the $userMapper->find(1); and I can call $user->company->name... but when I use the dynamic finders like such, $userMapper->findByUsername('DaveTheAve'); when I use $user->company->name I get an error because the lazy loading hasn't been initialized. (Error: "Specified column "company" is not in the row")
Lazy Loading inilized in: App_Model_Mapper_User::find();
Lazy Loading is done by: NeoeliteConsulting_ModelMapper
Dynamic Finders done by: NeoeliteConsulting_ModelTable
Lazy Loading inilized in: App_Model_Mapper_User::find();
Lazy Loading is done by: NeoeliteConsulting_ModelMapper
Dynamic Finders done by: NeoeliteConsulting_ModelTable
Code: Select all
class App_Model_Mapper_User extends NeoeliteConsulting_ModelMapper
{
protected $_tableName = 'users';
protected $_entityClass = 'App_Model_Entity_User';
protected $_modelTable = 'App_Model_Table_Users';
public function __construct()
{
parent::__construct(new $this->_modelTable);
}
public function save(App_Model_Entity_User $user)
{
$data = array(
'role_id' => $user->role->id,
'company_id' => $user->company->id,
'username' => $user->username,
'password' => $user->password,
);
if (!$user->id) {
$user->id = $this->_getGateway()->insert($data);
$this->_setIdentity($user->id, $user);
} else {
$where = $this->_getGateway()->getAdapter()->quoteInto('user_id = ?', $user->id);
$this->_getGateway()->update($data, $where);
}
}
public function find($id)
{
if ($this->_getIdentity($id)) {
return $this->_getIdentity($id);
}
$result = $this->_getGateway()->find($id)->current();
$user = new $this->_entityClass(array(
'id' => $result->user_id,
'username' => $result->username,
'password' => $result->password,
));
$user->setReferenceId('role', $result->role_id);
$user->setReferenceId('company', $result->company_id);
$this->_setIdentity($id, $user);
return $user;
}
public function delete($user)
{
if ($user instanceof App_Model_Entity_User) {
$where = $this->_getGateway()->getAdapter()->quoteInto('user_id = ?', $user->id);
} else {
$where = $this->_getGateway()->getAdapter()->quoteInto('user_id = ?', $user);
}
$this->_getGateway()->delete($where);
}
}
Code: Select all
class NeoeliteConsulting_ModelTable extends Zend_Db_Table_Abstract
{
/**
* Call method used to implement the dynamic finders
*
* @param string
* @param array
* @return function || void
*/
public function __call($method, $args) {
$watch = array('findBy','findAllBy');
foreach ($watch as $found) {
if (stristr($method, $found)) {
$fields = str_replace($found, '', $method);
return $this->{'_' . $found}($fields, $args);
}
}
throw new NeoeliteConsulting_Exception("Call to undefined method NeoeliteConsulting_ModelTable::{$method}()");
}
/**
* Find By
*
* This method only ever returns the first record it finds!
*
* @param string
* @param array
* @return object|false
*/
protected function _findBy($columns, $args) {
$stmt = $this->_buildQuery($columns, $args);
return $this->fetchRow($stmt);
}
/**
* Find All By
*
* @param string
* @param array
* @return object|false
*/
protected function _findAllBy($columns, $args) {
$stmt = $this->_buildQuery($columns, $args);
return $this->fetchAll($stmt);
}
/**
* Builds the query for the findBy methods
*
* @param string
* @param array
* @return Zend_Db_Select
*/
protected function _buildQuery($columns, $args) {
$fields = explode('And', $columns);
$count = count($fields);
$where = "{$this->_filterField($fields[0])} = ?";
$where_args = $args[0];
unset($args[0]);
$select = $this->select();
$select->where($where, $where_args);
if ($count > 1) {
array_shift($fields);
foreach ($fields as $field) {
$where = "{$this->_filterField($field)} = ?";
$where_args = array_shift($args);
$select->where($where, $where_args);
}
}
return $select;
}
/**
* Converts a camelCased word into an underscored word
*
* @param string
* @return string
*/
protected function _underscore($word) {
$word = preg_replace('/([A-Z]+)([A-Z])/', '\1_\2', $word);
return strtolower(preg_replace('/([a-z])([A-Z])/', '\1_\2', $word));
}
/**
* Converts field name to lowercase and if camelcased, converts to underscored
*
* @param string
* @return string
*/
protected function _filterField($item) {
$item = $this->_underscore($item);
return strtolower($item);
}
}
Code: Select all
class NeoeliteConsulting_ModelMapper
{
protected $_modelTable = null;
protected $_tableGateway = null;
protected $_identityMap = array();
public function __construct(Zend_Db_Table_Abstract $tableGateway)
{
if (is_null($tableGateway)) {
$this->_tableGateway = new $this->_modelTable();
} else {
$this->_tableGateway = $tableGateway;
}
if (!$this->_tableGateway instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
}
protected function _getGateway()
{
return $this->_tableGateway;
}
protected function _getIdentity($id)
{
if (array_key_exists($id, $this->_identityMap)) {
return $this->_identityMap[$id];
}
}
protected function _setIdentity($id, $entity)
{
$this->_identityMap[$id] = $entity;
}
/**
* Call method used to implement the dynamic finders
*
* @param string
* @param array
* @return function || void
*/
public function __call($method, $args) {
$watch = array('findBy','findAllBy');
foreach ($watch as $found) {
if (stristr($method, $found)) {
return $this->_getGateway()->$method($args);
}
}
throw new NeoeliteConsulting_Exception("Call to undefined method NeoeliteConsulting_ModelMapper::{$method}()");
}