Upload file with Symfony 2 and Angular.js - angularjs

I have reviewed official docs http://symfony.com/doc/2.8/cookbook/controller/upload_file.html and other topics, but can't find the solution
So, here is my angular action
$scope.uploadFile = function(files) {
var fd = new FormData();
fd.append("file", files[0]);
$http.put('/api/clients/' + id +'/files', fd, {
withCredentials: true,
headers: {'Content-Type': undefined },
transformRequest: angular.identity
}).success(function(resp) {
$mdToast.show(
$mdToast.simple()
.textContent(resp.message)
.hideDelay(1500)
);
}).error(function(resp) {
$mdToast.show(
$mdToast.simple()
.textContent(resp.message)
.hideDelay(1500)
);
})
};
And my entity for upload files
namespace PT\HearingBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class Client
*
* #ORM\Entity(repositoryClass="PT\HearingBundle\Repository\ClientRepository")
* #ORM\Table(name="`client_uploads`")
*
* #package PT\HearingBundle\Entity
* #author Roman Lunin <roman.lunin#primary.technology>
*/
class ClientUploads
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #JMS\Groups("list")
*/
protected $id;
/**
* #ORM\Column(type="string")
*
* #Assert\NotBlank(message="Please, upload the product brochure as a PDF file.")
* #Assert\File(mimeTypes={ "application/pdf" })
*/
private $files;
/**
* #ORM\ManyToOne(targetEntity="Client", inversedBy="files")
* #ORM\JoinColumn(name="client_id", referencedColumnName="id")
* #JMS\Groups("list")
*
* #var Client
*/
protected $client;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get client
*
* #return Client
*/
public function getClient()
{
return $this->client;
}
/**
* Get files
*
* #return string
*/
public function getFiles()
{
return $this->files;
}
/**
* Set files
*
* #param string $files
*
* #return ClientUploads
*/
public function setFiles($files)
{
$this->files = $files;
return $this;
}
/**
* Set client
*
* #param int $client
* #return Client
*/
public function setClient($client)
{
$this->client = $client;
return $this;
}
}
It's form
class ClientUploadsType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('files')
->add('files', FileType::class)
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'PT\HearingBundle\Entity\ClientUploads'
));
}
}
And, well, I can't get what exactly I should put in my symfony controller, now it's looks like that and doesn't working at all.
public function putClientFilesAction(Request $request, $id)
{
$upload = new ClientUploads();
$form = $this->createForm(ClientUploadsType::class, $upload);
$form->handleRequest($request);
var_dump($request->files->get('file'));
exit;
$em = $this->getDoctrine()->getEntityManager();
if ( ! $form->isValid()) {
return new JsonResponse(array(
'message' => 'File is not valid'
), Response::HTTP_BAD_REQUEST);
}
$file = $upload->getFiles();
$fileName = md5(uniqid()) . '.' . $file->guessExtension();
$file->move(
$this->container->getParameter('files_directory'),
$fileName
);
$upload->setClient($id);
$upload->setFiles($fileName);
$em->flush();
return new JsonResponse(array(
'message' => 'File saved'
), Response::HTTP_OK);
}

Related

Disable swagger for some entites only in API Platform

I would like to use a controller for downloading files.
The request is coming via an entity url and an included custom controller.
In the invoke function the requested file will be sent to the browser.
The problem is that the swagger documentation will be shown in a browser, the output of the controller will be ignored.
Only via a postman request the file content will be shown.
A solution would be to disable swagger for this entity.
Entity:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\GetMediaObjectAction;
/**
* #ApiResource(
* attributes={
* "route_prefix"="/api"
* },
* collectionOperations={},
* itemOperations={
* "archiveapi_get_file"={
* "path"="/file/{company_id}/{id}/{filename}",
* "defaults"={"_api_receive"=false},
* "read"=false,
* "requirements" = {
* "company_id" = "\d+",
* "id" = ".+",
* "filename" = "(.+)\.(.+)",
* },
* }
* },
* normalizationContext={"groups"={"MediaObject:read"}}
* )
*/
class MediaObject
{
/**
* #var string|null
*
* #ApiProperty(identifier=true)
*/
protected $id = null;
/**
* #var string|null
*
* #ApiProperty(identifier=true)
*/
protected $companyId = null;
/**
* #var string|null
*
* #ApiProperty(identifier=true)
*/
protected $filename = null;
/**
* #return string|null
*/
public function getId(): ?string
{
return $this->id;
}
/**
* #param string|null $id
* #return MediaObject
*/
public function setId(?string $id): MediaObject
{
$this->id = $id;
return $this;
}
/**
* #return string|null
*/
public function getCompanyId(): ?string
{
return $this->companyId;
}
/**
* #param string|null $companyId
* #return MediaObject
*/
public function setCompanyId(?string $companyId): MediaObject
{
$this->companyId = $companyId;
return $this;
}
/**
* #return string|null
*/
public function getFilename(): ?string
{
return $this->filename;
}
/**
* #param string|null $filename
* #return MediaObject
*/
public function setFilename(?string $filename): MediaObject
{
$this->filename = $filename;
return $this;
}
}
Controller:
<?php
namespace App\Controller;
use App\Entity\MediaObject;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use function PHPUnit\Framework\throwException;
final class GetMediaObjectAction extends AbstractController
{
/**
* #Route(
* name="archiveapi_get_file",
* path="/file/{companyId}/{id}/{filename}",
* methods={"GET"},
* defaults={
* "_api_resource_class"=MediaObject::class,
* "_api_item_operation_name"="archiveapi_get_file",
* "_api_receive"=false,
* "_api_respond"=false
* }
* )
*/
public function __invoke(Request $request, $companyId, $id, $filename): BinaryFileResponse
{
$projectDir = $this->getParameter('kernel.project_dir');
$file = sprintf("%s/var/data/invoices_%s/%s/%s", $projectDir, $companyId, $id, $filename);
if (!file_exists($file)) {
throw new NotFoundHttpException('file not available');
}
return new BinaryFileResponse($file);
}
}

Creating sorted array for KnpLabs/KnpMenu

I want to create a sorted Menu in PHP, Symfony which could be very deep.
Therefor I have added 2 fields in category db (parent_id, sort).
My problem is to get a sorted array like:
array(
//MAIN CATEGORY 1
array(
'id' => 1,
'name' => 'Main',
'child'=> false
),
//MAIN CATEGORY 2
array(
'id' => 2,
'name' => 'Main2',
'child'=> false
),
//MAIN CATEGORY 3
array(
'id' => 6,
'name' => 'Main3',
'child'=> array(
array(
'id' => 4,
'name' => 'Sub of Main3',
'child'=> array(
'id' => 4,
'name' => 'Sub Sub og Main3',
'child'=> false
)
),
array(
'id' => 7,
'name' => '2. Sub og Main3',
'child'=> false
)
)
)
);
So I can use it to create the menu with KnpMenu Bundle.
I could not find another way, which is economical in performance and works with this bundle.
Can anybody help me, how to create the array out of the DB?
I tested something around and found a solution with knpMenuBundle like this:
namespace AppBundle\Menu;
use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
class Builder implements ContainerAwareInterface
{
use ContainerAwareTrait;
public function mainMenu(FactoryInterface $factory, array $options)
{
$em = $this->container->get('doctrine')->getManager();
$mandant = $this->container->get('session')->get('mandantId');
$nodes = $em->getRepository('AppBundle:Categories')->findSorted($mandant);
$menu = $factory->createItem('root');
$menu->addChild('Startseite', array('route' => 'homepage'));
foreach($nodes as $node)
{
$childMenu = $menu->addChild($node['name'],array('route' => $node['route']));
$this->loadChild($childMenu,$node);
}
return $menu;
}
private function loadChild($childMenu,array $node)
{
if(isset($node['child']))
{
foreach ($node['child'] as $child)
{
$childMenu = $childMenu->addChild($child['name'],array('route' => $child['route']));
$this->loadChild($childMenu,$child);
}
}
return;
}
I had a very similar issue and here is how I solved it.
So my page entity looks something like this:
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Knp\Menu\NodeInterface;
/**
* Page
*
* #ORM\Table(name="PAGE")
* #ORM\Entity()
*/
class Page implements NodeInterface
{
/**
* #var int
*
* #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;
/**
* page | link | pdf
* #var string
*
* #ORM\Column(name="CONTENT_TYPE", type="string", length=255)
*/
private $contentType;
/**
* A page can have one parent
*
* #var FacetPage
*
* #ORM\ManyToOne(targetEntity="Page", inversedBy="childrenPages")
* #ORM\JoinColumn(name="PARENT_PAGE_ID", referencedColumnName="ID")
*/
private $parentPage;
/**
* A parent can have multiple children
*
* #var arrayCollection
*
* #ORM\OneToMany(targetEntity="Page", mappedBy="parentPage")
*
*/
private $childrenPages;
/**
* #var resource
*
* #ORM\Column(name="CONTENT", type="text", length=200000)
*/
private $content;
/**
* Many pages could have many allowed roles
*
* #var arrayCollection
*
* #ORM\ManyToMany(targetEntity="Role")
* #ORM\JoinTable(name="PAGE_ALLOWED_ROLES",
* joinColumns={#ORM\JoinColumn(name="page_id", referencedColumnName="ID")},
* inverseJoinColumns={#ORM\JoinColumn(name="role_id", referencedColumnName="ID")}
* )
*/
private $allowedRoles;
/**
* #var string
*
* #ORM\Column(name="SLUG", type="string", nullable=true)
*/
private $slug;
/**
* #var string
*
* #ORM\Column(name="PERMALINK", type="string", nullable=true)
*/
private $permalink;
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="User")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="CREATED_BY", referencedColumnName="ID", nullable=false)
* })
*
*/
private $author;
/**
* #var \DateTime
*
* #ORM\Column(name="CREATED_ON", type="datetime", nullable=false)
*/
private $createdOn;
/**
* The default status of new pages is published
*
* #var string
*
* #ORM\Column(name="STATUS", type="string", nullable=false, )
*/
private $status = 'published';
/**
* Page constructor.
*/
public function __construct( ) {
//https://knpuniversity.com/screencast/collections/many-to-many-setup#doctrine-arraycollection
$this->allowedRoles = new ArrayCollection();
$this->childrenPages = new ArrayCollection();
}
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #param int $id
*/
public function setId( int $id )
{
$this->id = $id;
}
/**
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* #param string $title
*/
public function setTitle( string $title )
{
$this->title = $title;
}
/**
* #return string
*/
public function getContentType()
{
return $this->contentType;
}
/**
* #param string $contentType
*/
public function setContentType( string $contentType )
{
$this->contentType = $contentType;
}
/**
* #return Page
*/
public function getParentPage()
{
return $this->parentPage;
}
/**
* #param Page $parentPage
*/
public function setParentPage( Page $parentPage )
{
$this->parentPage = $parentPage;
}
/**
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* #param string $content
*/
public function setContent( string $content )
{
$this->content = $content;
}
/**
* #return ArrayCollection|Role[]
*/
public function getAllowedRoles()
{
return $this->allowedRoles;
}
/**
* #param arrayCollection $allowedRoles
*/
public function setAllowedRoles( $allowedRoles )
{
$this->allowedRoles = $allowedRoles;
}
/**
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* #param string $slug
*/
public function setSlug( string $slug )
{
$this->slug = $slug;
}
/**
* #return string
*/
public function getPermalink()
{
return $this->permalink;
}
/**
* #param string $permalink
*/
public function setPermalink( string $permalink )
{
$this->permalink = $permalink;
}
/**
* #return User
*/
public function getAuthor()
{
return $this->author;
}
/**
* #param FacetUser $author
*/
public function setAuthor( User $author )
{
$this->author = $author;
}
/**
* #return \DateTime
*/
public function getCreatedOn()
{
return $this->createdOn;
}
/**
* #param \DateTime $createdOn
*/
public function setCreatedOn( \DateTime $createdOn )
{
$this->createdOn = $createdOn;
}
/**
* #return string
*/
public function getStatus()
{
return $this->status;
}
/**
* #param string $status
*/
public function setStatus( string $status )
{
$this->status = $status;
}
/**
* #return ArrayCollection
*/
public function getChildrenPages()
{
return $this->childrenPages;
}
/**
* #param ArrayCollection $childrenPages
*/
public function setChildrenPages( $childrenPages )
{
$this->childrenPages = $childrenPages;
}
/**
* Get the name of the node
*
* Each child of a node must have a unique name
*
* #return string
*/
public function getName() {
return $this->title;
}
/**
* Get the options for the factory to create the item for this node
*
* #return array
* #throws \Exception
*/
public function getOptions() {
if($this->contentType == 'page'){
return [
'route' => 'core_page_id',
'routeParameters' => ['id'=>$this->id]
];
}
if($this->contentType == 'doc'){
return [
'uri'=>'/'.$this->getContent()
];
}
if($this->contentType == 'link'){
return [
'uri'=>$this->content
];
}
throw new \Exception('No valid options found for page type',500);
}
/**
* Get the child nodes implementing NodeInterface
*
* #return \Traversable
*/
public function getChildren() {
return $this->getChildren();
}
}
The main difference here is that it implements Knp's NodeInterface and its functions which are defined at the end of the entity, getName(), getOptions(), and getChildren().
Now on to my Builder, which basically does the same thing as your recursive function.
<?php
namespace AppBundle\Menu;
use AppBundle\Entity\Page;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Knp\Menu\MenuItem;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
class Builder implements ContainerAwareInterface
{
use ContainerAwareTrait;
/** #var ItemInterface */
private $menu;
/**
* #param FactoryInterface $factory
* #param array $options
*
* #return ItemInterface
*/
public function mainMenu(FactoryInterface $factory, array $options)
{
$this->menu = $factory->createItem('root');
$this->menu->addChild('Home', array('route' => 'core_homepage'));
$em = $this->container->get('doctrine')->getManager();
// get all published pages
$pages = $em->getRepository(Page::class)->findBy(['status'=>'published']);
// build pages
try {
$this->buildPageTree( $pages );
} catch ( \Exception $e ) {
error_log($e->getMessage());
}
return $this->menu;
}
/**
*
* #param array $pages
* #param Page $parent
* #param MenuItem $menuItem
*
* #throws \Exception
*/
private function buildPageTree(array $pages, $parent = null, $menuItem = null)
{
/** #var Page $page */
foreach ($pages as $page) {
// If page doesn't have a parent, and no menuItem was passed then this is a top level add.
if(empty($page->getParentPage()) && empty($menuItem) )
$parentMenu = $this->menu->addChild($page->getTitle(), $page->getOptions());
// if the current page's parent is === supplied parent, go deeper
if ($page->getParentPage() === $parent) {
// if a menuItem was given, then this page is a child so added it to the provided menu.
if(!empty($menuItem))
$parentMenu = $menuItem->addChild($page->getTitle(), $page->getOptions());
// go deeper
$this->buildPageTree($pages, $page, $parentMenu);
}
}
}
}
I hope this helps in some way!

Foreign key not stored in database using embed form in symfony 3

I have the following entities, form types and controller
Entity Client
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Client
*
* #ORM\Table(name="client")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ClientRepository")
*/
class Client
{
/**
* #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="address", type="string", length=255)
*/
private $address;
/**
* #ORM\OneToMany(targetEntity="Contacts", mappedBy="client", cascade={"persist"})
*/
private $contacts;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Client
*/
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 Client
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* Get address
*
* #return string
*/
public function getAddress()
{
return $this->address;
}
/**
* Constructor
*/
public function __construct()
{
$this->contacts = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add contact
*
* #param \AppBundle\Entity\Contacts $contact
*
* #return Client
*/
public function addContact(\AppBundle\Entity\Contacts $contact)
{
$this->contacts[] = $contact;
return $this;
}
/**
* Remove contact
*
* #param \AppBundle\Entity\Contacts $contact
*/
public function removeContact(\AppBundle\Entity\Contacts $contact)
{
$this->contacts->removeElement($contact);
}
/**
* Get contacts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getContacts()
{
return $this->contacts;
}
}
Contacts entity is as below
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Contacts
*
* #ORM\Table(name="contacts")
* #ORM\Entity(repositoryClass="AppBundle\Repository\ContactsRepository")
*/
class Contacts
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="fullname", type="string", length=255)
*/
private $fullname;
/**
* #var int
*
* #ORM\Column(name="user_type", type="smallint")
*/
private $userType;
/**
* #ORM\ManyToOne(targetEntity="Client", inversedBy="contacts")
* #ORM\JoinColumn(name="client_id", referencedColumnName="id")
*/
private $client;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set fullname
*
* #param string $fullname
*
* #return Contacts
*/
public function setFullname($fullname)
{
$this->fullname = $fullname;
return $this;
}
/**
* Get fullname
*
* #return string
*/
public function getFullname()
{
return $this->fullname;
}
/**
* Set userType
*
* #param integer $userType
*
* #return Contacts
*/
public function setUserType($userType)
{
$this->userType = $userType;
return $this;
}
/**
* Get userType
*
* #return int
*/
public function getUserType()
{
return $this->userType;
}
/**
* Set client
*
* #param \AppBundle\Entity\Client $client
*
* #return Contacts
*/
public function setClient(\AppBundle\Entity\Client $client = null)
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* #return \AppBundle\Entity\Client
*/
public function getClient()
{
return $this->client;
}
}
Client form type is as below
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use AppBundle\Entity\Client;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class ClientForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class, array('attr' => array('class' => 'form-control', 'placeholder' => 'Client Name')))
->add('address', TextType::class, array('attr' => array('class' => 'form-control', 'placeholder' => 'Address')))
->add('contacts', CollectionType::class, array(
// each entry in the array will be an "email" field
'entry_type' => ContactsForm::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
))
->add('save', SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Client::class,
));
}
}
Contacts form type is as below
<?php
namespace AppBundle\Form;
use AppBundle\Entity\Contacts;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class ContactsForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('fullname', TextType::class, array('attr' => array('class' => 'form-control', 'placeholder' => 'Full Name')))
->add('user_type', TextType::class, array('attr' => array('class' => 'form-control', 'placeholder' => 'Co-Owner'))
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Contacts::class,
));
}
}
Finally the controller to store data in two different tables being client as main table and contacts having foreign ken as client_id from table client is as below
/
**
* #Route("/client/add", name="add_client")
*/
public function addClientAction(Request $request)
{
$client = new Client();
$form = $this->createForm(ClientForm::class, $client);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$client = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($client);
$em->flush();
$this->addFlash(
'notice',
'Client Added!'
);
return $this->redirectToRoute('homepage');
}
return $this->render('default/addClient.html.twig', array('form' => $form->createView()));
}
The problem here is the data is added in both tables but the foreign key of the added client is not stored in table contacts, the value is null
This solution seems to work for some people may be for older version of symfony
But not luck to me. How to insert the foreign id as well. Am new to symfony and I am using symfony 3.2
It seems for me like a little mess up.
I guess you should add a contact from ContactController addAction.
Than in your Contact form type add EntityType, so you can choose a client for your contact. Here is some examples: http://symfony.com/doc/current/reference/forms/types/entity.html
Or you can set client manually by simple $contact->setClient($client) before you presist.
PS: rename Contacts entity to Contact. It is a little confusing)

How to save the accent character é as é in a mysql database when it is inserted in a form in Symfony2 ?

I would like to know how to save the accent character é as é in a mysql database when it is inserted in a form in Symfony2. The explanation is as below:
This the code of the form builder I have:
<?php
namespace Ikproj\GroupeBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class MessagesType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('contenu','textarea', array('attr' => array('rows' => '6','cols' => '40')));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Ikproj\GroupeBundle\Entity\Messages'
));
}
/**
* #return string
*/
public function getName()
{
return 'ikproj_groupebundle_messages';
}
}
This is the code of the entity belonged to the form builder above:
<?php
namespace Ikproj\GroupeBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Messages
*
* #ORM\Table(name="messages")
* #ORM\Entity(repositoryClass="Ikproj\GroupeBundle\Entity\MessagesRepository")
*/
class Messages
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="actor", type="integer")
*/
private $actor;
/**
* #var integer
*
* #ORM\Column(name="subject", type="integer")
*/
private $subject;
/**
* #var string
*
* #ORM\Column(name="contenu", type="string")
*/
private $contenu;
/**
* #var string
*
* #ORM\Column(name="status", type="string", length=10)
*/
private $status;
/**
* #var string
*
* #ORM\Column(name="type", type="string", length=10)
*/
private $type;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set actor
*
* #param integer $actor
* #return Messages
*/
public function setActor($actor)
{
$this->actor = $actor;
return $this;
}
/**
* Get actor
*
* #return integer
*/
public function getActor()
{
return $this->actor;
}
/**
* Set subject
*
* #param integer $subject
* #return Messages
*/
public function setSubject($subject)
{
$this->subject = $subject;
return $this;
}
/**
* Get subject
*
* #return integer
*/
public function getSubject()
{
return $this->subject;
}
/**
* Set contenu
*
* #param string $contenu
* #return Messages
*/
public function setContenu($contenu)
{
$this->contenu = $contenu;
return $this;
}
/**
* Get contenu
*
* #return string
*/
public function getContenu()
{
return $this->contenu;
}
/**
* Set status
*
* #param string $status
* #return Messages
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* #return string
*/
public function getStatus()
{
return $this->status;
}
/**
* Set type
*
* #param string $type
* #return Messages
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* Get type
*
* #return string
*/
public function getType()
{
return $this->type;
}
}
This is the code of the controller I have:
public function SendMessageAction(Request $request, $actor, $subject, $cible) {
$message = new Messages();
$form = $this->createForm(new MessagesType(), $message);
$em = $this->getDoctrine()->getManager();
$actor1 = $actor;
$subject1 = $subject;
$status1 = "unseen";
$cible1 = $cible;
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$message->setActor($actor1);
$message->setSubject($subject1);
$message->setStatus($status1);
$message->setType($cible1);
$em->persist($message);
$em->flush();
return $this->redirect($this->generateUrl('task_success'));
}
}
else {
return $this->render('IkprojGroupeBundle:Messages:SendMessage.html.twig', array(
'form' => $form->createView(),
'actor' => $actor,
'subject' => $subject,
'cible' => $cible
));
}
}
And this is the code of the file config.yml belonged to the doctrine configuration:
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
The problem is that when I insert the accent character é in the form then I valid, it will be saved in the database as é not é as you can see in screenshot below:
Whereas when I run the code below in Symfony2:
<?php
$tab = $_REQUEST['table'];
$a = $tab[0];
$b = $tab[1];
$con=mysqli_connect("localhost","root","","wkayetdb");
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"INSERT INTO messages(actor,subject,contenu,status,type) VALUES ($a,$b,'é','unseen','G')");
mysqli_close($con);
?>
it works correctly and the character é will be saved as é as you can see below:
So, my questions are:
What is wrong in my code?
How can I save é as é in a mysql database once it is inserted in a form in Symfony2 ?
I do not know why you want to do that
but if you want to do this, simply comment that line "charset: UTF8"
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
# charset: UTF8

symfony2 file lost upon form error

I am using a standard implementation of file upload in connection with doctrine, as per the example on the symfony2 website tutorials.
When my upload form encounters an error in validation, and sends the user back to the form with error messages, it looses the file chosen for upload, although if I var_dump my $entity->file I can see that it has the file...
//if form is valid, do some stuff... if not:
else {
//var_dump($entity->file); //This works, I get my file
//die;
//Get and check the folder chosen as parent
$entity->setFolder( $this->checkFolderId($request->request->get('folder')) ); //will cause die() if folder doesn't belong to this company
$folders = $this->getFolders();
return $this->render('BizTVMediaManagementBundle:Image:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
'folders' => $folders,
'fileExists' => $fileExists,
));
}
After this is put to the twig view, there is nothing in the file field.
Here is my entity...
<?php
namespace BizTV\MediaManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* BizTV\MediaManagementBundle\Entity\Image
*
* #ORM\Table(name="image")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Image
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255)
* #Assert\NotBlank
*/
private $name;
/**
* #var integer $width
*
* #ORM\Column(name="width", type="integer")
*/
private $width;
/**
* #var integer $height
*
* #ORM\Column(name="height", type="integer")
*/
private $height;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $path;
/**
* #var object BizTV\BackendBundle\Entity\company
*
* #ORM\ManyToOne(targetEntity="BizTV\BackendBundle\Entity\company")
* #ORM\JoinColumn(name="company", referencedColumnName="id", nullable=false)
*/
protected $company;
/**
* #var object BizTV\MediaManagementBundle\Entity\Folder
*
* #ORM\ManyToOne(targetEntity="BizTV\MediaManagementBundle\Entity\Folder")
* #ORM\JoinColumn(name="folder", referencedColumnName="id", nullable=true)
*/
protected $folder;
/**
* #Assert\File(maxSize="6000000")
*/
public $file;
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->file) {
// do whatever you want to generate a unique name
$this->path = sha1(uniqid(mt_rand(), true)).'.'.$this->file->guessExtension();
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->file) {
return;
}
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
$this->file->move($this->getUploadRootDir(), $this->path);
unset($this->file);
}
/**
* #ORM\PostRemove()
*/
public function removeUpload()
{
if ($file = $this->getAbsolutePath()) {
unlink($file);
}
}
public function getAbsolutePath()
{
return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->path;
}
public function getWebPath()
{
return null === $this->path ? null : $this->getUploadDir().'/'.$this->path;
}
protected function getUploadRootDir()
{
// the absolute directory path where uploaded documents should be saved
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view.
return 'uploads/images';
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set width
*
* #param integer $width
*/
public function setWidth($width)
{
$this->width = $width;
}
/**
* Get width
*
* #return integer
*/
public function getWidth()
{
return $this->width;
}
/**
* Set height
*
* #param integer $height
*/
public function setHeight($height)
{
$this->height = $height;
}
/**
* Get height
*
* #return integer
*/
public function getHeight()
{
return $this->height;
}
/**
* Set path
*
* #param string $path
*/
public function setPath($path)
{
$this->path = $path;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set company
*
* #param BizTV\BackendBundle\Entity\company $company
*/
public function setCompany(\BizTV\BackendBundle\Entity\company $company)
{
$this->company = $company;
}
/**
* Get company
*
* #return BizTV\BackendBundle\Entity\company
*/
public function getCompany()
{
return $this->company;
}
/**
* Set folder
*
* #param BizTV\MediaManagementBundle\Entity\Folder $folder
*/
public function setFolder(\BizTV\MediaManagementBundle\Entity\Folder $folder = NULL)
{
$this->folder = $folder;
}
/**
* Get folder
*
* #return BizTV\MediaManagementBundle\Entity\Folder
*/
public function getFolder()
{
return $this->folder;
}
}
And the form:
<?php
namespace BizTV\MediaManagementBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class ImageType extends AbstractType
{
function __construct($createAction=0) {
$this->createAction = $createAction;
}
public function buildForm(FormBuilder $builder, array $options)
{
$createAction = $this->createAction;
if ($createAction) {
$builder
->add('file')
;
}
$builder
->add('name', 'text', array('label' => 'Namn'))
;
}
public function getName()
{
return 'biztv_mediamanagementbundle_imagetype';
}
}
You can't, for security purposes, set a file for the upload field. See here for more info. How to set the value of a HTML file field?
I suggest you are trying to access the file property of your entity in twig. Please take a quick look at your upload function.
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->file) {
return;
}
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
$this->file->move($this->getUploadRootDir(), $this->path);
unset($this->file);
}
As you can see the file property is being unset after the upload and persist operation has completed.
Now to have twig show your actual image you have to use the webPath property as this is the generated url to your newly uploaded image.
File uploading can be handled a bit easier with the Dustin10/VichUploaderBundle which also supports file system abstraction with KnpLabs/Gaufrette.
Hope this helps :)

Resources