StofDoctrineExtensionsBundle softdelete - How do I use it? - php

My boss installed this bundle for the softdelete filter, but the documentation is beyond sparse. How do I use this in my delete queries?

Enable it in your config:
stof_doctrine_extensions:
orm:
default:
...
softdeleteable: true
doctrine:
...
orm:
filters:
softdeleteable:
class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
enabled: true
Then in your entity:
<?php
namespace Foo\BarBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* ...
* #Gedmo\SoftDeleteable(fieldName="deletedAt")
* #ORM\Entity
*/
class Foo
{
/**
* #var \DateTime $deletedAt
*
* #ORM\Column(name="deleted_at", type="datetime", nullable=true)
*/
private $deletedAt;
Then just delete entities like you normally would (the extension takes care of the rest):
$em = $this->getDoctrine()->getManager();
$em->remove($entity);
$em->flush();

I also needed another puzzle part: The doctrine yaml config:
XYBundle\Entity\Adresse:
type: entity
table: adresse
gedmo:
soft_deleteable:
field_name: deleted_at
time_aware: false
id:
id:
type: integer
generator: { strategy: AUTO }
fields:
ort:
type: string
length: 100
plz:
type: string
columnDefinition: varchar(255) NOT NULL DEFAULT ''
deleted_at:
type: datetime
nullable: true

Related

Removing the generated hash when uploading an image with easy_admin / #Vich\Uploadable

My problem is simple but complicated at the same time.
Basically when you upload a image with easy_admin. The image get's a hash.
Like so:
/uploads/images/5f17449f4932f_image004.jpg
Is there any way to remove the generated hash before the image name ?
Here is my Entity:
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* Image
*
* #ORM\Column(type="string", length=255)
* #var string
*/
private $image = '';
/**
* ImageFile
*
* #Vich\UploadableField(mapping="images", fileNameProperty="image")
* #var File
*/
private $imageFile;
Is there a setting that I may use in the easy_admin.yml config ?
form:
fields:
- { property: 'imageFile', label: 'Image', type: 'vich_image'}
Let me know if any other information is needed.
Thank you.
UPDATE: The class
namespace App\Service\FileNamer;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\PropertyMapping;
use Vich\UploaderBundle\Naming\NamerInterface;
class FileNamer implements NamerInterface
{
public function name($object, PropertyMapping $mapping): string
{
/* #var $file UploadedFile */
$file = $mapping->getFile($object);
return $file->getClientOriginalName();
}
}
Easy_admin
db_driver: orm
mappings:
images:
uri_prefix: '%upload_images_folder%'
upload_destination: '%kernel.root_dir%/../public%upload_images_folder%'
namer:
service: App\Service\FileNamer
videos:
uri_prefix: '%upload_videos_folder%'
upload_destination: '%kernel.root_dir%/../public%upload_videos_folder%'
namer:
service: vich_uploader.namer_origname
pdfs:
uri_prefix: '%upload_pdfs_folder%'
upload_destination: '%kernel.root_dir%/../public%upload_pdfs_folder%'
namer:
service: vich_uploader.namer_origname
Create your own custom namer class. Just implement Vich\UploaderBundle\Naming\NamerInterface and add it to vich_uploader configuration.
https://github.com/dustin10/VichUploaderBundle/blob/master/docs/file_namer/howto/create_a_custom_file_namer.md

VichUploader: reupload image on entity update

I have entity Asset with field image
/**
* #ORM\Table(name="asset")
* #ORM\Entity(repositoryClass="AppBundle\Repository\AssetRepository")
* #Vich\Uploadable
*/
class Asset
{
/**
* #ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="assets")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;
/**
* #ORM\Column(name="image", type="string", length=255, nullable=true)
*/
private $image;
/**
* #Vich\UploadableField(mapping="assets", fileNameProperty="image")
* #var File
*/
protected $imageFile;
I am using VichUploader to upload images to S3 bucket. I created custom namer to create file name. During upload entity is uploaded to folder with category name and is named with entity name
public function name($obj, PropertyMapping $mapping)
{
$category = $obj->getCategory()->getName();
$name = $obj->getName();
$file = $mapping->getFile($obj);
if ($extension = $this->getExtension($file)) {
$name = sprintf('%s.%s', $name, $extension);
}
return $category.'/'.$name;
}
These my upload configurations
oneup_flysystem:
adapters:
assets_adapter:
awss3v3:
client: app.assets.s3
bucket: '%assets_bucket%'
prefix: assets
filesystems:
assets_fs:
adapter: assets_adapter
mount: assets_fs
vich_uploader:
db_driver: orm
storage: flysystem
mappings:
assets:
delete_on_remove: true
delete_on_update: true
uri_prefix: 'https://s3-%assets_region%.amazonaws.com/%assets_bucket%/'
upload_destination: assets_fs
namer: app.asset_namer
I have following situation: user changes category of Asset. How file can be re-uploaded to new category folder and update name?
UPDATE
I am using EasyAdminBundle. Which handles create and edit entities. So I didn't create FormType and Controller for Asset entity. Here are configs:
easy_admin:
entities:
Asset:
class: AppBundle\Entity\Asset
label: 'Assets'
form:
fields:
- name
- {property: 'category', type: entity, type_options: {expanded: false, multiple: false, class: 'AppBundle:Category', required: true}}
- {property: 'imageFile', type: 'vich_image' }
One solution would be to update the Asset::setCategory method logic, to create a new File object when the category name is changed, and pass it to Asset::setImageFile to cause VichUploader to run the update process.
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* #ORM\Table(name="asset")
* #ORM\Entity(repositoryClass="AppBundle\Repository\AssetRepository")
* #Vich\Uploadable
*/
class Asset
{
//...
public function setCategory(Category $category)
{
if ($this->imageFile && $this->category->getName() !== $category->getName()) {
$this->setImageFile(new UploadedFile(
$this->imageFile->getRealPath(), //physical path to image file
$this->image, //current image name
null,
null,
null,
true
));
}
$this->category = $category;
return $this;
}
}
One issue is that by default VichUploader does not populate the entity imageFile property.
To ensure Asset::$imageFile is available, without needing to interact with the vich_uploader.storage service, you will need to add inject_on_load: true to your vich_uploader.mappings settings. This will add a listener to the entity to automatically populate the imageFile property with a File object.
#app/config/config.yml
#...
vich_uploader:
db_driver: orm
storage: flysystem
mappings:
assets:
delete_on_remove: true
delete_on_update: true
uri_prefix: 'https://s3-%assets_region%.amazonaws.com/%assets_bucket%/'
upload_destination: assets_fs
namer: app.asset_namer
inject_on_load: true
The prefered method would be to add the logic to your controller edit action, or adding a custom event subscriber to a Symfony event that monitors the Asset entity. Though I am not aware of how to accomplish this in relation to a category name change in EasyAdminBundle.

Doctrine doesn't map fields from FOSUserBundle and FOSOAuthServerBundle

I am using Symfony 2.8, FOSUserBundle 1.3 and FOSOAuthServerBundle 1.5
For all of the class needed to those Bundles to work, I ended up with doctrine not updating my schema properly. I mean it doesn't take into account the fields from the Base Class.
CREATE TABLE oauh2_access_tokens (id INT NOT NULL, client_id INT NOT NULL, user_
id INT DEFAULT NULL, PRIMARY KEY(id));
CREATE TABLE oauth2_auth_codes (id INT NOT NULL, client_id INT NOT NULL, user_id
INT DEFAULT NULL, PRIMARY KEY(id));
CREATE TABLE oauth2_clients (id INT NOT NULL, PRIMARY KEY(id));
CREATE TABLE oauth2_refresh_tokens (id INT NOT NULL, client_id INT NOT NULL, use
r_id INT DEFAULT NULL, PRIMARY KEY(id));
Here's my config:
doctrine:
orm:
#auto_generate_proxy_classes: "%kernel.debug%"
default_entity_manager: default
entity_managers:
default:
connection: default
naming_strategy: doctrine.orm.naming_strategy.underscore
mappings:
COMPANYAuthBundle: ~
fos_user:
db_driver: orm
firewall_name: api
user_class: COMPANY\AuthBundle\Entity\User
#FOSOAuthBundle Configuration
fos_oauth_server:
db_driver: orm
client_class: COMPANY\AuthBundle\Entity\Client
access_token_class: COMPANY\AuthBundle\Entity\AccessToken
refresh_token_class: COMPANY\AuthBundle\Entity\RefreshToken
auth_code_class: COMPANY\AuthBundle\Entity\AuthCode
service:
user_provider: fos_user.user_manager
And here's my class User
<?php
namespace COMPANY\AuthBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Entity\User as BaseUser;
/**
* Utilisateur
*
* #ORM\Table(name="users")
* #ORM\Entity
*/
class User extends BaseUser
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct()
{
parent::__construct();
// your own logic
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
}
So, yes I did put the right use and not FOS\UserBundle\Model\User as BaseUser;
Same thing for the class of OAuthServerBundle: (I'm just putting one here, they're all following the same pattern)
<?php
namespace COMPANY\AuthBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\OAuthServerBundle\Entity\Client as BaseClient;
/**
* Client
*
* #ORM\Table(name="oauth2_clients")
* #ORM\Entity(repositoryClass="COMPANY\AuthBundle\Repository\ClientRepository")
*/
class Client extends BaseClient
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
public function __construct()
{
parent::__construct();
}
}
Does anybody have an idea why base class' fields aren't put into my db? Thanks :)
Okay, I found the solution after 10 hours of search...
And the solution is to not forget to add FOSUserBundle and FOSOAuthServerBundle and all the base class bundles to your mapping.....
So this should be the config:
doctrine:
orm:
#auto_generate_proxy_classes: "%kernel.debug%"
default_entity_manager: default
entity_managers:
default:
connection: default
naming_strategy: doctrine.orm.naming_strategy.underscore
mappings:
COMPANYAuthBundle: ~
FOSUserBundle: ~
FOSOAuthBundle: ~
Also, you can't make a bundle inherit from two bundles if you want to use the routes of each. So, create one bundle for each. Then in each of the Bundle class, add the following function:
public function getParent()
{
return "FOSOAuthServerBundle"; //Or return "FOSUserBundle"; but you can't put both
}

FOSMessageBundle - Not generating entities properly

I'm using FOSMessageBundle, and I thought i followed the instructions pretty well, but i cant seem to get the database to generate properly...
Heres my Message entity:
<?php
namespace Acme\Bundle\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
use FOS\MessageBundle\Entity\Message as BaseMessage;
use FOS\MessageBundle\Model\ParticipantInterface;
/**
* Message
*
* #ORM\Entity()
* #JMS\ExclusionPolicy("All")
*/
class Message extends BaseMessage implements EntityInterface
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #JMS\Groups({"list", "default"})
* #JMS\Expose()
*/
protected $id;
/**
* #var Thread
*
* #ORM\ManyToOne(targetEntity="Thread", inversedBy="messages", cascade={"persist"})
* #ORM\JoinColumn(name="thread_id")
* #JMS\Groups({"default"})
*/
protected $thread;
/**
* #ORM\ManyToOne(targetEntity="User")
* #var ParticipantInterface
*/
protected $sender;
/**
* #ORM\OneToMany(targetEntity="MessageMetadata", mappedBy="message", cascade={"all"})
* #var MessageMetadata
*/
protected $metadata;
}
And my config.yml
fos_message:
db_driver: orm
thread_class: Acme\Bundle\DemoBundle\Entity\Thread
message_class: Acme\Bundle\DemoBundle\Entity\Message
The issue is, my table ends up with only id, thread_id, and sender_id. Its missing the rest of the fields.
What am i missing!
check if all classes are correcly mapped :
php app/console doctrine:mapping:info
if not you have to MessageMetadata to the config file
message_class: Acme\Bundle\DemoBundle\Entity\Message
I'm not sure but in your case it seems like you have two different configurations for this entity - your annotations and xml from FOSCommentBundle
Please change your configuration to XML format, like this https://github.com/FriendsOfSymfony/FOSMessageBundle/blob/master/Resources/config/doctrine/Message.orm.xml and check again.
regards,
Merk, one of the contributors to the project pointed me at setting auto_mapping to true under the entity manager.
Once i set this, it solved my issue!
For me the auto_mapping did not work, I got the message
Unrecognized option "auto_mapping" under "doctrine.orm"
I solved the issue by adding the FOSMessageBundle like this:
orm:
auto_generate_proxy_classes: "%kernel.debug%"
default_entity_manager: default
entity_managers:
default:
naming_strategy: doctrine.orm.naming_strategy.underscore
connection: default
second_level_cache:
enabled: true
mappings:
AppBundle: ~
UserBundle: ~
FOSMessageBundle: ~

Mapping exception using Stof/Gedmo Translation

I'm migrating my Symfony 2.0 project to version 2.1rc1. After installing the stof/doctrine-extensions-bundle and the gedmo/doctrine-extensions and test my application I get the following error:
No identifier/primary key specified for Entity "Company\TestBundle\Entity\PageTranslation" sub class of "Gedmo\Translatable\Entity\MappedSuperclass\AbstractTranslation". Every Entity must have an identifier/primary key.
My config.yml looks like this:
# Doctrine Configuration
doctrine:
dbal:
driver: %database_driver%
host: %database_host%
port: %database_port%
dbname: %database_name%
user: %database_user%
password: %database_password%
charset: UTF8
orm:
auto_generate_proxy_classes: %kernel.debug%
connection: default
auto_mapping: true
mappings:
gedmo_translatable:
type: annotation
prefix: Gedmo\Translatable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
alias: GedmoTranslatable # this one is optional and 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 # this one is optional and will default to the name set for the mapping
is_bundle: false
stof_doctrine_extensions:
default_locale: en
translation_fallback: true
orm:
default:
translatable: true
sluggable: true
According to the documentation of StofDoctrineExtensionsBundle this should be fine. The only thing I'm not sure of is the auto_mapping: true option.
The only code I've changed in my project is in my CategoryTranslation class. I've replaced:
use Stof\DoctrineExtensionsBundle\Entity\AbstractTranslation;
by:
use Gedmo\Translatable\Entity\MappedSuperclass\AbstractTranslation;
Because the Stof-bundle doesn't have an AbstractTranslation class anymore.
Can someone tell me how I can fix this?
My PageTranslation entity before:
class PageTranslation extends AbstractTranslation
{
/**
* All required columns are mapped through inherited superclass
*/
}
My PageTranslation entity after generating the entities on the commandline:
class PageTranslation extends AbstractTranslation
{
/**
* All required columns are mapped through inherited superclass
*/
/**
* #var integer $id
*/
private $id;
/**
* #var string $locale
*/
private $locale;
.....etc....
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set locale
*
* #param string $locale
* #return PageTranslation
*/
public function setLocale($locale)
{
$this->locale = $locale;
return $this;
}
/**
* Get locale
*
* #return string
*/
public function getLocale()
{
return $this->locale;
}
..etc....
}
If you are using StofDoctrineExtensions you don't need gedmo/doctrine-extensions. Also isn't necessary to generate anything in PageTranslation

Categories