zend-framework - Zend Framework - ORM 关系和优化

标签 zend-framework model relationship zend-db-table mapper

我已经使用 ZF 几个月了,我对它非常满意,但是我不完全确定如何处理模型关系并同时避免对数据库进行多次查询。很多人都有这个问题,似乎没有人找到好的解决方案。 (并避免使用第三方 ORM)例如,我有一个用户列表,每个用户都属于一个组。我想要一个显示用户信息和组名的用户列表(表:用户和组。用户具有表组的外键)。 我有: 2 个映射器类来处理这些表,UserMapper 和 GroupMapper。 2 个模型类用户和组 2 扩展 Zend_DB_Table_Abstract 的数据源类

在用户映射器中,我可以执行 findParentRow 以获取每个用户的组信息,但问题是我对每一行都有一个额外的查询,这不好我认为在加入时我只能在一。当然,现在我们必须将该结果映射到一个对象。所以在我的抽象 Mapper 类中,我尝试使用列别名(类似于 Yii 所做的......我认为)为每个父行加载连接表,所以我在一个查询中得到一个这样的值对象 //用户模型对象

$userMapper= new UserMapper();
$users= $userMapper->fetchAll(); //Array of user objects
echo $user->id;
echo $user->getGroup()->name // $user->getParentModel('group')->name // this info is already in the object so no extra query is required.

我想您明白我的意思了……是否有原生解决方案(也许比我的更学术)来执行此操作而不避免多次查询?//Zend db table 执行额外的查询以获取可以缓存的元数据。我的问题是为了获取父行信息......就像在 yii 中......类似 $userModel->with('group')->fetchAll(); 谢谢你。

最佳答案

开发你的映射器来使用 Zend_Db_Select。这应该允许您需要的灵 active 。组表是否连接取决于提供给映射器方法的参数,在本例中组对象是关键参数。

class Model_User {
    //other fields id, username etc.
    //...

    /**
    * @var Model_Group
    */
    protected $_group;

    public function getGroup() {
        return $this->_group;
    }

    public function setGroup(Model_Group $group) {
        $this->_group = $group;
    }

}

class Model_Mapper_User {

    /**
    * User db select object, joins with group table if group model provided
    * @param Model_Group $group
    * @return Zend_Db_Select
    */
    public function getQuery(Model_Group $group = NULL) {
        $userTable = $this->getDbTable('user'); //mapper is provided with the user table
        $userTableName = $userTable->info(Zend_Db_Table::NAME); //needed for aliasing
        $adapter = $userTable->getAdapter();

        $select = $adapter->select()->from(array('u' => $userTableName));

        if (NULL !== $group) {
            //group model provided, include group in query
            $groupTable = $this->getDbTable('group');
            $groupTableName = $groupTable->info(Zend_Db_Table::NAME);
            $select->joinLeft(array('g' => $groupTableName), 
                                'g.group_id = u.user_group_id');
        }

        return $select;
    }

    /**
    * Returns an array of users (user group optional)
    * @param Model_User $user
    * @param Model_Group $group
    * @return array
    */
    public function fetchAll(Model_User $user, Model_Group $group = NULL) {
        $select = $this->getQuery();
        $adapter = $select->getAdapter();
        $rows = $adapter->fetchAll($select);

        $users = array();

        if (NULL === $group) {
            foreach ($rows as $row) {
                $users[] = $this->_populateUser($row, clone $user);
            }
        } else {
            foreach ($rows as $row) {
                $newUser = $this->_populateUser($row, clone $user);
                $newGroup = $this->_populateGroup($row, clone $group);

                //marrying user and group
                $newUser->setGroup($newGroup);

                $users[] = $newUser;
            }
        }

        return $users;
    }

    /**
    * Populating user object with data
    */
    protected function _populateUser($row, Model_User $user) {
        //setting fields like id, username etc
        $user->setId($row['user_id']);
        return $user;
    }

    /**
    * Populating group object with data
    */
    protected function _populateGroup($row, Model_Group $group) {
        //setting fields like id, name etc
        $group->setId($row['group_id']);
        $group->setName($row['group_name']);
        return $group;
    }

    /**
    * This method also fits nicely
    * @param int $id
    * @param Model_User $user
    * @param Model_Group $group 
    */
    public function fetchById($id, Model_User $user, Model_Group $group = NULL) {
        $select = $this->getQuery($group)->where('user_id = ?', $id);
        $adapter = $select->getAdapter();
        $row = $adapter->fetchRow($select);

        $this->_populateUser($row, $user);
        if (NULL !== $group) {
            $this->_populateGroup($row, $group);
            $user->setGroup($group);
        }

        return $user;
    }

}

使用场景

/**
 * This method needs users with their group names 
 */
public function indexAction() {
    $userFactory = new Model_Factory_User();
    $groupFactory = new Model_Factory_Group();
    $userMapper = $userFactory->createMapper();
    $users = $userMapper->fetchAll($userFactory->createUser(), 
                                        $groupFactory->createGroup());
}

/**
 * This method needs no user group
 */
public function otherAction() {
    $userFactory = new Model_Factory_User();
    $userMapper = $userFactory->createMapper();
    $users = $userMapper->fetchAll($userFactory->createUser());
}

干杯

关于zend-framework - Zend Framework - ORM 关系和优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9767347/

相关文章:

zend-framework - 为什么 ZEND 到处使用接口(interface)和抽象类,而 Codeigniter 根本不使用它们?

zend-framework - 从另一个 View 调用 View

symfony - 在 Symfony 2 中制作胖模型 - 组合或继承以及如何配置我的模型层

ios - 具有独特约束和关系的核心数据-IOS

zend-framework - Zend 框架 : How to POST data to some external page (e. g。外部支付门)不使用表格?

php - 序列化对象并缓存它们的奇怪行为

R:在 nlme 函数中使用因子变量

ruby-on-rails - Rails 3 模型子类让我发疯!请帮助更正 urls/params 哈希

java - 将 JPA 实体一分为二?

yii - 无效的 yii 关系 HAS_MANY