Я знаю о доступности FOSuserbundle, но для того, чтобы помочь узнать symfony2, я решил попытаться создать все с нуля, используя книгу/поваренную книгу.
После выполнения учебников по кулинарной книге для обеспечения безопасности у меня возникли проблемы с разработкой того, как сохранить нового пользователя в базе данных. У меня все работает нормально, логины, домены безопасности брандмауэра, шифрование паролей и т.д.
Когда я пытаюсь добавить пользователя, я получаю следующую ошибку:
Ни свойства "роли", ни один из методов "addRol()"/"removeRol()", "addRole()"/"removeRole()", "setRoles()", "role()", "__set ( ) "или" __call() "существуют и имеют открытый доступ в классе" Ampisoft\Bundle\etrackBundle\Entity\users "
Я заметил, что класс users()
не имеет метода setRoles, но я не уверен, как его добавить, поскольку он должен использовать объект массива (?). другое, что меня addRole()
заключается в том, что ошибка не addRoles
метод addRole()
(а не addRoles
), хотя член является roles
.
мой код выглядит следующим образом:
класс сущностей пользователей (его довольно много, поэтому это только те разделы, которые, как мне кажется, важны
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'),
));
}
});
Я вижу, что в addUser
roles()
есть метод addUser
но Im unsure о том, как его использовать. Я был бы очень благодарен, если бы кто-то мог указать мне в правильном направлении.
** обновление 1 **
Я попытался вставить предложенный метод setRoles() выше, и теперь Im получает следующую 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
** update 2 ** исправлена эта проблема: поняли, что у меня было многосотовое/многоголовое отношение между моими пользователями/ролями. Изменено для ManyToOne/OneToMany, и все хорошо.
У ваших class users
отсутствует его конструктор, который инициализирует свойство $roles
ArrayCollection
экземпляром ArrayCollection
. Я бы также посоветовал вам использовать $this->users[]
, чтобы рассматривать эти свойства как то, что они на самом деле:
$this->users->add($user);
Что касается ошибки, которую вы получаете, то до того, как Doctrine загружает свои сущности. Ошибка показывает, что доктрина ищет в классе сущностей, для того, чтобы установить свойство: либо roles
собственность должна быть публичной, или вам нужен метод с именем, которое выглядит как set<ucfirst-name-of-table-field>
, или интерфейс медленной магии приемника/сеттера.
Что касается методов 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
Serializable, которые могут содержать экземпляры Roles
, которые не реализуют Serializable
.
__construct()
, я просто не показывал его, когда пытался сократить содержание страницы. Я внес изменения в имена классов, как это было предложено. Это было кое-что, что я узнал после того, как начал и был слишком ленив, чтобы исправить !! сделано сейчас. Я попытаюсь решить проблему, а затем доложу