StofDoctrineExtensionsBundle Uploadable - symfony

I use the StofDoctrineExtensionsBundle Uploadable to upload a picture in User entity.
<?php
namespace Application\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* #ORM\Entity
* #ORM\Table(name="user")
* #Gedmo\Uploadable(pathMethod="getPath", filenameGenerator="SHA1", allowOverwrite=true, maxSize="100000", allowedTypes="image/jpeg,image/pjpeg,image/png,image/x-png")
*/
class User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
...
/**
* #ORM\Column(name="picture", type="string", length=255, nullable=true)
* #Gedmo\UploadableFilePath
*/
private $picture;
public function getPath()
{
return '/user';
}
public function setPhoto($photo)
{
$this->photo = $photo;
return $this;
}
public function getPhoto()
{
return $this->photo;
}
...
In the controller:
...
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$uploadableManager = $this->get('stof_doctrine_extensions.uploadable.manager');
$uploadableManager->markEntityToUpload($user, $user->getPath());
...
in the FormType:
...
->add('picture', FileType::class, array(
'label' => 'Picture',
'required' => false
))
...
config.yml:
# StofDoctrineExtensionsBundle Configuration
stof_doctrine_extensions:
default_locale: fr_FR
uploadable:
# Default file path: This is one of the three ways you can configure the path for the Uploadable extension
default_file_path: %kernel.root_dir%/../web/uploads
# Mime type guesser class: Optional. By default, we provide an adapter for the one present in the HttpFoundation component of Symfony
mime_type_guesser_class: Stof\DoctrineExtensionsBundle\Uploadable\MimeTypeGuesserAdapter
# Default file info class implementing FileInfoInterface: Optional. By default we provide a class which is prepared to receive an UploadedFile instance.
default_file_info_class: Stof\DoctrineExtensionsBundle\Uploadable\UploadedFileInfo
orm:
default:
uploadable: true
When I test it I get the message:
Unable to create "/user" directory.
Any idea to solve this problem. Thanks

Is your app in a server ? If so, verify the chmod.
Or remove the / at the beginning of (if your folder structure is web/user):
public function getPath()
{
return '/user';
}

Related

Upload image using VichUploaderBundle

I have a problem with VichUploaderBundle, I followed all the instructions but I dont know how my Controller should handle this after finished form becouse image failed to uploaded and database did not write.
my Entity class:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* #ORM\Entity
* #Vich\Uploadable
*/
class Product
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// ..... other fields
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="product_image", fileNameProperty="imageName", size="imageSize")
*
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $imageName;
/**
* #ORM\Column(type="integer")
*
* #var integer
*/
private $imageSize;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*
* #return Product
*/
public function setImageFile(File $image = null)
{
$this->imageFile = $image;
if ($image) {
var_dump($image);
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
return $this;
}
/**
* #return File|null
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* #param string $imageName
*
* #return Product
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* #return string|null
*/
public function getImageName()
{
return $this->imageName;
}
/**
* #param integer $imageSize
*
* #return Product
*/
public function setImageSize($imageSize)
{
$this->imagesize = $imageSize;
return $this;
}
/**
* #return integer|null
*/
public function getImageSize()
{
return $this->imageSize;
}
}
my FormType class:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
class AvatarType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('imageFile', FileType::class, array('label' => 'Brochure (PDF file)'))
;
}
public function getName()
{
return 'avatar_form';
}
}
config:
vich_uploader:
db_driver: orm # or mongodb or propel or phpcr
mappings:
product_image:
uri_prefix: /image/avatar
upload_destination: '%kernel.root_dir%/../web/image/avatar'
Twig template:
<div>
{{ form_start(form) }}
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form.imageFile) }}
<button type="submit" class="btn btn-default">Submit</button>
{{ form_end(form) }}
</div>
and finally Controller:
namespace AppBundle\Controller\User;
use AppBundle\Entity\Product;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use AppBundle\Controller\InitController;
use AppBundle\Form\AvatarType;
class UserController extends Controller implements InitController
{
/**
* #Route("/user/avatar", name="AvatarAction")
*/
public function AvatarAction(Request $request)
{
$form = $this->createForm('AppBundle\Form\AvatarType',null,array(
// To set the action use $this->generateUrl('route_identifier')
'action' => $this->generateUrl('AvatarAction'),
'method' => 'POST'
));
$form->handleRequest($request);
if ($request->isMethod('POST')) {
if($form->isValid()){
//$track = new Product();
//$em = $this->getDoctrine()->getManager();
//$em->persist($track);
//$em->flush();
}
return $this->render('default/avatar.html.twig',array(
'form' => $form->createView()
));
}
}
Thanks for all your advice!
Maybe this is not the solution, but your line :
->add('imageFile', FileType::class, array('label' => 'Brochure (PDF file)')):
Should be :
->add('imageFile', VichFileType::class, array('label' => 'Brochure (PDF file)'))
More info : https://github.com/dustin10/VichUploaderBundle/blob/master/Resources/doc/form/vich_file_type.md
What Symfony tells you as error ?
Have a nice day

Symfony how could I add fields to my FOSUser?

I'm trying to add a field 'name' to my user and this is how I proceeded
namespace User\UserBundle\Controller;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
class DefaultController extends BaseController
{
public function indexAction()
{
$response = parent::registerAction();
// ... do custom stuff
return $response;
}
And this is My userType
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('nom')
->add('prenom')
;
}
When I try to add,
{{ form_widget(form.name) }}
I get this error
Method "nom" for object "Symfony\Component\Form\FormView" does not exist in FOSUserBundle:Registration:register.html.twig at line
This is my user class
namespace User\UserBundle\Entity;
use FOS\UserBundle\Entity\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct()
{
parent::__construct();
// your own logic
}
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=255, nullable=true )
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="prenom", type="string", length=255, nullable=true )
*/
private $prenom;
/**
* Set nom
*
* #param string $nom
* #return User
*/
public function setNom($nom)
{
$this->nom = $nom;
return $this;
}
/**
* Get nom
*
* #return string
*/
public function getNom()
{
return $this->nom;
}
/**
* Set prenom
*
* #param string $prenom
* #return User
*/
public function setPrenom($prenom)
{
$this->prenom = $prenom;
return $this;
}
/**
* Get prenom
*
* #return string
*/
public function getPrenom()
{
return $this->prenom;
}
}
This is what I have under app/config
enter image description here
What should I do more? Any suggestions please? i'm newly starter with FOSUserBundle. THanks
It looks like you're trying to add the nom and prenom fields to the registration form. So you need to override the FOSUserBundle registration form. Follow the guide at Overriding Default FOSUserBundle Forms which shows how to override any form.
Maybe this link will help you http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_forms.html
This is my config.yml
Do you write it all in config.yml ?
you need to write this code in config.yml:
fos_user:
db_driver: orm
firewall_name: main
user_class: User\UserBundle\Entity\User
registration:
form:
type: user_userbundle_user
and the remaining write in ./config/services.yml
services:
fos_user.doctrine_registry:
alias: doctrine
app.form.registration:
class: UserUserBundle\Form\UserType
tags:
- { name: form.type, alias: user_userbundle_user }
So I finally got it ! I added construct to my userType
public function __construct($class)
{
parent::__construct($class);
}
And this is my new services.yml
parameters:
user_user.registration.class: User\UserBundle\Entity\User
services:
user.form.user:
class: User\UserBundle\Form\UserType
arguments: [%user_user.registration.class%]
tags:
- { name: form.type, alias: user_userbundle_user }
And that's it I hope it helps someOne. Thanks everyone

symfony 2.8 generated crud controller with errors

I try generate CRUD controllers for my entities.
For example I wanna generate CRUD controller for AppBundle\Entity\User\User:
namespace AppBundle\Entity\User;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\Group;
/**
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
public function __construct()
{
parent::__construct();
// your own logic
}
}
Generate entities:
$ app/console generate:doctrine:entities AppBundle
Generate crud:
$ app/console doctrine:generate:crud --entity=AppBundle:User\User
This command generete follow controller:
class UserController extends Controller
{
/**
* Lists all User\User entities.
*
* #Route("/", name="user_user_index")
* #Method("GET")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$user\Users = $em->getRepository('AppBundle:User\User')->findAll();
return $this->render('user/user/index.html.twig', array(
'user\Users' => $user\Users,
));
}
/**
* Finds and displays a User\User entity.
*
* #Route("/{id}", name="user_user_show")
* #Method("GET")
*/
public function showAction(User $user\User)
{
return $this->render('user/user/show.html.twig', array(
'user\User' => $user\User,
));
}
}
What the $user\Users? Symfony 2.8!
Maybe I can't use more directories in the Entity folder?
if you used the same namespace in your CRUD generation command as you have in this question, I expect that symfony is getting confused.
you have used:
AppBundle\Entity\User\User
note the extra \User.
If this isnt a typo, your entity should reside in the base Entity directory. The unusual path has probably confused it.
One would have thought however, that the generate command should have validated the string first.

saml2 identity provider in Symfony2

I must implement and integrate a SAML2 Identity Provider (IdP) with an existing Symfony 2 application.
I found some bundle that implement Service Provider (SP) but not Identity Provider so I think that I may use SimpleSAMLphp library. Are there other solutions?
How can I integrate my user provider logic with SimpleSAMLphp?
UPDATE
As Milos Tomic mentioned in his comment, aerialship/lightsaml is replaced by lightsaml/sp-bundle. You can find an introduction here.
+++++++++++++++++++++++++++
I have recently set up a SAML Solution using Simplesamlphp as IDP and SamlSPBundle as SP and everything is working well.
I recommend installing Simplesamlphp first, following this good Documentation here.
Once you have the IDP up and running, you should see a Welcome page and a Tab called Federation (or something like that, my Installation is in german). There you should see one option "SAML 2.0 IdP Metadata". Follow that link and copy the XML shown to a seperate file and save that file.
On the symfony side, I created a new Bundle and called that "SamlBundle". Download and install SamlSPBundle as described in their Documentation (Step 1 and Step 2).
Create your SSO State/User class (Step 3). Here is an example how I did it:
namespace SamlBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* #ORM\Entity
* #ORM\Table(name="samlUser")
*/
class SamlUser extends \AerialShip\SamlSPBundle\Entity\SSOStateEntity implements UserInterface
{
/**
* initialize User object and generates salt for password
*/
public function __construct()
{
if (!$this->userData instanceof UserData) {
$this->userData = new UserData();
}
$this->setRoles('ROLE_USER');
}
/**
* #var int
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string username
*
* #ORM\Column(type="string", length=64, nullable=true)
*/
protected $username;
/**
* #var string targetedId
*
* #ORM\Column(type="string", length=64, nullable=true, name="targeted_id")
*/
protected $targetedID;
/**
* #var string
* #ORM\Column(type="string", length=32, name="provider_id", nullable=true)
*/
protected $providerID;
/**
* #var string
* #ORM\Column(type="string", length=32, name="auth_svc_name")
*/
protected $authenticationServiceName;
/**
* #var string
* #ORM\Column(type="string", length=64, name="session_index", nullable=true)
*/
protected $sessionIndex;
/**
* #var string
* #ORM\Column(type="string", length=64, name="name_id")
*/
protected $nameID;
/**
* #var string
* #ORM\Column(type="string", length=64, name="name_id_format")
*/
protected $nameIDFormat;
/**
* #var \DateTime
* #ORM\Column(type="datetime", name="created_on")
*/
protected $createdOn;
/**
* #var UserData
* #ORM\OneToOne(targetEntity="UserData", cascade={"all"}, fetch="EAGER")
* #ORM\JoinColumn(name="user_data", referencedColumnName="id")
*/
protected $userData;
Add your class to config.yml (Step 4):
# app/config/config.yml
aerial_ship_saml_sp:
driver: orm
sso_state_entity_class: SamlBundle\Entity\SamlUser
Update your security.yml (Step 5). Example;
providers:
saml_user_provider:
id: SamlToState
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
saml:
pattern: ^/(?!login_check)
anonymous: true
aerial_ship_saml_sp:
login_path: /saml/sp/login
check_path: /saml/sp/acs
logout_path: /saml/sp/logout
failure_path: /saml/sp/failure
metadata_path: /saml/sp/FederationMetadata.xml
discovery_path: /saml/sp/discovery
local_logout_path: /logout
provider: saml_user_provider
create_user_if_not_exists: true
services:
openidp:
idp:
#the XML-File you saved from the IDP earlier
file: "#SamlBundle/Resources/idp-FederationMetadata.xml"
sp:
config:
# required, has to match entity id from IDP XML
entity_id: http://your-idp-domain.com
# if different then url being used in request
# used for construction of assertion consumer and logout urls in SP entity descriptor
base_url: http://your-sp-domain.com
signing:
#self signed certificate, see [SamlSPBundle docs][4]
cert_file: "#SamlBundle/Resources/saml.crt"
key_file: "#SamlBundle/Resources/saml.pem"
key_pass: ""
meta:
# must implement SpMetaProviderInterface
# id: my.sp.provider.service.id
# or use builtin SpMetaConfigProvider
# any valid saml name id format or shortcuts: persistent or transient
name_id_format: transient
binding:
# any saml binding or shortcuts: post or redirect
authn_request: redirect
logout_request: redirect
logout:
path: /logout
target: /
invalidate_session: true
Next import the routes as described in Step 6. Before you go on to Step 7, I recommend to create your User provider class first. Here is an example:
namespace SamlBundle\Models;
use SamlBundle\Entity\SamlUser;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use AerialShip\SamlSPBundle\Bridge\SamlSpInfo;
use AerialShip\SamlSPBundle\Security\Core\User\UserManagerInterface as UserManagerInterface;
class SamlToState implements UserManagerInterface
{
/**
* #var ContainerInterface base bundle container
*/
public $container;
/**
* Constructor with DependencyInjection params.
*
* #param \Symfony\Component\DependencyInjection\ContainerInterface $container
*/
public function __construct(ContainerInterface $container) {
$this->container = $container;
}
/**
* {#inheritdoc}
*/
public function loadUserBySamlInfo(SamlSpInfo $samlInfo)
{
$user = $this->loadUserByTargetedID($samlInfo->getAttributes()['eduPersonTargetedID']->getFirstValue());
return $user;
}
private function loadUserByTargetedID($targetedID) {
$repository = $this->container->get('doctrine')->getManager()->getRepository('MrmPosSamlBundle:SamlUser');
$user = $repository->findOneBy(
array('targetedID' => $targetedID)
);
if ($user) {
return $user;
}
throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException();
}
/**
* {#inheritdoc}
*/
public function createUserFromSamlInfo(SamlSpInfo $samlInfo)
{
$repository = $this->container->get('doctrine')->getManager()->getRepository('MrmPosSamlBundle:SamlUser');
$user = $repository->findOneBy(
array('nameID' => $samlInfo->getNameID()->getValue())
);
if ($user) {
$user->setUsername($samlInfo->getAttributes()['eduPersonPrincipalName']->getFirstValue());
$user->setTargetedID($samlInfo->getAttributes()['eduPersonTargetedID']->getFirstValue());
$user->setRoles($samlInfo->getAttributes()['role']->getFirstValue());
} else {
$user = new SamlUser();
$user->setUsername($samlInfo->getAttributes()['eduPersonPrincipalName']->getFirstValue());
$user->setTargetedID($samlInfo->getAttributes()['eduPersonTargetedID']->getFirstValue());
$user->setRoles($samlInfo->getAttributes()['role']->getFirstValue());
$user->setSessionIndex($samlInfo->getAuthnStatement()->getSessionIndex());
$user->setProviderID($samlInfo->getNameID()->getSPProvidedID());
$user->setAuthenticationServiceName($samlInfo->getAuthenticationServiceID());
$user->setNameID($samlInfo->getNameID()->getValue());
$user->setNameIDFormat($samlInfo->getNameID()->getFormat());
}
$em = $this->container->get('doctrine')->getManager();
$em->persist($user);
$em->flush();
return $user;
}
public function loadUserByUsername($username)
{
$repository = $this->container->get('doctrine')->getManager()->getRepository('MrmPosSamlBundle:SamlUser');
$user = $repository->findOneBy(
array('username' => $username)
);
if ($user) {
return $user;
}
throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException();
return false;
}
/**
* {#inheritdoc}
*/
public function refreshUser(UserInterface $user)
{
$repository = $this->container->get('doctrine')->getManager()->getRepository('MrmPosSamlBundle:SamlUser');
$newUser = $repository->findOneBy(
array('nameID' => $user->getNameID())
);
if (!$newUser) {
throw new \Symfony\Component\Security\Core\Exception\UsernameNotFoundException();
}
return $newUser;
}
/**
* {#inheritdoc}
*/
public function supportsClass($class)
{
return true;
}
}
Create your service in SamlBundle/Resources/config/services.yml:
services:
SamlToState:
class: SamlBundle\Models\SamlToState
arguments: [#service_container]
Now its time for Step 7, exchanging Metadata. get the SP XML as described and go back to your IDP. You find a "XML to simpleSAMLphp Metadata converter" Link on the Federation Tab. Follow that link and convert your SP XML Data to the simpleSAMLphp format. Add that data to the saml20-sp-remote.php file in your IDPs metadata folder.
Ok, I'm pretty sure that I forgot something, but hopefully this information helps. If you get stuck, your welcome to get back to me.
I found:
SURFnet SamlBundle that is a simple symfony2 wrapper of the library you found.
SamlSpBundle more used and well documented.
Take a look at this two. The first is very simple and i don't know if is sufficient documented, of course is an active project. The second seem more powerful and documented but can be more difficult to configure.
Hope this help

Update form vich uploader, cannot delete or edit file

I can't delete or edit my uploaded image with VichUploaderBundle. I have an Annonce and Photo entities with OneToMany (bidirectionnal relation). I try with an attribute setUpdatedAt to call vich prePersist but he doesn't work.
Here is Annonce :
class Annonce
{
// ...
/**
* #ORM\OneToMany(targetEntity="Immo\AnnonceBundle\Entity\Photo", mappedBy="annonce", cascade={"persist", "remove"})
*/
private $photos;
Photo entity with setter/getterImage() :
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Photo
* #Vich\Uploadable
* #ORM\Table()
*/
class Photo
{ // id, etc.
/**
* #Assert\File(
* maxSize="1M",
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
* )
* #Vich\UploadableField(mapping="uploads_image", fileNameProperty="url")
*
* #var File $image
*/
protected $image;
/**
* #ORM\Column(type="string", length=255, name="url")
*
* #var string $url
*/
protected $url;
/**
* #ORM\ManyToOne(targetEntity="Immo\AnnonceBundle\Entity\Annonce", inversedBy="photos")
*/
private $annonce;
/**
* #ORM\Column(type="datetime", nullable=true)
*
* #var \DateTime $updatedAt
*/
protected $updatedAt;
/**
* Set image
*
* #param string $image
* #return Photo
*/
public function setImage($image)
{
$this->image = $image;
if ($this->image instanceof UploadedFile) {
$this->updatedAt = new \DateTime('now');
}
return $this;
}
Here is my config.yml:
knp_gaufrette:
stream_wrapper: ~
adapters:
uploads_adapter:
local:
directory: %kernel.root_dir%/../web/img/uploads
filesystems:
uploads_image_fs:
adapter: uploads_adapter
vich_uploader:
db_driver: orm
twig: true
gaufrette: true
storage: vich_uploader.storage.gaufrette
mappings:
uploads_image:
delete_on_remove: true
delete_on_update: true
inject_on_load: true
uri_prefix: img/uploads
upload_destination: uploads_image_fs
namer: vich_uploader.namer_uniqid
My AnnonceType:
$builder->add('photos', 'collection', array('type' => new PhotoType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
)
)
PhotoType:
$builder->add('image', 'file')
The Controller :
public function updateAnnonceAction($id)
{
$em = $this->getDoctrine()->getManager();
$annonce = $em->getRepository('ImmoAnnonceBundle:Annonce')
->findCompleteAnnonceById($id);
$form = $this->createForm(new AnnonceType, $annonce);
$request = $this->get('request');
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($annonce);
$em->flush();
$this->get('session')->getFlashBag()->add('success', 'ok');
return $this->redirect($this->generateUrl('immo_admin_annonce_homepage'));
}
}
return $this->render('ImmoAnnonceBundle:Admin/Annonce:update.html.twig', array('annonce' => $annonce,
'form' => $form->createView()
)
);
}
And my template put input file for each Photo in Annonce in html :
{{ form_widget(form.photos) }} // With JS to manage add/delete on each input.
// Return this :
<input type="file" required="required" name="immo_annoncebundle_annonce[photos][2][image]" id="immo_annoncebundle_annonce_photos_2_image">
Add an "updateAt" attribute in your entity
See http://mossco.co.uk/symfony-2/vichuploaderbundle-how-to-fix-cannot-overwrite-update-uploaded-file/ for more informations
I know it is an old thread, but David's answer was not working in this case since OP tries to delete the Photo object within the Annonce object once it gets updated.
I had a similar case where i just had to check if the path (fileName) of the Photo object was null after the request handling (after performing a delete operation from the formular) and then if it is the case, i remove manually the Photo object calling entitymanager to perform the operation.
Looking into the code of VichUploaderBundle (see the remove method of UploadHandler class) shows that an event is being dispatched after requesting the deletion, and you could also bind to this event Events::POST_REMOVE (vich_uploader.post_remove) somewhere to handle the deletion. This solution sounds cleaner although the first one is also working well.

Resources