ZF2 - Doctrine ORM,简单表加入

时间:2014-05-05 08:40:35

标签: orm doctrine-orm zend-framework2

我目前正在学习如何将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 } ?>

如何抓住要在视图中显示的角色?

3 个答案:

答案 0 :(得分:0)

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

您的用户表将如下所示:

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

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

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

之后,您只需在视图中拨打$user->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);
    }
}

然后在bootstrap:

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

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

答案 1 :(得分:0)

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

$roles = $user->getRoleId();

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

我建议你以另一种方式做。一个实体应为用户,并具有名为角色的属性。另一方面,您可以拥有实体角色。它们之间的链接应为One-To-Many, Unidirectional with Join Table user_role_linker 表)。

答案 2 :(得分:0)

正如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