my nightmare of a day continues.....
after implimenting a successful solution in an earlier thread where I need to alter my inter-entity relationships I am now getting this error when I try to log a user into the app:
CRITICAL - Uncaught PHP Exception Symfony\Component\Debug\Exception\UndefinedMethodException: "Attempted to call method "getRole" on class "Closure"." at C:\Dropbox\xampp\htdocs\etrack3\src\Ampisoft\Bundle\etrackBundle\Entity\Users.php line 234
I changed from a manyToMany relationship, to a manyToOne/OneToMany between a Users/Roles entity.
Ive read that serialize could cause the issue but Ive taken it out and it didnt make any difference. The remnants of the serialize required methods are still in there so please ignore (unless they are the issue).
Please could someone tell me what Ive done wrong? Im wondering if its best to scrap all the database tables and start again!!!!
here is the entity class.
/**
* user
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Ampisoft\Bundle\etrackBundle\Entity\UsersRepository")
*/
class Users implements UserInterface
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=25, unique=true)
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=64)
*/
private $password;
/**
* #ORM\Column(name="firstname", type="string", length=25)
*/
private $firstname;
/**
* #ORM\Column(name="surname", type="string", length=25)
*/
private $lastname;
/**
* #var boolean
*
* #ORM\Column(name="isActive", type="boolean")
*/
private $isActive = 1;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, unique=true)
*/
private $email;
/**
* #var \DateTime
*
* #ORM\Column(name="lastLogged", type="string")
*/
private $lastLogged = '-0001-11-30 00:00:00';
/**
* #var string;
*
* #ORM\Column(name="salt", type="string", length=255)
*/
private $salt;
/**
* #ORM\ManyToOne(targetEntity="Roles", inversedBy="users")
*
*/
private $roles;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set Id
*
* #return integer
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Set username
*
* #param string $username
* #return user
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set password
*
* #param string $password
* #return user
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set isActive
*
* #param boolean $isActive
* #return user
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* Set email
*
* #param string $email
* #return user
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set lastLogged
*
* #param \DateTime $lastLogged
* #return user
*/
public function setLastLogged($lastLogged)
{
$this->lastLogged = $lastLogged;
return $this;
}
/**
* Get lastLogged
*
* #return \DateTime
*/
public function getLastLogged()
{
return $this->lastLogged;
}
public function __construct()
{
$this->roles = new ArrayCollection();
$this->isActive = true;
}
/**
* #inheritDoc
*/
public function getRoles()
{
$roles = array();
foreach ($this->roles as $role) {
$roles[] = $role->getRole();
}
return $roles;
}
/**
* #param $roles
* #return $this
*/
public function setRoles($roles)
{
$this->roles = $roles;
return $this;
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #inheritDoc
*/
public function getSalt()
{
return $this->salt;
}
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* Add roles
*
* #param \Ampisoft\Bundle\etrackBundle\Entity\Roles $roles
* #return users
*/
public function addRoles(Roles $roles)
{
$this->roles[] = $roles;
return $this;
}
/**
* Remove roles
*
* #param \Ampisoft\Bundle\etrackBundle\Entity\Roles $roles
*/
public function removeRoles(Roles $roles)
{
$this->roles->removeElement($roles);
}
/**
* Set firstname
*
* #param string $firstname
* #return users
*/
public function setFirstname($firstname)
{
$this->firstname = $firstname;
return $this;
}
/**
* Get firstname
*
* #return string
*/
public function getFirstname()
{
return $this->firstname;
}
/**
* Set lastname
*
* #param string $lastname
* #return users
*/
public function setLastname($lastname)
{
$this->lastname = $lastname;
return $this;
}
/**
* Get lastname
*
* #return string
*/
public function getLastname()
{
return $this->lastname;
}
/**
* #see \Serializable::serialize()
*/
/**
* Serializes the content of the current User object
* #return string
*/
public function serialize()
{
return \json_encode(
array($this->username, $this->password, $this->salt,
$this->roles, $this->id));
}
/**
* Unserializes the given string in the current User object
* #param serialized
*/
public function unserialize($serialized)
{
list($this->username, $this->password, $this->salt,
$this->roles, $this->id) = \json_decode(
$serialized);
}
}
update 1
this has worked but produced a new error Im going to move it to a new question when the post timer lets me.
Catchable Fatal Error: Argument 4 passed to Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken::__construct() must be of the type array, object given, called in C:\Dropbox\xampp\htdocs\etrack3\vendor\symfony\symfony\src\Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider.php on line 96 and defined
HI I think what you want is not this
public function getRoles()
{
$roles = array();
foreach ($this->roles as $role) {
$roles[] = $role->getRole();
}
return $roles;
}
but this
public function getRoles()
{
return $this->roles;
}
Roles should be an ArrayCollection already, so calling getRole on the ( I assume ) Role class seems to be possible the issue.
If you are using an IDE such as Eclipse then the class is Doctrine\Common\Collections\ArrayCollection; this should be your collection of Roles, I would suggest also is you are using an IDE to do something like this ( for type hinting )
//... at the top of the class file before the class deceleration
use Doctrine\Common\Collections\ArrayCollection;
/**
* #param ArrayCollection $roles
*/
public function setRoles(ArrayCollection $roles)
{
//.. type cast the input to allow only use of ArrayCollection class
$this->roles = $roles;
}
/**
* #return ArrayCollection
*/
public function getRoles()
{
return $this->roles;
}
Also there is a good chance you are setting $this->roles to be a standard array at some point. You should always type cast your input to a specific class if it can only accept that type of class to rule out errors such as using a plain array.
Last thing, is generally protected for the properties are preferred because latter you can extend the class, it's not accessible outside the class much like private, but unlike private it is accessible in inheriting classes.
Related
I'm creating an app that keeps user scores in the database based on questions they solve. I have User, Problem and Submission entities. For all of them I have One-to-Many relationship from the User entity. The problem entity has the point field that holds the score of a problem. I'm trying to retrieve all users with their total points.
Here is my controller;
$userService = $this->container->get('userservice');
$users = $userService->findAll();
foreach ($users as $user){
$usersWPoints = $user->getSubmissions()->getProblemId()->getPoints;
}
However this returns the following error;
Attempted to call an undefined method named "getProblemId" of class "Doctrine\ORM\PersistentCollection".
Here are my models
User.php
/**
* Class User
* #package AppBundle\Entity
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* #ORM\Table(name="user")
* #ORM\HasLifecycleCallbacks()
* #UniqueEntity(fields="username", message="Email already taken")
*
*/
class User implements UserInterface
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=255, unique=true)
* #Assert\NotBlank(message="Please enter a valid email address")
* #Assert\Email()
*/
private $username;
/**
* #ORM\Column(type="string", length=255, unique=true)
* #Assert\NotBlank(message="Please enter a valid email address")
*/
private $usrname;
/**
* #Assert\NotBlank()
* #Assert\Length(max=4096)
*/
private $plainPassword;
/**
* The below length depends on the "algorithm" you use for encoding
* the password, but this works well with bcrypt.
*
* #ORM\Column(type="string", length=64)
*/
private $password;
/**
* #ORM\Column(type="string", length=255, unique=true)
* #Assert\NotBlank(message="Please enter a valid name")
*/
private $fullname;
/**
* #var array
* #ORM\Column(name="roles", type="json_array")
*/
protected $roles;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Problem", mappedBy="createdby")
*/
protected $problems;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Feed", mappedBy="createdby")
*/
protected $feeds;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Comment", mappedBy="createdby")
*/
protected $comments;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Submission", mappedBy="user_id")
*/
protected $submissions;
// other properties and methods
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
}
public function getPlainPassword()
{
return $this->plainPassword;
}
public function setPlainPassword($password)
{
$this->plainPassword = $password;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
}
public function getSalt()
{
// The bcrypt algorithm doesn't require a separate salt.
// You *may* need a real salt if you choose a different encoder.
return null;
}
// other methods, including security methods like getRoles()
/**
* #return array
*/
public function getRoles()
{
return $this->roles;
}
public function setRoles(array $roles){
$this->roles = $roles;
return $this;
}
/**
* #return mixed
*/
public function getFullname()
{
return $this->fullname;
}
/**
* #param mixed $fullname
*/
public function setFullname($fullname)
{
$this->fullname = $fullname;
}
/**
* #return mixed
*/
public function getUsrname()
{
return $this->usrname;
}
/**
* #param mixed $usrname
*/
public function setUsrname($usrname)
{
$this->usrname = $usrname;
}
/**
* Removes sensitive data from the user.
*
* This is important if, at any given point, sensitive information like
* the plain-text password is stored on this object.
*/
public function eraseCredentials()
{
}
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #return \Doctrine\Common\Collections\Collection
*/
public function getSubmissions()
{
return $this->submissions;
}
Problem.php
/**
* Class Problem
* #package AppBundle\Entity
* #ORM\Entity(repositoryClass="AppBundle\Repository\ProblemRepository")
* #ORM\Table(name="problem")
* #ORM\HasLifecycleCallbacks()
*
*/
class Problem
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=255, unique=True)
* #Assert\NotBlank(message="Please enter a valid title")
*/
protected $title;
/**
* #ORM\Column(type="string")
* #Assert\NotBlank(message="Please enter a valid description")
*/
protected $description;
/**
* #ORM\Column(type="string")
* #Assert\NotBlank(message="Please enter a valid value")
*/
protected $points;
/**
* #ORM\Column(type="string")
* #Assert\NotBlank(message="Please enter a valid flag")
*/
protected $flag;
/**
* #ORM\Column(type="string")
* #Assert\NotBlank(message="Please enter a valid value")
*/
protected $category;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="problems")
* #ORM\JoinColumn(name="createdby", referencedColumnName="id")
*/
protected $createdby;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Submission", mappedBy="problem_id")
*/
protected $submissions;
/**
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(type="string", length=255, unique=false,)
*/
protected $slug;
/**
* #return mixed
*/
public function getTitle()
{
return $this->title;
}
/**
* #param mixed $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* #return mixed
*/
public function getDescription()
{
return $this->description;
}
/**
* #param mixed $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* #return mixed
*/
public function getPoints()
{
return $this->points;
}
/**
* #param mixed $points
*/
public function setPoints($points)
{
$this->points = $points;
}
/**
* #return mixed
*/
public function getFlag()
{
return $this->flag;
}
/**
* #param mixed $flag
*/
public function setFlag($flag)
{
$this->flag = $flag;
}
/**
* #return mixed
*/
public function getCategory()
{
return $this->category;
}
/**
* #param mixed $category
*/
public function setCategory($category)
{
$this->category = $category;
}
/**
* #return mixed
*/
public function getCreatedby()
{
return $this->createdby;
}
/**
* #param mixed $createdby
*/
public function setCreatedby($createdby)
{
$this->createdby = $createdby;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set slug
*
* #param string $slug
*
* #return Problem
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* #return mixed
*/
public function getSubmissions()
{
return $this->submissions;
}
/**
* #param mixed $submissions
*/
public function setSubmissions($submissions)
{
$this->submissions = $submissions;
}
}
Submission.php
class Submission
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Problem", inversedBy="submissions")
* #ORM\JoinColumn(name="problem_id", referencedColumnName="id")
*/
protected $problem_id;
/**
* #ORM\Column(type="boolean")
*/
protected $correct = false;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="submissions")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user_id;
/**
* #ORM\Column(type="string")
* #Assert\NotBlank(message="Flag cannot be blank")
*/
protected $submission_flag;
/**
* #return mixed
*/
public function getProblemId()
{
return $this->problem_id;
}
/**
* #param mixed $problem_id
*/
public function setProblemId($problem_id)
{
$this->problem_id = $problem_id;
}
/**
* #return mixed
*/
public function getCorrect()
{
return $this->correct;
}
/**
* #param mixed $correct
*/
public function setCorrect($correct)
{
$this->correct = $correct;
}
/**
* #return mixed
*/
public function getUserId()
{
return $this->user_id;
}
/**
* #param mixed $user_id
*/
public function setUserId($user_id)
{
$this->user_id = $user_id;
}
/**
* #return mixed
*/
public function getSubmissionFlag()
{
return $this->submission_flag;
}
/**
* #param mixed $submission_flag
*/
public function setSubmissionFlag($submission_flag)
{
$this->submission_flag = $submission_flag;
}
}
Any suggestions on accessing each user and their total points would be highly appreciated.
getSubmissions() returns collenction and getProblemId() is method of Submissions.
So as soon as you have many Submissions fo each user - i would create some getTotalPoints() method for User where you can run in foreach.
This kind of way:
public function getTotalPoints()
{
$submissions = $this->getSubmissions();
$points = 0;
foreach ($submissions as $submission) {
$points += $submission->getProblemId()->getPoints();
}
return $points;
}
You could do something like this:
$userService = $this->container->get('userservice');
$users = $userService->findAll();
$pointPerUser = array();
foreach ($users as $user){
$userSubmissions = $user->getSubmissions();
$pointPerUser[$user->getId()] = 0;
foreach ($userSubmissions as $userSubmission) {
// Probably here you want to check if the submission is correct
$pointPerUser[$user->getId()] += $userSubmission->getProblemId()->getPoints();
}
}
By the way, the submission attribute shouldn't be $problem_id but $problem, and the method is getProblem(), as you are getting a Problem instance, not an id. The field name for the table is ok, as you are storing an id.
I'm getting the following error when trying to submit the following form
I figured the error must be from the fact that the property for roles within User is userRoles and not roles. I'd like to know if there is a way to map the EntityType field to a property in Users I looked at this Answer but it does not seem to be the proper way to solve this problem, it is more of a work around.
class UserEditType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('roles', EntityType::class, array('multiple'=> true, 'class' => 'AuthBundle:Role', 'choice_label' => 'slug','attr' => array('class'=>'form-control')))
->add('email', EmailType::class, array('attr' => array('class'=>'form-control')))
->add('username', TextType::class, array('attr' => array('class'=>'form-control')))
->add('active', CheckboxType::class, array('attr' => array('class'=>'checkbox')));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::class,
));
}
}
The User Class
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=25, unique=true)
*/
private $username;
/**
* #Assert\Length(max=4096)
* #Assert\Length(min=8)
*/
private $plainPassword;
/**
* #ORM\Column(type="string", length=64)
*/
private $password;
/**
* #ORM\Column(type="string", length=240, nullable=true)
*/
private $profilePicture;
/**
* #ORM\Column(type="string", length=180, unique=true, options={"default" : "default.png"})
*/
private $email;
/**
* #ORM\Column(name="is_active", type="boolean", options={"default" : 0})
*/
private $isActive;
/**
* #ORM\ManyToMany(targetEntity="Role")
* #ORM\JoinTable(name="user_role",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="role_id", referencedColumnName="id")}
* )
*
* #var ArrayCollection $userRoles
*/
protected $userRoles;
public function __construct()
{
$this->userRoles = new ArrayCollection();
}
public function getUsername()
{
return $this->username;
}
//deprecated bcrypt does not require salt
public function getSalt()
{
// you *may* need a real salt depending on your encoder
// see section on salt below
return null;
}
public function isActive()
{
return $this->isActive;
}
public function getPassword()
{
return $this->password;
}
public function getplainPassword()
{
return $this->plainPassword;
}
public function getPicture()
{
return $this->profilePicture;
}
public function getRoles()
{
return $this->getUserRoles()->toArray();
}
public function eraseCredentials()
{
}
/** #see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
$this->isActive,
// see section on salt below
// $this->salt,
));
}
/** #see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
$this->isActive,
// see section on salt below
// $this->salt
) = unserialize($serialized);
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* 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 setPlainPassword($password)
{
$this->plainPassword = $password;
return $this;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set profilePicture
*
* #param string $profilePicture
*
* #return User
*/
public function setProfilePicture($profilePicture)
{
$this->profilePicture = $profilePicture;
return $this;
}
/**
* Get profilePicture
*
* #return string
*/
public function getProfilePicture()
{
return $this->profilePicture;
}
/**
* Set email
*
* #param string $email
*
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set isActive
*
* #param boolean $isActive
*
* #return User
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* Add userRole
*
* #param \AuthBundle\Entity\Role $userRole
*
* #return User
*/
public function addUserRole(\AuthBundle\Entity\Role $userRole)
{
$this->userRoles[] = $userRole;
return $this;
}
/**
* Remove userRole
*
* #param \AuthBundle\Entity\Role $userRole
*/
public function removeUserRole(\AuthBundle\Entity\Role $userRole)
{
$this->userRoles->removeElement($userRole);
}
/**
* Get userRoles
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUserRoles()
{
return $this->userRoles;
}
}
The Role Class
class Role implements RoleInterface
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*
* #var integer $id
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*
* #var string $name
*/
protected $name;
/**
* #ORM\Column(type="string", length=255)
*
* #var string $slug
*/
protected $slug;
/**
* #ORM\Column(type="datetime", name="created_at")
*
* #var DateTime $createdAt
*/
protected $createdAt;
/**
* #ORM\ManyToMany(targetEntity="AuthBundle\Entity\User")
*/
protected $users;
/**
*
*/
public function __construct()
{
$this->users = new ArrayCollection();
$this->createdAt = new \DateTime();
}
/**
*
*
* #return integer The id.
*/
public function getId()
{
return $this->id;
}
/**
*
*
* #return string The name.
*/
public function getName()
{
return $this->name;
}
/**
*
*
* #param string $value The name.
*/
public function setName($value)
{
$this->name = $value;
}
/**
*
*
* #return string The name.
*/
public function getSlug()
{
return $this->slug;
}
/**
*
*
* #param string $value The name.
*/
public function setSlug($value)
{
$this->slug = $value;
}
/**
*
*
* #return DateTime A DateTime object.
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* RoleInterface.
*
* #return string The role.
*/
public function getRole()
{
return $this->getName();
}
/**
* Set createdAt
*
* #param \DateTime $createdAt
*
* #return Role
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Add user
*
* #param \AuthBundle\Entity\User $user
*
* #return Role
*/
public function addUser(\AuthBundle\Entity\User $user)
{
$this->users[] = $user;
return $this;
}
/**
* Remove user
*
* #param \AuthBundle\Entity\User $user
*/
public function removeUser(\AuthBundle\Entity\User $user)
{
$this->users->removeElement($user);
}
/**
* Get users
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
}
I'm trying to add new user with ManyToMany relationship with group, but only user is saving in database
this is my
User.php
/**
* Acme\UserBundle\Entity\User
*
* #ORM\Table(name="User")
* #ORM\Entity(repositoryClass="Acme\UserBundle\Entity\UserRepository")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="username", type="string", length=25, unique=true)
*/
private $username;
/**
* #ORM\Column(name="salt", type="string", length=40)
*/
private $salt;
/**
* #ORM\Column(name="password", type="string", length=40)
*/
private $password;
/**
* #ORM\Column(name="email", type="string", length=60, unique=true)
*/
private $email;
/**
* #ORM\Column(name="isActive", type="boolean")
*/
private $isActive;
/**
* #ORM\ManyToMany(targetEntity="Group", inversedBy="users")
*
* #ORM\JoinTable(name="user_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*
*/
private $groups;
public function __construct()
{
$this->isActive = true;
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
$this->groups = new ArrayCollection();
}
/**
* #inheritDoc
*/
public function getRoles()
{
$roles = array();
foreach ($this->groups as $role) {
$roles[] = $role->getRole();
}
return $roles;
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
/*
* ! Don't serialize $roles field !
*/
return \json_encode(array(
$this->id,
$this->username,
$this->email,
$this->salt,
$this->password,
$this->isActive
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->email,
$this->salt,
$this->password,
$this->isActive
) = \json_decode($serialized);
}
public function eraseCredentials()
{
}
public function getUsername()
{
return $this->username;
}
public function getSalt()
{
return $this->salt;
}
public function getPassword()
{
return $this->password;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set salt
*
* #param string $salt
* #return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set isActive
*
* #param boolean $isActive
* #return User
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* Add groups
*
* #param \Acme\UserBundle\Entity\Group $groups
* #return User
*/
public function addGroup(\Acme\UserBundle\Entity\Group $groups)
{
$groups->addUser($this);
$this->groups -> add($groups);
return $this->groups;
}
/**
* Remove groups
*
* #param \Acme\UserBundle\Entity\Group $groups
*/
public function removeGroup(\Acme\UserBundle\Entity\Group $groups)
{
$this->groups->removeElement($groups);
}
/**
* Get groups
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getGroups()
{
return $this->groups;
}
}
my Group.php
<?php
namespace Acme\UserBundle\Entity;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Table(name="groups")
* #ORM\Entity
*/
class Group implements RoleInterface, \Serializable
{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/** #ORM\Column(name="name", type="string", length=30) */
private $name;
/** #ORM\Column(name="role", type="string", length=20, unique=true) */
private $role;
/** #ORM\ManyToMany(targetEntity="User", mappedBy="groups",cascade={"persist"}) */
private $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
// ... getters and setters for each property
/** #see RoleInterface */
public function getRole()
{
return $this->role;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
/*
* ! Don't serialize $users field !
*/
return \json_encode(array(
$this->id,
$this->role
));
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list(
$this->id,
$this->role
) = \json_decode($serialized);
}
/**
* Set name
*
* #param string $name
* #return Group
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set role
*
* #param string $role
* #return Group
*/
public function setRole($role)
{
$this->role = $role;
return $this;
}
/**
* Add users
*
* #param \Acme\UserBundle\Entity\User $users
* #return Group
*/
public function addUser(\Acme\UserBundle\Entity\User $users)
{
$this->users[] = $users;
return $this;
}
/**
* Remove users
*
* #param \Acme\UserBundle\Entity\User $users
*/
public function removeUser(\Acme\UserBundle\Entity\User $users)
{
$this->users->removeElement($users);
}
/**
* Get users
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
}
and fragment from my controller
public function newAction(Request $request)
{
$user = new User();
$form = $this->createFormBuilder($user)
->add('username', 'text')
->add('password', 'text')
->add('email', 'email')
->add('submit','submit')
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
$user=$form->getData();
$group=new Group();
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$user->setSalt(md5(time()));
$pass = $encoder->encodePassword($form->getData()->getPassword(), $user->getSalt());
$user->setPassword($pass);
$group->setRole('ROLE_USER');
$user->addGroup($group);
$em = $this->getDoctrine()->getManager();
$em->merge($user);
$em->flush();
return $this->redirect($this->generateUrl('login'));
}
return $this->render('AcmeUserBundle:User:new.html.twig', array(
'form' => $form->createView(),
));
in database i have 3 table : User, Group and user_group (user_id, group_id)
everything generated from entities. I can register new user but it isnt saving in user_group.
Thanks for any help.
Ps.Sorry for my poor english
From what i can tell, you're not saving your group. So because you're not saving it, there is no user_group to save, because your group doesn't exist in the database. However you'll have another problem once you do this because you have a unique constraint on the role field for your group, so you'll get a database error saying you have a duplicate once you try to register more than one person. You'll need to pull the group from the db instead of making a new one every time.
$group = $this->em->getRepository('Group')->findOneByRole('ROLE_USER');
$user->addGroup($group);
$em->persist($group);
$em->persist($user);
$em->flush();
Update your controller to contain:
$group = $em->getRepository('AcmeUserBundle:Group')->findOne(array('role' => 'ROLE_USER'));
$user->addGroup($group);
$em->persist($user);
$em->persist($group);
$em->flush();
You forgot to persist the Group entity in your code, so it didn't save any data.
By the way, I suggest using a UserService that handles all that logic instead of putting it all in your controllers.
Also, in your User.php, you can just do:
/**
* #ORM\ManyToMany(targetEntity="Group", inversedBy="user")
*/
protected $groups;
The #JoinColumn annotation is not required. If it is not specified the attributes name and referencedColumnName are inferred from the table and primary key names.
hello I'm having trouble with:
public function isAdmin()
{
$role = $this->getFirstRole();
if ($role->getRoleId() == "admin")
return true;
return false;
}
it causes: Call to a member function getRoleId() on a non-object
please guys, help. thanks
classes:
class Role implements HierarchicalRoleInterface
{
/**
* Store id.
* #var int
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* Store role kind.
* Possible user kinds: 'guest' (not signed in),
'user' (default for signed in user), 'admin'.
* #var string
* #ORM\Column(type="string", length=255,
unique=true, nullable=true)
*/
protected $roleId;
/**
* Store role parent for inheritance measure.
* #var Role
* #ORM\ManyToOne(targetEntity="User\Entity\Role")
*/
protected $parent;
/**
* Get id.
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set id.
* #param int $id
* #return void
*/
public function setId($id)
{
$this->id = (int)$id;
}
/**
* Get role kind.
* #return string
*/
public function getRoleId()
{
return $this->roleId;
}
/**
* Set role kind.
* #param string $roleId
* #return void
*/
public function setRoleId($roleId)
{
$this->roleId = (string) $roleId;
}
/**
* Get parent role
* #return Role
*/
public function getParent()
{
return $this->parent;
}
/**
* Set parent role.
* #param Role $parent
* #return void
*/
public function setParent(Role $parent)
{
$this->parent = $parent;
}
}
class User implements UserInterface, ProviderInterface
{
/**
* Store id.
* #var int
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* Store username.
* #var string
* #ORM\Column(type="string", length=255, unique=true)
*/
protected $username;
/**
* Store email.
* #var string
* #ORM\Column(type="string", unique=true, length=255)
*/
protected $email;
/**
* Store displayName.
* #var string
* #ORM\Column(type="string", length=50, nullable=true)
*/
protected $displayName;
/**
* Store password.
* #var string
* #ORM\Column(type="string", length=128)
*/
protected $password;
/**
* Store state.
* #var int
*/
protected $state;
/**
* Store mark.
* #var float
*/
protected $mark;
/**
* Store roles collection.
* #var \Doctrine\Common\Collections\Collection
* #ORM\ManyToMany(targetEntity="User\Entity\Role")
* #ORM\JoinTable(name="users_roles",
* joinColumns={
#ORM\JoinColumn(
name="user_id",
referencedColumnName="id"
)
},
* inverseJoinColumns={
#ORM\JoinColumn(
name="role_id",
referencedColumnName="id"
)
}
* )
*/
protected $roles;
/**
* Store albums collection
* #var \Doctrine\Common\Collections\Collection
* #ORM\OneToMany(targetEntity="Album\Entity\Album", mappedBy="user",
cascade={"all"})
*/
protected $albums;
/**
* Store comments collection.
* #var \Doctrine\Common\Collections\Collection
* #ORM\OneToMany(targetEntity="Comment\Entity\Comment", mappedBy="user",
cascade={"all"})
*/
protected $comments;
/**
* Store marks collection.
* #var \Doctrine\Common\Collections\Collection
* #ORM\OneToMany(targetEntity="Mark\Entity\Mark", mappedBy="user",
cascade={"all"})
*/
protected $marks;
/**
* Initialies collections.
*/
public function __construct()
{
$this->roles = new ArrayCollection();
$this->albums = new ArrayCollection();
$this->comments = new ArrayCollection();
$this->marks = new ArrayCollection();
}
/**
* Get id.
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set id.
* #param int $id
* #return void
*/
public function setId($id)
{
$this->id = (int) $id;
}
/**
* Get username.
* #return string
*/
public function getUsername()
{
return htmlspecialchars($this->username);
}
/**
* Set username.
* #param string $username
* #return void
*/
public function setUsername($username)
{
$this->username = $username;
}
/**
* Get email.
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set email.
* #param string $email
* #return void
*/
public function setEmail($email)
{
$this->email = $email;
}
/**
* Get displayName.
* #return string
*/
public function getDisplayName()
{
return $this->displayName;
}
/**
* Set displayName.
* #param string $displayName
* #return void
*/
public function setDisplayName($displayName)
{
$this->displayName = $displayName;
}
/**
* Get password.
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set password.
* #param string $password
* #return void
*/
public function setPassword($password)
{
$this->password = $password;
}
/**
* Get state.
* #return int
*/
public function getState()
{
return $this->state;
}
/**
* Set state.
* #param int $state
* #return void
*/
public function setState($state)
{
$this->state = $state;
}
/**
* Get roles collection.
* #return \Doctrine\Common\Collections\Collection
*/
public function getRoles()
{
return $this->roles;
}
public function getFirstRole() {
$roles = $this->getRoles();
$firstRole = $roles[0];
return $firstRole;
}
/**
* Get comments collection.
* #return \Doctrine\Common\Collections\Collection
*/
public function getComments()
{
return $this->comments;
}
/**
* Get marks collection.
* #return \Doctrine\Common\Collections\Collection
*/
public function getMarks()
{
return $this->marks;
}
/**
* Add a role to user.
* #param Role $role
* #return void
*/
public function addRole($role)
{
$this->roles[] = $role;
}
/**
* Get albums.
* #return \Doctrine\Common\Collections\Collection
*/
public function getAlbums()
{
return $this->albums;
}
public function isAdmin(){
$role = $this->getFirstRole();
if ($role->getRoleId() == "admin")
return true;
return false;
}
/**
* Calculate user mark.
* #return float
*/
public function mark()
{
if (!$this->mark) {
$albums = $this->getAlbums();
$result = 0;
foreach ($albums as &$album) {
$result += $album->mark();
}
$this->mark = $result;
}
return $this->mark;
}
}
anyone?
(writing this becaue it says my post is mostly code)
(writing this becaue it says my post is mostly code)
/**
* Get roles collection.
* #return \Doctrine\Common\Collections\Collection
*/
public function getRoles()
{
return $this->roles;
}
Collections are not accessed by [0], they are Collection objects, use like this:
public function getFirstRole() {
return $this->roles->first();
}
#h2ooooooo gave this helpful link to the docs, containing all methods of the collection: http://www.doctrine-project.org/api/common/2.3/class-Doctrine.Common.Collections.ArrayCollection.html
You can compare ID with an ID (integer), or string by string,
but the best is to compare Entities to keep the whole system integral:
public function isAdmin() {
$role = $this->getFirstRole();
$admin = $entityManager
->getRepository('User\Entity\Role')
->findOneByName('admin');
if ($role === $admin) {
return true;
} else {
return false;
}
}
it seems that $this->getFirstRole() returned user role as string. you just need to compare it as string.
try this:
public function isAdmin()
{
$role = $this->getFirstRole();
return $role == "admin" ? true : false;
}
Simple process,
Need to create Users with mapped Roles.
I followed the step from link
http://symfony.com/doc/current/cookbook/security/entity_provider.html
User and Roles table generated but users_roles table is not generated in MySql...
Will i need to create it manually?
Second
I have configured with User table for Authentication
After login it redirects to Error page,
FatalErrorException: Error: Call to a member function toArray() on a non-object in /var/www/vibilling_3/src/ViBillingPortal/AuthenticationBundle/Entity/users.php line 130
I searched, but i cant find any solutions... Below my code
Bill/PortalBundle/Entity/users.php
namespace ViBillingPortal\AuthenticationBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;
/**
* users
*/
class users implements UserInterface, \Serializable
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $username;
/**
* #var string
*/
private $password;
/**
* #var string
*/
private $created_date;
/**
* #ORM\ManyToMany(targetEntity="roles", inversedBy="users")
* #ORM\JoinTable(name="user_roles")
*/
private $userroles;
public function __construct()
{
$this->userroles = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return users
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set password
*
* #param string $password
* #return users
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set created_date
*
* #param string $created_date
* #return users
*/
public function setCreated_date($password)
{
$this->password = $created_date;
return $this;
}
/**
* Get Created_date
*
* #return string
*/
public function getCreated_date()
{
return $this->created_date;
}
/**
* Get Roles
*/
public function getRoles()
{
return $this->userroles->toArray();
}
/**
* #inheritDoc
*/
public function getSalt()
{
}
/**
* #inheritDoc
*/
public function eraseCredentials()
{
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
}
}
Bill/PortalBundle/Entity/roles.php
namespace ViBillingPortal\AuthenticationBundle\Entity;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* roles
*/
class roles implements RoleInterface, \Serializable
{
/**
* #var integer
*/
private $id;
/**
* #var string
*/
private $name;
/**
* #ORM\Column(name="role", type="string", length=20, unique=true)
*/
private $role;
/**
* #ORM\ManyToMany(targetEntity="users", mappedBy="userroles")
*/
protected $users;
public function __construct()
{
$this->users = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return roles
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #see RoleInterface
*/
public function getRole()
{
return $this->role;
}
/**
* #see \Serializable::serialize()
*/
public function serialize()
{
}
/**
* #see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
}
}
You should use a ManyToMany relation, not a ManyToOne if you want to use a join table : http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#many-to-many-bidirectional
For the second error, it's strange as you initialize usersroles as an ArrayCollection in your construct method, it should work.
Could you add a var_dump to look what is stored in this property ?
Why don't you get any setter/getter for usersroles ?
I think you should also read Symfony coding standards : http://symfony.com/doc/current/contributing/code/standards.html. You coding style is not consistent.