我实际上是在 Symfony2 中开发一个应用程序。我已经建立了一个具有不同角色的身份验证工作系统,根据官方文档的建议设置我的表结构:http: //symfony.com/doc/current/cookbook/security/entity_provider.html
我有两个页面,使用表单允许我创建一个新用户并编辑现有用户,现在我需要实现一个表单字段(选择)来选择与用户关联的角色。 无论如何,由于这种结构,我发现了一些困难:
这是我对 \Entity\User.php 的 ORM 定义
<?php
namespace Acme\MyBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
* @ORM\Table(name="Users")
*/
class User implements UserInterface, AdvancedUserInterface, \Serializable
{
// Definizione campi
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", unique=true)
*/
protected $username;
/**
* @ORM\Column(type="string")
*/
protected $password;
/**
* @ORM\Column(type="string")
*/
protected $salt;
/**
* @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
*
*/
private $roles;
/**
* @ORM\Column(type="integer", nullable=true)
*/
protected $idAnagrafica;
/**
* @ORM\Column(type="integer", nullable=true)
*/
protected $idTipoVisita;
/**
* @ORM\Column(type="boolean", nullable=true)
*/
protected $attivo;
// Definizioni delle funzioni Get
/**
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* @return string
*/
public function getPassword()
{
return $this->password;
}
/**
* @return string
*/
public function getSalt()
{
if (null === $this->salt)
{
$this->salt = sha512(sprintf('%s_%d_%f',uniqid(),rand(0, 99999),microtime(true)));
}
return $this->salt;
}
/**
* @return array
*/
public function getRoles()
{
return $this->roles->toArray();
}
/**
* @return integer
*/
public function getIdRole()
{
return $this->idRole;
}
/**
* @return integer
*/
public function getIdAnagrafica()
{
return $this->idAnagrafica;
}
/**
* @return integer
*/
public function getIdTipoVisita()
{
return $this->idTipoVisita;
}
/**
* @return boolean
*/
public function getAttivo()
{
return $this->attivo;
}
// Funzioni di servizio
public function __construct()
{
$this->roles = new ArrayCollection();
}
/**
* @see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array($this->id,));
}
/**
* @see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list ($this->id,) = unserialize($serialized);
}
// Definizione delle funzioni Set
/**
* @return void
*/
public function eraseCredentials()
{
$this->roles = null;
}
/**
* Set username
*
* @param string $username
* @return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set password
*
* @param string $password
* @return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set salt
*
* @param string $salt
* @return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Set idAnagrafica
*
* @param integer $idAnagrafica
* @return User
*/
public function setIdAnagrafica($idAnagrafica)
{
$this->idAnagrafica = $idAnagrafica;
return $this;
}
/**
* Set riferimento idTipoVisita
*
* @param integer $idTipoVisita
* @return User
*/
public function setIdTipoVisita($idTipoVisita)
{
$this->idTipoVisita = $idTipoVisita;
return $this;
}
/**
* Set attivo
*
* @param boolean $attivo
* @return User
*/
public function setAttivo($attivo)
{
$this->attivo = $attivo;
return $this;
}
// Funzioni advance user interface
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->attivo;
}
/**
* Add roles
*
* @param \Acme\MyBundle\Entity\Role $roles
* @return User
*/
public function addRole(\Acme\MyBundle\Entity\Role $roles)
{
$this->roles[] = $roles;
return $this;
}
/**
* Remove roles
*
* @param \Acmee\MyBundle\Entity\Role $roles
*/
public function removeRole(\Acme\MyBundle\Entity\Role $roles)
{
$this->roles->removeElement($roles);
}
}
在数据库中报告如下:
ID | USERNAME | PASSWORD | ATTIVO | SALT | IDANAGRAFICA | IDTIPOVISITA
----------------------------------------------------------------------
...| ... | ... | ... | ... | ... | ...
这是我对 \Entity\Role.php 的 ORM 定义
<?php
namespace Acme\MyBundle\Entity;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* @ORM\Entity
* @ORM\Table(name="roles")
*/
class Role implements RoleInterface
{
// Definizione campi
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id()
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="name", type="string")
*/
private $name;
/**
* @ORM\Column(name="role", type="string", unique=true)
*/
private $role;
/**
* @ORM\ManyToMany(targetEntity="User", mappedBy="roles")
*/
private $users;
// Funzioni di servizio
public function __construct()
{
$this->users = new ArrayCollection();
}
// Funzioni di tipo Get
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @see RoleInterface
*/
public function getRole()
{
return $this->role;
}
/**
* Set role
*
* @param string $role
* @return Role
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Set name
*
* @param string $name
* @return Role
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
}
在数据库中报告如下:
ID | NAME | ROLE
----------------
...| ... | ...
此外,ORM 命令会为我自动生成(无需在我的实体文件夹中编写自定义类)表 user_roles,它为我管理用户和角色之间的关系。
ID_USER | ID_ROLE
-----------------
... | ...
这是我的表格:
<?php
// src/Acme/MyBundle/Form/Type/UserType.php
namespace Acme\MyBundle\Form\Type;
use Acme\MyBundle\Entity\User;
use Acme\MyBundle\Entity\Role;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;
class UserType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('data_class' => 'Acme\MyBundle\Entity\User', 'Acme\MyBundle\Entity\Role'));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Crezione del form
$builder->add('username', 'text', array('label' => 'Username: ', 'required' => false));
$builder->add('password', 'repeated', array('first_name' => 'password', 'second_name' => 'confirm', 'type' => 'password'));
$builder->add('attivo', 'checkbox', array('label' => 'Attivo', 'required' => false));
$builder->add('idTipoVisita', 'choice', array('choices' => array('1' => 'Fisiatra', '2' => 'Genetista'), 'required' => false));
// $builder->add( ***I NEED TO INSERT HERE THE DROPODOWN FIELD TO SELECT THE ROLE*** );
$builder->add('save', 'submit');
$builder->add('annulla', 'submit');
}
public function getName()
{
return 'user';
}
}
这是我的控制器:
<?php
// src/Acme/MyBundle/Controller/UserController.php
namespace Acme\MyBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Acme\MyBundle\Form\Type\UserType;
use Acme\MyBundle\Entity\User;
class UserController extends Controller
{
// Funzione per la modifica dei dati dell utente
public function editAction($id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('AcmeMyBundle:User')->find($id);
$form = $this->createForm(new UserType(), $user );
if (!$user) { throw $this->createNotFoundException('Non esiste nessun utente associato a questo id.'); }
if ($request->isMethod('POST'))
{
$form->bind($request);
// Gestione bottone Annulla
if ($form->get('annulla')->isClicked())
{
return $this->redirect($this->generateUrl('AcmeMyBundle_showAnag', array('id' => $anagrafica->getId())));
}
if ($form->isValid())
{
$user = $form->getData();
$user->setSalt(md5(uniqid()));
$encoder = $this->container
->get('security.encoder_factory')
->getEncoder($user);
$user->setPassword($encoder->encodePassword($user->getPassword(), $user->getSalt()));
$em->persist($user);
$em->flush();
return $this->redirect($this->generateUrl('AcmeMyBundle_showAnag', array('id' => $user->getIdAnagrafica($id))));
}
}
return $this->render('AcmeMyBundle:User:edit.html.twig', array('form' => $form->createView(),'user' => $user));
}
// Funzione per la creazione di un nuovo utente
public function newAction($id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$anagrafica = $em->getRepository('AcmeMyBundle:Anagrafiche')->find($id);
if (!$anagrafica) { throw $this->createNotFoundException('Non esiste nessuna anagrafica associata a questo id.'); }
$query = $em->getRepository('AcmeMyBundle:User')->createQueryBuilder('p')
->where('p.idAnagrafica = :id')
->setParameter('id', $id)
->getQuery();
$user = $query->getOneOrNullResult();
if ($user)
{
throw $this->createNotFoundException('Non puoi accedere a questa pagina perchè esiste già un utente associato a questo id anagrafica.');
}
$form = $this->createForm(new UserType(), new User() );
if ($request->isMethod('POST'))
{
$form->bind($request);
// Gestione bottone Annulla
if ($form->get('annulla')->isClicked())
{
return $this->redirect($this->generateUrl('AcmeMyBundle_showAnag', array('id' => $anagrafica->getId())));
}
if ($form->isValid())
{
$user = $form->getData();
$user->setSalt(md5(uniqid()));
$encoder = $this->container
->get('security.encoder_factory')
->getEncoder($user);
$user->setPassword($encoder->encodePassword($user->getPassword(), $user->getSalt()));
$user->setIdAnagrafica($id);
$em->persist($user);
$em->flush();
return $this->redirect($this->generateUrl('AcmeMyBundle_showAnag', array('id' => $user->getIdAnagrafica($id))));
}
}
return $this->render('AcmeMyBundle:User:new.html.twig', array('form' => $form->createView(),'anagrafica' => $anagrafica));
}
// Funzione per la selezione della modifica o della creazione di un nuovo record
public function selectAction($id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$anagrafica = $em->getRepository('AcmeMyBundle:Anagrafiche')->find($id);
if (!$anagrafica) { throw $this->createNotFoundException('Non esiste nessuna anagrafica associata a questo id.'); }
$query = $em->getRepository('AcmeMyBundle:User')->createQueryBuilder('p')
->where('p.idAnagrafica = :id')
->setParameter('id', $id)
->getQuery();
$user = $query->getOneOrNullResult();
if ($user)
{
return $this->redirect($this->generateUrl('AcmeMyBundle_editUser', array('id' => $user->getId())));
}
else
{
return $this->redirect($this->generateUrl('AcmeMyBundle_newUser', array('id' => $id)));
}
return NULL;
}
}
1)我的表单映射在 User.php 实体上,我不知道如何添加一个引用另一个实体(Role.php)的表单字段,不同于默认的 'data_class'。
2)另一个问题是我需要提取一个字符串数组(角色的人类可读名称)以在我的下拉菜单中显示选项,但我需要在数据库中插入相关的 id 而不是字符串。我怎样才能做到这一点?我有没有做过这样的事情:http ://symfony.com/doc/current/cookbook/form/data_transformers.html ?
3)我认为表单字段实例(下拉列表)不允许我在我的数据库中自动插入带有 2 个字段的新记录(关联 ID_USER 和 ID_ROLE)。使这成为可能的最佳方法是什么?我想我需要从我的下拉字段中提取值并在控制器中构建一个查询,但我该怎么做呢?
非常感谢您的建议,问候。