code shogan
code shogan

Reputation: 839

Symfony2 - createForm called with custom form type's name/alias throws "Could not load type" exception

I was reading the documentation on defining forms as services and followed the guide. but I keep running into the following error:

Could not load type "submission"

here is my services.yml

services:
    submission.form.type.submission:
        class:Awesome\SubmissionBundle\Form\Type\SubmissionType
        tags:
            - {name: form.type, alias: submission}

here is my form

<?php

namespace Awesome\SubmissionBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class SubmissionType extends AbstractType 
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('contact', 'text')
            ->add('message', 'textarea')
            ->add('submit', 'submit')
        ;
    }

    public function getName() 
    {
        return 'submission';
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    {
        $resolver->setDefaults(array(
            'data_class' => 'Awesome\SubmissionBundle\Entity\Submission',
        ));
    }
}

In any controller I can $this->get('submission.form.type.submission') without errors.

But why can't I do $this->createForm('submission', $submission) ? as is dictated by the official documentation.

UPDATE I have made some progress. I found that if I put my services configuration in symfony's main config.yml rather than the bundles services.yml The code starts to work. This is perplexing but I guess it leads to me posting just how I'm loading the bundle's services.yml.

Here is my bundle's registered compiler pass:

<?php

namespace Awesome\SubmissionBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

class SubmissionCompilerPass implements CompilerPassInterface
{

    public function process(ContainerBuilder $container)
    {
        $relative_path = DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, array('..', '..', 'Resources', 'config'));
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . $relative_path));
        $loader->load('services.yml');
    }

}

and regardless of where I place my configuration the command container:debug submission.form.type.submission always gives the same output which seems fine to me:

[container] Information for service submission.form.type.submission
Service Id       submission.form.type.submission
Class            Awesome\SubmissionBundle\Form\Type\SubmissionType
Tags
    - form.type                      (alias: submission)
Scope            container
Public           yes
Synthetic        no
Required File    -

Upvotes: 1

Views: 2684

Answers (2)

Marmelatze
Marmelatze

Reputation: 188

I think your problem is within loading the services.yml in a CompilerPass. The loading of the "form.type" tags is happening also in a CompilerPass (Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass). So your CompilerPass is executed after the form CompilerPass and it won't find your form type.

If you are using the Symfony Standard Edition and you have created your bundle with the generator command you will have an AwesomeSubmissionExtension class in your DependencyInjection folder which is intended for loading service files.

The following code is the changed extension code for loading yaml files. (The default is to XmlFileLoader)

namespace Awesome\SubmissionBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

class AwesomeSubmissionExtension extends Extension
{
    /**
     * {@inheritDoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config = $this->processConfiguration($configuration, $configs);

        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.yml');
    }
}

Upvotes: 1

keyboardSmasher
keyboardSmasher

Reputation: 2811

Here's another issue: It's data_class, not data

public function setDefaultOptions(OptionsResolverInterface $resolver) 
{
    $resolver->setDefaults(array(
        'data_class' => 'Awesome\SubmissionBundle\Entity\Submission',
    ));
}

Upvotes: 0

Related Questions