Skip to content

Instantly share code, notes, and snippets.

@nclavaud
Created November 22, 2011 21:16
Show Gist options
  • Save nclavaud/1386997 to your computer and use it in GitHub Desktop.
Save nclavaud/1386997 to your computer and use it in GitHub Desktop.
Symfony2 standalone Form component example
<?php
/**
* @author Nicolas Clavaud <nclavaud@gmail.com>
* http://n.clavaud.free.fr/blog/index.php?article31/symfony2-standalone-form-component-tutorial
*/
namespace Me\MyApp;
use Symfony\Component\ClassLoader\UniversalClassLoader;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\Extension\Core\CoreExtension;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\Templating\TemplateNameParser;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Templating\TemplateReference;
use Symfony\Component\Templating\Loader\FilesystemLoader;
use Symfony\Component\Templating\PhpEngine;
use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper;
// validation
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\Constraints as Constraints;
/**
* Load and configure autoloader
* @see http://symfony.com/doc/2.0/cookbook/tools/autoloader.html
*/
require_once 'Symfony/Component/ClassLoader/UniversalClassLoader.php';
$loader = new UniversalClassLoader();
$loader->register();
$loader->registerNamespace('Symfony', __DIR__.'/');
/**
* Parameters
*/
$locale = null;
/**
* Entity
*/
class Message
{
public $sender;
public $recipient;
public $message;
// validation
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('sender', new Constraints\NotBlank());
$metadata->addPropertyConstraint('sender', new Constraints\Email());
$metadata->addPropertyConstraint('recipient', new Constraints\NotBlank());
$metadata->addPropertyConstraint('recipient', new Constraints\Email());
$metadata->addPropertyConstraint('message', new Constraints\NotBlank());
$metadata->addPropertyConstraint('message', new Constraints\MinLength(10));
}
}
/**
* Form Class
* @see http://symfony.com/doc/2.0/book/forms.html#creating-form-classes
*/
class MessageType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('sender', 'email')
->add('recipient', 'email')
->add('message', 'textarea');
}
public function getName()
{
return 'message';
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'Me\MyApp\Message',
);
}
}
/**
* Template name parser
* @see Symfony\Bundle\FrameworkBundle\Tests\Templating\Helper\Fixtures\StubTemplateNameParser
*
* Needed to load the templates used for rendering form items.
*/
class StubTemplateNameParser implements TemplateNameParserInterface
{
private $root;
private $rootTheme;
public function __construct($root, $rootTheme)
{
$this->root = $root;
$this->rootTheme = $rootTheme;
}
public function parse($name)
{
list($bundle, $controller, $template) = explode(':', $name);
if ($template[0] == '_') {
$path = $this->rootTheme.'/Custom/'.$template;
} elseif ($bundle === 'TestBundle') {
$path = $this->rootTheme.'/'.$controller.'/'.$template;
} else {
$path = $this->root.'/'.$controller.'/'.$template;
}
return new TemplateReference($path, 'php');
}
}
/**
* Create an entity
*/
$message = new Message();
$message->sender = 'nclavaud@gmail.com';
/**
* Build a form from a form factory
*/
$form_factory = new FormFactory(array(
new CoreExtension(),
// validation
new ValidatorExtension(
new Validator(
new ClassMetadataFactory(
new StaticMethodLoader()
),
new ConstraintValidatorFactory()
)
)
));
$form = $form_factory->create(new MessageType(), $message);
/**
* Create a PHP template engine
*/
$root = realpath(__DIR__ . '/Symfony/Bundle/FrameworkBundle/Resources/views');
$rootTheme = realpath(__DIR__ . '/Symfony/Bundle/FrameworkBundle/Resources');
$templateNameParser = new StubTemplateNameParser($root, $rootTheme);
$loader = new FilesystemLoader(array());
$engine = new PhpEngine($templateNameParser, $loader);
/**
* This helper will help rendering form items
*/
$form_helper = new FormHelper($engine, array(
'FrameworkBundle:Form',
));
/**
* Bind it to the engine
*/
$engine->setHelpers(array(
$form_helper,
new TranslatorHelper(new Translator($locale, new MessageSelector())),
));
/**
* Bind submitted data
*/
$submitted = false;
$valid = null;
if (isset($_POST[$form->getName()])) {
$form->bind($_POST[$form->getName()]);
$submitted = true;
// validation
if ($valid = $form->isValid()) {
// you may want to redirect at this state
}
}
/**
* Create the form view
*/
$form_view = $form->createView();
/**
* Now, it's time to render HTML!
*/
header('Content-type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html>
<body>
<form action="" method="post"
<?php print $form_helper->enctype($form_view) ?>
novalidate="novalidate">
<?php print $form_helper->widget($form_view) ?></div>
<input type="submit" />
</form>
<?php if ($submitted && $valid) : ?>
<p><strong>Submitted form is valid.</strong></p>
<?php endif; ?>
<p><em>Message object:</em></p>
<pre><?php print print_r($message, true); ?></pre>
</body>
</html>
@juanmf
Copy link

juanmf commented Jun 23, 2013

http://api.symfony.com/2.3/Symfony/Component/Form/Forms.html

Here there's an explanation of how to add all needed Extensions to the Form Component, so it can be rendered in a template, validated, Csrf Protected, Translated, etc...

protected function getFormExtensions()
{
// should be moved to the Form component once absolute file paths are supported
// by the default name parser in the Templating component
$reflClass = new \ReflectionClass('Symfony\Bundle\FrameworkBundle\FrameworkBundle');
$root = realpath(dirname($reflClass->getFileName()).'/Resources/views');
$rootTheme = realpath(DIR.'/Resources');
$templateNameParser = new FrameworkBundle\Tests\Templating\Helper\Fixtures\StubTemplateNameParser($root, $rootTheme);
$loader = new \Symfony\Component\Templating\Loader\FilesystemLoader(array());

    $this->_TemplateEngine = new \Symfony\Component\Templating\PhpEngine(
        $templateNameParser, $loader
    );
    $this->_TemplateEngine->addGlobal('global', '');
    $this->_TemplateEngine->setHelpers(array(
        new FrameworkBundle\Templating\Helper\TranslatorHelper(
            new FrameworkBundle\Tests\Templating\Helper\Fixtures\StubTranslator()
        ),
    ));
    $secret = 'SomeSecreteSecret';
    // $session = new \Symfony\Component\HttpFoundation\Session\Session();
    $validator = \Symfony\Component\Validator\Validation::createValidator();
    $csrfProvider = new \Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider(
            $secret
        );
    return array(
        new \Symfony\Component\Form\Extension\Validator\ValidatorExtension($validator),
        new \Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension(),
        new \Symfony\Component\Form\Extension\Csrf\CsrfExtension(
            $csrfProvider
        ),
        new \Symfony\Component\Form\Extension\Templating\TemplatingExtension(
            $this->_TemplateEngine, $csrfProvider, 
            array('FrameworkBundle:Form')
        ),
    );
}

// Then in your home made Framework __constructor
$this->_formFactory = \Symfony\Component\Form\Forms::createFormFactoryBuilder()
        ->addExtensions($this->getFormExtensions())
        ->getFormFactory();

Then you just need acces to the PhpEngine->get('form') helper's form() method with an instance of a $formView

My compser.json "require": { "symfony/form": "_", "symfony/validator": "_", "symfony/http-foundation": "_", "symfony/framework-bundle": "_", "symfony/routing": "_", "symfony/http-kernel": "_", "symfony/event-dispatcher": "*" },

@ivanchuryumov
Copy link

Thanks nclavaud for this example, it's been very useful for me!

@MacDada
Copy link

MacDada commented Sep 9, 2014

Big thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment