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;
}
}
Related
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).
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 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
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
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.