【问题标题】:ZF2 - Doctrine ORM, Simple Table JoinZF2 - Doctrine ORM,简单表连接
【发布时间】:2014-05-05 08:40:34
【问题描述】:

我目前正在学习如何将 Doctrine ORM 与 ZF2 一起使用,目前我的目标是从简单的表连接中检索数据并将其显示到屏幕上。

我已经阅读了文档,看起来很简单。

这些是我的桌子:

user
------------------------
|user_id | name | email   |
--------------------------
| 1      | John | j@b.com |
--------------------------
| 2      | Bob  | b@j.com |
--------------------------

user_role_linker
--------------------------
|user_id | role_id        |
--------------------------
| 1      | administrator  |
--------------------------
| 2      | staff          |
--------------------------

我想要实现的是我的观点列表如下:

ID       Name       Email      Role              Actions
--------------------------------------------------------
1        John       j@b.com    Administrator     Edit
2        Bob        b@j.com    Staff             Edit
--------------------------------------------------------
Paging goes here
----------------

这是我目前拥有的,它似乎可以工作,除了我不确定如何获取连接的表数据:

User entity::

<?php
    namespace Administration\Entity;
    use Doctrine\ORM\Mapping as ORM;
    use Doctrine\ORM\Mapping\ManyToMany;
    use Doctrine\ORM\Mapping\JoinTable;
    use Doctrine\ORM\Mapping\JoinColumn;
    use Doctrine\Common\Collections\ArrayCollection;

    /** @ORM\Entity */

    class User {
        /**
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         * @ORM\Column(type="integer",name="user_id")
         */

        protected $user_id;

        /** @ORM\Column(type="integer", name="parent_id") */
        protected $parent_id;

        /** @ORM\Column(type="string", name="name") */
        protected $name;

        /** @ORM\Column(type="string", name="email") */
        protected $email;

        //Setters and getters

        public function getUserId() {
            return $this->user_id;
        }

        public function setName($name) {
            $this->name = $name;
        }

        public function getName() {
            return $this->name;
        }

        public function getEmail() {
            return $this->email;
        }

        public function setEmail($email) {
            $this->email = $email;
        }

        /**
        * @ManyToMany(targetEntity="UserRoleLinker")
        * @JoinTable(
        * name="user_role_linker",
        * joinColumns={
        *   @JoinColumn(
        *     name="user_id",
        *     referencedColumnName="id")
        *  },
        * inverseJoinColumns={
            *   @JoinColumn(
             *     name="user_id",
             *     referencedColumnName="id",
             *     unique=true)
             * })
        */
        private $role_id;

        public function __construct()
        {
            $this->role_id = new ArrayCollection();
        }

        /** @return Collection */
        public function getRoleId()
        {
            return $this->role_id;
        }

    }

用户角色链接器实体::

 <?php
    namespace Administration\Entity;
    use Doctrine\ORM\Mapping as ORM;

/** @ORM\Entity */
class UserRoleLinker {
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer",name="user_id")
     */
    protected $user_id;

    /** @ORM\Column(type="string", name="role_id") */
    protected $role_id;

    /** @param User|null */
    public function getRoleId() {
       return $this->role_id;
    }
}

我的管理控制器::

public function usersAction() {
   $em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
   $userFunctions = new UserFunction($em);
   $userArray = $userFunctions->getUsers();
   $viewModel = new ViewModel(array('users' => $userArray));
   return $viewModel;
}

这调用了我的 UserFunctions 类::

public function getUsers()
{
    //This function returns the users
    return $this->em->getRepository('Administration\Entity\User')->findAll();
}

在我看来,我列出的数据如下:

<?php
    foreach ($this->users AS $user) {
?>
<tbody>
<tr class="odd gradeX">
    <td width="5%"><?php  echo $user->getUserId(); ?></td>
    <td><?php echo $user->getName(); ?></td>
    <td><?php echo $user->getEmail(); ?></td>
    <td class="center">*** HOW DO I SHOW THE ROLE ?? ***</td>
    <td>Edit</td>
</tr>
<?php } ?>

如何获取要在视图中显示的角色?

【问题讨论】:

标签: orm doctrine-orm zend-framework2


【解决方案1】:

您必须在实体定义中定义用户和角色之间的正确关系。 我不确定你为什么在这里使用链接器表。您是否真的想在用户和角色之间建立多对多关系(每个用户都可以有多个角色?)。 如果不是,您可以轻松地将角色 ID 移动到用户表中,然后在用户和角色之间定义 ManyToOne 关系。

您的用户表将如下所示:

-------------------------------------------
|user_id | name | email   | role_id       |
-------------------------------------------
| 1      | John | j@b.com | administrator |
-------------------------------------------
| 2      | Bob  | b@j.com | staff         |
-------------------------------------------

我建议以用户为拥有方查看ManyToOne。您可以在the Doctrine2 documentationthe Doctrine2 documentation

中检查如何在实体定义中正确定义单向多对一关系

之后,您可以在视图中简单地调用$user-&gt;getRole();...

编辑

使用连接表修复一对多的答案:

这在doctrine documentation here...中也有描述

你需要三张桌子;一个用户表、一个角色表和一个用户角色链接器表 用户是实体,角色是实体,角色链接器表在您的情况下不是实体。您应该删除该实体,链接器表仅用于连接数据库中的用户和角色。

用户表

---------------------------
|id      | name | email   |
---------------------------
| 1      | John | j@b.com |
---------------------------
| 2      | Bob  | b@j.com |
---------------------------

角色表

-----------------
| id            |
-----------------
| administrator |
-----------------
| staff         |
-----------------
| guest         |
-----------------
| another role  |
-----------------

链接器表

--------------------------
|user_id | role_id       |
--------------------------
| 1      | administrator |
--------------------------
| 2      | staff         |
--------------------------

在您的用户实体中:

/** ONE-TO-MANY UNIDIRECTIONAL, WITH JOIN TABLE ONLY WORK WITH MANY-TO-MANY ANNOTATION AND A UNIQUE CONSTRAINT
  * @ORM\ManyToMany(targetEntity="Administration\Entity\Role")
  * @ORM\JoinTable(name="user_role_linker",
  *      joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
  *      inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id", unique=true)}
  *      )
  */
protected $roles;

/**
 * Get roles.
 *
 * @return ArrayCollection
 */
public function getRoles()
{
    return $this->roles;
}

/**
 * Add a role to the user.
 *
 * @param Role $role
 *
 * @return User
 */
public function addRole(Role $role)
{
    $this->roles[] = $role;

    return $this;
}

/**
 * Remove a role from the user
 *
 * @param Role $role
 *
 * @return User
 */
public function removeRole(Role $role)
{
    $this->roles->removeElement($role);

    return $this;
}

你的角色实体:

/**
 * An example entity that represents a role.
 *
 * @ORM\Entity
 * @ORM\Table(name="role")
 * @property string $id
 */
class Role
{
    /**
     * @var string
     * @ORM\Id
     * @ORM\Column(type="string", length=255, unique=true, nullable=false)
     */
    protected $id;

    /**
     * Get the id.
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }
}

我认为这应该可以帮助您解决它...

也许您应该将以下内容添加到您的应用程序模块中:

public function doctrineValidate(MvcEvent $event){
    $application = $event->getParam('application');
    $serviceManager = $application->getServiceManager();
    $entityManager = $serviceManager->get('doctrine.entitymanager.orm_default');
    $validator = new SchemaValidator($entityManager);
    $errors = $validator->validateMapping();
    if (count($errors) > 0) {
        // Lots of errors!
        var_dump($errors);
    }
}

然后在引导中:

$eventManager->attach('dispatch', array($this, 'doctrineValidate'));

在模块中: Doctrine 将通过检查您的实体定义来帮助您。它可能会提前告诉您实体定义中有问题...

【讨论】:

    【解决方案2】:

    这令人困惑,但正如您在实体中定义的那样,您可以使用 User 实体 getRoleId 的函数获取角色集合。然后,对于每个 UserRoleLinker 实体,您必须再次使用 getRoleId 函数,该函数将返回“Administrator”或“Staff”字符串。循环示例:

    $roles = $user->getRoleId();
    
    foreach ( $roles as $role ) {
        $roleId = $role->getRoleId();
    }
    

    我建议你换一种方式。一个实体应该是User,具有一个名为roles 的属性。另一方面,您可以拥有实体 Role。它们之间的链接应该是One-To-Many, Unidirectional with Join Table(即 user_role_linker 表)。

    【讨论】:

    • 我已尝试使用您的建议使其正常工作,请查看我添加的答案...收到一些不寻常的通知,对象也没有获得所需的信息。
    【解决方案3】:

    正如 lluisaznar 所建议的(虽然我需要多对一的关系,因为每个用户只有一个角色)。

    我正在尝试以下方法:

    <?php
        namespace Administration\Entity;
        //use stuff
    
        /** @ORM\Entity */
    
        class User {
            /**
             * @ORM\Id
             * @ORM\GeneratedValue(strategy="AUTO")
             * @ORM\Column(type="integer",name="user_id")
             */
    
            //setters getters
    
    /**
     * @ManyToOne(targetEntity="Role")
     * @JoinColumn(name="user_id", referencedColumnName="id")
     */
            private $role;
    
            public function __construct()
            {
                $this->role = new ArrayCollection();
            }
    
            /** @return Collection */
            public function getRoleId()
            {
                return $this->role;
            }
    
        }
    

    以及角色实体:

    <?php
    namespace Administration\Entity;
    use Doctrine\ORM\Mapping as ORM;
    
    /** @ORM\Entity */
    class Role {
        /**
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         * @ORM\Column(type="integer",name="user_id")
         */
        protected $user_id;
    
        /** @ORM\Column(type="string", name="role_id") */
        protected $role;
    
        /** @param User|null */
        public function getRoleId() {
           return $this->role;
        }
    
    
    }
    

    当我运行它时,我会收到以下通知:

    Notice: Undefined index: id in trunk/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 2611
    

    Notice: Undefined index: user_id in trunk/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php on line 121
    

    角色也没有被显示,当我将 $user 对象转储到角色下时,我得到了这个:

     private 'role' => 
        object(DoctrineORMModule\Proxy\__CG__\Administration\Entity\Role)[609]
          public '__initializer__' => 
            object(Closure)[595]
          public '__cloner__' => 
            object(Closure)[596]
          public '__isInitialized__' => boolean false
          protected 'user_id' => null
          protected 'role' => null
    

    【讨论】:

    • 如果您有ManyToOne 关系,则不需要链接器表。删除链接器表并将role_id 列添加到您的用户表。查看我的答案了解更多详情。
    • 是的 - 这是我通常会做的事情。不幸的是,链接器表是 BjyAuthorize / ZFCUser 的一部分,并且每次更新第三方模块时都无法在不请求麻烦的情况下将其删除。通常我会做一个简单的 sql 连接,而不会三思而后行……似乎 ORM 中的一个简单连接需要火箭科学的 PHD! :)
    • 没有一个简单的连接只是一个简单的连接:) 如果我今天晚些时候有时间我会看看你的代码并帮助你。现在问题出在哪里?还是同样的问题?
    • 谢谢威尔特,将不胜感激。我可以通过标准实体访问数据库。我苦苦挣扎的地方是如何连接两个表(例如上面的)并将所需的信息返回到视图。理想情况下,我想在其中添加分页,但是我认为在考虑分页之前我需要先了解连接。
    • 成功了吗?
    猜你喜欢
    • 2023-01-26
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 2013-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多