Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite9b063c

Browse files
committed
Merge pull requestsymfony#2434 from WouterJ/add_remove
Refactored docs to use adders/removers
2 parentsf9f0c68 +2950097 commite9b063c

File tree

1 file changed

+87
-43
lines changed

1 file changed

+87
-43
lines changed

‎cookbook/form/form_collections.rst‎

Lines changed: 87 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,6 @@ objects. Start by creating a simple ``Task`` class::
5353
{
5454
return $this->tags;
5555
}
56-
57-
public function setTags(ArrayCollection $tags)
58-
{
59-
$this->tags = $tags;
60-
}
6156
}
6257

6358
..note::
@@ -240,9 +235,9 @@ zero tags when first created).
240235

241236
<!-- ... -->
242237

243-
When the user submits the form, the submitted data for the ``Tags`` fields
244-
areused to construct an ArrayCollection of ``Tag`` objects, which is then
245-
seton the ``tag`` field of the ``Task`` instance.
238+
When the user submits the form, the submitted data for the ``Tags`` fields are
239+
used to construct an``ArrayCollection`` of ``Tag`` objects, which is then set
240+
on the ``tag`` field of the ``Task`` instance.
246241

247242
The ``Tags`` collection is accessible naturally via ``$task->getTags()``
248243
and can be persisted to the database or used however you need.
@@ -286,7 +281,6 @@ add the ``allow_add`` option to your collection field::
286281
// src/Acme/TaskBundle/Form/Type/TaskType.php
287282

288283
// ...
289-
290284
use Symfony\Component\Form\FormBuilderInterface;
291285

292286
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -296,18 +290,59 @@ add the ``allow_add`` option to your collection field::
296290
$builder->add('tags', 'collection', array(
297291
'type' => new TagType(),
298292
'allow_add' => true,
299-
'by_reference' => false,
300293
));
301294
}
302295

303-
Note that ``'by_reference' => false`` was also added. Normally, the form
304-
framework would modify the tags on a `Task` object *without* actually
305-
ever calling `setTags`. By setting:ref:`by_reference<reference-form-types-by-reference>`
306-
to `false`, `setTags` will be called. This will be important later as you'll
307-
see.
296+
Now that the form type knows tags can be added, the ``Tasks`` class needs to
297+
add methods to make editing the tags possible. This is done by creating an
298+
"adder". In this case, the adder will be ``addTag``::
299+
300+
// src/Acme/TaskBundle/Entity/Task.php
301+
namespace Acme\TaskBundle\Entity;
302+
303+
// ...
304+
class Task
305+
{
306+
// ...
307+
308+
public function addTag($tag)
309+
{
310+
$this->tags->add($tag);
311+
}
312+
313+
public function removeTag($tag)
314+
{
315+
// ...
316+
}
317+
}
318+
319+
But, the form type will still use ``getTags`` now. You need to set the
320+
``by_reference`` option to ``false``, otherwise the form type will get the
321+
object by using the getter and change that object.
322+
323+
..caution::
324+
325+
If no ``addTag`` **and** ``removeTag`` method is found, the form will
326+
still ``setTag`` when setting ``by_reference`` to ``false``. You'll learn
327+
more about the ``removeTag`` method later in this article.
328+
329+
..code-block::php
330+
331+
// src/Acme/TaskBundle/Form/Type/TaskType.php
332+
333+
// ...
334+
public function buildForm(FormBuilderInterface $builder, array $options)
335+
{
336+
// ...
337+
338+
$builder->add('tags', 'collection', array(
339+
// ...
340+
'by_reference' => false,
341+
));
342+
}
308343
309344
In addition to telling the field to accept any number of submitted objects, the
310-
``allow_add`` also makes a "prototype" variable available to you. This "prototype"
345+
``allow_add`` also makes a*"prototype"* variable available to you. This "prototype"
311346
is a little "template" that contains all the HTML to be able to render any
312347
new "tag" forms. To render it, make the following change to your template:
313348

@@ -321,7 +356,9 @@ new "tag" forms. To render it, make the following change to your template:
321356

322357
..code-block::html+php
323358

324-
<ul class="tags" data-prototype="<?php echo $view->escape($view['form']->row($form['tags']->vars['prototype'])) ?>">
359+
<ul class="tags" data-prototype="<?php
360+
echo $view->escape($view['form']->row($form['tags']->vars['prototype']))
361+
?>">
325362
...
326363
</ul>
327364

@@ -430,13 +467,14 @@ into new ``Tag`` objects and added to the ``tags`` property of the ``Task`` obje
430467

431468
..sidebar::Doctrine: Cascading Relations and saving the "Inverse" side
432469

433-
Toget the new tagsto save inDoctrine, you need to consider a couple
434-
morethings. First, unless you iterate over all of the new ``Tag`` objects
435-
andcall ``$em->persist($tag)`` on each, you'll receive an error from
470+
Tosave the new tagswithDoctrine, you need to consider a couple more
471+
things. First, unless you iterate over all of the new ``Tag`` objects and
472+
call ``$em->persist($tag)`` on each, you'll receive an error from
436473
Doctrine:
437474

438-
A new entity was found through the relationship `Acme\TaskBundle\Entity\Task#tags`
439-
that was not configured to cascade persist operations for entity...
475+
A new entity was found through the relationship
476+
``Acme\TaskBundle\Entity\Task#tags`` that was not configured to
477+
cascade persist operations for entity...
440478

441479
To fix this, you may choose to "cascade" the persist operation automatically
442480
from the ``Task`` object to any related tags. To do this, add the ``cascade``
@@ -492,29 +530,25 @@ into new ``Tag`` objects and added to the ``tags`` property of the ``Task`` obje
492530
of the relationship is modified.
493531

494532
The trick is to make sure that the single "Task" is set on each "Tag".
495-
One easy way to do this is to add some extra logic to ``setTags()``,
496-
which is called by the formframework since:ref:`by_reference<reference-form-types-by-reference>`
497-
is set to``false``::
533+
One easy way to do this is to add some extra logic to ``addTag()``,
534+
which is called by the formtype since``by_reference`` is set to
535+
``false``::
498536

499537
// src/Acme/TaskBundle/Entity/Task.php
500538

501539
// ...
502-
503-
public function setTags(ArrayCollection $tags)
540+
public function addTag(ArrayCollection $tag)
504541
{
505-
foreach ($tags as $tag) {
506-
$tag->addTask($this);
507-
}
542+
$tag->addTask($this);
508543

509-
$this->tags = $tags;
544+
$this->tags->add($tag);
510545
}
511546

512547
Inside ``Tag``, just make sure you have an ``addTask`` method::
513548

514549
// src/Acme/TaskBundle/Entity/Tag.php
515550

516551
// ...
517-
518552
public function addTask(Task $task)
519553
{
520554
if (!$this->tasks->contains($task)) {
@@ -523,7 +557,7 @@ into new ``Tag`` objects and added to the ``tags`` property of the ``Task`` obje
523557
}
524558

525559
If you have a ``OneToMany`` relationship, then the workaround is similar,
526-
except that you can simply call ``setTask`` from inside ``setTags``.
560+
except that you can simply call ``setTask`` from inside ``addTag``.
527561

528562
.. _cookbook-form-collections-remove:
529563

@@ -538,20 +572,31 @@ Start by adding the ``allow_delete`` option in the form Type::
538572
// src/Acme/TaskBundle/Form/Type/TaskType.php
539573

540574
// ...
541-
use Symfony\Component\Form\FormBuilderInterface;
542-
543575
public function buildForm(FormBuilderInterface $builder, array $options)
544576
{
545-
$builder->add('description');
577+
// ...
546578

547579
$builder->add('tags', 'collection', array(
548-
'type' => new TagType(),
549-
'allow_add' => true,
580+
// ...
550581
'allow_delete' => true,
551-
'by_reference' => false,
552582
));
553583
}
554584

585+
Now, you need to put some code into the ``removeTag`` method of ``Task``::
586+
587+
// src/Acme/TaskBundle/Entity/Task.php
588+
589+
// ...
590+
class Task
591+
{
592+
// ...
593+
594+
public function removeTag($tag)
595+
{
596+
$this->tags->removeElement($tag);
597+
}
598+
}
599+
555600
Templates Modifications
556601
~~~~~~~~~~~~~~~~~~~~~~~
557602

@@ -604,11 +649,11 @@ the relationship between the removed ``Tag`` and ``Task`` object.
604649
..sidebar::Doctrine: Ensuring the database persistence
605650

606651
When removing objects in this way, you may need to do a little bit more
607-
work to ensure that the relationship between the Task and the removed Tag
608-
is properly removed.
652+
work to ensure that the relationship between the``Task`` and the removed
653+
``Tag``is properly removed.
609654

610655
In Doctrine, you have two side of the relationship: the owning side and the
611-
inverse side. Normally in this case you'll have a ManyToMany relation
656+
inverse side. Normally in this case you'll have a``ManyToMany`` relation
612657
and the deleted tags will disappear and persist correctly (adding new
613658
tags also works effortlessly).
614659

@@ -623,7 +668,6 @@ the relationship between the removed ``Tag`` and ``Task`` object.
623668
// src/Acme/TaskBundle/Controller/TaskController.php
624669

625670
// ...
626-
627671
public function editAction($id, Request $request)
628672
{
629673
$em = $this->getDoctrine()->getManager();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp