How To Override FOSUserBundle

Before learning how to override FOS, one should know what exactly FOS is and how it works! FOS is short for Friends Of Symfony. So now, before using FOSUserBundle, you should probably find more about what Symfony2 exactly is.

Symfony2

Symfony2 is a flexible Framework for the development of PHP web application. Symfony2 can be used to build dynamic websites, web apps, web services and resources.
in-the-future-we-all-use-symfony2-1-728

Why Are We Using Symfony2?

Webmuch has always picked Symfony2 as the framework of choice for large scale PHP projects.

Well, it’s an advanced full stack PHP framework, which means it’s a complete solution for just about any kind of application. The other reason for using Symfony2 is that it uses CMF(content management framework) which makes it easier for developers to add CMF functionality to applications built with the Symfony2 PHP framework.

Webmuch team fashions outstanding applications and business workflow with the help of Symfony2 web application framework.

Advantages Of Using Symfony2

advantages

  • Symfony2 is very fast and comparable to other web frameworks.
  • It reduces the number of resources needed.
  • Symfony2 encourages to write framework independent, and it’s built commercial enterprise web application.
  • It allows a lot of flexibility around how the project is setup.
  • Symfony2  is an Open source technology.

What Is FOSUserBundle?

5779484d04a8e47017db438ee3378a52

FOSUserBundle provides a default functionality for a user for registration or login on to a website. One just needs to download FOSUserBundle and install the application. It provides a login panel for the user to register on the website. It contains some fields:

  • E-Mail
  • User name
  • Password
  • Verification

And here are some simple steps for overriding FOSUserBundle.

Installation Steps

symfony_fosuser Installation

Installation is a quick (For Real!)

  1. Download FOSUserBundle using composer
  2. Enable the Bundle
  3. Create your User class
  4. Configure your application’s security.yml
  5. Configure the FOSUserBundle
  6. Import FOSUserBundle routing
  7. Update your database schema

 

What These Steps Do 

In FOSUserBundle, the fields like username and email idare not null by default. Admin or some Power Users may want to create a new vendor whose

In FOSUserBundle the fields like username and email id are not null by default. Admins or some Power Users may want to create a new vendor whose username and email id may not be known to the Admin or the Power User. So there is a requirement that username and email should remain null.

For this purpose, a new base user is created which may override the default components of the FOS User. This new base user is created in FOS/UserBundle/Model/User.php as follows:

NewBaseUser:
override ->username(null=true,unique=true)
override ->email(null=true,unique=true)
override ->username_cannonical(null=true ,unique=true)
override ->email_cannonical(null=true,unique=true)

 

 

From the above code, it can be seen that all the fields are allowed to be null which is not the case in FOSUserBundle.

After creating this NewBaseUser, it is used in the file ‘user.php’ of the UserBundle. Instead of using the FOSUserBundle in the ‘user.php’, the following statement should be used on the top of the file.

use NewBaseUser/UserBundle/Model/User as BaseUser;

 

Again in the front registration page, email id and username cannot remain null. For this purpose, we have to assign validation to the username and email id for the normal user to get registered.

This is achieved as follows :

App/Resources/Config/Validation.xml
username -> (null=false,unique=true)
email -> (null=false,unique=true)
username_canonical -> (null=false,unique=true)
email_canonical -> (null=false,unique=true)

 

 

The code for overriding is as follows:

<?php
namespace Webmuch\UserBundle\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use FOS\UserBundle\Model\UserInterface;
use FOS\UserBundle\Model\GroupableInterface;
use FOS\UserBundle\Model\GroupInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* BaseUser
*/
 abstract class BaseUser implements UserInterface, GroupableInterface
{
	protected $id;
	/**
	* @var string
	*/
	protected $username;
	/**
	* @var string
	*/
	protected $usernameCanonical;
	/**
	* @var string
	*/
	protected $email;
	/**
	* @var string
	*/
	protected $emailCanonical;
	/**
	* @var boolean
	*/
	protected $enabled;
	/**
	* The salt to use for hashing
	*
	* @var string
	*/
	protected $salt;
	/**
	* Encrypted password. Must be persisted.
	*
	* @var string
	*/
	protected $password;
	/**
	* Plain password. Used for model validation. Must not be persisted.
	*
	* @var string
	*/
	protected $plainPassword;
	/**
	* @var \DateTime
	*/
	protected $lastLogin;
	/**
	* Random string sent to the user email address in order to verify it
	*
	* @var string
	*/
	protected $confirmationToken;
	/**
	* @var \DateTime
	*/
	protected $passwordRequestedAt;
	/**
	* @var Collection
	*/
	protected $groups;
	/**
	* @var boolean
	*/
	protected $locked;
	/**
	* @var boolean
	*/
	protected $expired;
	/**
	* @var \DateTime
	*/
	protected $expiresAt;
	/**
	* @var array
	*/
	protected $roles;
	/**
	* @var boolean
	*/
	protected $credentialsExpired;
	/**
	* @var \DateTime
	*/	
	 protected $credentialsExpireAt;
 	public function __construct()
{
 		$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
 		$this->enabled = false;
 		$this->locked = false;
 		$this->expired = false;
 		$this->roles = array();
 		$this->credentialsExpired = false;
}
public function addRole($role)
{
 		$role = strtoupper($role);
 		if ($role === static::ROLE_DEFAULT) {
 		return $this;
}
 	if (!in_array($role, $this->roles, true)) {
 	$this->roles[] = $role;
}
 	return $this;
}
	/**
	* Serializes the user.
	*
	* The serialized data have to contain the fields used by the equals method and the username.
	*	
	* @return string
	*/
	public function serialize()
{
		 return serialize(array(
 		$this->password,
 		$this->salt,
 		$this->usernameCanonical,
 		$this->username,
 		$this->expired,
 		$this->locked,
 		$this->credentialsExpired,
 		$this->enabled,
 		$this->id,
 		));
}
/**
* Unserializes the user.
*
* @param string $serialized
*/
public function unserialize($serialized)
{
 		$data = unserialize($serialized);
// add a few extra elements in the array to ensure that we have enough keys whe n unserializing
// older data which does not include all properties.
 		$data = array_merge($data, array_fill(0, 2, null));
 		list(
 		$this->password,
 		$this->salt,
 		$this->usernameCanonical,
 		$this->username,
 		$this->expired,
 		$this->locked,
 		$this->credentialsExpired,
 		$this->enabled,
 		$this->id
 		) = $data;
}
/**
* Removes sensitive data from the user.
*/
public function eraseCredentials()
{
 		$this->plainPassword = null;
}
/**
* Returns the user unique id.
*
* @return mixed
*/
public function getId()
{
 		return $this->id;
}
public function getUsername()
{
 		return $this->username;
}
public function getUsernameCanonical()
{
 		return $this->usernameCanonical;
}
public function getSalt()
{
 		return $this->salt;
}
public function getEmail()
{
 		return $this->email;
}
public function getEmailCanonical()
{
 		return $this->emailCanonical;
}
/**
* Gets the encrypted password.
*
* @return string
*/
public function getPassword()
{
		return $this->password;
}
public function getPlainPassword()
{
 		return $this->plainPassword;
}
/**
* Gets the last login time.
*
* @return \DateTime
*/
public function getLastLogin()
{
 		return $this->lastLogin;
}
public function getConfirmationToken()
{
 		return $this->confirmationToken;
}
/**
* Returns the user roles
*
* @return array The roles
*/
public function getRoles()
{
		 $roles = $this->roles;
 		foreach ($this->getGroups() as $group) {
 		$roles = array_merge($roles, $group->getRoles());
}
// we need to make sure to have at least one role
	$roles[] = static::ROLE_DEFAULT; 
	return array_unique($roles);
}
/**
* Never use this to check if this user has access to anything!
*
* Use the SecurityContext, or an implementation of AccessDecisionManager
* instead, e.g.
*
*         $securityContext->isGranted('ROLE_USER');
*
* @param string $role
*
* @return boolean
*/
public function hasRole($role)
{
 		return in_array(strtoupper($role), $this->getRoles(), true);
}
public function isAccountNonExpired()
{
		 if (true === $this->expired) 
{
 		return false;
}
 if (null !== $this->expiresAt && $this->expiresAt->getTimestamp() < time()) {
 		return false;
}
	 return true;
}
 public function isAccountNonLocked()
{
 		return !$this->locked;
}
 public function isCredentialsNonExpired()
{
 		if (true === $this->credentialsExpired) {
		return false;
}
 if (null !== $this->credentialsExpireAt && $this->credentialsExpireAt->getTime stamp() < time()) {
 	return false;
}
	return true;
}
 public function isCredentialsExpired()
{
 		return !$this->isCredentialsNonExpired();
}
 public function isEnabled()
{
 		return $this->enabled;
}
 public function isExpired()
{
 		return !$this->isAccountNonExpired();
}
 public function isLocked()
{
 		return !$this->isAccountNonLocked();
}
 public function isSuperAdmin()
{
 		return $this->hasRole(static::ROLE_SUPER_ADMIN);
}
 public function removeRole($role)
{
 		if (false !== $key = array_search(strtoupper($role), $this->roles, true)) {
 		unset($this->roles[$key]);
 		$this->roles = array_values($this->roles);
}
 	return $this;
}
	 public function setUsername($username)
{
 		$this->username = $username;
	 return $this;
}
 	public function setUsernameCanonical($usernameCanonical)
{
 		$this->usernameCanonical = $usernameCanonical;
 		return $this;
}
/**
* @param \DateTime $date
*
* @return User
*/
public function setCredentialsExpireAt(\DateTime $date = null)
{
		 $this->credentialsExpireAt = $date;
 		return $this;
}
/**
* @param boolean $boolean
*
* @return User
*/
	public function setCredentialsExpired($boolean)
{
		 $this->credentialsExpired = $boolean;
 		return $this;
}
	 public function setEmail($email)
{
		 $this->email = $email;
 		return $this;
}
	public function setEmailCanonical($emailCanonical)
{
		 $this->emailCanonical = $emailCanonical;
		 return $this;
}
	public function setEnabled($boolean)
{
		 $this->enabled = (Boolean) $boolean;
 		return $this;
}
/**
* Sets this user to expired.
*
* @param Boolean $boolean
*
* @return User
*/
	public function setExpired($boolean)
{
		 $this->expired = (Boolean) $boolean;
 		return $this;
}
/**
* @param \DateTime $date
*
* @return User
*/
	public function setExpiresAt(\DateTime $date = null)
{
		 $this->expiresAt = $date;
 		return $this;
}
	public function setPassword($password)
{
		 $this->password = $password;
 		return $this;
}
	public function setSuperAdmin($boolean)
{
		 if (true === $boolean) {
		 $this->addRole(static::ROLE_SUPER_ADMIN);
} else {
 		$this->removeRole(static::ROLE_SUPER_ADMIN);
}
	return $this;
}
	public function setPlainPassword($password)
{
		 $this->plainPassword = $password;
		 return $this;
}
	public function setLastLogin(\DateTime $time = null)
{
		 $this->lastLogin = $time;
 		return $this;
}
	public function setLocked($boolean)
{
		 $this->locked = $boolean;
		 return $this;
}
	public function setConfirmationToken($confirmationToken)
{
 		$this->confirmationToken = $confirmationToken;
 		return $this;
}
	public function setPasswordRequestedAt(\DateTime $date = null)
{
 		$this->passwordRequestedAt = $date;
 		return $this;
}
/**
* Gets the timestamp that the user requested a password reset.
*
* @return null|\DateTime
*/
	public function getPasswordRequestedAt()
{
 		return $this->passwordRequestedAt;
}
	public function isPasswordRequestNonExpired($ttl)
{
 		return $this->getPasswordRequestedAt() instanceof \DateTime &&
 		$this->getPasswordRequestedAt()->getTimestamp() + $ttl > time();
}
	public function setRoles(array $roles)
{
		 $this->roles = array();
 		foreach ($roles as $role) {
 		$this->addRole($role);
}
 	return $this;
}
/**
* Gets the groups granted to the user.
*
* @return Collection
*/
	public function getGroups()
{
		 return $this->groups ?: $this->groups = new ArrayCollection();
}
	public function getGroupNames()
{
		 $names = array();
		 foreach ($this->getGroups() as $group) {
		 $names[] = $group->getName();
}
	 return $names;
}
/**
* @param string $name
*
* @return boolean
*/
	public function hasGroup($name)
{
 		return in_array($name, $this->getGroupNames());
}
	public function addGroup(GroupInterface $group)
{
		 if (!$this->getGroups()->contains($group)) {
		 $this->getGroups()->add($group);
}
	 return $this;
}
	public function removeGroup(GroupInterface $group)
{
		 if ($this->getGroups()->contains($group)) {
		 $this->getGroups()->removeElement($group);
}
	 return $this;
}
	public function __toString()
{
		 return (string) $this->getUsername();
}
/**
* Get enabled
*
* @return boolean
*/
	public function getEnabled()
{
 		return $this->enabled;
}
/**
* Set salt
*
* @param string $salt
* @return BaseUser
*/
	public function setSalt($salt)
{
		 $this->salt = $salt;
		 return $this;
}
/**
* Get locked
*
* @return boolean
*/
	public function getLocked()
{
		 return $this->locked;
}
/**
* Get expired
*
* @return boolean
*/
	public function getExpired()
{
		 return $this->expired;
}
/**
* Get expiresAt
*
* @return \DateTime
*/
	public function getExpiresAt()
{
		 return $this->expiresAt;
}
/**
* Get credentialsExpired
*
* @return boolean
*/
	public function getCredentialsExpired()
{
		 return $this->credentialsExpired;
}
/**
* Get credentialsExpireAt
*
* @return \DateTime
*/
	public function getCredentialsExpireAt()
{
		 return $this->credentialsExpireAt;
}
}
/*After created this New BaseUser it is used in the file user.php
of the UserBundle. Instead of using the FOSUserBundle in the user.php the following statement should be used on the top of the file:
use Webmuch/UserBundle/Entity/BaseUser;
The user.php file is given as follows :*/
<?php
namespace Webmuch\UserBundle\Entity;
use Webmuch\UserBundle\Entity\BaseUser;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*/
class User extends BaseUser
{
/**
	* @var integer
*/
	 protected $id;
/**
	* @var string
*/
 	private $slug;
/**
	* @var vendor
*/
	private $vendor;
/**
	* @var reviews
*/
	private $reviews;
/**
* Get id
*
	* @return integer
*/
	public function getId()
{
		 return $this->id;
}
/**
* Constructor
*/
	public function __construct()
{
		 parent::__construct();
 		$this->reviews = new \Doctrine\Common\Collections\ArrayCollection();
}
	public function setRoles(array $roles)
{
		 $this->roles = $roles;
}
/**
* Returns the user roles
*
* @return array The roles
*/
	public function getRoles()
{
		 $roles = $this->roles;
 		foreach ($this->getGroups() as $group) {
 		$roles = array_merge($roles, $group->getRoles());
}
// we need to make sure to have at least one role
//$roles[] = static::ROLE_DEFAULT;
	return array_unique($roles);
}
/**
* Set vendor
* @param \Webmuch\VendorBundle\Entity\Vendor $vendor
* @return User
*/
	public function setVendor(\Webmuch\VendorBundle\Entity\Vendor $vendor = null)
{
		 $this->vendor = $vendor;
		 return $this;
}
/**
* Get vendor
*
* @return \Webmuch\VendorBundle\Entity\Vendor
*/
	public function getVendor()
{
		 return $this->vendor;
}
/**
* Add reviews
*
* @param \Webmuch\VendorBundle\Entity\Review $reviews
* @return User
*/
	public function addReview(\Webmuch\VendorBundle\Entity\Review $reviews)
{
		$this->reviews[] = $reviews; 
		return $this;
}
/**
* Remove reviews
*
* @param \Webmuch\VendorBundle\Entity\Review $reviews
*/
	public function removeReview(\Webmuch\VendorBundle\Entity\Review $reviews)
{
		$this->reviews->removeElement($reviews);
} 
/**
* Get reviews
*
* @return \Doctrine\Common\Collections\Collection
*/
	public function getReviews()
{
		return $this->reviews;
}
/**
* Set slug
*
* @param string $slug
* @return User
*/
	public function setSlug($slug)
{
		$this->slug = $slug;
		return $this;
}
/**
* Get slug
*
* @return string
*/
	public function getSlug()
{
		return $this->slug;
}
/**
* @var \Webmuch\UserBundle\Entity\UserProfile
*/
private $userProfile; 
/**
* Set userProfile
*
* @param \Webmuch\UserBundle\Entity\UserProfile $userProfile
* @return User
*/
	public function setUserProfile(\Webmuch\UserBundle\Entity\UserProfile $userProfile = null)
{
		$this->userProfile = $userProfile; 
		return $this;
}
/**
* Get userProfile
*
* @return \Webmuch\UserBundle\Entity\UserProfile
*/
	public function getUserProfile()
{
		return $this->userProfile;
}
}

 

Wooh! That was a long one, eh? Just a bit more to go, you’re almost there.

PseudoCode For The Code Above:

Again in front registration page, email id and username cannot remain null. For this purpose, we have to assign validation to the username and email id for the normal user to get registered.

This is achieved as follows:

App/Resources/Config/Validation.xml
username -> (null=false,unique=true)
email -> (null=false,unique=true)
username_canonical -> (null=false,unique=true)
email_canonical -> (null=false,unique=true)
The code for the same is given as follows :*/
<?xml version="1.0" encoding="UTF-8" ?>
	<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
<class name="Webmuch\UserBundle\Entity\User">
<constraint name="Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity">
	<option name="fields">usernameCanonical</option>
	<option name="errorPath">username</option>
	<option name="message">fos_user.username.already_used</option>
	<option name="groups">
	<value>Registration</value>
	<value>Profile</value>
	</option>
</constraint>
	<property name="username">
<constraint name="NotBlank">
	<option name="message">fos_user.username.blank</option>
	<option name="groups">
	<value>Registration</value>
	<value>Profile</value>
	</option>
</constraint>
<constraint name="Length">
	<option name="min">2</option>
	<option name="minMessage">fos_user.username.short</option>
	<option name="max">255</option>
	<option name="maxMessage">fos_user.username.long</option>
	<option name="groups">
	<value>Registration</value>
	<value>Profile</value>
	</option>
</constraint>
</property>
<constraint name="Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity">
	<option name="fields">emailCanonical</option>
	<option name="errorPath">email</option>
	<option name="message">fos_user.email.already_used</option>
	<option name="groups">
	<value>Registration</value>
	<value>Profile</value>
	</option>
</constraint>
	<property name="email">
<constraint name="NotBlank">
	<option name="message">fos_user.email.blank</option>
	<option name="groups">
	<value>Registration</value>
	<value>Profile</value>
	</option>
</constraint>
<constraint name="Length">
	<option name="min">2</option>
	<option name="minMessage">fos_user.email.short</option>
	<option name="max">254</option>
	<option name="maxMessage">fos_user.email.long</option>
	<option name="groups">
	<value>Registration</value>
	<value>Profile</value>
	</option>
</constraint>
<constraint name="Email">
	<option name="message">fos_user.email.invalid</option>
	<option name="groups">
	<value>Registration</value>
	<value>Profile</value>
	</option>
</constraint>
</property>
	<property name="plainPassword">
	<constraint name="NotBlank">
	<option name="message">fos_user.password.blank</option>
	<option name="groups">
	<value>Registration</value>
	<value>ResetPassword</value>
	<value>ChangePassword</value>
	</option>
</constraint>
<constraint name="Length">
	<option name="min">2</option>
	<option name="max">4096</option>
	<option name="minMessage">fos_user.password.short</option>
	<option name="groups">
	<value>Registration</value>
	<value>Profile</value>
	<value>ResetPassword</value>
	<value>ChangePassword</value>
	</option>
</constraint>
</property>
</class>
</constraint-mapping>
*/Also the following code is required for the proper mapping of new base user created :
Resources/Config/Doctrine/BaseUser.orm.xml*/
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<mapped-superclass name="Webmuch\UserBundle\Entity\BaseUser">
<field name="username" column="username" type="string" length="255" unique="true" nullable="true"/>
<field name="usernameCanonical" column="username_canonical" type="string" length="255" unique="true" nullable="true" />
<field name="email" column="email" type="string" length="255" nullable="true" unique="true" />
<field name="emailCanonical" column="email_canonical" type="string" length="255" unique="true" nullable="true" />
<field name="enabled" column="enabled" type="boolean" />
<field name="salt" column="salt" type="string" />
<field name="password" column="password" type="string" />
<field name="lastLogin" column="last_login" type="datetime" nullable="true" />
<field name="locked" column="locked" type="boolean" />
<field name="expired" column="expired" type="boolean" />
<field name="expiresAt" column="expires_at" type="datetime" nullable="true" />
<field name="confirmationToken" column="confirmation_token" type="string" nullable="true" />
<field name="passwordRequestedAt" column="password_requested_at" type="datetime" nullable="true" />
<field name="roles" column="roles" type="array" />
<field name="credentialsExpired" column="credentials_expired" type="boolean" />
<field name="credentialsExpireAt" column="credentials_expire_at" type="datetime" nullable="true" />
</mapped-superclass>
</doctrine-mapping>

 

Feel free to leave comments if you appreciate the tutorial or if you have any queries. Do Subscribe to our newsletter. Keep reading, and enjoy!

Cheerio!

 

 

FOR MORE AWESOME TUTORIALS:

 

 

1. How To Embed EAV Model In Symfony2 Collection Form

newfeatimagecollection

 

 

 

 

 

 

2. How To Create A Business Application In Data Grid – ORO Platform

Oro Platform

 

 

 

 

 

 

3. How To Create A Multi Column Design Layout Using Wookmark jQuery.

wookmark jquery

 

 

 

 

 

4. Image Flip Using jQuery

imageflip

 

 

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.