Symfony2 security: Multiple providers - symfony

I have 2 bundles in my project:
src/Korea/AlmacenBundle
src/Galvez/RepuestosBundle
Each with their own database
korea_motos -> AlmacenBundle
galvez_motos -> RepuestosBundle
Actually my security.yml has only one provider:
providers:
korea:
entity: { class: Korea\AlmacenBundle\Entity\Usuario, property: username }
As you can see, both bundles are authenticated by the same table: Usuario, in korea_motos
TABLE: Usuario (korea_motos database)
--ID--|----USERNAME----|---------BUNDLE---
-----1-----|-------------admin----------------|----------AlmacenBundle----------
-----2-----|-------------admin----------------|----------RepuestosBundle-------
Now i want to validate the users, for RepuestosBundle with a table Usuario in galvez_motos, removing the column "bundle" in the previous table.
The problem is in the security.yml file. If i make this:
providers:
korea:
entity: { class: Korea\AlmacenBundle\Entity\Usuario, property: username }
galvez:
entity: { class: Galvez\RepuestosBundle\Entity\Usuario, property: username }
Symfony launch a exception:
The class 'Galvez\RepuestosBundle\Entity\Usuario' was not found in the chain configured namespaces Korea\AlmacenBundle\Entity
Im trying to use 2 providers, one table per each bundle.. is this possible?
Files:
security.yml
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
Korea\AlmacenBundle\Entity\Usuario:
algorithm: sha1
encode_as_base64: false
iterations: 1
Galvez\RepuestosBundle\Entity\Usuario:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ]
providers:
korea:
entity: { class: Korea\AlmacenBundle\Entity\Usuario, property: username }
galvez:
entity: { class: Galvez\RepuestosBundle\Entity\Usuario, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/demo/secured/login$
security: false
secured_area:
pattern: ^/
anonymous: ~
access_denied_handler: accessdenied_handler
form_login:
login_path: /login
check_path: /login_check
default_target_path: /redirect
always_use_default_target_path: true
logout:
path: /logout
target: /login
#anonymous: ~
#http_basic:
# realm: "Secured Demo Area"
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/redirect, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/galvez, roles: ROLE_ADMIN_GALVEZ }
- { path: ^/, roles: ROLE_ADMIN_KOREA }
config.yml -- can't copy/paste all :(
doctrine:
dbal:
default_connection: default
connections:
default:
driver: "%database_driver%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
host: "%database_host%"
port: "%database_port%"
charset: UTF8
galvez:
driver: %database_driver%
dbname: %database_name2%
user: %database_user2%
password: %database_password2%
host: %database_host%
port: %database_port%
charset: UTF8
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
AlmacenBundle: ~
galvez:
connection: galvez
mappings:
RepuestosBundle: ~
parameters.yml
parameters:
database_driver: pdo_mysql
database_host: localhost
database_port: null
database_name: korea_motos
database_user: root
database_password:
mailer_transport: smtp
mailer_host: localhost
mailer_user: null
mailer_password: null
locale: en
secret: 5f7ac4e7c2b38d6dbe55a1f05bee2b02
database_path: null
database_name2: galvez_motos
database_user2: root
database_password2:
PD: Sry for my english :S

Old question but for anyone looking for a solution, the manual explains it all here.
Basically, you need to chain your providers like this:
# app/config/security.yml
security:
providers:
chain_provider:
chain:
providers: [korea, galvez]
korea:
entity: { class: Korea\AlmacenBundle\Entity\Usuario, property: username }
galvez:
entity: { class: Galvez\RepuestosBundle\Entity\Usuario, property: username }

This is probably an issue with namespaces of your classes. Check if class Galvez\RepuestosBundle\Entity\Usuario is in the right namespace and if configuration is correct - maybe you accidentally left some copy-and-paste code from the other entity.
Try to persist both of these entities and fetch them (without security context) - I think you'll find your issue there.

I made a test with both entities:
abcController.php
$em= $this->get('doctrine')->getManager('galvez');
$usuario_g = $this->get('doctrine')->getRepository('RepuestosBundle:Usuario', 'galvez')->find(1);
$usuario_g->setUsername('asdasd');
$em->persist($usuario_g);
$em->flush();
Works fine, but if i use
$em = $this->getDoctrine()->getEntityManager();
instead of
$em = $this->get('doctrine')->getManager('galvez');
When i try to flush, Symfony launchs the same error:
The class 'Galvez\RepuestosBundle\Entity\Usuario' was not found in the chain configured namespaces Korea\AlmacenBundle\Entity
Usuario.php (AlmacenBundle)
<?php
namespace Korea\AlmacenBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* Usuario
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Korea\AlmacenBundle\Entity\UsuarioRepository")
*/
class Usuario 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=255)
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #var string
*
* #ORM\Column(name="salt", type="string", length=255)
*/
private $salt;
Usuario.php (RepuestosBundle)
<?php
namespace Galvez\RepuestosBundle\Entity;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* Usuario
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Galvez\RepuestosBundle\Entity\UsuarioRepository")
*/
class Usuario 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=255)
*/
private $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=255)
*/
private $password;
/**
* #var string
*
* #ORM\Column(name="salt", type="string", length=255)
*/
private $salt;
PD: Well, i think it's not possible, if i change this:
default_connection: korea
to:
default_connection: galvez
Symfony says:
MappingException: The class 'Korea\AlmacenBundle\Entity\Usuario' was not found in the chain configured namespaces Galvez\RepuestosBundle\Entity
the same error, but in reverse..
It seems like the monolog validation take the default connection (korea in this case) for search and validate

Related

Symfony 4.1 - Two EntityManagers. Migration goes twice on second EntityManager

I've followed the directions on this page:
https://symfony.com/doc/current/doctrine/multiple_entity_managers.html
And my doctrine.yaml file looks like:
doctrine:
dbal:
default_connection: one
connections:
one:
# configure these for your database server
url: '%env(DATABASE_ONE_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
two:
# configure these for your database server
url: '%env(DATABASE_TWO_URL)%'
driver: 'pdo_mysql'
server_version: '5.7'
charset: utf8mb4
orm:
default_entity_manager: one
entity_managers:
one:
connection: one
mappings:
One:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/One'
prefix: 'App\Entity\One'
alias: One
two:
connection: two
mappings:
Two:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/Two'
prefix: 'App\Entity\Two'
alias: Two
I've got a One and Two directory inside my Entity directory with a simple Entity class in both:
A Person in One:
<?php
namespace App\Entity\One;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="person")
*/
class Person
{
/**
* #var int
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string")
*/
private $name;
{Getters and setters ...}
}
A Post in Two:
<?php
namespace App\Entity\Two;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="post")
*/
class Post
{
/**
* #var int
*
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
*
* #ORM\Column(type="string")
*/
private $title;
{Getters and setters ...}
}
When I run bin/console doctrine:migrations:diff and bin/console doctrine:migrations:migrate the Person is added to the One database correctly.
When I run bin/console doctrine:migrations:diff --em=two and bin/console doctrine:migrations:migrate --em=two both this and the Person migration for One are executed and the Two database has both a Person and a Page table.
I can't seem to figure out where I'm going wrong with this

Symfony3 FosUser and FosAuthServer, login user with LDAP on AuthenticationFailureHandler

I'm working in symfony with FosUser and FosAuthServer.
I have a front web site who access to an API by Oauth2. On the front web site, if the user is not logon, redirect him to the oauth serveur and after the user is login, redirect him to the font web site with an oauth2 token.
It's work well, but I need this :
if user is find in the database (my user provider), longin him
if the user is not find in the database, I search him in LDAP and I login him manually.
To do this, I use the AuthenticationFailureHandler to find the user in the LDAP. After find him, I create a User Entity and dispatch envent FOSUserEvents::SECURITY_IMPLICIT_LOGIN, but I don't know who can I create a token and redirect to the front web site.
security.yml
security:
encoders:
AppBundle\Entity\User: sha512
Symfony\Component\Security\Core\User\User: plaintext
providers:
api:
id: fos_user.user_provider.username_email
admin:
memory:
users:
admin: { password: password}
firewalls:
doc:
pattern: ^/api/doc
anonymous: true
oauth_token:
pattern: ^/oauth/v2/token
security: false
oauth_authorize:
pattern: ^/oauth/v2/auth
guard:
authenticators:
- app.security.login_form_authenticator
form_login:
provider: api
csrf_token_generator: security.csrf.token_manager
login_path: fos_user_security_login
check_path: fos_user_security_check
failure_handler: app.authentification_failure_handler
logout:
path: fos_user_security_logout
target: fos_user_security_login
anonymous: true
admin:
pattern: ^/admin
http_basic:
realm: 'Secured Area'
provider: admin
anonymous: false
api:
pattern: ^/api
fos_oauth: true
stateless: true
anonymous: false
access_control:
- { path: ^/oauth/v2/auth, roles: [ IS_AUTHENTICATED_ANONYMOUSLY ] }
- { path: ^/api/doc, roles: [ IS_AUTHENTICATED_ANONYMOUSLY ] }
- { path: ^/admin, roles: [ IS_AUTHENTICATED_FULLY ] }
- { path: ^/, roles: [ ROLE_USER ] }
Service.yml
app.authentification_failure_handler:
public: false
class: AppBundle\Handler\AuthenticationFailureHandler
arguments:
- '#utilities.active_directory.ageo'
- '#doctrine.orm.entity_manager'
- '#fos_user.user_manager'
- '#security.token_storage'
- '#debug.event_dispatcher'
- '#router'
- '#http_kernel'
- '#security.http_utils'
AuthentificationFaillureHandler.php
<?php
namespace AppBundle\Handler;
use AppBundle\Entity\Assure;
use AppBundle\Entity\BrokerStructur;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use FOS\OAuthServerBundle\Model\AuthCodeManager;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Event\UserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Model\UserManager;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\HttpUtils;
class AuthenticationFailureHandler extends DefaultAuthenticationFailureHandler
{
// private $cafeteriaEntityManager;
private $router;
/**
* #var \Ageo\UtilitiesBundle\ActiveDirectory\Ageo Connection au LDAP Ageo
*/
private $ldap;
/**
* #var $entityManagerSql Manager des entitées de la base mysql
*/
private $entityManagerSql;
/**
* #var UserManager Manager des utilisateurs (FosUserBundle)
*/
private $userManager;
/**
* #var EventDispatcher
*/
private $eventDispatcher;
/**
* #var TokenStorage
*/
private $tokenStorage;
public function __construct(\Ageo\UtilitiesBundle\ActiveDirectory\Ageo $ldap, EntityManager $entityManagerSql, UserManager $userManager,
TokenStorage $tokenStorage, \Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher $eventDispatcher,
RouterInterface $router, HttpKernelInterface $httpKernel, HttpUtils $httpUtils)
{
$this->ldap = $ldap;
$this->router = $router;
$this->entityManagerSql = $entityManagerSql;
$this->userManager = $userManager;
$this->tokenStorage = $tokenStorage;
$this->eventDispatcher = $eventDispatcher;
parent::__construct($httpKernel, $httpUtils, array(), null);
}
/**
* Si l'utilisateur n'est pas présent dans la base de données local, on le cherche dans l'Active directory pour le logguer
* On vérifie ensuite s'il existe dans la base de donné local. S'il existe, on le charge et on le met à jour, sinon, on le crée.
* #param Request $request
* #param AuthenticationException $exception
* #return RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$username = trim($request->request->get('_username'));
$password = trim($request->request->get('_password'));
/*
* Manupulation to find the user in LDAP => $userAd
*/
$loaclUser = $this->userManager->createUser();
$loaclUser
->setEnabled(true)
->setUsername($username)
->setPlainPassword($password)
->setEmail($userAd->hasAttribute('mail') ? $userAd->getAttribute('mail')[0] : null )
$this->userManager->updateUser($loaclUser);
$this->eventDispatcher->dispatch(FOSUserEvents::SECURITY_IMPLICIT_LOGIN, new UserEvent($loaclUser, $request));
//$this->eventDispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($loaclUser, $request, $response));
// I need to login my user on authServeur
// I have test this, but it's not working
if ($this->session->has('_security.oauth_authorize.target_path'))
{
parse_str(parse_url($this->session->get('_security.oauth_authorize.target_path'), PHP_URL_QUERY), $target_path);
$url = $this->session->get('_security.oauth_authorize.target_path');
}
$response = new RedirectResponse($url);
return $response;
}
}
Anyone say who can I do the same proccess of the login_check ?
I never done it but this seems to be the use case of the chain provider
security:
providers:
chain_provider:
chain:
providers: [api, admin, ldap_provider]

Empty Dashboard Symfony3 sonata adminBundle

Faced the problem of setting up the admin panel. I do everything according to the documentation, there are no errors, Dashboard opens and everything is empty. The project is simple as a door - the simplest blog. Nothing shows up - neither the names of categories nor posts. The whole brain broke itself.
config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: en
framework:
#esi: ~
translator: { fallbacks: [en] }
secret: '%secret%'
router:
resource: '%kernel.project_dir%/app/config/routing.yml'
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: '%locale%'
trusted_hosts: ~
session:
# https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
handler_id: session.handler.native_file
save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
fragments: ~
http_method_override: true
assets: ~
php_errors:
log: true
# Twig Configuration
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: '%kernel.project_dir%/var/data/data.sqlite'
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
#path: '%database_path%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: '%mailer_transport%'
host: '%mailer_host%'
username: '%mailer_user%'
password: '%mailer_password%'
spool: { type: memory }
#Cache
doctrine_cache:
providers:
my_markdown_cache:
type: file_system
file_system:
directory: /tmp/doctrine_cache
sonata_admin:
title: My Blog Admin
sonata_block:
default_contexts: [cms]
blocks:
sonata.admin.block.admin_list:
contexts: [admin]
services.yml
parameters:
#parameter_name: value
services:
# default configuration for services in *this* file
_defaults:
# automatically injects dependencies in your services
autowire: true
# automatically registers your services as commands, event subscribers, etc.
autoconfigure: true
# this means you cannot fetch services directly from the container via $container->get()
# if you need to do this, you can override this setting on individual services
public: false
# makes classes in src/AppBundle available to be used as services
# this creates a service per class whose id is the fully-qualified class name
AppBundle\:
resource: '../../src/AppBundle/*'
# you can exclude directories or files
# but if a service is unused, it's removed anyway
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
# controllers are imported separately to make sure they're public
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
# add more services, or override services that need manual wiring
# AppBundle\Service\ExampleService:
# arguments:
# $someArgument: 'some_value'
services:
app.admin.category:
class: AppBundle\Admin\CategoryAdmin
arguments: [~, AppBundle\Entity\Category, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: Category }
public: true
app.admin.articles:
class: AppBundle\Admin\ArticlesAdmin
arguments: [~, AppBundle\Entity\Articles, ~]
tags:
- { name: sonata.admin, manager_type: orm, label: Blog post }
public: true
CategoryAdmin class
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
class CategoryAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('name', 'text', array('label' => 'Название'));
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add('name');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('name');
}
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
->add('name');
}
}
Category Entity Class
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Category
*
* #ORM\Table(name="category")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository")
*/
class Category
{
/**
* #ORM\OneToMany(targetEntity="Articles", mappedBy="category")
*/
private $blogPosts;
public function __construct()
{
$this->blogPosts = new ArrayCollection();
}
public function getBlogPosts()
{
return $this->blogPosts;
}
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
The problem is solved. The solution was not in the documentation for the bundle but in the documentation of the symphony

FOSUserBundle + JMSSerializerBundle + exposing extra fields

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

Doctrine Behaviors fields in Symfony2 auto-generated CRUD

I'm starting with Symfony and I have Entity "Post"
<?php
namespace My\BackendBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Post
*
* #ORM\Table()
* #ORM\Entity
*/
class Post
{
/**
* #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=255)
*/
private $title;
/**
* #var string
*
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(type="string", length=255, unique=true)
*/
private $slug;
/**
* #var string
*
* #ORM\Column(name="text", type="text")
*/
private $text;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
* #return Post
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set text
*
* #param string $text
* #return Post
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
/**
* Get text
*
* #return string
*/
public function getText()
{
return $this->text;
}
/**
* Set slug
*
* #param string $slug
* #return Post
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
}
I've generated table in database:
app/console doctrine:schema:update --force
And CRUD panel:
app/console doctrine:generate:crud
with options:
Entity: MyBackendBundle:Post
"write" action: yes
But as you can see, I have "slug" field and I want Doctrine to auto-generate it. But default CRUD panel at "/post/new" have inputs for all 3 fields (title, slug and text). And after hours of searching for solution only one I can do is manually delete "slug" input from My/BackendBundle/Form/PostType.php.
I don't know if I'm doing something wrong or it's just works like that? Sluggable behavior works good when I'm adding entity manually (by creating new Post() with title and text and doing $manager->flush()).
My /app/config/config.yml file:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
framework:
#esi: ~
translator: { fallback: %locale% }
secret: %secret%
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_proxies: ~
session: ~
fragments: ~
# Twig Configuration
twig:
debug: %kernel.debug%
strict_variables: %kernel.debug%
# Assetic Configuration
assetic:
debug: %kernel.debug%
use_controller: false
bundles: [ ]
#java: /usr/bin/java
filters:
cssrewrite: ~
#closure:
# jar: %kernel.root_dir%/Resources/java/compiler.jar
#yui_css:
# jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar
# Doctrine Configuration
doctrine:
dbal:
driver: %database_driver%
host: %database_host%
port: %database_port%
dbname: %database_name%
user: %database_user%
password: %database_password%
charset: UTF8
# if using pdo_sqlite as your database driver, add the path in parameters.yml
# e.g. database_path: %kernel.root_dir%/data/data.db3
# path: %database_path%
orm:
auto_generate_proxy_classes: %kernel.debug%
auto_mapping: true
mappings:
StofDoctrineExtensionsBundle: false
stof_doctrine_extensions:
default_locale: en_US
orm:
default:
sluggable: true
# Swiftmailer Configuration
swiftmailer:
transport: %mailer_transport%
host: %mailer_host%
username: %mailer_user%
password: %mailer_password%
spool: { type: memory }
fos_user:
db_driver: orm
firewall_name: main
user_class: My\UserBundle\Entity\User
If it's normal and I have to do it manually simple confirmation would be great.
app/console doctrine:generate:crud command use generate:doctrine:form command which generate fields for all entity properties.
So yes, you must remove unnecessary fields from form OR use more advenced generators like AdmigeneratorGeneratorBundle.

Resources