0

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

DevDonkey
  • 4,835
  • 2
  • 27
  • 41
  • Closure is the class ( built into PHP ) for lambada style functions such as $f = function(){}, why your accessing that in your ArrayCollecdtion which is what doctrine uses for these things I am not sure of, what does this say $rolls is \Doctrine\Common\Util\Debug::dump($this->roles); – ArtisticPhoenix Nov 12 '14 at 17:44
  • everything in the class is from the cookbook, so Im not sure either! I really am running out of brain with this.. Im hoping the fog will pass soon. – DevDonkey Nov 12 '14 at 18:18

1 Answers1

1

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.

ArtisticPhoenix
  • 21,464
  • 2
  • 24
  • 38