FOSUserBundle + JMSSerializerBundle + exposing extra fields - symfony

I have an issue when serializing a User instance with one additional field $name, which extends the base User from FOSUserBundle:
<?php
namespace AppBundle\Entity\User;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
/**
* User
*/
class User extends BaseUser
{
/**
* #var string
*/
private $name;
/**
* Set name
* #param string $name
* #return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
* #return string
*/
public function getName()
{
return $this->name;
}
}
To simplify, I need to expose only $salt field from User entity using JMSSerializerBundle
#AppBundle\Resources\config\serializer\Model.User.yml
FOS\UserBundle\Model\User:
exclusion_policy: all
properties:
salt:
expose: true
Here's the config for it:
#app\config\config.yml
jms_serializer:
metadata:
auto_detection: true
directories:
FOSUserBundle:
namespace_prefix: "FOS\\UserBundle"
path: "#AppBundle/Resources/config/serializer"
The issue is that the serializer exposes also $name field, which I don't want as I need only to have $salt exposed:
{
"salt": "abcdefg",
"name": "Admin"
}
I believe I need to tell the serializer to use a config for my AppBundle\Entity\User instead of the base user entity from FOSUserBundle, but I have no clue how to implement it.

This is how I solved the issue . I have a User.php class that
inherit from FOS\UserBundle\Model\User as BaseUser. I need control the serialization from both my BaseUser class and my User class.
Solution: you need 2 separated config file to control each class.
config.yml
#Serializer configuration
jms_serializer:
metadata:
directories:
AppBundle:
path: "#AppBundle/Resources/config/serializer"
FOSUB:
namespace_prefix: "FOS\\UserBundle"
path: "%kernel.root_dir%/serializer/FOSUB"
Model.User.yml
FOS\UserBundle\Model\User:
exclusion_policy: ALL
properties:
id:
expose: true
username:
expose: true
email:
expose: true
enabled:
expose: true
Entity.User.yml
AppBundle\Entity\User:
exclusion_policy: ALL
properties:
imageAvatar:
expose: true
updatedAt:
expose: true
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*
* #ORM\Table(name="usuario")
* #ORM\Entity(repositoryClass="DietaBundle\Repository\UserRepository")
*
*
*/
class User extends BaseUser
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $imageAvatar;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
Clear the cache after each change in the configuration files.
cache:clear

It happens because you are using the exclusion_policy: all on the parent entity, instead of on the child entity, which still exposing all of it's properties.
you should switch to your bundle in the configuration (config.yml) under the jms_seriazlier:directories.
any-name:
namespace_prefix: "My\\FooBundle"
path: "#MyFooBundle/Resources/config/serializer"
now you could use the same configuration to expose only the desired property.
#AppBundle\Resources\config\serializer\Entity.User.yml
My\FooBundle\Entity\User:
exclusion_policy: all
properties:
salt:
expose: true

Related

Doctrine MappedSuperClass, override custom annotation

I am wondering if there is a way to change (or define inside) annotations in a child class inheriting a MappedSuperClass, for example, let say we have a class BaseUser (mappedsuperclass), a child class User :
<?php
...
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
...
/**
* #ORM\MappedSuperclass
*/
class BaseUser
{
/**
* #ORM\Column(name="firstname", type="string", length=100)
* #Serializer\SerializedName("First_Name")
* #Serializer\Expose
* #Serializer\Type("string")
* #Serializer\Groups({"Basic"})
*/
protected $firstName;
}
/**
* #ORM\Entity
*/
class User extends BaseUser
{
/**
* #ORM\Column(name="sign", type="string", length=50)
*/
private $sign;
}
What I would like to do is either defining the "Serializer" annotations from User class directly (but let the property firstName to be defined in the BaseUser class), OR, overriding the definition of Serialize from the User class.
I did not found anything about this topic, has someone already figured it out? Thanks
You can tell the JMS Serializer what to expose or not in your config.
app/config/config.yml:
jms_serializer:
metadata:
directories:
- { path: %kernel.root_dir%/Resources/FOSUserBundle/serializer, namespace_prefix: 'FOS\UserBundle' }
app/Resources/FOSUserBundle/serializer/Model.User.yml:
FOS\UserBundle\Model\User:
exclusion_policy: ALL
properties:
id:
expose: true
email:
expose: true
username:
expose: true
enabled:
expose: true
locked:
expose: true
Source: https://github.com/schmittjoh/JMSSerializerBundle/issues/78#issuecomment-31831236

Symfony2 JMSSerializerBundle expose property in YML

I want to expose only a few properties of my User class, using JMSSerializerBundle and FOSRestBundle.
It seems like the serializer bundle is not reading my configuration file.
My User class is in src/AppBundle/Entity/User and it extends the FOSUserBundle user class.
Here is my User class:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Validator\Constraints as Assert;
/**
* User
*
* #ORM\Table(name="backoffice_user")
* #ORM\Entity(repositoryClass="AppBundle\Entity\Repository\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="lastname", type="string", length=70)
*/
private $lastname;
/**
* #var string
*
* #ORM\Column(name="firstname", type="string", length=70)
*/
private $firstname;
}
This is my app/config.yml file
jms_serializer:
metadata:
debug: true
auto_detection: true
And the yml mappgin file in src/AppBundle/Resources/config/serializer/Entity.User.yml :
AppBundle\Entity\User:
exclusion_policy: ALL
exclude: true
properties:
email:
exclude: true
expose: true
The file is not read (or at least not taken into account), because my API returns me all fields of my entity.
Am I forgetting something ?
Your mapping file is not loaded, because the serializer applies the rules to the class where the properties are defined. In your case - that is FOS\UserBundle\Model\User. What you need is to override the Third-Party Metadata - a brief sample can be seen in bundle's documentation
In your config.yml, jms_serializer should probably look like this:
jms_serializer:
metadata:
auto_detection: true
directories:
FOSUserBundle:
namespace_prefix: "FOS\\UserBundle"
path: "#AppBundle/Resources/config/serializer"
Inside directory serializer you should have a file named Model.User.yml with configuration like this:
FOS\UserBundle\Model\User:
exclusion_policy: ALL
# add your desired configuration below.
In JMSSerializer you need to have one file for each class of the hierarchy.
So, the exclusion policy only apply to properties id, lastname and firstname; for BaseUser it use the default rule, which is to include everything.
To override a configuration file from another bundle, you first need to setup the folder for the namespace in the configuration with:
jms_serializer:
metadata:
directories:
FOSUB:
namespace_prefix: "FOS\\UserBundle"
path: "%kernel.root_dir%/serializer/FOSUB"
And add the serializer config file in app/serializer/FOSUB/Model.User.yml. See the official docs for other configurations option.

Could not load type "acme_user_registration"

I know this problem is highly common, I surf the solution of this problem but i don't fined. I try override the form type in FOSUserBundle (add name field), and i follow this documentation:
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/1.3.x/Resources/doc/overriding_forms.md, I get an error : "Could not load type "acme_user_registration".
My Entity User:
//src/MyBlogBundle/UserBundle/Entity/User.php
namespace MyBlogBundle\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=50)
* #Assert\NotBlank(message="Please enter your name.", groups= {"Registration", "Profile"})
* #Assert\Length(min=3,max=50, minMessage="The name is too short.",
* maxMessage = "Your first name cannot be longer than {{ limit }} characters long",
* groups={"Registration", "Profile"})
*/
protected $name;
public function __construct()
{
parent::__construct();
}
}
My FormType:
// src/MyBlogBundle/UserBundle/Form/Type/RegistrationFormType.php
namespace MyBlogBundle\UserBundle\Form\Type;
use Symfony\Component\Form\FormBuilderInterface;
use FOS\UserBundle\Form\Type\RegistrationFormType as BaseType;
class RegistrationFormType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->add('name');
}
public function getName()
{
return 'acme_user_registration';
}
}
Configuring form type:
# src/MyBlogBundle/UserBundle/Resources/config/services.yml
services:
acme_user.registration.form.type:
class: MyBlogBundle\UserBundle\Form\Type\RegistrationFormType
arguments: [%fos_user.model.user.class%]
tags:
- { name: form.type, alias: acme_user_registration }
And app/config/config.yml:
fos_user:
db_driver: orm
firewall_name: main
user_class: MyBlogBundle\UserBundle\Entity\User
registration:
form:
type: acme_user_registration
Can any give me a tip what i do wrong?
transfered configuring from src/MyBlogBundle/UserBundle/Resources/config/services.yml to src/MyBlogBundle//Resources/config/services.yml and add Set and Get method to User Entity - it's solve my problem.

StofDoctrineExtensionsBundle seems to not work with Entities configured by YML

I try to use softdelete in my application, but it doesn't work. When I delete an entity, it's also deleted from the database.
I installed "stof/doctrine-extensions-bundle": "1.2.*#dev" and added it to the Kernel.
My Configuration:
stof_doctrine_extensions:
orm:
default:
...
softdeleteable: true
doctrine:
...
orm:
filters:
softdeleteable:
class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
enabled: true
My YML-Definition:
...\Entity\Person:
type: entity
table: person
id:
id:
...
fields:
salutation:
type: string
length: 255
...
deletedAt:
type: datetime
nullable: true
My Entity:
<?php
namespace ...\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Person
* #Gedmo\SoftDeleteable(fieldName="deletedAt")
*/
class Person
{
...
/**
* #var \DateTime
*/
private $deletedAt;
...
/**
* Set deletedAt
*
* #param \DateTime $deletedAt
* #return NaturalPerson
*/
public function setDeletedAt($deletedAt)
{
$this->deletedAt = $deletedAt;
return $this;
}
/**
* Get deletedAt
*
* #return \DateTime
*/
public function getDeletedAt()
{
return $this->deletedAt;
}
}

Symfony2 - translatable field - The class 'Gedmo\Translatable\Entity\Translation' was not found in the chain configured namespaces

I'm trying to translate some fields of my entity and I have the following error when I'm try create an object...
<?php
namespace XXXX\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Translatable\Translatable;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Line
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="XXXX\Entity\LineRepository")
*/
class Line implements Translatable
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #Gedmo\Translatable
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Line
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
public function setTranslatableLocale($locale)
{
$this->locale = $locale;
}
}
And the error:
[Doctrine\Common\Persistence\Mapping\MappingException]
The class 'Gedmo\Translatable\Entity\Translation' was not found in the chain configured namespaces
I'm using Symfony 2.5, but in 2.4 occurs too. Any idea how I can solve this?
You need to configure the translatable Entity to use as well. In config.yml:
orm:
(....)
mappings:
translatable:
type: annotation
is_bundle: false
prefix: Gedmo\Translatable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
alias: GedmoTranslatable
Update for Symfony 5 :
Configure the /config/packages/doctrine.yaml file and add the following
orm:
(....)
mappings:
translatable:
type: annotation
is_bundle: false
prefix: Gedmo\Translatable\Entity
dir: '%kernel.project_dir%/vendor/gedmo/doctrine-extensions/src/Translatable/Entity'
alias: GedmoTranslatable

Resources