Synfony 3 + Vich upload bundle - Failed to set metadata before uploading the file - vichuploaderbundle

My problem is to retrieve metadata before uploading the file.
My config file:
vich_uploader:
db_driver: orm
mappings:
media:
uri_prefix: /uploads/
upload_destination: '%kernel.root_dir%/../web/uploads'
inject_on_load: false
delete_on_update: true
delete_on_remove: true
I have an entity MEDIA :
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
**
* #ORM\Entity
* #Vich\Uploadable
*/
class Media
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #Vich\UploadableField(mapping="media", fileNameProperty="fileName",originalName="originalFileName")
*
* #var File
*/
private $file;
/**
* #ORM\Column(type="string", length=50)
*/
private $fileName;
/**
* #ORM\Column(type="string", length=255, nullable=false)
*/
private $originalFileName;
/**
* #ORM\Column(type="datetime")
*/
private $updatedAt;
/**
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $file
*
* #return Media
*/
public function setFile(File $file = null)
{
$this->file = $file;
if ($file) {
$this->updatedAt = new \DateTimeImmutable();
}
return $this;
}
/**
* #return File|null
*/
public function getFile()
{
return $this->file;
}
/**
* #param string $fileName
*
* #return Media
*/
public function setFileName($fileName)
{
$this->fileName = $fileName;
return $this;
}
/**
* #return string|null
*/
public function getFileName()
{
return $this->fileName;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return Media
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Set originalFileName
*
* #param string $originalFileName
*
* #return Media
*/
public function setOriginalFileName($originalFileName)
{
$this->originalFileName = $originalFileName;
return $this;
}
/**
* Get originalFileName
*
* #return string
*/
public function getOriginalFileName()
{
return $this->originalFileName;
}
}
And here is my controller:
/**
* Creates a new media entity.
*
* #Route("/new", name="media_new")
* #Method({"GET", "POST"})
*
* #param Request $request
*
* #return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function newAction(Request $request)
{
$media = new Media();
$form = $this->createForm(MediaType::class, $media);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($media);
$em->flush();
return $this->redirectToRoute(
'media_list'
);
}
return $this->render(
'media/new.html.twig',
[
'media' => $media,
'form' => $form->createView(),
]
);
}
And my form:
<?php
/**
* Created by PhpStorm.
* User: rafael
* Date: 4/10/17
* Time: 12:46 PM
*/
namespace AppBundle\Form;
use AppBundle\Entity\Media;
use AppBundle\Entity\MediaDescriptionHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class MediaType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file', FileType::class)
->add('save', SubmitType::class, [
'attr' => ['class' => 'btn-primary btn-block']
]);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(['data_class' => Media::class]);
}
}
The problem is with the mapping of these values :
#Vich\UploadableField(mapping="media", fileNameProperty="fileName",originalName="originalFileName")
When I submit my form these values are 'null' :
An exception occurred while executing 'INSERT INTO media (file_name, original_file_name, updated_at) VALUES (?, ?, ?)' with params ["get_image_resultat_sans_cache2.php.jpeg", null, "2017-04-12 10:11:56"]:
I have these issues with all parameters :
(https://github.com/dustin10/VichUploaderBundle/blob/master/Resources/doc/usage.md)
The UploadableField annotation has a few options. They are as follows:
mapping: required, the mapping name specified in the bundle configuration to use;
fileNameProperty: required, the property that will contain the name of the uploaded file;
size: the property that will contain the size in bytes of the uploaded file;
mimeType: the property that will contain the mime type of the uploaded file;
originalName: the property that will contain the origilal name of the uploaded file.
I don't see what I did wrong...
Here is my Media (entity) after the form is submitted :
Media {#403 ▼
-id: null
-file: UploadedFile {#15 ▼
-test: false
-originalName: "get_image_resultat_sans_cache2.php.jpeg"
-mimeType: "image/jpeg"
-size: 203751
-error: 0
path: "/tmp"
filename: "php9xsTdF"
basename: "php9xsTdF"
pathname: "/tmp/php9xsTdF"
extension: ""
realPath: "/tmp/php9xsTdF"
aTime: 2017-04-12 10:11:56
mTime: 2017-04-12 10:11:56
cTime: 2017-04-12 10:11:56
inode: 6160452
size: 203751
perms: 0100600
owner: 1000
group: 1000
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
-fileName: null
-originalFileName: null
It seems that's a problem when set metadata before uploading the file...
Thanks a lot in advance...

Which version of VichUploaderBundle do you use?
The documentation for the annotations refers to the dev-master one, while the stable one (1.5.3) doesn't support annotation for metadata out of the box.
You can see that Vich\UploaderBundle\Mapping\Annotation\UploadableField.php in the 1.5.3 version handles only annotations 'mapping' and 'fileNameProperty'.
While in the dev-master, it handles those and size, mimeType and originalName.
Same thing with Vich\UploaderBundle\Metadata\Driver\AnnotationDriver
If you want to achieve this in the 1.5.3 version you need to create an eventListener.
Here are the event triggered by Vich : https://github.com/dustin10/VichUploaderBundle/blob/1.5.3/Event/Events.php

Related

Symfony 4 : Doctrine2 LAZY Fetch Collection still empty after calling the getter

I have an issue with some entities : according to the doctrine documentation, lazy loading should allow me to load my collection only when I call the getters, but it doesn't.
Here is the relation description :
One Location has many Venues, mapped by the Location "externalId" field.
Here is a simplified code sample of my entities and their relation :
// Location.php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\LocationRepository")
* #ORM\Table(name="Location")
*/
class Location extends Entity
{
/**
* #var integer
* #ORM\Column(type="integer", unique=true, nullable=true)
*/
protected $locationId;
/**
* #var integer
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer", nullable=false)
*/
protected $externalId;
/**
* #var Venue[]|Collection
* #ORM\OneToMany(targetEntity="App\Entity\Venue", mappedBy="locationExternalId", orphanRemoval=true, fetch="LAZY")
*/
protected $venues;
/**
* Location constructor.
* #param array $data
*/
public function __construct(array $data)
{
$this->venues = new ArrayCollection;
$this->hydrate($data);
}
/**
* #return int
*/
public function getLocationId()
{
return $this->locationId;
}
/**
* #param int $locationId
* #return $this
*/
public function setLocationId($locationId)
{
$this->locationId = $locationId;
return $this;
}
/**
* #return Venue[]|Collection
*/
public function getVenues()
{
return $this->venues;
}
/**
* #param Venue[]|Collection $venues
* #return $this
*/
public function setVenues($venues)
{
$this->venues = $venues;
return $this;
}
}
// Venue.php
namespace App\Entity;
use App\Entity\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\VenueRepository")
* #ORM\Table(name="Venue", indexes={#ORM\Index(name="IDX_Venue", columns={"location_id"})})
*/
class Venue extends Entity
{
/**
* #var integer
* #ORM\Column(type="integer", unique=true, nullable=true)
*/
protected $venueId;
/**
* #var integer
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer", nullable=false)
*/
protected $externalId;
/**
* #var Location
* #ORM\ManyToOne(targetEntity="App\Entity\Location", inversedBy="venues")
* #ORM\JoinColumn(name="location_external_id", referencedColumnName="external_id", nullable=true)
*/
protected $locationExternalId;
/**
* Venue constructor.
* #param array $data
*/
public function __construct(array $data)
{
$this->hydrate($data);
}
/**
* #return int
*/
public function getVenueId()
{
return $this->venueId;
}
/**
* #param int $venueId
* #return $this
*/
public function setVenueId($venueId)
{
$this->venueId = $venueId;
return $this;
}
/**
* #return int
*/
public function getExternalId()
{
return $this->externalId;
}
/**
* #param int $externalId
* #return $this
*/
public function setExternalId($externalId)
{
$this->externalId = (int)$externalId;
return $this;
}
/**
* #return Location
*/
public function getLocationExternalId()
{
return $this->locationExternalId;
}
/**
* #param Location $locationExternalId
* #return $this
*/
public function setLocationExternalId($locationExternalId)
{
$this->locationExternalId = $locationExternalId;
return $this;
}
}
If I load a Location, Venues is not initialized, that's what is expected :
// Controller.php
use App\Entity\Basketball\Location;
use App\Entity\Basketball\Venue;
$location = $this->getDoctrine()->getRepository(Location::class)->findOneBy(['externalId' => 1]);
dump($location);
// Dump results
App\Entity\Location {#1438 ▼ #locationId: 1644
#externalId: 1
#venues: Doctrine\ORM\PersistentCollection {#1450 ▼
-snapshot: []
-owner: App\Entity\Location {#1438}
-association: array:15 [ …15]
-em: Doctrine\ORM\EntityManager {#75 …11}
-backRefFieldName: "locationExternalId"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata {#1441 …}
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection {#1700 ▶}
#initialized: false
But it should by calling the getter, and it's not working as expected
// Controller.php
dump($location->getVenues());
// Dump results
Doctrine\ORM\PersistentCollection {#1450 ▼
-snapshot: []
-owner: App\Entity\Location {#1438 ▶}
-association: array:15 [ …15]
-em: Doctrine\ORM\EntityManager {#75 …11}
-backRefFieldName: "locationExternalId"
-typeClass: Doctrine\ORM\Mapping\ClassMetadata {#1441 …}
-isDirty: false
#collection: Doctrine\Common\Collections\ArrayCollection {#1700 ▼
-elements: []
}
#initialized: false
}
Environment
Symfony v4.4.7
Doctrine v2.7 ("doctrine/doctrine-fixtures-bundle":
"^3.3")
By specifying "fetch=EAGER", it works, but I don't want to...
Any idea? What should I do to initialize my collection?
Edit
Thanks to this Github issue I found a workaround by initializing the collection inside the getter but still; there should be a way to do it automatically :
public function getVenues()
{
$this->venues->initialize();
return $this->venues;
}
Does it really need to you? For initializing collection you need to call some method of this collection. If you are using JMSSerializer or Symfony Serializer you can just return the serialized data, serializers do all job for you, because they call toArray method, that initialize your collection.

Symfony 2.8 Entity when access displayAction Route SQLSTATE[42P01]: Undefined table: 7 ERROR: missing FROM-clause entry for table "t10"

hi im trying added customer section when customer can do something like see address list and add/update/delete address. a
so im trying my first step make customer entity like this
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Customer
*
* #ORM\Table(name="customer")
* #ORM\Entity(repositoryClass="AppBundle\Repository\CustomerRepository")
*/
class Customer
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="name", type="text")
*/
private $name;
/**
* #var string
*
* #ORM\Column(name="address", type="text")
*/
private $address;
/**
* #ORM\OneToOne(targetEntity="User", inversedBy="customer")
*/
private $user;
/**
* #ORM\OneToOne(targetEntity="Cart", mappedBy="user", cascade={"persist"})
*/
protected $cart;
// public function __construct()
// {
// parent::__construct();
// // your own logic
// }
// other properties and methods
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Customer
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set address
*
* #param string $address
*
* #return Customer
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* Get address
*
* #return string
*/
public function getAddress()
{
return $this->address;
}
/**
* Set cart
*
* #param \AppBundle\Entity\Cart $cart
* #return User
*/
public function setCart(\AppBundle\Entity\Cart $cart = null)
{
$this->cart = $cart;
return $this;
}
/**
* Get cart
*
* #return \AppBundle\Entity\Cart
*/
public function getCart()
{
return $this->cart;
}
// public function __construct()
// {
// parent::__construct();
// $this->addRole("ROLE_CUSTOMER");
// }
}
and when i access localhost/customer i got error message like this
An exception occurred while executing 'SELECT t0.id AS id_1, t0.name
AS name_2, t0.address AS address_3, t0.user_id AS user_id_4, t5.id AS
id_6, t5.total_price AS total_price_7, t5.quantity AS quantity_8,
t5.user_id AS user_id_9 FROM customer t0 LEFT JOIN cart t5 ON
t5.user_id = t10.id':
SQLSTATE[42P01]: Undefined table: 7 ERROR: missing FROM-clause entry
for table "t10" LINE 1: ..._9 FROM customer t0 LEFT JOIN cart t5 ON
t5.user_id = t10.id ^
ive done open some thread in stackoverflow but many of them still confusing me to get the clear answer how to fix this issue,the topic mostly discuss about postgres not the entity.
and this is my customer controller
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use AppBundle\Entity\User;
use AppBundle\Entity\Customer;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class CustomerController extends Controller
{
/**
* #Route("customer/new", name="new_address")
*/
public function newAction(Request $request)
{
$user = new Customer();
$form = $this->createFormBuilder($user)
->add('name', TextType::class)
->add('address', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$doct = $this->getDoctrine()->getManager();
$doct->persist($user);
$doct->flush();
return $this->redirectToRoute('address_list');
} else {
return $this->render('customer/new.html.twig', array(
'form' => $form->createView(),
));
}
}
/**
* #Route("/customer", name="address_list")
*/
public function displayAction()
{
$user = $this->getDoctrine()
->getRepository('AppBundle:Customer')
->findAll();
return $this->render('customer/display.html.twig', array('data' => $user));
}
/**
* #Route("/customer/update/{id}", name="address_update")
*/
public function updateAction($id, Request $request)
{
$doct = $this->getDoctrine()->getManager();
$user = $doct->getRepository('AppBundle:Customer')->find($id);
if (!$user) {
throw $this->createNotFoundException(
'No customer found for id '.$id
);
}
$form = $this->createFormBuilder($user)
->add('address', TextType::class)
->add('save', SubmitType::class, array('label' => 'Submit'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$doct = $this->getDoctrine()->getManager();
$doct->persist($user);
$doct->flush();
return $this->redirectToRoute('address_display');
}
return $this->render('customer/new.html.twig', array(
'form' => $form->createView(),
));
}
/**
* #Route("customer/delete/{id}", name="customer_delete")
*/
public function deleteAction($id) {
$doct = $this->getDoctrine()->getManager();
$user = $doct->getRepository('AppBundle:Customer')->find($id);
if (!$user) {
throw $this->createNotfoundException('No customer found for id ',$id);
}
$doct->remove($user);
$doct->flush();
return $this->redirectToRoute('address_display');
}
}
i expect the output i can access the customer display action router again and show the list all data from customer controller.
i dunno why this can solve this issue,so i try to uncomment this line
public function __construct()
{
parent::__construct();
$this->addRole("ROLE_CUSTOMER");
}
its solved the issue i can open and access the localhost/customer

A choice list based on database values in sonata

is it possible to add a choice list in configureformfields with choices values mapped from the database instead of configuring it manually like this :
->add('testfield', 'choice', array('choices' => array(
'1' => 'choice 1',
'2' => 'choice 2',)))
if the entity is correctly mapped then you can just use:
->add('testfield')
and Sonata admin will do the job.
Let's say you have a Product class linked to a Category class:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Product
*
* #ORM\Table(name="product")
*
*/
class Product
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="products")
*/
protected $category;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set category
*
* #param Category $category
*
* #return Product
*/
public function setCategory(Category $category = null)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return Category
*/
public function getCategory()
{
return $this->category;
}
}
Simply using:
->add('category')
will provide a select form field with all the categories.
You can also use SONATA_TYPE_MODEL if you want something more advanced:
<?php
// src/AppBundle/Admin/ProductAdmin.php
class ProductAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$imageFieldOptions = array(); // see available options below
$formMapper
->add('category', 'sonata_type_model', $imageFieldOptions)
;
}
}
The documentation is on this page: Form Types
Hope this helps!

Unknown Entity namespace alias in symfony2

Hey I have two bundles in my symfony2 project. one is Bundle and the other one is PatentBundle.
My app/config/route.yml file is
MunichInnovationGroupPatentBundle:
resource: "#MunichInnovationGroupPatentBundle/Controller/"
type: annotation
prefix: /
defaults: { _controller: "MunichInnovationGroupPatentBundle:Default:index" }
MunichInnovationGroupBundle:
resource: "#MunichInnovationGroupBundle/Controller/"
type: annotation
prefix: /v1
defaults: { _controller: "MunichInnovationGroupBundle:Patent:index" }
login_check:
pattern: /login_check
logout:
pattern: /logout
inside my controller i have
<?php
namespace MunichInnovationGroup\PatentBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use JMS\SecurityExtraPatentBundle\Annotation\Secure;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Security\Core\SecurityContext;
use MunichInnovationGroup\PatentBundle\Entity\Log;
use MunichInnovationGroup\PatentBundle\Entity\UserPatent;
use MunichInnovationGroup\PatentBundle\Entity\PmPortfolios;
use MunichInnovationGroup\PatentBundle\Entity\UmUsers;
use MunichInnovationGroup\PatentBundle\Entity\PmPatentgroups;
use MunichInnovationGroup\PatentBundle\Form\PortfolioType;
use MunichInnovationGroup\PatentBundle\Util\SecurityHelper;
use Exception;
/**
* Portfolio controller.
* #Route("/portfolio")
*/
class PortfolioController extends Controller {
/**
* Index action.
*
* #Route("/", name="v2_pm_portfolio")
* #Template("MunichInnovationGroupPatentBundle:Portfolio:index.html.twig")
*/
public function indexAction(Request $request) {
$portfolios = $this->getDoctrine()
->getRepository('MunichInnovationGroupPatentBundle:PmPortfolios')
->findBy(array('user' => '$user_id'));
// rest of the method
}
Edit:
My Entity Class
<?php
namespace MunichInnovationGroup\PatentBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* MunichInnovationGroup\PatentBundle\Entity\PmPortfolios
*
* #ORM\Table(name="pm_portfolios")
* #ORM\Entity
*/
class PmPortfolios
{
/**
* #var string $id
*
* #ORM\Column(name="id", type="string", length=36, nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
* #var string $portfolioName
*
* #ORM\Column(name="portfolio_name", type="string", length=255, nullable=false)
*/
private $portfolioName;
/**
* #var text $description
*
* #ORM\Column(name="description", type="text", nullable=true)
*/
private $description;
/**
* #var string $permalink
*
* #ORM\Column(name="permalink", type="string", length=255, nullable=false)
*/
private $permalink;
/**
* #var string $sharingCode
*
* #ORM\Column(name="sharing_code", type="string", length=255, nullable=false)
*/
private $sharingCode;
/**
* #var boolean $shared
*
* #ORM\Column(name="shared", type="boolean", nullable=false)
*/
private $shared;
/**
* #var integer $sharedPortfolioCalls
*
* #ORM\Column(name="shared_portfolio_calls", type="integer", nullable=true)
*/
private $sharedPortfolioCalls;
/**
* #var boolean $isDefault
*
* #ORM\Column(name="is_default", type="boolean", nullable=false)
*/
private $isDefault;
/**
* #var UmUsers
*
* #ORM\ManyToOne(targetEntity="UmUsers")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $user;
/**
* Get id
*
* #return string
*/
public function getId()
{
return $this->id;
}
/**
* Set portfolioName
*
* #param string $portfolioName
*/
public function setPortfolioName($portfolioName)
{
$this->portfolioName = $portfolioName;
}
/**
* Get portfolioName
*
* #return string
*/
public function getPortfolioName()
{
return $this->portfolioName;
}
/**
* Set description
*
* #param text $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* Get description
*
* #return text
*/
public function getDescription()
{
return $this->description;
}
/**
* Set permalink
*
* #param string $permalink
*/
public function setPermalink($permalink)
{
$this->permalink = $permalink;
}
/**
* Get permalink
*
* #return string
*/
public function getPermalink()
{
return $this->permalink;
}
/**
* Set sharingCode
*
* #param string $sharingCode
*/
public function setSharingCode($sharingCode)
{
$this->sharingCode = $sharingCode;
}
/**
* Get sharingCode
*
* #return string
*/
public function getSharingCode()
{
return $this->sharingCode;
}
/**
* Set shared
*
* #param boolean $shared
*/
public function setShared($shared)
{
$this->shared = $shared;
}
/**
* Get shared
*
* #return boolean
*/
public function getShared()
{
return $this->shared;
}
/**
* Set sharedPortfolioCalls
*
* #param integer $sharedPortfolioCalls
*/
public function setSharedPortfolioCalls($sharedPortfolioCalls)
{
$this->sharedPortfolioCalls = $sharedPortfolioCalls;
}
/**
* Get sharedPortfolioCalls
*
* #return integer
*/
public function getSharedPortfolioCalls()
{
return $this->sharedPortfolioCalls;
}
/**
* Set isDefault
*
* #param boolean $isDefault
*/
public function setIsDefault($isDefault)
{
$this->isDefault = $isDefault;
}
/**
* Get isDefault
*
* #return boolean
*/
public function getIsDefault()
{
return $this->isDefault;
}
/**
* Set user
*
* #param MunichInnovationGroup\PatentBundle\Entity\UmUsers $user
*/
public function setUser(\MunichInnovationGroup\PatentBundle\Entity\UmUsers $user)
{
$this->user = $user;
}
/**
* Get user
*
* #return MunichInnovationGroup\PatentBundle\Entity\UmUsers
*/
public function getUser()
{
return $this->user;
}
}
My bundle main class: MunichInnovationGroupPatentBundle.php
<?php
namespace MunichInnovationGroup\PatentBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class MunichInnovationGroupPatentBundle extends Bundle
{
}
when i try to load localhost/web/app_dev.php/portfolio
It says
Unknown Entity namespace alias 'MunichInnovationGroupPatentBundle'.
I am unable to figure out this error
please help me if anyone has any idea I googled it a lot :(
Thanks in advance
500 Internal Server Error - ORMException
Please, check your config.yml.
Reviewed in section mappings of entity_managers.
You should have something like MunichInnovationGroupPatentBundle: ~
That is:
doctrine:
orm:
entity_managers:
defaults:
mappings:
MunichInnovationGroupPatentBundle: ~
In my case I was missing namespace name in the security.yml under providers
I had:
entity: { class: AdministratorBundle:AdminUser }
and needed to have:
entity: { class: NamespaceAdministratorBundle:AdminUser }
If you use 2 or more entity managers -- you need to specify manager also
getManager('YourManager')
$repository =
$this->getDoctrine()
->getManager('YourManager')
->getRepository('YourBundle:YourEntity');
Check you bundle logical name (MunichInnovationGroupPatentBundle). Bundle logical name is name of main class of your bundle, e.g. JobsBundle
and provide your entity sourcecode.
Documentation here states you can use the string 'MunichInnovationGroupPatentBundle:PmPortfolios' as shortcut to 'MunichInnovationGroupPatentBundle\Entity\PmPortfolios' as long as your entity lives under the Entity namespace of your bundle.
Your bundle is MunichInnovationGroupBundle so instead of
->getRepository('MunichInnovationGroupPatentBundle:PmPortfolios')
use
->getRepository('MunichInnovationGroupPatentBundle\Entity\PmPortfolios')
Try being more explicit in your config.yml file by adding some fields:
orm:
...
mappings:
MunichInnovationGroupPatentBundle:
type: annotation
dir: "MunichInnovationGroupPatentBundle/Controller"
is_bundle: true
prefix: MunichInnovationGroup\PatentBundle
alias: MunichInnovationGroupPatentBundle
[more mappings..]
Please, check your config.yml + AppKernel.php
config.yml must be
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
or replace auto_mapping with
mappings:
StoreShopBundle: ~
for more, check this: https://stackoverflow.com/a/37652091/5809937
in AppKernel.php
don't forget to check if bundle is activated:
new MunichInnovationGroup\PatentBundle\MunichInnovationGroupPatentBundle(),
I had this when tried to use bandle name without core folder name. It was in config/security.yml
Folder structure in my case is the next src/Dp/UserBundle/....
I changed this
`providers:
main:
entity: { class: UserBundle:User, property: username }`
to this
`providers:
main:
entity: { class: DpUserBundle:User, property: username }`
So copy name of unknown Entity name and search each entries in project, check - they have to be with folder prefix (Dp in my case)
As at Symfony version 2.3.7, I used NameofCompanySomethingBundle:EntityRequired e.g. AcmeBlogBundle:User and it works.
auto-mapping: true (default) was used under orm: in config.yml.
This error will occur if you use multiple entity managers and you do not specify the entity manager in your controller function.
$em = $this->get('doctrine.orm.//your_entity_manager_name_here//_entity_manager');
$dql = "SELECT ...";
$query = $em->createQuery($dql);
this worked for me.
open your app\config.yml, must be
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
replace to
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
mappings:
MunichInnovationGroupPatentBundle: ~

Multiple file upload with Symfony2

I'm trying to upload multiple files via a form, but I can only upload one file at a time, the last one I mark in the browser. Is there a way to upload more images with Symfony2 using a simple form?
Here is the twig template of the form I'm using to be able to mark more than one file:
{{ form_widget(form.post_image, { 'attr': {'multiple': 'multiple' }}) }}
Ok binding issue solved (enctype syntax error) : i'll give you the code i use. maybe it will help...
I have a Gallery Entity
class Gallery
{
protected $id;
protected $name;
protected $description;
private $urlName;
public $files; // the array which will contain the array of Uploadedfiles
// GETTERS & SETTERS ...
public function getFiles() {
return $this->files;
}
public function setFiles(array $files) {
$this->files = $files;
}
public function __construct() {
$files = array();
}
}
I have a form class that generate the form
class Create extends AbstractType {
public function buildForm(FormBuilder $builder, array $options) {
$builder->add('name','text',array(
"label" => "Name",
"required" => TRUE,
));
$builder->add('description','textarea',array(
"label" => "Description",
"required" => FALSE,
));
$builder->add('files','file',array(
"label" => "Fichiers",
"required" => FALSE,
"attr" => array(
"accept" => "image/*",
"multiple" => "multiple",
)
));
}
}
Now in the controller
class GalleryController extends Controller
{
public function createAction() {
$gallery = new Gallery();
$form = $this->createForm(new Create(), $gallery);
// Altering the input field name attribute
$formView = $form->createView();
$formView->getChild('files')->set('full_name', 'create[files][]');
$request = $this->getRequest();
if($request->getMethod() == "POST")
{
$form->bindRequest($request);
// print "<pre>".print_r($gallery->getFiles(),1)."</pre>";
if($form->isValid())
{
// Do what you want with your files
$this->get('gallery_manager')->save($gallery);
return $this->redirect($this->generateUrl("_gallery_overview"));
}
}
return $this->render("GalleryBundle:Admin:create.html.twig", array("form" => $formView));
}
}
Hope this help...
NB: If someone know a better way to alter this f** name attribute, maybe in the FormView class or by declaring a new field type, feel free to show us your method...
No extra classes needed (except the gallery_manger service but the issue you describe happens before...)
I don't really know what's wrong. Check for your template (maybe wrong enctype... or name attr missmatching)
first try to do a single file upload, check the documentation:
file Field Type
How to handle File Uploads with Doctrine
Once it works, you have to edit some lines.
add input file multiple attribute.
append [] at the end of the input file name attribute (mine is
create...[] because my form class name is create, if your is
createType it will be createType...[])
init $files as an array.
Copy/paste your code here.
All the suggestions I've found here are workarounds for the real situation.
In order to be able to have multiple attachments, you should use form collection.
Quote from the documentation:
In this entry, you'll learn how to create a form that embeds a collection of many other forms. This could be useful, for example, if you had a Task class and you wanted to edit/create/remove many Tag objects related to that Task, right inside the same form.
http://symfony.com/doc/2.0/cookbook/form/form_collections.html
Example case: You have a document, which form is specified by DocumentType. The document must have multiple attachments, which you can have by defining AttachmentType form and adding it as a collection to the DocumentType form.
For sf > 2.2 :
In you form type class, add this overrided method :
public function finishView(FormView $view, FormInterface $form, array $options) {
$view->vars['form']->children['files']->vars['full_name'] .= '[]';
}
Note that i try to do the same thing in sf2 using this syntax:
In the controller:
public function stuffAction() {
$form = $this->createFormBuilder()
->add('files','file',array(
"attr" => array(
"accept" => "image/*",
"multiple" => "multiple",
)
))
->getForm();
$formView = $form->createView();
$formView->getChild('files')->set('full_name', 'form[files][]');
// name param (eg 'form[files][]') need to be the generated name followed by []
// try doing this : $formView->getChild('files')->get('full_name') . '[]'
$request = $this->getRequest();
if($request->getMethod() == "POST") {
$form->bindRequest($request);
$data = $form->getData();
$files = $data["files"];
// do stuff with your files
}
}
return $this->render('Bundle:Dir:index.html.twig',array("form" => $formView));
}
$files will be an array of uploaded files...
Calling $form->createView() to alter the name attribute is certainly not the best way / cleanest way to do it but it's the only one i found that keeps the csrf functionality working, because altering the name attribute in a twig template makes it invalid...
Now I still have an issue using a form class which generate the form, I don't know why during the binding of the form data & object attached to the form my array of uploaded files is transformed in array of (file) name ???
use this methode :
$form = $this->createFormBuilder()
->add('attachments','file', array('required' => true,"attr" => array(
"multiple" => "multiple",
)))
->add('save', 'submit', array(
'attr' => array('class' => 'btn btn-primary btn-block btn-lg'),
'label' => 'save'
))
->getForm();
then you add [] to the name of your input via jQuery :
<input id="form_attachments" name="form[attachments]" required="required" multiple="multiple" type="file">
jQuery code :
<script>
$(document).ready(function() {
$('#form_attachments').attr('name',$('#form_attachments').attr('name')+"[]");
});
</script>
Here is easy example to upload multiple files. I have similar problem with upload files.
https://github.com/marekz/example_symfony_multiply_files_example
For symfony 3.*
First: Both form declatartion:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use AppBundle\Form\FilesType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class UserType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('lastName')
->add('files', CollectionType::class,array(
'entry_type' => FilesType::class,
'allow_add' => true,
'by_reference' => false,
))
;
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\User'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_user';
}
}
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class FilesType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file');
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Files'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_files';
}
}
Now, my entities:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User {
/**
* #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;
/**
* #var string
*
* #ORM\Column(name="lastName", type="string", length=255)
*/
private $lastName;
/**
* #ORM\ManyToMany(targetEntity="Files", cascade={"persist"})
*/
private $files;
function __construct() {
$this->files = new ArrayCollection();
}
/**
* Get id
*
* #return int
*/
public function getId() {
return $this->id;
}
/**
* 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;
}
/**
* Set lastName
*
* #param string $lastName
*
* #return User
*/
public function setLastName($lastName) {
$this->lastName = $lastName;
return $this;
}
/**
* Get lastName
*
* #return string
*/
public function getLastName() {
return $this->lastName;
}
/**
* Get files
*
* #return ArrayCollection
*/
function getFiles() {
return $this->files;
}
/**
* Set files
* #param type $files
*/
function setFiles($files) {
$this->files = $files;
}
}
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Files
*
* #ORM\Table(name="files")
* #ORM\Entity(repositoryClass="AppBundle\Repository\FilesRepository")
*/
class Files
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="file", type="string", length=255, unique=true)
* #Assert\NotBlank(message="Please, upload the product brochure as a PDF file.")
* #Assert\File(mimeTypes={ "application/pdf" })
*/
private $file;
/**
*
* #return Files
*/
function getUser() {
return $this->user;
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set file
*
* #param string $file
*
* #return Files
*/
public function setFile($file)
{
$this->file = $file;
return $this;
}
/**
* Get file
*
* #return string
*/
public function getFile()
{
return $this->file;
}
}
Finaly, Symfony Controller:
/**
* Creates a new user entity.
*
* #Route("/new", name="user_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request) {
$user = new User();
$form = $this->createForm('AppBundle\Form\UserType', $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$attachments = $user->getFiles();
if ($attachments) {
foreach($attachments as $attachment)
{
$file = $attachment->getFile();
var_dump($attachment);
$filename = md5(uniqid()) . '.' .$file->guessExtension();
$file->move(
$this->getParameter('upload_path'), $filename
);
var_dump($filename);
$attachment->setFile($filename);
}
}
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute('user_show', array('id' => $user->getId()));
}
return $this->render('user/new.html.twig', array(
'user' => $user,
'form' => $form->createView(),
));
}
You need to alter the input file name attribute which need to map an array.
<input type="file" name="name[]" multiple />
Methods getChild and set() were removed in 2.3.
Instead of this you should use children[] and vars properties
before:
$formView->getChild('files')->set('full_name', 'form[files][]');
after:
$formView->children['files']->vars = array_replace($formView->children['files']->vars, array('full_name', 'form[files][]'));
Symfony introduced 'multiple' option to file field type in symfony 2.5
$builder->add('file', 'file', array('multiple' => TRUE));
What would happen if there would be some validation errors? Will Symfony Form repost multiple file upload field. Because I tried it and I think for this purpose you need to use collection of file fields. Than symfony form must render all fields have added before correctly.