Advanced usage: example with Doctrine

That's not really an advanced topic, but the sample will be a bit hard to read (as it takes many files), so let's say it targets more experienced Symfony users.

In this demo, we're displaying a MyArray of MyElements, both persisted into the database. The MyArray entity only have an id and a name, and MyElement has id, MyArray's id and a value. This is quite the same as we seen in all demos, but persisted.

Array name:
Add an element...

Existing arrays:
Name Open Delete
gufc fucvuy Open Delete
_ Open Delete
___ Array with Elements ... Click Open to test loading Open Delete
____ Open Delete
_____ Open Delete
____________________________1 test Open Delete
___%20%E2%98%98%20Cela%20fonctionne%20%E2%98%98 Open Delete
Open Delete
---#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
---#i21ef661e2506d5d0e513dce166c17d49 Open Delete
---#i27992875ec4286a24e569b1e015b0473 Open Delete
---#i8c18088ea4d8dd4d6e5e986bceed35da Open Delete
!! Open Delete
. Open Delete
() Open Delete
(orphée) Open Delete
@12 Open Delete
#1 Open Delete
#456 Open Delete
#72 Open Delete
#72uuuu Open Delete
%231 Open Delete
%2391 Open Delete
%25237233333#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
%25237233333#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
%25237233333#i21ef661e2506d5d0e513dce166c17d49 Open Delete
%25237233333#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
%25237233333#ie025efbbb0738ed01a63b326c174233e Open Delete
%252372uuuu#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
%252372uuuu#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
%252372uuuu#ie025efbbb0738ed01a63b326c174233e Open Delete
%253F#i21ef661e2506d5d0e513dce166c17d49 Open Delete
%253F#ie025efbbb0738ed01a63b326c174233e Open Delete
%3F Open Delete
%C3%83%C2%B1lkjlkj Open Delete
%C3%B1sfkjaldsa Open Delete
< Open Delete
<script>alert('test')</script> Open Delete
<script>alert('test')</script>%n%n%n%n%n%n Open Delete
<script>alert('test')</script>%n%n%n%n%n%n<script>alert('test')</script>%n%n%n%n%n%n<script>alert('test')</script>%n%n%n%n%n%n<script>alert('test')</script>%n%n%n%n%n%n<script>alert('test')</script>%n%n%n%n%n%n<script>alert('test')</script>%n%n%n%n%n%n<sc Open Delete
<sdsads Open Delete
000tom Open Delete
01233 Open Delete
10 Open Delete
11#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
11#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
11#i21ef661e2506d5d0e513dce166c17d49 Open Delete
11#ic3ee8978c60737ab5d058b5a3f6a1b09 Open Delete
1111#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
1111#i21ef661e2506d5d0e513dce166c17d49 Open Delete
1111#i8c18088ea4d8dd4d6e5e986bceed35da Open Delete
11111 Open Delete
1111111111111111111111111111111111#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
1111111111111111111111111111111111#i27992875ec4286a24e569b1e015b0473 Open Delete
1111111111111111111111111111111111#i5784b3886628c4362594ffa43547edb4 Open Delete
1111111111111111111111111111111111#ic3ee8978c60737ab5d058b5a3f6a1b09 Open Delete
11111111aaa Open Delete
1111Yapi Open Delete
121113aaaaa Open Delete
123 Open Delete
1231 Open Delete
12345 Open Delete
1aa Open Delete
2222 example Open Delete
2222%20example Open Delete
2344234 Open Delete
3 Open Delete
32jnni Open Delete
33 Open Delete
454 Open Delete
4545 Open Delete
888 Open Delete
8888 Open Delete
8899 Open Delete
890 Open Delete
8chan.org Open Delete
969 Open Delete
99 Open Delete
999 Open Delete
ñlkjlkj Open Delete
ñsf Open Delete
ñsfkjaldsa Open Delete
a2 Open Delete
ñlkjlkj Open Delete
ñsfkjaldsa Open Delete
Aaa Open Delete
aaaa Open Delete
ñsfkjaldsa Open Delete
aaaaa Open Delete
aaaaaaa Open Delete
aaaaaaaaaaaaaaaaaaaaaaaaaa Open Delete
тест Open Delete
aaamine Open Delete
aaamine22222 Open Delete
aaamine22222#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
aaamine22222#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
aaamine22222#i21ef661e2506d5d0e513dce166c17d49 Open Delete
Abc Open Delete
Abc1 Open Delete
adasdada Open Delete
Addresses Open Delete
adfadf'A=0 Open Delete
adsada Open Delete
AlgoSucks Open Delete
any Open Delete
array new Open Delete
array%20new Open Delete
articulo Open Delete
as Open Delete
asaasexample Open Delete
asas Open Delete
asd Open Delete
asdaexample Open Delete
asdas Open Delete
asdasd#i27992875ec4286a24e569b1e015b0473 Open Delete
asdasd#i5784b3886628c4362594ffa43547edb4 Open Delete
asdasd#i8c18088ea4d8dd4d6e5e986bceed35da Open Delete
asdasd#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
asdasd#ic3ee8978c60737ab5d058b5a3f6a1b09 Open Delete
asdasdadasd Open Delete
asdasdadasd#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
asdasdadasd#ie025efbbb0738ed01a63b326c174233e Open Delete
asdf Open Delete
asdfasdfasd Open Delete
asdfasdfasd8888 Open Delete
asds Open Delete
assa Open Delete
AU Open Delete
balala Open Delete
bbbbbbbbbbbbbbbb Open Delete
bc Open Delete
bcvbcvb Open Delete
bdfdfdfdf Open Delete
bjfhj#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
bjfhj#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
blah#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
born Open Delete
Bra Open Delete
caca Open Delete
caracas Open Delete
cccio Open Delete
cela Open Delete
Cela fonctionne pas Open Delete
Christos Open Delete
Cmucik Open Delete
colombo Open Delete
cool Open Delete
crap Open Delete
cups Open Delete
cx Open Delete
cx<wc Open Delete
cx<wc'A=0 Open Delete
D happy 2018 Open Delete
D#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
D#i5784b3886628c4362594ffa43547edb4 Open Delete
D#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
D#ie025efbbb0738ed01a63b326c174233e Open Delete
dadd Open Delete
dasdsad Open Delete
dcdc Open Delete
dddd Open Delete
ddddd Open Delete
delete_empty Open Delete
dfa Open Delete
dfa#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
dfa#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
dfa#i5784b3886628c4362594ffa43547edb4 Open Delete
dfdt Open Delete
dgh Open Delete
dra Open Delete
dsadsadd Open Delete
dsd Open Delete
dsdfgsdfgdf Open Delete
dsds Open Delete
dsf Open Delete
dsfsdfs Open Delete
dsvfdsfg%5D Open Delete
e Open Delete
eeeeee Open Delete
ejemplito 2 Open Delete
ejemplo 2017 Open Delete
ejemplo 2017-11-23 Open Delete
eqweqwe Open Delete
erwgfuıgj8hlı Open Delete
erwgfuıgj8hlı Open Delete
ewe Open Delete
exadasdas Open Delete
exampldfdfe Open Delete
example Open Delete
example123#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
example123#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
example123#i21ef661e2506d5d0e513dce166c17d49 Open Delete
example123#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
example123#ie025efbbb0738ed01a63b326c174233e Open Delete
example2 Open Delete
example22222222222222 Open Delete
exampleasdas Open Delete
exampleasfsafa Open Delete
exampleasfsafasf#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
exampleaz Open Delete
exampled Open Delete
exampledsdsdda Open Delete
exampleeaze Open Delete
examplefffffffffffff Open Delete
examplefsd Open Delete
examplejjj Open Delete
examplemmm Open Delete
exampleqqqq Open Delete
exampleRW Open Delete
examplesdddd Open Delete
examplew Open Delete
examqdqsple Open Delete
Existing arrays: Open Delete
eze Open Delete
familly Open Delete
fdf#i21ef661e2506d5d0e513dce166c17d49 Open Delete
fdf#i5784b3886628c4362594ffa43547edb4 Open Delete
fdf#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
fdf#ic3ee8978c60737ab5d058b5a3f6a1b09 Open Delete
fdg Open Delete
fdgdf Open Delete
fdgfdgfdgfdgfd Open Delete
fe Open Delete
fff Open Delete
ffff Open Delete
ffsss Open Delete
fgdfgfg Open Delete
fghjk, Open Delete
fgt Open Delete
Fora Bolsonaro Open Delete
fr Open Delete
frfrf Open Delete
Fruits Open Delete
fsdfsdf Open Delete
fsgv Open Delete
gdfg Open Delete
gdfg#i21ef661e2506d5d0e513dce166c17d49 Open Delete
gfdgdf Open Delete
gg Open Delete
ghjk#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
ghjk#i21ef661e2506d5d0e513dce166c17d49 Open Delete
ghk Open Delete
Ghy Open Delete
Group%20B Open Delete
Group%2BC#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
Group%2BC#i5784b3886628c4362594ffa43547edb4 Open Delete
Group%2BC#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
gufc fucvuy dd Open Delete
hahah Open Delete
Hallo Open Delete
hbhbhb Open Delete
hello Open Delete
Hello World Open Delete
Hello World ! Open Delete
Hello%20World%20! Open Delete
hellowrld Open Delete
HEYY%2520:D#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
HEYY%2520:D#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
HEYY%2520:D#i27992875ec4286a24e569b1e015b0473 Open Delete
hgfh Open Delete
hghgh Open Delete
hhh Open Delete
hi bitches Open Delete
hi%20bitches Open Delete
ho Open Delete
htt Open Delete
hujpizda Open Delete
i Open Delete
ilesh Open Delete
iuy Open Delete
j Open Delete
jb Open Delete
jghjghjgj Open Delete
jhgfgh Open Delete
jhkl Open Delete
jk Open Delete
jtujjk Open Delete
julio Open Delete
kappa Open Delete
kfhk Open Delete
khj#i8c18088ea4d8dd4d6e5e986bceed35da Open Delete
khj#ic3ee8978c60737ab5d058b5a3f6a1b09 Open Delete
kjh Open Delete
kjkk Open Delete
kk Open Delete
kkik Open Delete
kkk#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
kkk#i8c18088ea4d8dd4d6e5e986bceed35da Open Delete
kkk#ic3ee8978c60737ab5d058b5a3f6a1b09 Open Delete
kkk#ie025efbbb0738ed01a63b326c174233e Open Delete
kljlk Open Delete
klklklkl Open Delete
kln Open Delete
kmkm Open Delete
l Open Delete
lel Open Delete
lkj Open Delete
lkjlkj Open Delete
ll Open Delete
llllllllllllllll Open Delete
lmklk Open Delete
lolo Open Delete
Lorenz du Open Delete
Lorenz du stinker Open Delete
Lundi Open Delete
m Open Delete
mec Open Delete
medicion 2 Open Delete
mjn Open Delete
mon tableau Open Delete
msqdgj Open Delete
mt Open Delete
myarr Open Delete
mytest Open Delete
n Open Delete
name Open Delete
new%2520test Open Delete
nmn#i27992875ec4286a24e569b1e015b0473 Open Delete
nnn Open Delete
Numeros de prueba Open Delete
o Open Delete
o%C4%B1 Open Delete
oı Open Delete
oezjfez Open Delete
Open Delete
ojkj Open Delete
oui Open Delete
Ouiiiiiiiiiiii Open Delete
Ouiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii Open Delete
Ouiiiiiiiiiiiiiiiiiiiiiiiilul Open Delete
pablo Open Delete
PC Open Delete
pepiii Open Delete
peppo Open Delete
perses#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
perses#i21ef661e2506d5d0e513dce166c17d49 Open Delete
perses#i5784b3886628c4362594ffa43547edb4 Open Delete
perses#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
perses#ic3ee8978c60737ab5d058b5a3f6a1b09 Open Delete
polo Open Delete
pp Open Delete
pppppii Open Delete
pppppii#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
pppppii#i5784b3886628c4362594ffa43547edb4 Open Delete
pppppii#i8c18088ea4d8dd4d6e5e986bceed35da Open Delete
pppppp Open Delete
Product Open Delete
Putin Open Delete
qqq Open Delete
qsd Open Delete
quantite%20--1 Open Delete
qwert Open Delete
r Open Delete
rar Open Delete
rdfgdf Open Delete
rerwrer Open Delete
resr Open Delete
RET Open Delete
rr Open Delete
rrrr#i21ef661e2506d5d0e513dce166c17d49 Open Delete
rrrr#i5784b3886628c4362594ffa43547edb4 Open Delete
rtr Open Delete
RV Open Delete
sa Open Delete
saASD Open Delete
saassa Delete
sadsd Open Delete
salut les gens Open Delete
samArray Open Delete
sample Open Delete
sd Open Delete
sdasdafs Open Delete
sdf Open Delete
sdg Open Delete
sdsd Open Delete
sed Open Delete
seeme Open Delete
seeme#i1dcd1cbb0d8eeb1fd3a32dc2aa9c8013 Open Delete
seeme#i27992875ec4286a24e569b1e015b0473 Open Delete
seeme#ic3ee8978c60737ab5d058b5a3f6a1b09 Open Delete
seeme#ie025efbbb0738ed01a63b326c174233e Open Delete
seqtest Open Delete
sfsa Open Delete
sfsdfsd Open Delete
someNewArray Open Delete
someNewArray#i1097c8b84b58a65ed6ec7b4f0da3ab67 Open Delete
someNewArray#i27992875ec4286a24e569b1e015b0473 Open Delete
ss Open Delete
ssssssssssssss Open Delete
Starojitski Open Delete
Stringkey Open Delete
suck my co Open Delete
suck%20my%20cock%20fgts Open Delete
t Open Delete
t11 Open Delete
Ta mere la grosse choin Open Delete
Ta%2520mere%2520la%2520grosse%2520choin Open Delete
Ta%2520mere%2520la%2520grosse%2520choin#i5784b3886628c4362594ffa43547edb4 Open Delete
Ta%2520mere%2520la%2520grosse%2520choin#i8c18088ea4d8dd4d6e5e986bceed35da Open Delete
Ta%2520mere%2520la%2520grosse%2520choin#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
TATA Open Delete
terst Open Delete
tesr Open Delete
tesst Open Delete
Test Open Delete
test nours Open Delete
test--1 Open Delete
test2 Open Delete
test22 Open Delete
test34 Open Delete
TESTEN Open Delete
testname Open Delete
testtest Open Delete
Teszt Open Delete
Thais Open Delete
the+test Open Delete
This Open Delete
this%20is%20an%20array Open Delete
timo Open Delete
toto Open Delete
totototototo Open Delete
trololo Open Delete
try01 Open Delete
tset Open Delete
tzzttz Open Delete
uhj Open Delete
uiu Open Delete
ukh Open Delete
uytuuyt Open Delete
Vai que da Open Delete
Vai%20que%20da Open Delete
vcbbc Open Delete
vdsvd Open Delete
Volta%2 Open Delete
Volta%20Di Open Delete
Volta%20Dilma%20Fo Open Delete
Volta%20Dilma%20Fora% Open Delete
Volta%2520Dilma%2520Fora% Open Delete
Volta%2520Dilma%2520Fora%2520Temer Open Delete
Volta%2520Dilma%2520Fora%2520Temer#i21ef661e2506d5d0e513dce16 Open Delete
Volta%2520Dilma%2520Fora%2520Temer#i21ef661e2506d5d0e513dce166c17d49 Open Delete
Volta%2520Dilma%2520Fora%2520Temer#ibcac9f4c58199eeaa7ba5c7750b8434b Open Delete
Volta%2520Dilma%2520Fora%2520Temer#ie025efbbb0738ed01a63b326c174233e Open Delete
Volta+Dilma+Fo Open Delete
Volta+Dilma+Fora+Temer Open Delete
werweexample Open Delete
why doctrine Open Delete
Woop wooop Open Delete
Woop%20wooop Open Delete
wqeqe Open Delete
wxc<wxc Open Delete
Xbox Series X > PS5 Open Delete
xcxcxcx Open Delete
xx Open Delete
xy Open Delete
yfcx Open Delete
You Open Delete
yut Open Delete
yytutyutyu Open Delete
yyyyyyyyyyyyyy Open Delete
zizizizizi Open Delete
zzzz Open Delete
zzzzzz Open Delete
ролр Open Delete
File: Base/BaseController.php
<?php

namespace Fuz\AppBundle\Base;

use Fuz\AppBundle\Entity\Value;
use Fuz\AppBundle\Form\ValueType;
use Fuz\QuickStartBundle\Base\BaseController as QuickStartBase;
use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\HttpFoundation\Request;

class BaseController extends QuickStartBase
{
    protected function createContextSample(Request $request, $name = 'form', $values = ['a', 'b', 'c'])
    {
        $data = ['values' => $values];

        $form = $this
           ->get('form.factory')
           ->createNamedBuilder($name, Type\FormType::class, $data)
           ->add('values', Type\CollectionType::class, [
               'entry_type'    => Type\TextType::class,
               'label'         => 'Add, move, remove values and press Submit.',
               'entry_options' => [
                   'label' => 'Value',
               ],
               'allow_add'    => true,
               'allow_delete' => true,
               'prototype'    => true,
               'attr'         => [
                   'class' => "{$name}-collection",
               ],
           ])
           ->add('submit', Type\SubmitType::class)
           ->getForm()
        ;

        $form->handleRequest($request);
        if ($form->isValid()) {
            $data = $form->getData();
        }

        return [
            $name         => $form->createView(),
            "{$name}Data" => $data,
        ];
    }

    protected function createAdvancedContextSample(Request $request, $name = 'advancedForm')
    {
        $a = new Value('a');
        $b = new Value('b');
        $c = new Value('c');

        $data = ['values' => [$a, $b, $c]];

        $form = $this
           ->get('form.factory')
           ->createNamedBuilder($name, Type\FormType::class, $data)
           ->add('values', Type\CollectionType::class, [
               'entry_type'   => ValueType::class,
               'label'        => 'Add, move, remove values and press Submit.',
               'allow_add'    => true,
               'allow_delete' => true,
               'prototype'    => true,
               'required'     => false,
               'attr'         => [
                   'class' => "{$name}-collection",
               ],
           ])
           ->add('submit', Type\SubmitType::class)
           ->getForm()
        ;

        $form->handleRequest($request);
        if ($form->isValid()) {
            $data = $form->getData();
        }

        return [
            $name         => $form->createView(),
            "{$name}Data" => $data,
        ];
    }
}
File: Base/BaseController.php
File: Controller/AdvancedController.php
<?php

namespace Fuz\AppBundle\Controller;

use Fuz\AppBundle\Base\BaseController;
use Fuz\AppBundle\Entity\Address;
use Fuz\AppBundle\Entity\Addresses;
use Fuz\AppBundle\Entity\Fancy;
use Fuz\AppBundle\Entity\FancyCollection;
use Fuz\AppBundle\Entity\Value;
use Fuz\AppBundle\Form\AddressesType;
use Fuz\AppBundle\Form\FancyCollectionType;
use Fuz\AppBundle\Form\MyArrayType;
use Fuz\AppBundle\Form\ValueType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\HttpFoundation\Request;

/**
 * @Route("/advanced")
 */
class AdvancedController extends BaseController
{
    /**
     * Advanced usage
     *
     * You can reference your form collection in the view, instead of
     * putting a selector in the form type.
     *
     * @Route("/mvcCompliance", name="mvcCompliance")
     * @Template()
     */
    public function mvcComplianceAction(Request $request)
    {
        $data = ['values' => ['a', 'b', 'c']];

        $form = $this
           ->createFormBuilder($data)
           ->add('values', Type\CollectionType::class, [
               'entry_type'    => Type\TextType::class,
               'label'         => 'Add, move, remove values and press Submit.',
               'entry_options' => [
                   'label' => 'Value',
               ],
               'allow_add'    => true,
               'allow_delete' => true,
               'prototype'    => true,
               'required'     => false,
//                   'attr' => array (
//                           'class' => 'my-selector', <--- Not MVC compliant!
//                   ),
           ])
           ->add('submit', Type\SubmitType::class)
           ->getForm()
        ;

        $form->handleRequest($request);
        if ($form->isValid()) {
            $data = $form->getData();
        }

        return [
            'form' => $form->createView(),
            'data' => $data,
        ];
    }

    /**
     * Advanced usage
     *
     * A custom form theme helps define button's layout and positions as and where you want.
     *
     * @Route("/customFormTheme", name="customFormTheme")
     * @Template()
     */
    public function customFormThemeAction(Request $request)
    {
        $data = ['values' => [new Value('a'), new Value('b'), new Value('c')]];

        $form = $this
           ->createFormBuilder($data)
           ->add('values', Type\CollectionType::class, [
               'entry_type'   => ValueType::class,
               'label'        => 'Add, move, remove values and press Submit.',
               'allow_add'    => true,
               'allow_delete' => true,
               'prototype'    => true,
               'required'     => false,
               'attr'         => [
                   'class' => 'collection',
               ],
           ])
           ->add('submit', Type\SubmitType::class)
           ->getForm()
        ;

        $form->handleRequest($request);
        if ($form->isValid()) {
            $data = $form->getData();
        }

        return [
            'form' => $form->createView(),
            'data' => $data,
        ];
    }

    /**
     * Advanced usage
     *
     * Same demo as above, but with the add button located at the bottom of
     * the form instead of close to each field.
     *
     * @Route("/customFormThemeAddBottom", name="customFormThemeAddBottom")
     * @Template()
     */
    public function customFormThemeAddBottomAction(Request $request)
    {
        return $this->customFormThemeAction($request);
    }

    /**
     * Advanced usage
     *
     * Collection of collections are useful on the most dynamic forms, and a good
     * way to test if the plugin is working as expected too.
     *
     * @Route("/collectionOfCollections", name="collectionOfCollections")
     * @Template()
     */
    public function collectionOfCollectionsAction(Request $request)
    {
        $data = [
            'collections' => [
                [new Value('a'), new Value('b'), new Value('c')],
                [new Value('d'), new Value('e'), new Value('f')],
                [new Value('g'), new Value('h'), new Value('i')],
            ],
        ];

        $form = $this
           ->get('form.factory')
           ->createNamedBuilder('form', Type\FormType::class, $data)
           ->add('collections', Type\CollectionType::class, [
               'entry_type'    => Type\CollectionType::class,
               'label'         => 'Add, move, remove collections',
               'entry_options' => [
                   'entry_type'    => ValueType::class,
                   'label'         => 'Add, move, remove values',
                   'entry_options' => [
                       'label' => 'Value',
                   ],
                   'allow_add'      => true,
                   'allow_delete'   => true,
                   'prototype'      => true,
                   'prototype_name' => '__children_name__',
                   'attr'           => [
                       'class' => 'child-collection',
                   ],
               ],
               'allow_add'      => true,
               'allow_delete'   => true,
               'prototype'      => true,
               'prototype_name' => '__parent_name__',
               'attr'           => [
                   'class' => 'parent-collection',
               ],
           ])
           ->add('submit', Type\SubmitType::class)
           ->getForm()
        ;

        $form->handleRequest($request);
        if ($form->isValid()) {
            $data = $form->getData();
        }

        return [
            'form' => $form->createView(),
            'data' => $data,
        ];
    }

    /**
     * Advanced usage
     *
     * Looks like there are weird behaviours with Doctrine:
     * https://github.com/ninsuo/symfony-collection/issues/7
     * Let's test that live!
     *
     * ... hmm, doesn't look bad anyway
     *
     * @Route(
     *      "/usageWithDoctrine/{name}",
     *      name = "usageWithDoctrine",
     *      defaults = {
     *          "name" = "example"
     *      }
     * )
     * @Template()
     */
    public function usageWithDoctrineAction(Request $request, $name)
    {
        $repo = $this->getDoctrine()->getRepository('FuzAppBundle:MyArray');

        $data = $repo->findOneByName($name);
        if (is_null($data)) {
            $data = $repo->create($name);
        }

        $form = $this->createForm(MyArrayType::class, $data);
        $form->handleRequest($request);

        $form->get('save')->isClicked() && $form->isValid() && $repo->save($data);

        return [
            'names' => $repo->getArrayNames(),
            'form'  => $form->createView(),
            'data'  => $data,
        ];
    }

    /**
     * Related to usageWithDoctrine demo
     *
     * @Route(
     *      "/usageWithDoctrineDelete/{name}",
     *      name = "usageWithDoctrineDelete"
     * )
     */
    public function usageWithDoctrineDeleteAction(Request $request, $name)
    {
        $repo = $this->getDoctrine()->getRepository('FuzAppBundle:MyArray');
        if (!is_null($data = $repo->findOneByName($name))) {
            $repo->delete($data);
        }

        return $this->forward('FuzAppBundle:Advanced:usageWithDoctrine', [
            'name' => 'example',
        ]);
    }

    /**
     * A form having a theme and containing several fields
     *
     * @Route(
     *      "/formHavingSeveralFields",
     *      name = "formHavingSeveralFields"
     * )
     * @Template()
     */
    public function formHavingSeveralFieldsAction(Request $request)
    {
        $address = new Address();
        $address->setName('Mickael Steller');
        $address->setCompany('fuz.org');
        $address->setStreet('41 rue de la Paix');
        $address->setPostalcode('75002');
        $address->setCity('Paris');
        $address->setCountry('France');

        $addresses = new Addresses();
        $addresses->getAddresses()->add($address);

        $form = $this->createForm(AddressesType::class, $addresses);
        if ($request->isMethod('POST')) {
            $form->handleRequest($request);
        }

        return [
            'form' => $form->createView(),
            'data' => $addresses,
        ];
    }

    /**
     * Another example of form theme
     *
     * @Route(
     *      "/fancyFormTheme",
     *      name = "fancyFormTheme"
     * )
     * @Template()
     */
    public function fancyFormThemeAction(Request $request)
    {
        $fancyCollection = new FancyCollection();

        for ($i = 0; $i < 3; $i++) {
            $fancy = new Fancy();
            $fancyCollection->getFancyCollection()->add($fancy);
        }

        $form = $this->createForm(FancyCollectionType::class, $fancyCollection);

        $form->handleRequest($request);
        if ($form->isValid()) {
            $data = $form->getData();
        }

        return [
            'form' => $form->createView(),
            'data' => $fancyCollection,
        ];
    }
}
File: Controller/AdvancedController.php
File: Entity/MyArray.php
<?php

namespace Fuz\AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * MyArray
 *
 * @ORM\Table(
 *      name="my_array",
 *      uniqueConstraints={@ORM\UniqueConstraint(name="name_idx", columns={"name"})}
 * )
 * @ORM\Entity(repositoryClass="Fuz\AppBundle\Repository\MyArrayRepository")
 */
class MyArray
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    protected $name;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="MyElement", mappedBy="array", cascade={"all"}, orphanRemoval=true)
     */
    protected $elements;

    public function __construct()
    {
        $this->elements = new ArrayCollection();
    }

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    public function getElements()
    {
        return $this->elements;
    }
}
File: Entity/MyArray.php
File: Entity/MyElement.php
<?php

namespace Fuz\AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * MyElement
 *
 * @ORM\Table(name="my_element"),
 * @ORM\Entity
 */
class MyElement
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var MyArray
     *
     * @ORM\ManyToOne(targetEntity="MyArray", inversedBy="elements")
     * @ORM\JoinColumn(name="my_array_id", referencedColumnName="id")
     */
    protected $array;

    /**
     * @var string
     *
     * @ORM\Column(name="value", type="string", length=255)
     */
    protected $value;

    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    public function getId()
    {
        return $this->id;
    }

    public function setArray(MyArray $array)
    {
        $this->array = $array;

        return $this;
    }

    public function getArray()
    {
        return $this->array;
    }

    public function setValue($value)
    {
        $this->value = $value;

        return $this;
    }

    public function getValue()
    {
        return $this->value;
    }
}
File: Entity/MyElement.php
File: Form/MyArrayType.php
<?php

namespace Fuz\AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class MyArrayType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name', TextType::class, [
                'label' => 'Array name:',
        ]);

        $builder->add('elements', CollectionType::class, [
            'label'        => 'Add an element...',
            'entry_type'   => MyElementType::class,
            'allow_add'    => true,
            'allow_delete' => true,
            'prototype'    => true,
            'required'     => false,
            'by_reference' => true,
            'delete_empty' => true,
            'attr'         => [
                'class' => 'doctrine-sample',
            ],
        ]);

        $builder->add('save', SubmitType::class, [
                'label' => 'Save this array',
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'Fuz\AppBundle\Entity\MyArray',
        ]);
    }

    public function getBlockPrefix()
    {
        return 'my_array';
    }
}
File: Form/MyArrayType.php
File: Form/MyElementType.php
<?php

namespace Fuz\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 MyElementType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('value', TextType::class, [
            'required' => false,
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'Fuz\AppBundle\Entity\MyElement',
        ]);
    }

    public function getBlockPrefix()
    {
        return 'my_element';
    }
}
File: Form/MyElementType.php
File: Repository/MyArrayRepository.php
<?php

namespace Fuz\AppBundle\Repository;

use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\ORM\EntityRepository;
use Fuz\AppBundle\Entity\MyArray;

/**
 * MyArrayRepository.
 */
class MyArrayRepository extends EntityRepository
{
    public function create($name)
    {
        $data = new MyArray();
        $data->setName($name);
        try {
            $this->_em->persist($data);
            $this->_em->flush();
        } catch (UniqueConstraintViolationException $e) {
            return null;
        }

        return $data;
    }

    public function save(MyArray $data)
    {
        foreach ($data->getElements() as $element) {
            $element->setArray($data);
        }
        try {
            $this->_em->persist($data);
            $this->_em->flush();
        } catch (UniqueConstraintViolationException $e) {
            return null;
        }

        return $data;
    }

    public function getArrayNames()
    {
        $arrays = $this
            ->_em
            ->createQuery("
               SELECT arr.name
               FROM Fuz\AppBundle\Entity\MyArray arr
            ")
            ->execute();
        $names = [];
        foreach ($arrays as $array) {
            $names[] = $array['name'];
        }

        return $names;
    }

    public function delete(MyArray $data)
    {
        foreach ($data->getElements() as $element) {
            $this->_em->remove($element);
        }
        $this->_em->remove($data);
        $this->_em->flush();
    }
}
File: Repository/MyArrayRepository.php
File: Resources/views/Advanced/doctrine-theme.html.twig

{% block my_element_label %}{% endblock %}
{% block my_element_errors %}{% endblock %}

{% block my_element_widget %}

    <div class="row">
        <div class="col-md-7">
            {{ form_widget(form.value) }}
        </div>
        <div class="col-md-2">
            <a href="#" class="collection-up btn btn-default">Up</a>
            <a href="#" class="collection-down btn btn-default">Down</a>
        </div>
        <div class="col-md-2">
            <a href="#" class="collection-remove btn btn-default">Remove</a>
            <a href="#" class="collection-add btn btn-default">Add</a>
        </div>
        <div class="col-md-1">
            <a href="#" class="collection-duplicate btn btn-default">Duplicate</a>
        </div>
    </div>

{% endblock %}
File: Resources/views/Advanced/doctrine-theme.html.twig
File: Resources/views/Advanced/usageWithDoctrine.html.twig
{% extends 'FuzAppBundle::layout.html.twig' %}

{% block extra_js %}
    <script src="{{ asset('js/jquery.collection.js') }}"></script>
{% endblock %}

{% block title %}Advanced usage: example with Doctrine{% endblock %}

{% block body %}

    <h2>{{ block('title') }}</h2>

    <p>
        That's not really an <i>advanced</i> topic, but the sample will be a bit hard to read (as it takes many files),
        so let's say it targets more experienced Symfony users.
    </p>

    <p>
        In this demo, we're displaying a MyArray of MyElements, both persisted into the database. The MyArray entity
        only have an id and a name, and MyElement has id, MyArray's id and a value. This is quite the same as we seen
        in all demos, but persisted.
    </p>

    <div class="text-center">
        <input type="button" id="new" class="btn btn-default" value="Create new array"/>
    </div>

    {%
        form_theme form
            'jquery.collection.html.twig'
            'FuzAppBundle:Advanced:doctrine-theme.html.twig'
    %}
    {{ form(form) }}

    <hr/>

    {% if names|length %}
        Existing arrays:
        <table class="table">
            <thead>
                <th>Name</th>
                <th>Open</th>
                <th>Delete</th>
            </thead>
            <tbody>
                {% for name in names %}
                    <tr>
                        <td>{{ name }}</td>
                        <td>
                            {% if data.name != name %}<a href="{{ path('usageWithDoctrine', {'name': name}) }}">Open</a>{% endif %}
                        </td>
                        <td><a href="{{ path('usageWithDoctrineDelete', {'name': name}) }}">Delete</a></td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    {% endif %}

    {{
        tabs([
            'Base/BaseController.php',
            'Controller/AdvancedController.php',
            'Resources/views/Advanced/usageWithDoctrine.html.twig',
            'Resources/views/Advanced/doctrine-theme.html.twig',
            'Entity/MyArray.php',
            'Form/MyArrayType.php',
            'Entity/MyElement.php',
            'Form/MyElementType.php',
            'Repository/MyArrayRepository.php',
        ])
    }}

{% endblock %}

{% block script %}

    <script type="text/javascript">

        // only useful for the "new" button...
        $('#new').on('click', function() {
           var name = prompt("Which name would you like to use?");
           if (name) {
               var uri = '{{ path('usageWithDoctrine', {'name': 'a'}) }}';
               document.location = uri.substr(0, uri.length - 1) + encodeURIComponent(name);
           }
        });

        $('.doctrine-sample').collection();

    </script>

{% endblock %}
File: Resources/views/Advanced/usageWithDoctrine.html.twig