I'm new to Symfony and just making my first Project with the 3.4 version.
I have a problem when using Constraints on my form, I'm trying to make a field having some Length constraints, but as I test it with a short value that shouldn't be accepted, the form displays a default message in a speech bubble instead of the one I put in minMessage, and instead of displaying a message for maxLength, it just don't let me put more thant 20 characters in the field instead of displaying a message if there is more than 20. I'm not sure this is how it should work (???) and if it is can I manage error messages with another technic? I'm just putting constraints on a single field until I resolved this issue that's why the others one don't have any.
Here's the Controller Code :
<?php
namespace AppBundle\Controller;
use AppBundle\Form\UserType;
use AppBundle\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
/**
* Class UserController
* #package AppBundle\Controller
* #Route("/user")
*/
class UserController extends Controller
{
/**
* #return \Symfony\Component\HttpFoundation\Response
* #Route("/add", name="add_user")
*/
public function addAction(Request $request)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
if($form->isSubmitted() && $form->isValid()){
$user->setPwd(md5($user->getPwd()));
$em->persist($user);
$em->flush();
return $this->render('#App/User/show.html.twig', array(
'user'=>$user
));
}
return $this->render('#App/User/add.html.twig', array(
'form'=>$form->createView()
));
}
}
UserType code:
<?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\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
class UserType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('pseudo')
->add('nom')
->add('prenom')
->add('enseignant')
->add('pwd', PasswordType::class)
->add('confirm_pwd', PasswordType::class);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\User'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_user';
}
}
User code (I'll just pute the code where my constraints are):
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User
{
/**
* #var string
*
* #ORM\Column(name="pseudo", type="string", length=100, unique=true)
* #Assert\Length(
* min = 8,
* max = 20,
* minMessage = "Your first name must be at least {{ limit }} characters long",
* maxMessage = "Your first name cannot be longer than {{ limit }} characters"
* )
*/
private $pseudo;
}
And the twig page that I render:
{% extends 'base.html.twig' %}
{% block body %}
<h1 class="display-4">Formulaire d'inscription</h1>
{{ form_start(form) }}
{{ form_row(form.pseudo, {'label': 'Pseudo', 'attr':
{'placeholder': 'Pseudonyme ...'}}) }}
{{ form_row(form.nom, {'label': 'Nom', 'attr':
{'placeholder': 'Nom ...'}}) }}
{{ form_row(form.prenom, {'label': 'Prenom', 'attr':
{'placeholder': 'Prenom ...'}}) }}
{{ form_row(form.enseignant, {'label': 'Enseignant'}) }}
{{ form_row(form.pwd, {'label': 'Mot De Passe', 'attr':
{'placeholder': 'Mot De Passe'}}) }}
{{ form_row(form.confirm_pwd, {'label': 'Confirmation Mot De Passe', 'attr':
{'placeholder': 'Mot De Passe'}}) }}
<button type="submit" class="btn btn-success">Inscription </button>
{{ form_end(form) }}
{% endblock %}
Do you know what should I do to make it work?
I am sorry if my english is bad, and tell me if you need more or less code!
Have a nice day and thank you !
PS: I'm a real beginner with Symfony so be nice pls :)
PSbis: I already checked the documentation and I made everything that should have been made, but I could have missed something (even if I checked multiple times)
Edit: I added EqualTo and Unique constraints on other fields, and both error messages are displaying, so this is comming from the Length constraint and I really don't know why
You're forgetting to add form_errors. Check this out.
Related
I have a Symfony form where I get errors when the fields are blanks.
I already try to set error_bubbling to false but it still not work (And is supposed to be false by default)
This is my code where I remove everything that is not necessary:
Controller:
/**
* #Route("/add", name="add")
*/
public function add(Request $request)
{
$post = new Post();
$form = $this->createForm(PostType::class, $post);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { } else { }
return $this->render('blog/add.html.twig', array('form' => $form->createView()));
}
Entity:
/**
* #ORM\Entity(repositoryClass="App\Repository\PostRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Post
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
* #Assert\NotBlank
*/
private $Title;
/**
* #ORM\Column(type="text")
* #Assert\NotBlank
*/
private $Content;
...
FormType:
namespace App\Form;
use App\Entity\Post;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title')
->add('content');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Post::class
]);
}
}
Form:
{% extends "base.html.twig" %}
{% block body %}
<h2>
Create a post
</h2>
{{ form_start(form) }}
{{ form_widget(form) }}
<input type="submit" class="btn" value="Create" />
{{ form_end(form) }}
{% endblock %}
When I look at the object after the post all the errors are linked to the form and there's no errors in the childs (The form fields).
Does anyone know what can be wrong?
In buildForm(), you need to capitalize your fields. They are case sensitive and they are capitalized in your database.
I don't understand why the rendering of this subform doesn't render the required tag on my TextType firstName;
My form in based on a Order entity
OrderFormType has a CollectionType of Tent, based on TentFormType
TentFormType has a CollectionType of Camper, based on CamperFormType
So Order > Tent > Camper
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
//...
class CamperFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('firstName', TextType::class, [
'required' => true, //Should even not been usefull since SF2.8
'label' => 'First name',
'attr' => [
'placeholder' => 'First name'
],
]);
//...
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\Camper',
'csrf_protection' => true,
'error_bubbling' => true,
'csrf_field_name' => '_token',
//...
]);
}
}
The fields are simply rendered with a form_widget:
{{ form_widget(form.firstName) }}
{{ form_widget(form.lastName) }}
But that not add the required field:
<input id="app_order_form_type_tents_0_campers_0_firstName" name="app_order_form_type[tents][0][campers][0][firstName]" placeholder="First name" class="form-control" type="text">
<input id="app_order_form_type_tents_0_campers_0_lastName" name="app_order_form_type[tents][0][campers][0][lastName]" placeholder="Last name" class="form-control" type="text">
I could do
{{ form_widget(form.firstName, {'attr': {'required': 'required'}}) }}
{{ form_widget(form.lastName, {'attr': {'required': 'required'}}) }}
But it shouldn't be required with my FormType...
Does anyone knows why ?
--EDIT--
My Camper Entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Camper.
*
* #ORM\Table(name="camper")
* #ORM\Entity()
*/
class Camper
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
* #Assert\NotBlank()
*
* #ORM\Column(name="firstName", type="string", length=255, nullable=false)
*/
private $firstName;
// ...
}
I'm sorry, i can not use comments so i put a suggestion here...
Try:
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
I can't store value to database if use Embedded Controller, if I don't use embedded controller I can store it.
Entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="tbl_mail")
*/
class Mail
{
/**
* #ORM\Column(type="string", length=255)
*/
public $email;
}
Controller:
class SendContactController extends Controller
{
public function Email(Request $request)
{
$mail = new Mail();
$form = $this->createFormBuilder($mail)
->add('email','email')
->getForm();
$form->handleRequest($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
$em->persist($mail);
$em->flush();
//return $this->redirectToRoute('');
}
return $this->render('frontend/mail.html.twig', array('form' => $form->createView()));
}
}
View (twig template):
<div>
{{ form_start(form) }}
{{ form_widget(form.email) }}
<input type="submit" class="btn btn-primary" value="OK" />
{{ form_end(form) }}
</div>
i render this controller in my base.html.twig
{%render(controller('AppBundle\Controller\FrontEnd\SendContactController::Email ')) %}
when I press ok to submit nothing happens.
I'm upgrading from Symfony 1.4 to Symfony 2.6.4 and can't figure out how to set up a form field to hold a set of choices (seems simple enough) from a stored entity. I get an error when I go to create my schema.
Code:
<?php
namespace PlantBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class PlantForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('propagationMethod', 'entity', array(
'class' => 'PlantBundle:PropagationMethod',
'property' => 'name',
'expanded' => true,
'multiple' => true,
'required' => false,
'label' => 'Propagation Methods',
'attr' => array(
'class' => 'checkboxes'
)));
}
}
<?php
namespace PlantBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="PlantBundle\Entity\Repository\PlantRepository")
* #ORM\Table(name="plant")
* #ORM\HasLifecycleCallbacks
*/
class Plant
{
# ...
/**
* #ORM\Column(type="array", nullable=true)
*/
protected $propagationMethodIds;
/**
* #ORM\ManyToOne(targetEntity="PlantBundle\Entity\PropagationMethod")
* #ORM\JoinColumn(name="propagationMethodIds", referencedColumnName="id")
*/
protected $propagationMethod;
# ...
public function __construct()
{
$this->propagationMethod = new ArrayCollection();
}
# ...
}
Error message when generating schema:
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1170 BLOB/TEXT column 'propagationMethodIds'
used in key specification without a key length
I've tried adding a length=255 to the field but still get the error. From the research I've done troubleshooting the problem, it seems that the field is being indexed, and since it is a blob it needs the length specified. But the field is an array of ids from a related table. Confused :/
After a lot of searching and experimentation I found a solution that works. Since the documentation is lacking, and there weren't any answers to the question, I do not know if this is the correct or best way to achieve the desired outcome, but as I mentioned, it works. I'm providing the solution here in hopes that it helps others stuck on the issue.
<?php
// Correct. No changes needed.
namespace PlantBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class PlantForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('propagationMethod', 'entity', array(
'class' => 'PlantBundle:PropagationMethod',
'property' => 'name',
'expanded' => true,
'multiple' => true,
'required' => false,
'label' => 'Propagation Methods',
'attr' => array(
'class' => 'checkboxes'
)));
}
}
<?php
namespace PlantBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="PlantBundle\Entity\Repository\PlantRepository")
* #ORM\Table(name="plant")
* #ORM\HasLifecycleCallbacks
*/
class Plant
{
# ...
/*
* This column is not needed at all. It creates all kinds of problems by keeping it. Delete:
*
* /**
* * #ORM\Column(type="array", nullable=true)
* */
* protected $propagationMethodIds;
*
*/
// Add the column type above to the ORM mapping below. Also remove the name association on the JoinColumn.
/**
* #ORM\Column(type="array", nullable=true)
* #ORM\ManyToOne(targetEntity="PlantBundle\Entity\PropagationMethod")
* #ORM\JoinColumn(referencedColumnName="id")
*/
protected $propagationMethod;
// Correct. No changes:
# ...
public function __construct()
{
$this->propagationMethod = new ArrayCollection();
}
# ...
}
/*
* This is how I displayed the stored array data:
*
*/
// show.html.twig
{% extends 'PlantBundle::layout.html.twig' %}
{% block stylesheets %}
{{ parent() }} <link href="{{ asset('bundles/~/plant.css') }}" type="text/css" rel="stylesheet" />
{% endblock %}
{% block title %}Plant Details{% endblock%}
{% block body %}
{% for method in plant.propagationMethod %}{{ method.name }} {% endfor %}
{% endblock %}
I have a problem to get a object from a controller called by the render controller method.
This is my Entity with the self OneToOne relation :
class Family
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\OneToOne(targetEntity="Family")
* #ORM\JoinColumn(name="brother_id", referencedColumnName="id")
**/
private $brother;
/**
* #ORM\Column(type="string", length=100)
*/
private $label;
}
This is my action:
/**
* #Template()
*/
public function testAction()
{
$em = $this->getDoctrine()->getManager();
$brothers = $em->getRepository('FifaAdminBundle:Family')->findAll();
return array(
'brothers' => $brothers,
);
}
My view
{% for brother in brothers %}
{{ brother.id }} - {{ brother.label }}
<hr />
{% render controller('AdminBundle:Test:show', {'brother': brother}) %}
<hr />
{{ render(controller('AdminBundle:Test:show', { 'brother': brother })) }}
<hr />
{% endfor %}
My other controller
public function showAction($brother)
{
if (is_object($brother))
{
return new \Symfony\Component\HttpFoundation\Response('OK');
}
else
{
var_dump($brother);
return new \Symfony\Component\HttpFoundation\Response('KO');
}
}
The first element isgood.
But if it has a brother_id, this brother in not load by the showAction.
It gives me this:
array(1) { ["__isInitialized__"]=> string(1) "1" }
Please help me.
You probably want to use the #ParamConverter annotation in your case.
Your controller would go as follow:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Admin\Bundle\Entity\Family;
/**
* #Route("/show/{id}")
* #ParamConverter("family", class="AdminBundle:Family")
*/
public function showAction(Family $brother)
{
//Do your stuff
}
And the view:
{% for brother in brothers %}
{{ brother.id }} - {{ brother.label }}
<hr />
{{ render(controller('AdminBundle:Test:show', { 'brother': brother.id })) }}
<hr />
{% endfor %}
Note that if no Family object is found, a 404 Response is generated. So you don't need to check if $brother is an object or not in your controller.
http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
Thank you cheesemacfly
Indeed, it's work with the #ParamConverter
But it is wird because if I remove the OneToOne relation, it works without #ParamConverter