我知道FOSuserbundle的可用性,但为了帮助学习symfony2,我决定尝试使用book/cookbook从头开始创建所有内容。
在遵循有关安全性的说明书教程后,我在弄清楚如何将新用户持久保存到数据库中时遇到了问题。 我有其他一切正常,登录,防火墙安全域,密码加密等
当我尝试添加用户时,出现以下错误:
属性"roles"和方法之一"addRol(("/"removeRol((","addRole(("/"removeRole((","setRoles((","roles((","__set(("或"__call(("都不存在,并且在类"Ampisoft''Bundle''etrackBundle''Entity''users"中具有公共访问权限
我注意到 users()
类没有 setRoles 方法,但我不确定如何添加一个,因为它需要使用数组对象(? 让我感到困惑的另一件事是,即使成员roles
,该错误也没有突出显示addRole()
(而不是addRoles
方法(。
我的代码如下:
用户实体类(它有很多,所以这些只是我认为重要的部分
class users implements AdvancedUserInterface, 'Serializable
{
// ......
/**
* @ORM'ManyToMany(targetEntity="roles", inversedBy="users")
*
*/
private $roles;
/**
* @inheritDoc
*/
public function getRoles()
{
return $this->roles->toArray();
}
/**
* Add roles
*
* @param 'Ampisoft'Bundle'etrackBundle'Entity'roles $roles
* @return users
*/
public function addRoles(roles $roles)
{
$this->roles[] = $roles;
return $this;
}
// ......
}
角色实体类(再次,相关部分(
class roles implements RoleInterface
{
// .........
/**
* @ORM'ManyToMany(targetEntity="users", mappedBy="roles")
*/
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
/**
* Add users
*
* @param 'Ampisoft'Bundle'etrackBundle'Entity'users $user
* @return roles
*/
public function addUser(users $user)
{
$this->users[] = $user;
return $this;
}
// .........
}
控制器
public function admin_new_userAction()
{
$user = new users();
$form = $this->createForm(new usersType(), $user);
$request = $this->getRequest();
// if form is posted
if ($request->getMethod() === 'POST') {
$form->bind($request);
$user->setSalt(md5(time()));
$encoder = $this->container->get('security.encoder_factory')->getEncoder($user); //get encoder for hashing pwd later
$tempPassword = $encoder->encodePassword($user->getPassword(), $user->getSalt());
$user->setPassword($tempPassword);
// flush to db
$em = $this->getDoctrine()->getEntityManager();
$em->persist($user);
$em->flush();
return $this->redirect($this->generateUrl('admin_users'));
}
// BUILD FORM
return $this->render('etBundle:Admin:new_user.html.twig', array(
'form' => $form->createView(),
));
}
usersType 类(我计划用它来编辑用户以及监听器(
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$user = $event->getData();
$form = $event->getForm();
// check if the User object is "new"
if (!$user || null === $user->getId()) {
$form->add('username', 'text');
$form->add('firstname', 'text');
$form->add('lastname', 'text');
$form->add('password', 'repeated', array(
'type' => 'password',
'invalid_message' => 'The password fields must match.',
'options' => array('attr' => array('class' => 'password-field')),
'required' => false,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password'),
));
$form->add('email', 'repeated', array(
'type' => 'email',
'invalid_message' => 'The email address fields must match.',
'options' => array('attr' => array('class' => 'email-field')),
'required' => true,
'first_options' => array('label' => 'Email'),
'second_options' => array('label' => 'Repeat Email'),
));
$form->add('email', 'repeated', array(
'type' => 'email',
'invalid_message' => 'The email address fields must match.',
'options' => array('attr' => array('class' => 'email-field')),
'required' => true,
'first_options' => array('label' => 'Email'),
'second_options' => array('label' => 'Repeat Email'),
));
$form->add('lastLogged', 'hidden');
$form->add('roles', 'entity', array(
'class' => 'etBundle:roles',
'property' => 'name',
));
} else {
$form->add('id', 'hidden');
$form->add('username', 'text');
$form->add('firstname', 'text');
$form->add('lastname', 'text');
$form->add('password', 'repeated', array(
'type' => 'password',
'invalid_message' => 'The password fields must match.',
'options' => array('attr' => array('class' => 'password-field')),
'required' => false,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password'),
));
$form->add('email', 'repeated', array(
'type' => 'email',
'invalid_message' => 'The email address fields must match.',
'options' => array('attr' => array('class' => 'email-field')),
'required' => true,
'first_options' => array('label' => 'Email'),
'second_options' => array('label' => 'Repeat Email'),
));
}
});
我看到roles()
类中有一个addUser
方法,但我不确定如何使用它。如果有人能为我指出正确的方向,我将不胜感激。
更新 1**
我尝试在上面插入建议的 setRoles(( 方法,现在我收到以下内容 error: Catchable Fatal Error: Argument 1 passed to Doctrine'Common'Collections'ArrayCollection::__construct() must be of the type array, object given, called in C:'Dropbox'xampp'htdocs'etrack3'vendor'doctrine'orm'lib'Doctrine'ORM'UnitOfWork.php on line 555 and defined
更新 2**修复了此问题:意识到我的用户/角色实体之间存在多对多/多对多关系。 改为多对一/一对多,一切都很好。
您的class users
缺少其构造函数,该构造函数将 $roles
属性初始化为 ArrayCollection
实例。我还建议您不要使用$this->users[]
表示法,而赞成将这些属性视为它们的真实情况:
$this->users->add($user);
至于你得到的错误,这取决于Doctrine如何加载其实体。该错误显示了 doctrine 在实体类中查找的内容,以便设置属性:要么 roles
属性应该是公共的,要么你需要一个名称看起来像 set<ucfirst-name-of-table-field>
的方法,或者一个慢速的魔术 getter/setter 接口。
就setRoles
和setUsers
方法而言,这是一个简单的事情:
public function setRoles($roles)
{
$this->roles = $roles;
return $this;
}
使用添加类型提示的选项:
public function setRoles( ArrayCollection $roles)
{
$this->roles = $roles;
return $this;
}
我想提一下其他一些问题:
编码标准很重要,请在此处查看最常用的标准。Doctrine, Symfony2, ZendFW2, ...所有主要参与者都同意这些标准,您也应该如此。例如,类名以大写字符开头,因此class users
应该变为class Users
等等......
我还建议不要在学说实体上实现Serializable
接口,特别是如果您使users
可序列化,其中可能包含Roles
实例,这不会实现Serializable
。