(Symfony3) How to add a custom property to FOSUserBundle and persist it? - php

I'm trying to add a custom property (psptCode) to my User entity, extending UserBundle.
This is my User class:
<?php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use JMS\Serializer\Annotation as JMSSerializer;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Model\UserInterface;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*
* #UniqueEntity("email")
* #UniqueEntity("username")
* #UniqueEntity("psptCode")
* #JMSSerializer\ExclusionPolicy("all")
* #JMSSerializer\AccessorOrder("custom", custom = {"id", "emailCanonical", "account"})
*/
class User extends BaseUser implements UserInterface
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #JMSSerializer\Expose
* #JMSSerializer\Type("string")
*/
protected $id;
/**
* #var string The canonical representation of the email of the user.
*
* #JMSSerializer\Expose
* #JMSSerializer\Type("string")
* #JMSSerializer\SerializedName("email")
* #JMSSerializer\Groups({"user_all", "user_summary"})
*/
protected $emailCanonical;
/**
* #var string
*
* #ORM\Column(type="string", name="pspt_code", length=16, nullable=true)
*/
private $psptCode;
/**
* #var Account The Pspt account related to this user, if any
*
* #ORM\OneToOne(targetEntity="Account")
* #ORM\JoinColumn(name="pspt_code", referencedColumnName="cli_id", nullable=true)
* #JMSSerializer\Expose
* #JMSSerializer\Type("AppBundle\Entity\Account")
* #JMSSerializer\Groups({"user_all"})
*/
protected $account;
public function __construct()
{
parent::__construct();
}
/**
* #param $pspt_code
*
* Set the cli_id to retrieve the account, if any
* #return User
*/
public function setPsptCode($pspt_code)
{
$this->psptCode = $pspt_code;
return $this;
}
/**
* Get psptCode
* #return string
*/
public function getPsptCode()
{
return $this->psptCode;
}
}
When I create the database schema, my custom property gets created, but when I try to store a value into my custom property, it isn't persisted into the database:
$user = $this->userManager->createUser();
$user->setEnabled(true);
$user->setUsername('peter');
$user->setEmail('peter#test.com');
$user->setPlainPassword('testpass');
$user->setPsptCode('XXXXXXXXXX');
$this->userManager->updateUser($user);
The user gets stored like this:
AppBundle\Entity\User {#4041
#id: 1
#emailCanonical: "peter#test.com"
-psptCode: null
#account: null
#username: "peter"
#usernameCanonical: "peter"
#email: "peter#test.com"
#enabled: true
#salt: null
#password: "$2y$15$OJ4ynZmpBaDYbK7N.d35m.FdcSHGpZG7Yemcwxrg4kHhKzIyP3XOO"
#plainPassword: null
#lastLogin: null
#confirmationToken: null
#passwordRequestedAt: null
#groups: null
#roles: []
}
So, I'm unable to store my user's custom property.
Please help!

Related

Doctrine, ralation ManyToOne

When a try update my database I got error:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails
(symfony.#sql-d8c_55, CONSTRAINT FK_957A6479A233CB39 FOREIGN KEY
(klient_id) REFERENCES klient (id))
My class user:
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* Class User
* #package AppBundle\Entity
*
* #ORM\Table("fos_user")
* #ORM\Entity()
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Klient", inversedBy="users")
* #ORM\JoinColumn(nullable=false)
*/
private $klient;
/**
* #return mixed
*/
public function getKlient()
{
return $this->klient;
}
/**
* #param mixed $klient
*/
public function setKlient($klient)
{
$this->klient = $klient;
}
public function __construct()
{
parent::__construct();
}
}
class Klient
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* Klient
*
* #ORM\Table(name="klient")
* #ORM\Entity(repositoryClass="AppBundle\Repository\KlientRepository")
*/
class Klient
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nazwa", type="string", length=255, unique=true)
*/
private $nazwa;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\User", mappedBy="klient")
*/
private $users;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set nazwa
*
* #param string $nazwa
*
* #return Klient
*/
public function setNazwa($nazwa)
{
$this->nazwa = $nazwa;
return $this;
}
/**
* Get nazwa
*
* #return string
*/
public function getNazwa()
{
return $this->nazwa;
}
public function __construct()
{
$this->users = new ArrayCollection();
}
}
in my opinion you have this error because you already have datas in your database. When you try to add the foreign key on your user table, kcient_id is null. And in your definition, you specify nullable: false.
I suggest you proceed in two times.
Edit your annotation to nullable: true, update your database and link your client to klient
Re-edit your annotation to nullable: false, it should be ok

Creating a password recovery table - Error when inserting a value

I have a User class with attributes like id, name, mail, etc.
I'm implementing the password recovery process, so I created a password_recovery table with these columns:
id
user_id
token
createdDate
expiryDate
isExpired
This is my PasswordRecovery Class:
namespace \UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="password_recovery")
*/
class PasswordRecovery {
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="User")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $idUser;
/**
* #ORM\Column(type="string")
*/
private $token;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
*/
private $createdDate;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
*/
private $expireDate;
/**
* #ORM\Column(type="boolean")
*/
private $expired; }
When the user wants to recover his password, he must enter his email. If the mail is in the db, I create a PasswordRecovery Object and store it in the db. This is how I'm doing that: (small part of the code)
if (!empty($resetMail))
{
$recovery = new PasswordRecovery();
$token = bin2hex(openssl_random_pseudo_bytes(16));
$recovery->setToken($token);
$userId = $resetMail->getId();
$recovery->setIdUser($userId);
$recovery->setCreatedDate(new \DateTime('now'));
$expiry = (new \DateTime('now + 1day'));
$recovery->setExpireDate($expiry);
$recovery->setExpired(false);
$em = $this->getDoctrine()->getManager();
$em->persist($recovery);
$em->flush(); }
I got this error:
Catchable Fatal Error: Argument 1 passed to \UserBundle\Entity\PasswordRecovery::setIdUser() must be an instance of \UserBundle\Entity\User, integer given, called in /home/user/project/src/UserBundle/Controller/AccountController.php on line 553 and defined
Why?
You need to use setIdDUser(User). This is a proxy object because it's a reference to another table (entity)
In the same way when you call getIdUser() you will get a proxy object again, which you will have to call getId() on if you want the int value.

StofDoctrineExtensionsBundle checking the uniqueness of slug by the two fields

I use Knp\DoctrineBehaviors for Translation and StofDoctrineExtensionsBundle for Sluggable. How to make checking the uniqueness of slug by the sluggable and locale? I want to get the slug look like this:
for EN: /contacts
for PT: /pt/contacts
for PT (if duplicate): /pt/contacts-1
for ES: /es/contacts
But now, i have this database filter_node_translation
Entity\FilterNode.php:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
/**
* #ORM\Table(name="filter_node")
* #ORM\Entity()
*/
class FilterNode
{
use ORMBehaviors\Translatable\Translatable;
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(name="id", type="integer")
*/
protected $id;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
}
FilterNodeTranslation:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* #ORM\Table(name="filter_node_translation")
* #ORM\Entity()
*/
class FilterNodeTranslation
{
use ORMBehaviors\Translatable\Translation;
/**
* #var string
*
* #ORM\Column(type="string", nullable=true)
*/
protected $sluggable;
/**
* #var string
*
* #Gedmo\Slug(fields={"sluggable"})
* #ORM\Column(type="string", nullable=true)
*/
protected $slug;
/**
* #return string
*/
public function getSluggable()
{
return $this->sluggable;
}
/**
* #param string $sluggable
*/
public function setSluggable($sluggable)
{
$this->sluggable = $sluggable;
}
}
I found solution. Gedmo sluggable have other configuration option "unique_base".
It looks like this:
class FilterNodeTranslation
{
/**
* #var string
*
* #Gedmo\Slug(updatable=true, unique=true, unique_base="locale", fields={"sluggable"})
* #ORM\Column(type="string")
*/
protected $slug;
}

Why does the Doctrine getter method return null for the ID?

I use the auto-generated getters in a class table inheritance setup in a Symfony project. getId() returns null, while every other getter works. Can you spot any problem? What should I search for? I imported the database entries manually, but I don't think that is the cause.
The abstract parent entity
//src/Acme/WebzineBundle/Entity/Content.php
namespace Acme\WebzineBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Content
*
* #ORM\Table()
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="heading", type="integer")
* #ORM\DiscriminatorMap({
* 0 = "Review"
* })
*/
abstract class Content
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
* #ORM\Column(name="edited", type="date")
*/
private $edited;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get edited
*
* #return \DateTime
*/
public function getEdited()
{
return $this->edited;
}
}
The child entity
//src/Acme/WebzineBundle/Entity/Review.php
namespace Acme\WebzineBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Review articles
*
* #ORM\Table()
* #ORM\Entity
*/
class Review extends Content
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=127)
*/
private $title;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
}
The next foreign key constraint is on the table of the child entity:
CONSTRAINT `FK_7EEF84F0BF396750` FOREIGN KEY (`id`) REFERENCES `Content` (`id`)
ON DELETE CASCADE
The query
//src/Acme/AdminBundle/Controller/MainController.php
namespace Acme\AdminBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class MainController extends Controller
{
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT post FROM AcmeWebzineBundle:Content post
ORDER BY post.edited DESC'
);
$query->setMaxResults(30);
$posts = $query->getResult();
$latest_post = $posts[0];
return $this->render('AcmeAdminBundle:Main:index.html.twig', array(
'posts' => $posts,
'id' => gettype($latest_post->getId()), // This returns null!
'edited' => $latest_post->getEdited(), // Any other getter works
'title' => $latest_post->getTitle(), // also from the child entity.
));
}
}
You need to remove the id property and getId() method from the child class
//src/Acme/WebzineBundle/Entity/Review.php
namespace Acme\WebzineBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Review articles
*
* #ORM\Table()
* #ORM\Entity
*/
class Review extends Content
{
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=127)
*/
private $title;
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
}
You can not create object of Content class.
And better use only unique properties and methods in Review class, because others are inherited from abstract Content class.

FOSUserBundle not applying User entity changes

I have just installed FosUserBundle in a Symfony version 2.3.3 application.
I'm able to manage users, login, register and whatnot but changes I make to my User class in MyApp\UserBundle\Entity aren't being applied when I run app/console doctrine:schema:update
The database structure contains:
id,
username,
username_canonical,
email,
email_canonical,
enabled,
salt,
password,
last_login,
locked,
expired,
expires_at,
confirmation_token,
password_requested_at,
roles,
credentials_expired,
credentials_expire_at
The field that I have added, rate, isnt being created in the database structure no matter what I do.
Inside /app/AppKernel.php
new MyApp\UserBundle\MyAppUserBundle(),
new FOS\UserBundle\FOSUserBundle(),
Inside /app/config/config.yml
fos_user:
db_driver: orm
firewall_name: main
user_class: MyApp\UserBundle\Entity\User
registration:
confirmation:
enabled: true
And inside /src/MyApp/UserBundle/Entity/User.php
<?php
namespace MyApp\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*
* #ORM\Table(name="fos_user")
* #ORM\Entity(repositoryClass="MyApp\UserBundle\Entity\UserRepository")
*/
class User extends BaseUser
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="token", type="string", length=255)
*/
private $token;
/**
* #var integer
*
* #ORM\Column(name="rate", type="integer")
*/
private $rate;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set token
*
* #param string $token
* #return User
*/
public function setToken($token)
{
$this->token = $token;
return $this;
}
/**
* Get token
*
* #return string
*/
public function getToken()
{
return $this->token;
}
/**
* Set rate
*
* #param integer $rate
* #return User
*/
public function setRate($rate)
{
$this->rate = $rate;
return $this;
}
/**
* Get rate
*
* #return integer
*/
public function getRate()
{
return $this->rate;
}
}
Don't forget the constructor, clear the cache and try php app/console doctrine:schema:update --force
namespace Acme\UserBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser; use Doctrine\ORM\Mapping as
ORM;
/** * #ORM\Entity * #ORM\Table(name="fos_user") / class User
extends BaseUser {
/*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct()
{
parent::__construct();
// your own logic
}
}
Need to add MyUserBundle mappings to your config.yml file:
doctrine:
orm:
mappings:
FOSUserBundle: ~
MyUserBundle: ~

Categories