I have an article entity. When I create an article, I want to be able to add zero to n images to it.
To do so, I upload files with a jQuery plugin in a temporary directory, and add an <input type=hidden>
to my form, with the file's full path as value.
It works fine when there is no validation error. But when there is, I got an error saying:
An exception has been thrown during the rendering of a template ("Notice: Array to string conversion") in form_div_layout.html.twig at line 13
And I'm pretty sure it's because it tries to do this :
ErrorHandler ->handleError ('8', 'Array to string conversion', '/var/www/project/app/cache/dev/twig/47/a4/ac9a00176739f843e919f5f89883191930038a6e0aaa218869e4966ab7c6.php', '175', array('context' => array('value' => array('njm4uqsa9y6@54edfdaedd0736w3wstk.jpeg'),...
Here is my formType :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('content')
->add('maxVote')
->add('expireAt', 'datetime', array(
'widget' => 'single_text',
'input' => 'string',
'format' => 'dd-mm-yyyy',
)
)
->add('category', 'entity', array(
'class' => 'AppBundle:StoryCategory',
'required' => true
)
)
->add('answers', 'collection', array(
'type' => new AnswerType()
)
)
->add('visibility', 'choice', array(
'choices' => array(1 => "label.public", 2 => "label.semiprivate", 3 => "label.private"),
'expanded' => false,
'multiple' => false
)
)
->add('attachment', 'hidden', array(
'mapped' => false,
'required' => false
)
)
->add('save', 'submit')
;
}
Do you have any idea what is happening, or what should I do ?
Edit:
The form is empty. I create a new instance of Story
$story = new Story();
$form = $this->createForm(new StoryType(), $story);
And when I submit the form I do
$form->handleRequest($request);
Edit 2: Story.php
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Story
*
* @ORM\Table(name="story")
* @ORM\Entity(repositoryClass="AppBundle\Repository\StoryRepository")
*/
class Story
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
* @Assert\NotBlank()
*/
private $title;
/**
* @var string
*
* @ORM\Column(name="content", type="text")
* @Assert\NotBlank()
*/
private $content;
/**
* @var string
*
* @ORM\Column(name="token", type="string", length=70, unique=true)
*/
private $token;
/**
* @var \DateTime
*
* @ORM\Column(name="created_at", type="datetime")
*/
private $createdAt;
/**
* @var \DateTime
*
* @ORM\Column(name="updated_at", type="datetime")
*/
private $updatedAt;
/**
* @var \DateTime
*
* @ORM\Column(name="expire_at", type="datetime")
* @Assert\NotBlank()
*/
private $expireAt;
/**
* @var string
*
* @ORM\Column(name="author_ip", type="string", length=50, nullable=true)
*/
private $authorIp;
/**
* @var integer
*
* @ORM\Column(name="max_vote", type="integer", nullable=true)
* @Assert\Type(type="integer")
* @Assert\Range(
* min = 0,
* max = 20000,
* minMessage = "validation.story.maxvote.min",
* maxMessage = "validation.story.maxvote.max"
* )
*/
private $maxVote;
/**
* @var integer
*
* @ORM\Column(name="nb_vote", type="integer")
*/
private $nbVote;
/**
* @var integer
* 1 = public, 2 = semi-private, 3 = private (only invited members)
*
* @ORM\Column(name="visibility", type="integer")
*
*/
private $visibility;
/**
* @var boolean
*
* @ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* @var StoryCategory
*
* @ORM\ManyToOne(targetEntity="StoryCategory", inversedBy="stories")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
* })
* @Assert\NotNull()
*/
private $category;
/**
* @ORM\OneToMany(targetEntity="Answer", mappedBy="story", cascade={"persist", "remove"})
* @Assert\Count(
* min = "2",
* max = "4",
* minMessage = "validation.story.answer.min",
* maxMessage = "validation.story.answer.max",
* groups={"premium"}
* )
* @Assert\Count(
* min = "2",
* max = "2",
* minMessage = "validation.story.answer.min",
* maxMessage = "validation.story.answer.max",
* )
*/
private $answers;
/**
* @ORM\OneToMany(targetEntity="Attachment", mappedBy="story", cascade={"persist", "remove"})
*/
private $attachments;
/**
* @var User
*
* @ORM\ManyToOne(targetEntity="User", inversedBy="stories")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
* })
*/
private $author;
public function __construct()
{
$datetime = new \DateTime();
$this->createdAt = $datetime;
$this->updatedAt = $datetime;
$this->token = base_convert(time(), 10, 36).\AppBundle\Library\StringHelper::randomString();
$this->isActive = false;
$this->nbVote = 0;
}
}
Twig view :
{% extends '::base.html.twig' %}
{% block basecontent %}
{{ form_errors(form) }}
{{ form_start(form, {attr: {id: 'story-form', novalidate: 'novalidate'}}) }}
{{ form_row(form.title) }}
{{ form_row(form.content) }}
{{ form_row(form.category) }}
<h3>Les choix de réponses possibles</h3>
{% for answer in form.answers %}
{{ form_widget(answer) }}
{% endfor %}
{{ form_row(form.visibility) }}
{{ form_row(form.expireAt) }}
{% for attachement in form.attachment %}
{{ form_row(attachment) }}
{% endfor %}
{{ form_end(form) }}
{# upload zone #}
<div class="upload-block">
<form action='{{ path('story_file_upload') }}' id="dropzone" class="dropzone">
</form>
</div>
{% endblock basecontent %}
This is what I add with javascript :
$("#story-form").append('<input type="hidden" name="story_form[attachment][]" value="'+response.filename+'"/>');
So I tried without it being an array (I removed the ending [] in the name), and it works. So I assume the problem comes from that, I have to tell the formType that it's an array. But how ?
Thank you
I couldn't make it work, so I removed the "attachments" field from the formType.
When I upload a file, I then add using javascript an <input type="hidden">
with a name that does not match the fields from the formType.
For example, the fields generated by Symfony are named story_form['name']
. I just named mine attachments[]
. That way Symfony doesn't tell me that there is an extra field.
In my controller I get the values with $request->request->get('attachments')
.
There probably is a better way to do it, but I haven't found it.