I created code for tags in symfony but I have this bug:
The autoloader expected class "Tag\TagBundle\Form\Types\TagsType" to be defined in file "/var/www/html/TagProject/vendor/composer/../../src/Tag/TagBundle/Form/Types/TagsType.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
TagsType.php:
<?php
namespace Tag\TagBundle\Form\Types;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Tag\TagBundle\Form\DataTransformer\TagsTransformer;
use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionArrayTransformer;
use Symfony\Component\Form\FormBuilderInterface;
class TagsTypes extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options){
$builder
->addModelTransformer(new CollectionArrayTransformer(),true)
->addModelTransformer(new TagsTransformer(),true);
}
public function getParent(){
return TextType::class;
}
}
}
TagsTransformer.php:
<?php
namespace Tag\TagBundle\Form\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
class tagsTransformer implements DataTransformerInterface {
public function transform($value){
dump($value);
return "";
}
public function reverseTransform($value){
}
}
PostType.php:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Tag\TagBundle\Form\Types\TagsType;
class PostType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name')
->add('content')
->add('tags',TagsType::class);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Post'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_post';
}
}
Your error is naming class.
You have TagsType.php is php file and your class name is TagsTypes:
You have to change class name:
class TagsTypes
to
class TagsType
Related
I try add fields with form events in symfony but fields is add automatically when refresh page ... scenario is when I fill input email fields body is display ...
code PostType:
<?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\FormEvent;
use Symfony\Component\Form\FormEvents;
class PostType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('titl')->add('email')->add('phone');
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event){
$post = $event->getData();
$form = $event->getForm();
if(!empty($post->getEmail))
{
$form->add('body');
}
});
$builder->add('save', SubmitType::class);
}/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Post'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_post';
}
}
as it says in comment you have to use Javascript to do this, for example make an ajax request to submit the form and to apply, always in javascript, the HTML response.
There is a great video tutorial for this (in french) https://www.youtube.com/watch?v=F0Z-D3MSjA0&t=1504s
I have a Filter and FilterCollection object. The FilterCollection holds a collection of Filters, just like the name indicate.
Now I need to validate everything, so I created a FilterType and FilterTypeCollection Forms. In the FilterCollectionType I have:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('filters', CollectionType::class, array(
'entry_type' => FilterType::class
));
}
And in the FilterCollection definition I have the following:
/**
* #var array
* #Assert\Valid()
*/
private $filters = [];
I created a paramConverter so I could convert elements from my request into FilterCollection ones. In the apply method I try to validate everything by using:
public function apply(Request $request, ParamConverter $configuration)
$filterCollection = new FilterCollection();
$form = $this->formFactory->create(
FilterTypeCollection::class,
$filterCollection
);
$form->submit($request->query->all());
if ($form->isSubmitted() && $form->isValid()) {
$request->attributes->set($configuration->getName(), $filterCollection);
return true;
} else {
throw new FormValidationException($form);
}
}
I was expecting that the validation not only validates the FilterCollection but also the Filters. But the validations I have in my Filter definition, are not working, even if I have validations that should fail, it still passes. I think the validator is not passing on the Filter elements.
Any idea on what might be happening?
I finally got it to work. Perhaps you made the same mistake as me, forgetting to add "data_class" in the configureOptions in the formType.
Anyway, here's the code that works (on fresh install of Symfony 3.3)
DefaultController.php
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Filter;
use AppBundle\Entity\FilterCollection;
use AppBundle\Form\FilterCollectionType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* #Route("/", name="homepage")
*/
public function indexAction(Request $request)
{
// add first filter, so we don't have to implement the collection javascript etc to test quickly
$collection = new FilterCollection();
$collection->filters[] = new Filter();
$form = $this->createForm(FilterCollectionType::class, $collection);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
echo "valid input"; // we don't want to see this ;)
}
}
// replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'form' => $form->createView()
]);
}
}
Filter.php
<?php
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
class Filter {
/**
* #var string
* #Assert\NotBlank()
* #Assert\Regex(pattern="/[0-9]+/")
*/
public $name;
}
FilterCollection.php
<?php
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
class FilterCollection {
/**
* #var Filter[]
* #Assert\Valid()
*/
public $filters = [];
}
FilterType.php
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class FilterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', TextType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\Filter'
]);
}
}
FilterCollectionType
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class FilterCollectionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('filters', CollectionType::class, [
'entry_type' => FilterType::class,
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\FilterCollection',
]);
}
public function getName()
{
return 'app_bundle_filter_collection_type';
}
}
Note: I didn't make a ParamConverter like you did, but that seems beside the point of the question. You can change the code to use a ParamConverter easily.
I'm trying to populate form from database by using two entities. Here's the code I use
CategoryType
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CategoryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text');
}
public function configureOptions(OptionsResolver $options)
{
return array(
'data_class' => 'AppBundle\Entity\Category',
);
}
public function getName()
{
return 'questionnaire';
}
}
ProductType
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text');
}
public function configureOptions(OptionsResolver $options)
{
return array(
'data_class' => 'AppBundle\Entity\Product',
);
}
public function getName()
{
return 'questionnaire';
}
}
CommonType
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use AppBundle\Form\CategoryType;
use AppBundle\Form\ProductType;
class CommonType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('category', new CategoryType());
$builder->add('product', new ProductType());
}
public function getName()
{
return 'app_common_type';
}
}
DefaultController
<?php
namespace AppBundle\Controller;
use AppBundle\Form\CommonType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* #Route("/", name="homepage")
*/
public function indexAction(Request $request)
{
$data = $this->getDoctrine()->getRepository('AppBundle:Product')->findOneBy(['id' => 2]);
$form = $this->createForm(new CommonType(), $data);
return $this->render('AppBundle:Default:index.html.twig', ['form' => $form->createView()]);
}
}
But I get this error
The form's view data is expected to be of type scalar, array or an instance of \ArrayAccess, but is an instance of class Proxies\__CG__\AppBundle\Entity\Category. You can avoid this error by setting the "data_class" option to "Proxies\__CG__\AppBundle\Entity\Category" or by adding a view transformer that transforms an instance of class Proxies\__CG__\AppBundle\Entity\Category to scalar, array or an instance of \ArrayAccess.
So what I'm doing wrong and is this the correct way to populate form based on two or more entities?
Your Common form's model data format is an array (as far as no data_class given). So the right data to set is an array with product and category keys:
$product = $this->getDoctrine()->getRepository('AppBundle:Product')->findOneBy(['id' => 2]);
$form = $this->createForm(new CommonType(), ['product' => $product]);
I am trying to create a form by merging 2 form types as following.
Teacher Entity that has a one to one relation with User Entity.
I am using FOSUserBundle and i want to merge the ResettingFormType with my custom TeacherFormType, to end up with a form that both fields from my custom & fos reset password form.
1- Teacher Entity:
/**
* #var \User
*
* #ORM\OneToOne(targetEntity="ITJari\UserBundle\Entity\User", fetch="EAGER")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*
*/
private $user;
public function getUser() {
return $this->user;
}
public function setUser($user) {
$this->user = $user;
return $this;
}
2- Extending FOS Reset password:
namespace ITJari\SchoolBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ResettingFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
}
public function getParent() {
return 'fos_user_resetting';
}
public function getName() {
return 'ragab';
}
}
3- Teacher Form Type
namespace ITJari\SchoolBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class TeacherFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
}
public function setDefaultOptions(OptionsResolverInterface $resolver) {
$resolver->setDefaults(array(
'data_class' => 'ITJari\SchoolBundle\Entity\Teacher',
));
}
public function getParent() {
return 'fos_user_resetting';
}
public function getName() {
return 'teacherform';
}
}
4- Inside controller:
$teacher = new \ITJari\SchoolBundle\Entity\Teacher();
$teacher->setUser($user);
$form = $this->createForm('teacherform', $teacher);
But i got the following error:
Neither the property "plainPassword" nor one of the methods "getPlainPassword()", "isPlainPassword()", "hasPlainPassword()", "__get()" exist and have public access in class "ITJari\SchoolBundle\Entity\Teacher".
500 Internal Server Error - NoSuchPropertyException
With symfony I am trying to listen to the preset data event on a form declared as a service.
I have a parent form in which I call ->add('unit', 'fmu_unit')
EDIT : I add here a full simple example. It's not working as expected.
My controller:
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\MarketPlace\Product;
use AppBundle\Form\UnitTestType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class DefaultController extends Controller
{
/**
* #Route("/", name="home")
* #Method({"POST", "GET"})
* #Template(":Default:index.html.twig")
*/
public function indexAction()
{
$formManager = $this->get('form_manager');
$product = new Product();
$unit = $this->getDoctrine()->getRepository('AppBundle:FoodAnalytics\Unit')->findOneByName('g');
$product->setUnit($unit);
$form = $formManager->createForm(new UnitTestType(), $product ,'POST', 'home');
return array('form' => $form->createView());
}
}
My first Type (UnitTest):
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UnitTestType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('unit', 'fmu_unit')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\MarketPlace\Product'
));
}
/**
* #return string
*/
public function getName()
{
return 'unit_test';
}
}
My second type (the service one in which I try to use Form Events):
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UnitType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
$product = $event->getData();
$form = $event->getForm();
//This is not working
$form->add('unit','entity', array(
'class' => 'AppBundle:FoodAnalytics\Unit'
));
});
//This is working
// $builder->add('unit','entity', array(
// 'class' => 'AppBundle:FoodAnalytics\Unit'
// ));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'inherit_data' => true,
));
}
/**
* #return string
*/
public function getName()
{
return 'fmu_unit';
}
}
The declaration as a service:
services:
unit.type:
class: %unit.type.class%
tags:
- { name: form.type, alias: fmu_unit }
The view : {{ form(form) }}
Nothing shows up but the label when I use the form Events. It works fine if I don't use it.