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

Appearance settings

Commit 68e8c04

Browse filesBrowse files
committed
Merge branch '2.3' into 2.4
2 parents 07822b8 + a1050eb commit 68e8c04
Copy full SHA for 68e8c04

File tree

Expand file treeCollapse file tree

15 files changed

+284
-96
lines changed
Filter options
Expand file treeCollapse file tree

15 files changed

+284
-96
lines changed

‎book/routing.rst

Copy file name to clipboardExpand all lines: book/routing.rst
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ The route is simple:
6969
return $collection;
7070
7171
.. versionadded:: 2.2
72-
The ``path`` option is new in Symfony2.2, ``pattern`` is used in older
72+
The ``path`` option is new in Symfony 2.2, ``pattern`` is used in older
7373
versions.
7474

7575
The path defined by the ``blog_show`` route acts like ``/blog/*`` where
@@ -705,7 +705,7 @@ be accomplished with the following route configuration:
705705
return $collection;
706706
707707
.. versionadded:: 2.2
708-
The ``methods`` option is added in Symfony2.2. Use the ``_method``
708+
The ``methods`` option is added in Symfony 2.2. Use the ``_method``
709709
requirement in older versions.
710710

711711
Despite the fact that these two routes have identical paths (``/contact``),

‎book/testing.rst

Copy file name to clipboardExpand all lines: book/testing.rst
+51-28Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ it has its own excellent `documentation`_.
2121
needed to test the Symfony core code itself.
2222

2323
Each test - whether it's a unit test or a functional test - is a PHP class
24-
that should live in the `Tests/` subdirectory of your bundles. If you follow
24+
that should live in the ``Tests/`` subdirectory of your bundles. If you follow
2525
this rule, then you can run all of your application's tests with the following
2626
command:
2727

@@ -783,47 +783,70 @@ PHPUnit Configuration
783783
~~~~~~~~~~~~~~~~~~~~~
784784

785785
Each application has its own PHPUnit configuration, stored in the
786-
``phpunit.xml.dist`` file. You can edit this file to change the defaults or
787-
create a ``phpunit.xml`` file to tweak the configuration for your local machine.
786+
``app/phpunit.xml.dist`` file. You can edit this file to change the defaults or
787+
create an ``app/phpunit.xml`` file to setup a configuration for your local
788+
machine only.
788789

789790
.. tip::
790791

791-
Store the ``phpunit.xml.dist`` file in your code repository, and ignore the
792+
Store the ``phpunit.xml.dist`` file in your code repository and ignore the
792793
``phpunit.xml`` file.
793794

794-
By default, only the tests stored in "standard" bundles are run by the
795-
``phpunit`` command (standard being tests in the ``src/*/Bundle/Tests`` or
796-
``src/*/Bundle/*Bundle/Tests`` directories) But you can easily add more
797-
directories. For instance, the following configuration adds the tests from
798-
the installed third-party bundles:
795+
By default, only the tests from your own custom bundles stored in the standard
796+
directories ``src/*/*Bundle/Tests`` or ``src/*/Bundle/*Bundle/Tests`` are run
797+
by the ``phpunit`` command, as configured in the ``phpunit.xml.dist`` file:
799798

800799
.. code-block:: xml
801800
802-
<!-- hello/phpunit.xml.dist -->
803-
<testsuites>
804-
<testsuite name="Project Test Suite">
805-
<directory>../src/*/*Bundle/Tests</directory>
806-
<directory>../src/Acme/Bundle/*Bundle/Tests</directory>
807-
</testsuite>
808-
</testsuites>
801+
<!-- app/phpunit.xml.dist -->
802+
<phpunit>
803+
<!-- ... -->
804+
<testsuites>
805+
<testsuite name="Project Test Suite">
806+
<directory>../src/*/*Bundle/Tests</directory>
807+
<directory>../src/*/Bundle/*Bundle/Tests</directory>
808+
</testsuite>
809+
</testsuites>
810+
<!-- ... -->
811+
</phpunit>
812+
813+
But you can easily add more directories. For instance, the following
814+
configuration adds tests from a custom ``lib/tests`` directory:
815+
816+
.. code-block:: xml
817+
818+
<!-- app/phpunit.xml.dist -->
819+
<phpunit>
820+
<!-- ... -->
821+
<testsuites>
822+
<testsuite name="Project Test Suite">
823+
<!-- ... --->
824+
<directory>../lib/tests</directory>
825+
</testsuite>
826+
</testsuites>
827+
<!-- ... --->
828+
</phpunit>
809829
810830
To include other directories in the code coverage, also edit the ``<filter>``
811831
section:
812832

813833
.. code-block:: xml
814834
815-
<!-- ... -->
816-
<filter>
817-
<whitelist>
818-
<directory>../src</directory>
819-
<exclude>
820-
<directory>../src/*/*Bundle/Resources</directory>
821-
<directory>../src/*/*Bundle/Tests</directory>
822-
<directory>../src/Acme/Bundle/*Bundle/Resources</directory>
823-
<directory>../src/Acme/Bundle/*Bundle/Tests</directory>
824-
</exclude>
825-
</whitelist>
826-
</filter>
835+
<!-- app/phpunit.xml.dist -->
836+
<phpunit>
837+
<!-- ... -->
838+
<filter>
839+
<whitelist>
840+
<!-- ... -->
841+
<directory>../lib</directory>
842+
<exclude>
843+
<!-- ... -->
844+
<directory>../lib/tests</directory>
845+
</exclude>
846+
</whitelist>
847+
</filter>
848+
<!-- ... --->
849+
</phpunit>
827850
828851
Learn more
829852
----------

‎components/form/type_guesser.rst

Copy file name to clipboardExpand all lines: components/form/type_guesser.rst
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ that the type guesser cannot guess the type.
7474

7575
The ``TypeGuess`` constructor requires 3 options:
7676

77-
* The type name (one of the :doc:`form types </reference/forms/types`);
77+
* The type name (one of the :doc:`form types </reference/forms/types>`);
7878
* Additional options (for instance, when the type is ``entity``, you also
7979
want to set the ``class`` option). If no types are guessed, this should be
8080
set to an empty array;

‎components/routing/introduction.rst

Copy file name to clipboardExpand all lines: components/routing/introduction.rst
+14-14Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -141,28 +141,26 @@ Using Prefixes
141141

142142
You can add routes or other instances of
143143
:class:`Symfony\\Component\\Routing\\RouteCollection` to *another* collection.
144-
This way you can build a tree of routes. Additionally you can define a prefix,
145-
default requirements, default options and host to all routes of a subtree with
146-
the :method:`Symfony\\Component\\Routing\\RouteCollection::addPrefix` method::
144+
This way you can build a tree of routes. Additionally you can define a prefix
145+
and default values for the parameters, requirements, options, schemes and the
146+
host to all routes of a subtree using methods provided by the
147+
``RouteCollection`` class::
147148

148149
$rootCollection = new RouteCollection();
149150

150151
$subCollection = new RouteCollection();
151152
$subCollection->add(...);
152153
$subCollection->add(...);
153-
$subCollection->addPrefix(
154-
'/prefix', // prefix
155-
array(), // requirements
156-
array(), // options
157-
'admin.example.com', // host
158-
array('https') // schemes
159-
);
154+
$subCollection->addPrefix('/prefix');
155+
$subCollection->addDefaults(array(...));
156+
$subCollection->addRequirements(array(...));
157+
$subCollection->addOptions(array(...));
158+
$subCollection->setHost('admin.example.com');
159+
$subCollection->setMethods(array('POST'));
160+
$subCollection->setSchemes(array('https'));
160161

161162
$rootCollection->addCollection($subCollection);
162163

163-
.. versionadded:: 2.2
164-
The ``addPrefix`` method is added in Symfony2.2. This was part of the
165-
``addCollection`` method in older versions.
166164

167165
Set the Request Parameters
168166
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -177,7 +175,9 @@ with this class via its constructor::
177175
$host = 'localhost',
178176
$scheme = 'http',
179177
$httpPort = 80,
180-
$httpsPort = 443
178+
$httpsPort = 443,
179+
$path = '/',
180+
$queryString = ''
181181
)
182182

183183
.. _components-routing-http-foundation:

‎components/security/authentication.rst

Copy file name to clipboardExpand all lines: components/security/authentication.rst
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ own, it just needs to follow these rules:
204204
:method:`Symfony\\Component\\Security\\Core\\Encoder\\PasswordEncoderInterface::isPasswordValid`
205205
must first of all make sure the password is not too long, i.e. the password length is no longer
206206
than 4096 characters. This is for security reasons (see `CVE-2013-5750`_), and you can use the
207-
:method:`Symfony\\Component\\Security\\Core\\Encoder\\BasePasswordEncoder::isPasswordTooLong`_
208-
method for this check:
207+
:method:`Symfony\\Component\\Security\\Core\\Encoder\\BasePasswordEncoder::isPasswordTooLong`
208+
method for this check::
209209

210210
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
211211

‎cookbook/email/cloud.rst

Copy file name to clipboardExpand all lines: cookbook/email/cloud.rst
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ How to use the Cloud to Send Emails
77
Requirements for sending emails from a production system differ from your
88
development setup as you don't want to be limited in the number of emails,
99
the sending rate or the sender address. Thus,
10-
:doc:`using Gmail </cookbook/email/gmail>`_ or similar services is not an
10+
:doc:`using Gmail </cookbook/email/gmail>` or similar services is not an
1111
option. If setting up and maintaining your own reliable mail server causes
1212
you a headache there's a simple solution: Leverage the cloud to send your
1313
emails.

‎cookbook/form/dynamic_form_modification.rst

Copy file name to clipboardExpand all lines: cookbook/form/dynamic_form_modification.rst
+95-16Lines changed: 95 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ sport like this::
476476
// src/Acme/DemoBundle/Form/Type/SportMeetupType.php
477477
namespace Acme\DemoBundle\Form\Type;
478478

479+
use Symfony\Component\Form\AbstractType;
479480
use Symfony\Component\Form\FormBuilderInterface;
480481
use Symfony\Component\Form\FormEvent;
481482
use Symfony\Component\Form\FormEvents;
@@ -486,7 +487,10 @@ sport like this::
486487
public function buildForm(FormBuilderInterface $builder, array $options)
487488
{
488489
$builder
489-
->add('sport', 'entity', array(...))
490+
->add('sport', 'entity', array(
491+
'class' => 'AcmeDemoBundle:Sport',
492+
'empty_value' => '',
493+
))
490494
;
491495

492496
$builder->addEventListener(
@@ -497,12 +501,19 @@ sport like this::
497501
// this would be your entity, i.e. SportMeetup
498502
$data = $event->getData();
499503

500-
$positions = $data->getSport()->getAvailablePositions();
504+
$sport = $data->getSport();
505+
$positions = null === $sport ? array() : $sport->getAvailablePositions();
501506

502-
$form->add('position', 'entity', array('choices' => $positions));
507+
$form->add('position', 'entity', array(
508+
'class' => 'AcmeDemoBundle:Position',
509+
'empty_value' => '',
510+
'choices' => $positions,
511+
));
503512
}
504513
);
505514
}
515+
516+
// ...
506517
}
507518

508519
When you're building this form to display to the user for the first time,
@@ -539,21 +550,28 @@ The type would now look like::
539550
namespace Acme\DemoBundle\Form\Type;
540551

541552
// ...
542-
use Acme\DemoBundle\Entity\Sport;
543553
use Symfony\Component\Form\FormInterface;
554+
use Acme\DemoBundle\Entity\Sport;
544555

545556
class SportMeetupType extends AbstractType
546557
{
547558
public function buildForm(FormBuilderInterface $builder, array $options)
548559
{
549560
$builder
550-
->add('sport', 'entity', array(...))
561+
->add('sport', 'entity', array(
562+
'class' => 'AcmeDemoBundle:Sport',
563+
'empty_value' => '',
564+
));
551565
;
552566

553-
$formModifier = function(FormInterface $form, Sport $sport) {
554-
$positions = $sport->getAvailablePositions();
567+
$formModifier = function(FormInterface $form, Sport $sport = null) {
568+
$positions = null === $sport ? array() : $sport->getAvailablePositions();
555569

556-
$form->add('position', 'entity', array('choices' => $positions));
570+
$form->add('position', 'entity', array(
571+
'class' => 'AcmeDemoBundle:Position',
572+
'empty_value' => '',
573+
'choices' => $positions,
574+
));
557575
};
558576

559577
$builder->addEventListener(
@@ -579,17 +597,78 @@ The type would now look like::
579597
}
580598
);
581599
}
600+
601+
// ...
602+
}
603+
604+
You can see that you need to listen on these two events and have different
605+
callbacks only because in two different scenarios, the data that you can use is
606+
available in different events. Other than that, the listeners always perform
607+
exactly the same things on a given form.
608+
609+
One piece that is still missing is the client-side updating of your form after
610+
the sport is selected. This should be handled by making an AJAX call back to
611+
your application. Assume that you have a sport meetup creation controller::
612+
613+
// src/Acme/DemoBundle/Controller/MeetupController.php
614+
namespace Acme\DemoBundle\Controller;
615+
616+
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
617+
use Symfony\Component\HttpFoundation\Request;
618+
use Acme\DemoBundle\Entity\SportMeetup;
619+
use Acme\DemoBundle\Form\Type\SportMeetupType;
620+
// ...
621+
622+
class MeetupController extends Controller
623+
{
624+
public function createAction(Request $request)
625+
{
626+
$meetup = new SportMeetup();
627+
$form = $this->createForm(new SportMeetupType(), $meetup);
628+
$form->handleRequest($request);
629+
if ($form->isValid()) {
630+
// ... save the meetup, redirect etc.
631+
}
632+
633+
return $this->render(
634+
'AcmeDemoBundle:Meetup:create.html.twig',
635+
array('form' => $form->createView())
636+
);
637+
}
638+
639+
// ...
582640
}
583641

584-
You can see that you need to listen on these two events and have different callbacks
585-
only because in two different scenarios, the data that you can use is available in different events.
586-
Other than that, the listeners always perform exactly the same things on a given form.
642+
The associated template uses some JavaScript to update the ``position`` form
643+
field according to the current selection in the ``sport`` field:
644+
645+
.. configuration-block::
646+
647+
.. code-block:: html+jinja
648+
649+
{# src/Acme/DemoBundle/Resources/views/Meetup/create.html.twig #}
650+
{{ form_start(form) }}
651+
{{ form_row(form.sport) }} {# <select id="meetup_sport" ... #}
652+
{{ form_row(form.position) }} {# <select id="meetup_position" ... #}
653+
{# ... #}
654+
{{ form_end(form) }}
655+
656+
.. include:: /cookbook/form/dynamic_form_modification_ajax_js.rst.inc
657+
658+
.. code-block:: html+php
659+
660+
<!-- src/Acme/DemoBundle/Resources/views/Meetup/create.html.php -->
661+
<?php echo $view['form']->start($form) ?>
662+
<?php echo $view['form']->row($form['sport']) ?> <!-- <select id="meetup_sport" ... -->
663+
<?php echo $view['form']->row($form['position']) ?> <!-- <select id="meetup_position" ... -->
664+
<!-- ... -->
665+
<?php echo $view['form']->end($form) ?>
666+
667+
.. include:: /cookbook/form/dynamic_form_modification_ajax_js.rst.inc
587668

588-
One piece that may still be missing is the client-side updating of your form
589-
after the sport is selected. This should be handled by making an AJAX call
590-
back to your application. In that controller, you can submit your form, but
591-
instead of processing it, simply use the submitted form to render the updated
592-
fields. The response from the AJAX call can then be used to update the view.
669+
The major benefit of submitting the whole form to just extract the updated
670+
``position`` field is that no additional server-side code is needed; all the
671+
code from above to generate the submitted form can be reused.
593672

594673
.. _cookbook-dynamic-form-modification-suppressing-form-validation:
595674

+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<script>
2+
var $sport = $('#meetup_sport');
3+
// When sport gets selected ...
4+
$sport.change(function(){
5+
// ... retrieve the corresponding form.
6+
var $form = $(this).closest('form');
7+
// Simulate form data, but only include the selected sport value.
8+
var data = {};
9+
data[$sport.attr('name')] = $sport.val();
10+
// Submit data via AJAX to the form's action path.
11+
$.ajax({
12+
url : $form.attr('action'),
13+
type: $form.attr('method'),
14+
data : data,
15+
success: function(html) {
16+
// Replace current position field ...
17+
$('#meetup_position').replaceWith(
18+
// ... with the returned one from the AJAX response.
19+
$(html).find('#meetup_position')
20+
);
21+
// Position field now displays the appropriate positions.
22+
}
23+
});
24+
});
25+
</script>

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.