将新用户保存到数据库


persisting a new user to the db

我知道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 接口。

setRolessetUsers方法而言,这是一个简单的事情:

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