I have configured Symfony 3 to auto serialize my action. It works, but the relations aren't serialized:
0
id 1
name "Liste de course"
creation_date "2017-07-07T00:00:00+00:00"
last_update_date "2017-07-07T20:57:06+00:00"
user_entity
_todo_entity_entities
_parent_entity
1
id 2
name "domotique"
creation_date "2017-07-07T00:00:00+00:00"
last_update_date "2017-07-07T21:22:52+00:00"
user_entity
_todo_entity_entities
_parent_entity
If I explicitly use JMSSerializerBundle, it works (user_entity is an object):
0
id 1
name "Liste de course"
creation_date "2017-07-07T00:00:00+00:00"
last_update_date "2017-07-07T20:57:06+00:00"
user_entity Object
_todo_entity_entities
1
id 2
name "domotique"
creation_date "2017-07-07T00:00:00+00:00"
last_update_date "2017-07-07T21:22:52+00:00"
user_entity Object
_todo_entity_entities
I think FOSRestBundle uses the default seralizer, not JMSSerializerBundle:
/**
* #Rest\Get("/projects")
* #View(
* serializerGroups = {"all"}
* )
*/
public function getProjectsAction()
{
$projectEntity = $this->getDoctrine()->getRepository('todoListAdminBundle:Project');
$projects = $projectEntity->findAll();
/*
$data = $this->get('jms_serializer')->serialize($projects, 'json');
// this is work !
$response = new Response($data);
$response->headers->set('Content-Type', 'application/json');
return $response;
*/
return $projects;
}
The entity I serialize :
/**
* Project
*
* #ORM\Table(name="project")
* #ORM\Entity(repositoryClass="todoListAdminBundle\Repository\ProjectRepository")
*/
class Project
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #Serializer\Groups({"all"})
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
* #Assert\Length(max=50)
* #Assert\Type(type="string")
* #Serializer\Groups({"all"})
*/
private $name;
/**
* #var \DateTime
*
* #ORM\Column(name="creation_date", type="date")
* #Assert\DateTime()
* #Serializer\Groups({"all"})
*/
private $creationDate;
/**
* #var \DateTime
*
* #ORM\Column(name="last_update_date", type="datetime")
* #Assert\DateTime()
* #Serializer\Groups({"all"})
*/
private $lastUpdateDate;
/**
*
* #ORM\ManyToOne(targetEntity="PW\UserBundle\Entity\User", inversedBy="projectEntities" , cascade={"persist"}, inversedBy="projectEntities")
* #Assert\Type(type="integer")
* #Serializer\Groups({"all"})
*/
private $userEntity;
/**
* #ORM\OneToMany(targetEntity="todoListAdminBundle\Entity\TodoEntity", mappedBy="projectEntity", fetch="EAGER")
* #Serializer\Groups({"all"})
*/
private $TodoEntityEntities;
/**
* #var int
*
* #ORM\JoinColumn(nullable=true, referencedColumnName="id")
* #ORM\OneToOne(targetEntity="todoListAdminBundle\Entity\Project")
* #Assert\Type(type="integer")
* #Serializer\Groups({"all"})
*/
private $ParentEntity;
My configuration :
fos_rest:
param_fetcher_listener: true
body_listener: true
zone:
- { path: ^/api/* }
body_converter:
enabled: true
view:
formats: { json: true, xml: false, rss: false }
view_response_listener: true
serializer:
serialize_null: true
format_listener:
enabled: true
rules:
- { path: '^/api', priorities: ['json'], fallback_format: 'json' }
routing_loader:
default_format: json
sensio_framework_extra:
view: { annotations: true }
How can I use JMSSerializerBundle automatically ?
First of all, you need to configure JMSSerializer in your config.yml like:
jms_serializer:
metadata:
cache: file
debug: "%kernel.debug%"
file_cache:
dir: "%kernel.cache_dir%/serializer"
auto_detection: true
Then, create directory with serializer for the given entity YourBundleName/Resources/config/serializer/Entity.Project.yml with this code:
YourBundleName\Entity\Project:
exclusion_policy: ALL
properties:
id:
expose: true
name:
expose: true
"exclusion_policy: ALL" - exclude all the fields from the serialized result. And then you add needed fields with "expose: true". Just do not add "ParentEntity" there and you will not see it in the serialized data (also, I do not think, that mix of camel and pascal case is a good practice, but it's the question of taste).
Related
I use personal translation of StofDoctrineExtensionsBundle.
I've configured my App but i can't retrieve the translated labels, i get always the default text.
config.yml
# Doctrine Configuration
doctrine:
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
menu_tree:
type: annotation
prefix: Gedmo\Tree\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity"
alias: MenuTree
is_bundle: false
gedmo_translatable:
type: annotation
prefix: Gedmo\Translatable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
alias: GedmoTranslatable # (optional) it will default to the name set for the mapping
is_bundle: false
gedmo_translator:
type: annotation
prefix: Gedmo\Translator\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translator/Entity"
alias: GedmoTranslator # (optional) it will default to the name set for the mapping
is_bundle: false
stof_doctrine_extensions:
default_locale: "%locale%"
translation_fallback: true
orm:
default:
tree: true
translatable: true
sluggable: true
Then i wrote my personal Entity, this is a MenuItem
<?php
namespace App\Entity\Menu;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
*
* #ORM\Table(name="mnu_item")
* #ORM\Entity(repositoryClass="App\Repository\Menu\MenuItem")
* #Gedmo\Tree(type="nested")
* #Gedmo\TranslationEntity(class="App\Entity\Menu\MenuItemTranslation")
*/
class MenuItem{
/**
*
* #var integer
*
* #ORM\Column(name="id", type="integer", options={"unsigned"=true})
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #var string
* #Gedmo\Translatable
* #ORM\Column(name="label", type="string", length=255, nullable=true)
*/
private $label;
/**
* #Gedmo\Locale
* Used locale to override Translation listener`s locale
* this is not a mapped field of entity metadata, just a simple property
* and it is not necessary because globally locale can be set in listener
*/
private $locale;
/**
* #ORM\OneToMany(targetEntity="\App\Entity\Menu\MenuItemTranslation",
* mappedBy="object",
* cascade={"persist", "remove"})
*/
private $translations;
/**
* #var \App\Entity\Menu\Menu
*
* #ORM\ManyToOne(targetEntity="App\Entity\Menu\Menu", inversedBy="menuItems")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="menu_id", referencedColumnName="id", onDelete="CASCADE")
* })
*/
private $menu;
/**
* Constructor
*/
public function __construct() {
$this->ruoli = new \Doctrine\Common\Collections\ArrayCollection();
$this->children = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set label
*
* #param string $label
*
* #return MenuItem
*/
public function setLabel($label) {
$this->label = $label;
return $this;
}
/**
* Get label
*
* #return string
*/
public function getLabel() {
return $this->label;
}
/**
* Set menu
*
* #param \App\Entity\Menu\Menu $menu
*
* #return MenuItem
*/
public function setMenu(\App\Entity\Menu\Menu $menu = null) {
$this->menu = $menu;
return $this;
}
/**
* Get menu
*
* #return \App\Entity\Menu\Menu
*/
public function getMenu() {
return $this->menu;
}
/**
*
* #return type
*/
public function getTranslations(){
return $this->translations;
}
/**
*
* #param \App\Entity\Menu\MenuItemTranslation $t
*/
public function addTranslation(MenuItemTranslation $t){
if (!$this->translations->contains($t)) {
$this->translations[] = $t;
$t->setObject($this);
}
}
public function setTranslatableLocale($locale){
$this->locale = $locale;
}
}
At least i have my Translator Class
<?php
namespace App\Entity\Menu;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation;
/**
* Description of MenuItemTranslation
/*
* #ORM\Entity
* #ORM\Table(name="mnu_menu_item_translations",
* uniqueConstraints={#ORM\UniqueConstraint(name="lookup_unique_idx", columns={
* "locale", "object_id", "field"
* })}
* )
*/
class MenuItemTranslation extends AbstractPersonalTranslation {
/**
* Convenient constructor
*
* #param string $locale
* #param string $field
* #param string $value
*/
public function __construct($locale, $field, $value)
{
$this->setLocale($locale);
$this->setField($field);
$this->setContent($value);
}
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Menu\MenuItem", inversedBy="translations")
* #ORM\JoinColumn(name="object_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $object;
}
I have translated my label and it works, but in a twig tempate, using item.label or item.getLabel() i obtain always the default MenuItem valu (E.g. Test insted of Prova, see images)
Menu Item
Menu Item Translation
I've messed with locale.
I changed the stof config 'cos my site is all in english and i need italian translation
stof_doctrine_extensions:
default_locale: "%locale%" #this is my error, just remove this line
# to set it back to en_US (default value).
# This indicates the locale of original table,
# if it's set to the same
# locale of the entire system it won't
# retrieve any translation
translation_fallback: true
orm:
default:
tree: true
translatable: true
sluggable: true
So the correct one is
Then i changed the stof config 'cos my site is all in english and i need italian translation
stof_doctrine_extensions:
translation_fallback: true
orm:
default:
tree: true
translatable: true
sluggable: true
I'm using FOSRestBundle - with automatic rotues and automatic views. My action in Controller looks like this:
public function getAction($user_id)
{
$user = $this->em->getRepository('SBGUserBundle:User')->find($user_id);
return $user;
}
Everything is OK, my response in JSON format looks like this:
{
"id": 20,
"username": "fwojciechowski",
"mpks": [{
"id": 91,
"name": "Testowe MPK 1",
"managers": []
}, {
"id": 92,
"name": "Testowe MPK 2",
"teta_id": 1,
"managers": []
}]
}
But I have to take 1 level depth more - i need "managers" in "mpks" array.
But I don't need 3 levels in other cases.
How can I do it?
annotations
if you are using annotations you can do it like this yml configs later for reference.
first you go to the manager entity and add the following :
/**
* Manager
*
* #ORM\Table(name="manager")
* #ORM\Entity
*
* #Serializer\ExclusionPolicy("all")
*/
class Manager
{
......
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*
* #Serializer\Expose
* #Serializer\Groups({
* "user",
* })
*/
private $id;
now you decide what properties you need from the managers and add the following before each entity
* #Serializer\Expose
* #Serializer\Groups({
* "user",
* })
$property
then before your getAction you add this
/**
* Get User.
*
* #param User $user
*
* #return User
*
* #Route\Get("/users", options={"expose"=true})
*
* #View(serializerGroups={"user"}) \\notice that its the same group name from before Serializer\Groups({"user"})
*
* #ApiDoc(
* ....
* )
*/
public function getAction()
yml
it should look something like this
Acme\User:
exclusion_policy: ALL
properties:
id:
expose: true
username:
expose: true
mpks:
expose: true
Acme\Manager
exclusion_policy: ALL
properties:
id:
expose: true
first_name:
expose: true
last_name:
expose: true
#and the rest of your wanted properties
I need to configure the payum bundle in order to let clients process paypal payments.
I just followed the getting started official recomendations, but need to configure something more, I guess (maybe I am missing to configure the storage for PaymentDetails somewhere).
my config files are as follows:
**app/config.yml**
doctrine:
orm:
auto_generate_proxy_classes: true
entity_managers:
default:
mappings:
WebsiteDeviceBundle: ~
WebsiteOnePageBundle: ~
payum:
is_bundle: false
type: xml
dir: %kernel.root_dir%/../vendor/payum/payum/src/Payum/Core/Bridge/Doctrine/Resources/mapping
prefix: Payum\Core\Model
payum:
security:
token_storage:
Website\Bundle\DeviceBundle\Entity\PaymentToken: { doctrine: orm }
storages:
Website\Bundle\DeviceBundle\Entity\PaymentDetails: { doctrine: orm }
contexts:
express_euro:
paypal_express_checkout_nvp:
username: ''
password: ''
signature: ''
sandbox: true
this is my controller action to start the payment process
public function prepareAction(){
$paymentName = 'express_euro';
$storage = $this->get('payum')->getStorage('Website\DeviceBundle\Entity\PaymentDetails');
$order = $storage->createModel();
$order->setNumber(uniqid());
$order->setCurrencyCode('EUR');
$order->setTotalAmount($this->view['user']->money);
$order->setDescrizione('annual account subscription');
$order->setUser($this->view['user']->getId());
$order->setCreatedAt(new \DateTime());
$order->setClientEmail($this->view['user']->getEmail());
$storage->updateModel($order);
$captureToken = $this->get('payum.security.token_storage')->createCaptureToken(
$paymentName,
$order,
'done' // the route to redirect after capture;
);
return $this->redirect($captureToken->getTargetUrl());
}
and this is PaymentDetails class
<?php
namespace Website\Bundle\DeviceBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Payum\Core\Model\ArrayObject;
/**
* PaymentDetails
*
* #ORM\Table(name="PaymentDetails", indexes={#ORM\Index(name="user", columns={"user"})})
* #ORM\Entity(repositoryClass="Website\Bundle\DeviceBundle\Entity\PaymentsDetailsRepository")
*/
class PaymentDetails extends ArrayObject
{
/**
* #var string
*
* #ORM\Column(name="currency_code", type="string", length=255, nullable=false)
*/
private $currencyCode;
/**
* #var string
*
* #ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="datetime", nullable=true)
*/
private $createdAt;
/**
* #var integer
*
* #ORM\Column(name="number", type="integer", nullable=false)
*/
private $number;
/**
* #var integer
*
* #ORM\Column(name="total_amount", type="integer", nullable=false)
*/
private $totalAmount;
/**
* #var string
*
* #ORM\Column(name="client_email", type="text", nullable=false)
*/
private $clientEmail;
/**
* #var integer
*
* #ORM\Column(name="id", type="bigint")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \Website\Bundle\DeviceBundle\Entity\Users
*
* #ORM\ManyToOne(targetEntity="Website\Bundle\DeviceBundle\Entity\Users")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user", referencedColumnName="id")
* })
*/
private $user;
and the error it comes when I GET the doneAction() url, is this
A storage for model Website\DeviceBundle\Entity\PaymentDetails was not registered. There are storages for next models: Website\Bundle\DeviceBundle\Entity\PaymentDetails.
any helps or suggestions?
thank you in advance
just changed this line
$storage = $this->get('payum')->getStorage('Website\DeviceBundle\Entity\PaymentDetails');
into
$storage = $this->get('payum')->getStorage('Website\Bundle\DeviceBundle\Entity\PaymentDetails');
and now it works.
i have two tables news and news_category. for that i have created two mapping class using symfony command 'doctrine:mapping:convert'. the two file as bellow.
news.orm.yml.
News:
type: entity
table: news
fields:
newsId:
id: true
type: integer
unsigned: false
nullable: false
column: news_id
generator:
strategy: IDENTITY
newsTitle:
type: string
length: 255
fixed: false
nullable: false
column: news_title
newsDescription:
type: text
nullable: false
column: news_description
newsStatus:
type: string
length: 255
fixed: false
nullable: false
column: news_status
createdAt:
type: date
nullable: false
column: created_at
manyToOne:
category:
targetEntity: NewsCategory
cascade: { }
mappedBy: null
inversedBy: null
joinColumns:
category_id:
referencedColumnName: category_id
orphanRemoval: false
lifecycleCallbacks: { }
2). NewCategory.orm.yml
NewsCategory:
type: entity
table: news_category
fields:
categoryId:
id: true
type: integer
unsigned: false
nullable: false
column: category_id
generator:
strategy: IDENTITY
categoryTitle:
type: string
length: 255
fixed: false
nullable: false
column: category_title
categoryDescription:
type: text
nullable: false
column: category_description
lifecycleCallbacks: { }
after that i have used the another symfony command "doctrine:mapping:import" using this i have again generate two file in Entity folder News.php and NewsCategory.php
which is as bellow.
1) news.php
<?php
namespace Admin\NewsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* News
*
* #ORM\Table(name="news")
* #ORM\Entity
*/
class News
{
/**
* #var integer
*
* #ORM\Column(name="news_id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $newsId;
/**
* #var string
*
* #ORM\Column(name="news_title", type="string", length=255, nullable=false)
*/
private $newsTitle;
/**
* #var string
*
* #ORM\Column(name="news_description", type="text", nullable=false)
*/
private $newsDescription;
/**
* #var string
*
* #ORM\Column(name="news_status", type="string", length=255, nullable=false)
*/
private $newsStatus;
/**
* #var \DateTime
*
* #ORM\Column(name="created_at", type="date", nullable=false)
*/
private $createdAt;
/**
* #var \NewsCategory
*
* #ORM\ManyToOne(targetEntity="NewsCategory")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="category_id", referencedColumnName="category_id")
* })
*/
private $category;
}
And, 2) NewCategory.php
namespace Admin\NewsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* NewsCategory
*
* #ORM\Table(name="news_category")
* #ORM\Entity
*/
class NewsCategory
{
/**
* #var integer
*
* #ORM\Column(name="category_id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $categoryId;
/**
* #var string
*
* #ORM\Column(name="category_title", type="string", length=255, nullable=false)
*/
private $categoryTitle;
/**
* #var string
*
* #ORM\Column(name="category_description", type="text", nullable=false)
*/
private $categoryDescription;
}
the problem is now when i am creating the Entities using the "doctrine:generate:entities"
it is giving me the following error.
D:\wamp\www\Symfony>php app/console doctrine:generate:entities AdminNewsBundle
Generating entities for bundle "AdminNewsBundle"
[Doctrine\Common\Persistence\Mapping\MappingException]
Invalid mapping file 'Admin.NewsBundle.Entity.News.orm.yml' for class 'Admi
n\NewsBundle\Entity\News'.
doctrine:generate:entities [--path="..."] [--no-backup] name
sorry for poor english please help me out come from this problem as i am new to symfony2
Try:
1) php app/console doctrine:mapping:convert yml ./src/Admin/NewsBundle/Resources/config/doctrine/metadata/orm --from-database --force --namespace="Admin\\NewsBundle\\Entity\\"
for Linux namespace="Admin\\NewsBundle\\Entity\\", for Win probably namespace="Admin\NewsBundle\Entity\\"
Watch that mapping is in right place, has correct names and correct syntax.
2) php app/console doctrine:mapping:import AdminNewsBundle annotation
3) php app/console doctrine:generate:entities AdminNewsBundle
Try replacing the first line of YML with the entity name with naspace
Admin\NewsBundle\Entity\News:
for exemple.
I'm trying to apply Doctrine to an existing database that has a OneToMany relationship between two tables: Commerce and Area.
I generated the yml schema from the database resulting in the following:
Area:
type: entity
table: area
fields:
id:
id: true
type: integer
unsigned: false
nullable: false
generator:
strategy: IDENTITY
name:
type: string
length: 255
fixed: false
nullable: true
lifecycleCallbacks: { }
Commerce:
type: entity
table: commerce
fields:
id:
id: true
type: integer
unsigned: false
nullable: false
generator:
strategy: IDENTITY
name:
type: string
length: 255
fixed: false
nullable: true
manyToOne:
area:
targetEntity: Area
cascade: { }
mappedBy: null
inversedBy: null
joinColumns:
area_id:
referencedColumnName: id
orphanRemoval: false
lifecycleCallbacks: { }
From that schema I generated the Entities:
use Doctrine\ORM\Mapping as ORM;
/**
* Model\EntitiesBundle\Entity\Area
*
* #ORM\Table(name="area")
* #ORM\Entity
*/
class Area
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #return string
*/
public function getName()
{
return $this->name;
}
}
use Doctrine\ORM\Mapping as ORM;
/**
* Model\EntitiesBundle\Entity\Commerce
*
* #ORM\Table(name="commerce")
* #ORM\Entity
*/
class Commerce
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #var Area
*
* #ORM\ManyToOne(targetEntity="Area")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="area_id", referencedColumnName="id")
* })
*/
private $area;
/**
* #return \Model\EntitiesBundle\Entity\Area
*/
public function getArea()
{
return $this->area;
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
}
My problem comes when I try:
$commerce = $em->getRepository('ModelEntitiesBundle:Commerces')
->find($id);
echo $commerce->getArea()->getName();
The Area entity has empty attributes.
Any ideas? Thank you!
I solved the problem. It was somewhere else, I have two Entity Managers and the one I needed was not the default.