Skip to content

Instantly share code, notes, and snippets.

@webmozart
Created August 4, 2012 11:51
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save webmozart/3256975 to your computer and use it in GitHub Desktop.
Save webmozart/3256975 to your computer and use it in GitHub Desktop.
DON'T USE THIS GIST! Please clone https://github.com/bschussek/standalone-forms instead.
{
"require": {
"symfony/form": "2.1.*",
"symfony/validator": "2.1.*",
"symfony/templating": "2.1.*",
"symfony/framework-bundle": "2.1.*"
},
"minimum-stability": "dev"
}
<html>
<head>
<title>Standalone Form Component</title>
</head>
<body>
<form action="#" method="post">
<?php echo $view['form']->widget($form); ?>
<input type="submit" />
</form>
</body>
</html>
<?php
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Constraints\MinLength;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Form\Forms;
use Symfony\Component\Form\Extension\Validator\ValidatorExtension;
use Symfony\Component\Form\Extension\Templating\TemplatingExtension;
use Symfony\Component\Form\Extension\Csrf\CsrfExtension;
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider;
use Symfony\Component\Templating\PhpEngine;
use Symfony\Component\Templating\TemplateReference;
use Symfony\Component\Templating\TemplateNameParserInterface;
use Symfony\Component\Templating\Loader\FilesystemLoader;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\XliffFileLoader;
use Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper;
require __DIR__ . '/../vendor/autoload.php';
class SimpleTemplateNameParser implements TemplateNameParserInterface
{
private $root;
public function __construct($root)
{
$this->root = $root;
}
public function parse($name)
{
if (false !== strpos($name, ':')) {
$path = str_replace(':', '/', $name);
} else {
$path = $this->root . '/' . $name;
}
return new TemplateReference($path, 'php');
}
}
// Overwrite this with your own secret
$csrfSecret = 'c2ioeEU1n48QF2WsHGWd2HmiuUUT6dxr';
// Set up requirements - hopefully we can facilitate this more in 2.2
$validator = Validation::createValidator();
$translator = new Translator('en');
$translator->addLoader('xlf', new XliffFileLoader());
$translator->addResource('xlf', realpath(__DIR__ . '/../vendor/symfony/form/Symfony/Component/Form/Resources/translations/validators.en.xlf'), 'en', 'validators');
$translator->addResource('xlf', realpath(__DIR__ . '/../vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.en.xlf'), 'en', 'validators');
$engine = new PhpEngine(new SimpleTemplateNameParser(realpath(__DIR__ . '/../views')), new FilesystemLoader(array()));
$engine->addHelpers(array(new TranslatorHelper($translator)));
// Set up the form factory with all desired extensions
$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new CsrfExtension(new DefaultCsrfProvider($csrfSecret)))
->addExtension(new TemplatingExtension($engine, null, array(
// Will hopefully not be necessary anymore in 2.2
realpath(__DIR__ . '/../vendor/symfony/framework-bundle/Symfony/Bundle/FrameworkBundle/Resources/views/Form'),
)))
->addExtension(new ValidatorExtension($validator))
->getFormFactory();
// Create our first form!
$form = $formFactory->createBuilder()
->add('firstName', 'text', array(
'constraints' => array(
new NotBlank(),
new MinLength(4),
),
))
->add('lastName', 'text', array(
'constraints' => array(
new NotBlank(),
new MinLength(4),
),
))
->add('gender', 'choice', array(
'choices' => array('m' => 'Male', 'f' => 'Female'),
))
->add('newsletter', 'checkbox', array(
'required' => false,
))
->getForm();
if (isset($_POST[$form->getName()])) {
$form->bind($_POST[$form->getName()]);
if ($form->isValid()) {
var_dump('VALID', $form->getData());
die;
}
}
echo $engine->render('index.html.php', array(
'form' => $form->createView(),
));
@harikt
Copy link

harikt commented Aug 4, 2012

I am not sure how I can give a PR on this gist . So that's why such a wait to respond on composer.json . It needs translation also :) .

@harikt
Copy link

harikt commented Aug 6, 2012

Oh probably it may be taking from other composer.json . I was just looking the classes added .

@webmozart
Copy link
Author

Yes, the other components will be loaded automatically by Composer.

@amnotafraid
Copy link

Composer worked beautifully to load the other components. I've summarized some of the snags I ran into and the solutions below. I am working on a Windows 7 machine with a xampp stack.

1.) I had to download composer from http://getcomposer.org/download/. For me, using curl or php –r “eval… methods did not work. I copied the composer.phar to the root of my project directory. (In Firefox, view latest source, right click > view page source, File > Save page as > enter place to save composer.phar.)

2.) When I tried executing php composer.phar install from the command line, I got the error: “'git' is not recognized as an internal or external command, operable program or batch file.” I had to modify the path statement in the environment variables to make sure that git was available from the command line.

3.) When I tried to display index.php, I got an error that autoload.php couldn’t be found. So, In index.php, change from this:
require DIR . '/../vendor/autoload.php';
To this:
require DIR . '\vendor\autoload.php';

4.) Next, when I tried displaying index.php, I got the error: Fatal error: Class 'IntlDateFormatter' not found. I found php_intl.dll in my php\ext file folder and added extension=php_intl.dll to php.ini (Had to stop and start server.)

5.) So, now when I display index.php I get a bad parameter in Fatal error: Uncaught exception 'InvalidArgumentException' with message 'The template "/index.html.php" does not exist.' in C:\xampp\htdocs\FormTrial\vendor\symfony\templating\Symfony\Component\Templating\PhpEngine.php on line 565. I haven’t been able to overcome this yet, but I did check to make sure index.html.php exists in the root of my project directory.

Lucky me, my challenges are not over, but the message is that composer works beautifully.

(If anybody has ideas on overcoming this last one, please let me know.)

@amnotafraid
Copy link

Possibly, this line (approximately line 52 of index.php) is causing grief:

$engine = new PhpEngine(new SimpleTemplateNameParser(realpath(DIR . '/../views')), new FilesystemLoader(array()));

There are no views included in the download.

I assume I need to create a view directory and put something in there. What shall I put in there?

@amnotafraid
Copy link

6.) I added a views directory and put index.html.php in the views directory.

7.) I changed the directories passed to the translator. I changed from this:

$translator->addResource('xlf', realpath(DIR . '/../vendor/symfony/form/Symfony/Component/Form/Resources/translations/validators.en.xlf'), 'en', 'validators');
$translator->addResource('xlf', realpath(DIR . '/../vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.en.xlf'), 'en', 'validators');

$engine = new PhpEngine(new SimpleTemplateNameParser(realpath(DIR . '/../views')), new FilesystemLoader(array()));

To this:

$translator->addResource('xlf', realpath(DIR . '/vendor/symfony/form/Symfony/Component/Form/Resources/translations/validators.en.xlf'), 'en', 'validators');
$translator->addResource('xlf', realpath(DIR . '/vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.en.xlf'), 'en', 'validators');

$engine = new PhpEngine(new SimpleTemplateNameParser(realpath(DIR . '/views')), new FilesystemLoader(array()));

8.) In index.php, I changed this line from this:

$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new CsrfExtension(new DefaultCsrfProvider($csrfSecret)))
->addExtension(new TemplatingExtension($engine, null, array(
// Will hopefully not be necessary anymore in 2.2
realpath(DIR . '/../vendor/symfony/framework-bundle/Symfony/Bundle/FrameworkBundle/Resources/views/Form'),
)))
->addExtension(new ValidatorExtension($validator))
->getFormFactory();

To this:

$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new CsrfExtension(new DefaultCsrfProvider($csrfSecret)))
->addExtension(new TemplatingExtension($engine, null, array(
// Will hopefully not be necessary anymore in 2.2
realpath(DIR . '/vendor/symfony/framework-bundle/Symfony/Bundle/FrameworkBundle/Resources/views/Form'),
)))
->addExtension(new ValidatorExtension($validator))
->getFormFactory();

However, I still have a problem. When I try to display index.php, I get "Symfony\Component\Form\Exception\FormException: Unable to render the form as none of the following blocks exist: "_form_widget", "form_widget". in C:\xampp\htdocs\FormTrial\vendor\symfony\form\Symfony\Component\Form\FormRenderer.php on line 221"

So, now what am I doing wrong?

@amnotafraid
Copy link

To get it working, here are the steps I followed:

1.) Download the gist and extract. Place these three files in these directories:
composer.json . [root directory]
index.html.php views
index.php web
2.) I get composer.phar in the root directory and execute ‘php composer.phar install’. (See Output from composer)
3.) In index.php, I replace $csrfSecret with my own value generated by md5(uniqid(rand(), TRUE));
4.) I display \web\index.php in a browser and get an error. (See Error)

I am running PHP Version 5.3.8

I tried to debug it in NetBeans using Xdebug. See Debugging notes.

Error:

Fatal error: Uncaught exception 'Symfony\Component\Form\Exception\FormException' with message 'Unable to render the form as none of the following blocks exist: "_form_widget", "form_widget".' in C:\xampp\htdocs\FormTrial4\vendor\symfony\form\Symfony\Component\Form\FormRenderer.php on line 221

Debugging notes:

In C:\xampp\htdocs\FormTrial4\vendor\symfony\form\Symfony\Component\Form\Extension\Templating \TemplatingRendererEngine.php:
57 protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName)
58 {
59 // Recursively try to find the block in the themes assigned to $view,
60 // then of its parent form, then of the parent form of the parent and so on.
61 // When the root form is reached in this recursion, also the default
62 // themes are taken into account.
63
64 // Check each theme whether it contains the searched block
65 if (isset($this->themes[$cacheKey])) {
66 for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) {
67 if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->themes[$cacheKey][$i])) {
68 return true;
69 }
70 }
71 }
72
73 // Check the default themes once we reach the root form without success
74 if (!$view->parent) {
75 for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) {
76 if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->defaultThemes[$i])) {
77 return true;
78 }
79 }
80 }

At line 65, these are the variable values:

$cacheKey = "_form_form"
$blockName = "_form_widget"

The if statement is false and control passes to line 74. A call is made to loadResourceFromTheme. These are the parameter values:

$cacheKey = "_form_form"
$blockName = "_form_widget"
$i = 0
$this->defaultThemes[$i] = "C:\xampp\htdocs\FormTrial4\vendor\symfony\framework-bundle\Symfony\Bundle\FrameworkBundle\Resources\views\Form"

Stepping into the function, in C:\xampp\htdocs\FormTrial4\vendor\symfony\form\Symfony\Component\Form\Extension\Templating\TemplatingRendererEngine.php:

115 protected function loadResourceFromTheme($cacheKey, $blockName, $theme)
116 {
117 if ($this->engine->exists($templateName = $theme . ':' . $blockName . '.html.php')) {
118 $this->resources[$cacheKey][$blockName] = $templateName;
119 return true;
120 }
121 return false;
122 }

At line 117, these are the values of the variables:

$cacheKey = "_form_form"
$blockName = "_form_widget"
$theme = "C:
mpp\htdocs\FormTrial4
endor\symfony
ramework-bundle\Symfony\Bundle\FrameworkBundle\Resources
iews\Form"

It is possible that there is a bug in NetBeans or XDebug, but it looks like the value of the third parameter of the call is getting overwritten. This could even be a compiler error, hence, I provided the version of PHP (5.3.8) that I am working with.

Please advise.

@amnotafraid
Copy link

Oh yeah. I forgot something. My versions.

Output from Composer

C:\xampp\htdocs\FormTrial4>php composer.phar install
Installing dependencies

  • Installing doctrine/common (2.3.x-dev)
    Cloning 2ec4bc6db13db6a0976a16b71058083c55cbcdbd
  • Installing symfony/options-resolver (dev-master)
    Cloning 6a1159eb868b3af059d0a8c578db1f7efab89850
  • Installing symfony/locale (dev-master)
    Cloning 58ff3213b4e187f410d6795a1da11dfde8a0e118
  • Installing symfony/event-dispatcher (dev-master)
    Cloning 76c76f62702b09e0f182ae618be0f1d79e2a711f
  • Installing symfony/form (dev-master)
    Cloning 74583bb7a8ed758c29431b4900467db04ddd0b32
  • Installing symfony/validator (dev-master)
    Cloning 2794f1d7bfea5c017c50f870ca1bf2dd1c363f03
  • Installing symfony/translation (dev-master)
    Cloning d7a6083e76a3af3f247bff523bc47b41e7208a87
  • Installing symfony/templating (dev-master)
    Cloning v2.1.0-RC1
  • Installing symfony/routing (dev-master)
    Cloning v2.1.0-RC1
  • Installing symfony/filesystem (dev-master)
    Cloning 72acf65c2390c9066e1174d269a4e146ffad9296
  • Installing symfony/http-foundation (dev-master)
    Cloning 8d5e7f909fa519853e71bcfc57a1da8c637ebcbb
  • Installing symfony/http-kernel (dev-master)
    Cloning 0d0ee371ab0425f3399dba9e25d7ad98ca5c0d62
  • Installing symfony/config (dev-master)
    Cloning f68ad44f3ee1603ce96387bacba0ecba488c2a33
  • Installing symfony/dependency-injection (dev-master)
    Cloning 98fa735a7ef5dc07c43bfe6faa4367a983b6ba6f
  • Installing symfony/framework-bundle (dev-master)
    Cloning 4f0d296b4414cb5322e7ee45af117e5234bc75d0

symfony/validator suggests installing symfony/yaml (dev-master)
symfony/translation suggests installing symfony/yaml (dev-master)
symfony/routing suggests installing symfony/yaml (dev-master)
symfony/http-kernel suggests installing symfony/browser-kit (dev-master)
symfony/http-kernel suggests installing symfony/class-loader (dev-master)
symfony/http-kernel suggests installing symfony/console (dev-master)
symfony/http-kernel suggests installing symfony/finder (dev-master)
symfony/dependency-injection suggests installing symfony/yaml (dev-master)
symfony/framework-bundle suggests installing symfony/console (dev-master)
symfony/framework-bundle suggests installing symfony/finder (dev-master)
Writing lock file
Generating autoload files
gist3256975-6c5ede69a9a07f3a09c3c32ee37543885a4c0f2a.tar.gz

@g-alonso
Copy link

g-alonso commented Sep 1, 2012

I downloaded https://github.com/bschussek/standalone-forms then I downloaded the dependences with composer and everything was fine.

But I'm getting the same error:

Fatal error: Uncaught exception 'Symfony\Component\Form\Exception\FormException' with message 'Unable to render the form as none of the following blocks exist: "_form_widget", "form_widget".' in ...dev\standalone-forms\vendor\symfony\form\Symfony\Component\Form\FormRenderer.php:221

@andrewdavidcostello
Copy link

I am getting the above error as well, it seems to be when the renderBlock function is triggered and there is no resource available in the array to be built and therefore returns false every time.

This is for both Twig and PHP versions.

@webmozart
Copy link
Author

IMPORTANT NOTICE: Please clone https://github.com/bschussek/standalone-forms instead of trying to reproduce this Gist. I just updated the vendors and tested that project again, and everything worked for me out of the box.

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