2016-12-20 13 views
1

Doctrineを使用して、1対多データベースを設定しようとしています。 1人のユーザーは複数のロールを持つことができます。ユーザーを取得すると、関連するロールを取得したいと考えています。私はそれを行う生のMySQLクエリを持っています。DoctrineへのMySQLクエリの移植

SELECT 
    u.*, 
    GROUP_CONCAT(r.role) as roles 
FROM 
    users u 
    INNER JOIN user_roles ur ON ur.user_id = u.id 
    INNER JOIN roles r ON r.id = ur.role_id 
GROUP BY id; 

+----+----------+------------------------+--------------------------------------------------------------+-----------+----------------------+ 
| id | username | email     | password              | is_active | GROUP_CONCAT(r.role) | 
+----+----------+------------------------+--------------------------------------------------------------+-----------+----------------------+ 
| 1 | admin | [email protected]  | $2a$08$jHZj/wJfcVKlIwr5AvR78euJxYK7Ku5kURNhNx.7.CSIJ3Pq6LEPC |   1 | ROLE_USER,ROLE_ADMIN | 
+----+----------+------------------------+--------------------------------------------------------------+-----------+----------------------+ 

これは実際にDoctrineで自動的に複製できるものですか?もしそうなら、私はどこが間違っているのですか?ここに私の現在の(壊れた)クラス(コードダンプに対する謝罪)があります。

これが現在ログインしているエラーは次のとおりです。

[2016-12-20 12:01:35] security.INFO: Authentication request failed. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\Auth 
enticationServiceException(code: 0): Notice: Undefined index: user at /var/www/vendor/symfony/symfony/src/Symfony/Component/Security/Core/Authe 
ntication/Provider/DaoAuthenticationProvider.php:94, Symfony\\Component\\Debug\\Exception\\ContextErrorException(code: 0): Notice: Undefined in 
dex: user at /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:1768)"} [] 

User.php

<?php 
namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Security\Core\User\UserInterface; 
use Doctrine\Common\Collections\ArrayCollection; 

/** 
* @ORM\Table(name="users") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository") 
*/ 
class User implements UserInterface, \Serializable 
{ 

    ... 

    /** 
    * @var \Doctrine\Common\Collections\ArrayCollection 
    * 
    * @ORM\OneToMany(targetEntity="UserRoles", mappedBy="user", fetch="EAGER") 
    */ 
    private $roles; 


    public function __construct() 
    { 
     $this->isActive = true; 
     // may not be needed, see section on salt below 
     // $this->salt = md5(uniqid(null, true)); 

     $this->roles = new ArrayCollection(); 
    } 

    ... 

    public function getRoles() 
    { 
     return $this->roles; 
    } 
    /** 
    * Add role 
    * 
    * @param \AppBundle\Entity\UserRoles $role 
    * 
    * @return User 
    */ 
    public function addRole(\AppBundle\Entity\UserRoles $role) 
    { 
     $this->roles[] = $role; 

     return $this; 
    } 

    /** 
    * Remove role 
    * 
    * @param \AppBundle\Entity\UserRoles $role 
    */ 
    public function removeRole(\AppBundle\Entity\UserRoles $role) 
    { 
     $this->roles->removeElement($role); 
    } 
} 

Role.php

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* Role 
* 
* @ORM\Table(name="roles") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\RoleRepository") 
*/ 
class Role 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="role", type="string", length=255, unique=true) 
    */ 
    private $role; 


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

    /** 
    * Set role 
    * 
    * @param string $role 
    * 
    * @return Role 
    */ 
    public function setRole($role) 
    { 
     $this->role = $role; 

     return $this; 
    } 

    /** 
    * Get role 
    * 
    * @return string 
    */ 
    public function getRole() 
    { 
     return $this->role; 
    } 
} 

UserRoles.php

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 

/** 
* UserRoles 
* 
* @ORM\Table(name="user_roles") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRolesRepository") 
*/ 
class UserRoles 
{ 

    /** 
    * @ORM\Column(type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 


    /** 
    * @var int 
    * 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="userroles") 
    * @ORM\JoinColumn(name="user_id", referencedColumnName="id") 
    */ 
    private $userId; 

    /** 
    * @var int 
    * 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Role") 
    * @ORM\JoinColumn(name="role_id", referencedColumnName="id") 
    */ 
    private $roleId; 


    /** 
    * Set userId 
    * 
    * @param integer $userId 
    * 
    * @return UserRoles 
    */ 
    public function setUserId($userId) 
    { 
     $this->userId = $userId; 

     return $this; 
    } 

    /** 
    * Get userId 
    * 
    * @return int 
    */ 
    public function getUserId() 
    { 
     return $this->userId; 
    } 

    /** 
    * Set roleId 
    * 
    * @param integer $roleId 
    * 
    * @return UserRoles 
    */ 
    public function setRoleId($roleId) 
    { 
     $this->roleId = $roleId; 

     return $this; 
    } 

    /** 
    * Get roleId 
    * 
    * @return int 
    */ 
    public function getRoleId() 
    { 
     return $this->roleId; 
    } 

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

答えて

1

Userエンティティ内の$rolesの関連ではにmappedBy属性を設定しますが、UserRolesエンティティにはこのようなフィールドはありません。代わりにuserIdというフィールドがあります。 Doctrineはあなたのマッピングを使って関連付けを見つけようとします。

未定義のインデックス...あなたがオブジェクトをマッピングしているので

あなたUserRoles内の命名規則を再考する必要がありますあなたの@mappedBy属性からuser値は、データベース内で、したがって、エラーメッセージを見つけることができませんエンティティ。 $userId$roleIdを使用せず、単にUserRoleを使用し、セッターとゲッターの中の依存性注入と戻り値をUserRoleクラスに合わせてください。

UserRolesはエンティティでありコレクションではないため、UserRole(単数)に改名することをお勧めします。あなたが持っているものを理解するのに役立ちます。

スタート、このようなあなたのUserRolesを変更すると:

<?php 

namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use AppBundle\Entity\User; 
use AppBundle\Entity\Role; 

/** 
* UserRole 
* 
* @ORM\Table(name="user_roles") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRoleRepository") 
*/ 
class UserRole 
{ 
    /** 
    * @ORM\Column(type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var User 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="userRoles") 
    * @ORM\JoinColumn(name="user_id", referencedColumnName="id") 
    */ 
    private $user; 

    /** 
    * @var Role 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Role") 
    * @ORM\JoinColumn(name="role_id", referencedColumnName="id") 
    */ 
    private $role; 

    /** 
    * Set user 
    * 
    * @param User $user 
    * @return UserRole 
    */ 
    public function setUser(User $user) 
    { 
     $this->user = $user; 

     return $this; 
    } 

    /** 
    * Get user 
    * 
    * @return User 
    */ 
    public function getUser() 
    { 
     return $this->user; 
    } 

    /** 
    * Set role 
    * 
    * @param Role $role 
    * @return UserRole 
    */ 
    public function setRole(Role $role) 
    { 
     $this->role = $role; 

     return $this; 
    } 

    /** 
    * Get role 
    * 
    * @return Role 
    */ 
    public function getRole() 
    { 
     return $this->role; 
    } 

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

し、それに応じて、これらの変更に合わせてUserエンティティを変更:あなたのUserクラスのリポジトリがUserRepositoryと呼ばれているので

<?php 
namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Symfony\Component\Security\Core\User\UserInterface; 
use Doctrine\Common\Collections\ArrayCollection; 
use AppBundle\Entity\UserRole; 
use Serializable; 

/** 
* @ORM\Table(name="users") 
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository") 
*/ 
class User implements UserInterface, Serializable 
{ 
    ... 

    /** 
    * @var ArrayCollection 
    * 
    * @ORM\OneToMany(targetEntity="UserRole", mappedBy="user", fetch="EAGER") 
    */ 
    private $userRoles; 

    public function __construct() 
    { 
     $this->isActive = true; 
     // may not be needed, see section on salt below 
     // $this->salt = md5(uniqid(null, true)); 

     $this->userRoles = new ArrayCollection(); 
    } 

    ... 

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

    /** 
    * Add user role 
    * 
    * @param UserRole $userRole 
    * 
    * @return User 
    */ 
    public function addUserRole(UserRole $userRole) 
    { 
     $this->userRoles[] = $userRole; 

     return $this; 
    } 

    /** 
    * Remove role 
    * 
    * @param UserRole $userRole 
    */ 
    public function removeUserRole(UserRole $userRole) 
    { 
     $this->userRoles->removeElement($userRole); 
    } 
} 

を私はまた、 UserRolesRepositoryからUserRoleRepository(単数)に変更されました。

+0

ありがとうございます!これでエラーが分類され、ユーザーのすべての役割を取得できるようになりました。私は、このようなUserInterfaceのための 'getRoles()'メソッドを実装しなければなりませんでした。http://pastebin.com/CdbY7PGZこれは適切な方法でしょうか、これを行うより良い方法がありますか? –

+0

@TomHartあなたが 'User'ロールのためにあなたの' Role'エンティティだけを使用するなら、所有サイドとして 'User'との多対多の関係を作成することも考えられます。そのような場合、 'UserRole'エンティティ全体を削除することができます。あなたのペーストビンのコードはうまく見えますが、コレクションを直接反復できるはずなので、 'toArray'パーツをスキップすることができます。 – Wilt

+0

さて、 'toArray'を使わずに試してみるつもりです。多対多の関係について、いくつかの研究をして、どうすればそれを使うことができるでしょうか。ありがとう:) –

関連する問題