Help cleanly integrating three classes

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
DaveTheAve
Forum Contributor
Posts: 385
Joined: Tue Oct 03, 2006 2:25 pm
Location: 127.0.0.1
Contact:

Help cleanly integrating three classes

Post by DaveTheAve »

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

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}()");
    }
Post Reply