Skip to content

Commit 5185799

Browse files
committed
Merge branch 'master' of https://github.com/symfony/symfony-docs
2 parents e891b58 + 26d17e3 commit 5185799

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2002
-650
lines changed

book/controller.rst

+2
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ the following guidelines in mind while you develop.
313313
the name of the route that was matched (e.g. ``hello``). Though not usually
314314
useful, this is equally available as a controller argument.
315315

316+
.. _book-controller-request-argument:
317+
316318
The ``Request`` as a Controller Argument
317319
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
318320

book/doctrine.rst

+12-12
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,21 @@ Configuring the Database
4444

4545
Before you really begin, you'll need to configure your database connection
4646
information. By convention, this information is usually configured in an
47-
``app/config/parameters.ini`` file:
47+
``app/config/parameters.yml`` file:
4848

49-
.. code-block:: ini
49+
.. code-block:: yaml
5050
51-
;app/config/parameters.ini
52-
[parameters]
53-
database_driver = pdo_mysql
54-
database_host = localhost
55-
database_name = test_project
56-
database_user = root
57-
database_password = password
51+
# app/config/parameters.yml
52+
parameters:
53+
database_driver: pdo_mysql
54+
database_host: localhost
55+
database_name: test_project
56+
database_user: root
57+
database_password: password
5858
5959
.. note::
6060

61-
Defining the configuration via ``parameters.ini`` is just a convention.
61+
Defining the configuration via ``parameters.yml`` is just a convention.
6262
The parameters defined in that file are referenced by the main configuration
6363
file when setting up Doctrine:
6464

@@ -326,7 +326,7 @@ in your application. To do this, run:
326326
needed to *update* the database to where it should be. In other words, if you add
327327
a new property with mapping metadata to ``Product`` and run this task
328328
again, it will generate the "alter table" statement needed to add that
329-
new column to the existing ``products`` table.
329+
new column to the existing ``product`` table.
330330

331331
An even better way to take advantage of this functionality is via
332332
:doc:`migrations</bundles/DoctrineMigrationsBundle/index>`, which allow you to
@@ -861,7 +861,7 @@ table, and ``product.category_id`` column, and new foreign key:
861861

862862
This task should only be really used during development. For a more robust
863863
method of systematically updating your production database, read about
864-
:doc:`Doctrine migrations</bundles/DoctrineFixturesBundle/index>`.
864+
:doc:`Doctrine migrations</bundles/DoctrineMigrationsBundle/index>`.
865865

866866
Saving Related Entities
867867
~~~~~~~~~~~~~~~~~~~~~~~

book/forms.rst

+147-3
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,20 @@ the label, errors and HTML form widget of each field inside a ``div`` tag
598598
by default. In the :ref:`form-theming` section, you'll learn how the ``form_row``
599599
output can be customized on many different levels.
600600

601+
.. tip::
602+
603+
You can access the current data of your form via ``form.vars.value``:
604+
605+
.. configuration-block::
606+
607+
.. code-block:: jinja
608+
609+
{{ form.vars.value.task }}
610+
611+
.. code-block:: html+php
612+
613+
<?php echo $view['form']->get('value')->getTask() ?>
614+
601615
.. index::
602616
single: Forms; Rendering each field by hand
603617

@@ -746,6 +760,8 @@ Placing the form logic into its own class means that the form can be easily
746760
reused elsewhere in your project. This is the best way to create forms, but
747761
the choice is ultimately up to you.
748762

763+
.. _book-forms-data-class:
764+
749765
.. sidebar:: Setting the ``data_class``
750766

751767
Every form needs to know the name of the class that holds the underlying
@@ -936,9 +952,12 @@ and can be persisted to the database or used however you need.
936952
Embedding a Collection of Forms
937953
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
938954

939-
You can also embed a collection of forms into one form. This is done by
940-
using the ``collection`` field type. For more information, see the
941-
:doc:`collection field type reference</reference/forms/types/collection>`.
955+
You can also embed a collection of forms into one form (imagine a ``Category``
956+
form with many ``Product`` sub-forms). This is done by using the ``collection``
957+
field type.
958+
959+
For more information see the ":doc:`/cookbook/form/form_collections`" cookbook
960+
entry and the :ref:`collection</reference/forms/types/collection>` field type reference.
942961

943962
.. index::
944963
single: Forms; Theming
@@ -1295,6 +1314,130 @@ section.
12951314
The ``intention`` option is optional but greatly enhances the security of
12961315
the generated token by making it different for each form.
12971316

1317+
.. index:
1318+
single: Forms; With no class
1319+
1320+
Using a Form without a Class
1321+
----------------------------
1322+
1323+
In most cases, a form is tied to an object, and the fields of the form get
1324+
and store their data on the properties of that object. This is exactly what
1325+
you've seen so far in this chapter with the `Task` class.
1326+
1327+
But sometimes, you may just want to use a form without a class, and get back
1328+
an array of the submitted data. This is actually really easy::
1329+
1330+
// make sure you've imported the Request namespace above the class
1331+
use Symfony\Component\HttpFoundation\Request
1332+
// ...
1333+
1334+
public function contactAction(Request $request)
1335+
{
1336+
$defaultData = array('message' => 'Type your message here');
1337+
$form = $this->createFormBuilder($defaultData)
1338+
->add('name', 'text')
1339+
->add('email', 'email')
1340+
->add('message', 'textarea')
1341+
->getForm();
1342+
1343+
if ($request->getMethod() == 'POST') {
1344+
$form->bindRequest($request);
1345+
1346+
// data is an array with "name", "email", and "message" keys
1347+
$data = $form->getData();
1348+
}
1349+
1350+
// ... render the form
1351+
}
1352+
1353+
By default, a form actually assumes that you want to work with arrays of
1354+
data, instead of an object. There are exactly two ways that you can change
1355+
this behavior and tie the form to an object instead:
1356+
1357+
1. Pass an object when creating the form (as the first argument to ``createFormBuilder``
1358+
or the second argument to ``createForm``);
1359+
1360+
2. Declare the ``data_class`` option on your form.
1361+
1362+
If you *don't* do either of these, then the form will return the data as
1363+
an array. In this example, since ``$defaultData`` is not an object (and
1364+
no ``data_class`` option is set), ``$form->getData()`` ultimately returns
1365+
an array.
1366+
1367+
.. tip::
1368+
1369+
You can also access POST values (in this case "name") directly through
1370+
the request object, like so:
1371+
1372+
.. code-block:: php
1373+
1374+
$this->get('request')->request->get('name');
1375+
1376+
Be advised, however, that in most cases using the getData() method is
1377+
a better choice, since it returns the data (usually an object) after
1378+
it's been transformed by the form framework.
1379+
1380+
Adding Validation
1381+
~~~~~~~~~~~~~~~~~
1382+
1383+
The only missing piece is validation. Usually, when you call ``$form->isValid()``,
1384+
the object is validated by reading the constraints that you applied to that
1385+
class. But without a class, how can you add constraints to the data of your
1386+
form?
1387+
1388+
The answer is to setup the constraints yourself, and pass them into your
1389+
form. The overall approach is covered a bit more in the :ref:`validation chapter<book-validation-raw-values>`,
1390+
but here's a short example::
1391+
1392+
// import the namespaces above your controller class
1393+
use Symfony\Component\Validator\Constraints\Email;
1394+
use Symfony\Component\Validator\Constraints\MinLength;
1395+
use Symfony\Component\Validator\Constraints\Collection;
1396+
1397+
$collectionConstraint = new Collection(array(
1398+
'name' => new MinLength(5),
1399+
'email' => new Email(array('message' => 'Invalid email address')),
1400+
));
1401+
1402+
// create a form, no default values, pass in the constraint option
1403+
$form = $this->createFormBuilder(null, array(
1404+
'validation_constraint' => $collectionConstraint,
1405+
))->add('email', 'email')
1406+
// ...
1407+
;
1408+
1409+
Now, when you call `$form->isValid()`, the constraints setup here are run
1410+
against your form's data. If you're using a form class, override the ``getDefaultOptions``
1411+
method to specify the option::
1412+
1413+
namespace Acme\TaskBundle\Form\Type;
1414+
1415+
use Symfony\Component\Form\AbstractType;
1416+
use Symfony\Component\Form\FormBuilder;
1417+
use Symfony\Component\Validator\Constraints\Email;
1418+
use Symfony\Component\Validator\Constraints\MinLength;
1419+
use Symfony\Component\Validator\Constraints\Collection;
1420+
1421+
class ContactType extends AbstractType
1422+
{
1423+
// ...
1424+
1425+
public function getDefaultOptions(array $options)
1426+
{
1427+
$collectionConstraint = new Collection(array(
1428+
'name' => new MinLength(5),
1429+
'email' => new Email(array('message' => 'Invalid email address')),
1430+
));
1431+
1432+
$options['validation_constraint'] = $collectionConstraint;
1433+
}
1434+
}
1435+
1436+
Now, you have the flexibility to create forms - with validation - that return
1437+
an array of data, instead of an object. In most cases, it's better - and
1438+
certainly more robust - to bind your form to an object. But for simple forms,
1439+
this is a great approach.
1440+
12981441
Final Thoughts
12991442
--------------
13001443

@@ -1320,6 +1463,7 @@ Learn more from the Cookbook
13201463
* :doc:`File Field Reference </reference/forms/types/file>`
13211464
* :doc:`Creating Custom Field Types </cookbook/form/create_custom_field_type>`
13221465
* :doc:`/cookbook/form/form_customization`
1466+
* :doc:`/cookbook/form/dynamic_form_generation`
13231467

13241468
.. _`Symfony2 Form Component`: https://github.com/symfony/Form
13251469
.. _`DateTime`: http://php.net/manual/en/class.datetime.php

book/http_cache.rst

+9-8
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ The HTTP specification defines two caching models:
396396
until the cached version reaches its expiration time and becomes "stale".
397397

398398
* When pages are really dynamic (i.e. their representation changes often),
399-
the `validation model`_ model is often necessary. With this model, the
399+
the `validation model`_ is often necessary. With this model, the
400400
cache stores the response, but asks the server on each request whether
401401
or not the cached response is still valid. The application uses a unique
402402
response identifier (the ``Etag`` header) and/or a timestamp (the ``Last-Modified``
@@ -846,7 +846,7 @@ independent of the rest of the page.
846846
847847
In this example, we've given the full-page cache a lifetime of ten minutes.
848848
Next, let's include the news ticker in the template by embedding an action.
849-
This is done via the ``render`` helper (See `templating-embedding-controller`
849+
This is done via the ``render`` helper (See :ref:`templating-embedding-controller`
850850
for more details).
851851

852852
As the embedded content comes from another page (or controller for that
@@ -939,9 +939,9 @@ the ``_internal`` route:
939939

940940
Since this route allows all actions to be accessed via a URL, you might
941941
want to protect it by using the Symfony2 firewall feature (by allowing
942-
access to your reverse proxy's IP range). See the
943-
:doc:`Security Configuration Reference </reference/configuration/security>`
944-
for more information on how to do this.
942+
access to your reverse proxy's IP range). See the :ref:`Securing by IP<book-security-securing-ip>`
943+
section of the :doc:`Security Chapter </book/security>` for more information
944+
on how to do this.
945945

946946
One great advantage of this caching strategy is that you can make your
947947
application as dynamic as needed and at the same time, hit the application as
@@ -983,8 +983,9 @@ too far away in the future.
983983

984984
.. note::
985985

986-
It's also because there is no invalidation mechanism that you can use any
987-
reverse proxy without changing anything in your application code.
986+
Since invalidation is a topic specific to each type of reverse proxy,
987+
if you don't worry about invalidation, you can switch between reverse
988+
proxies without changing anything in your application code.
988989

989990
Actually, all reverse proxies provide ways to purge cached data, but you
990991
should avoid them as much as possible. The most standard way is to purge the
@@ -1003,7 +1004,7 @@ Here is how you can configure the Symfony2 reverse proxy to support the
10031004
}
10041005

10051006
$response = new Response();
1006-
if (!$this->store->purge($request->getUri())) {
1007+
if (!$this->getStore()->purge($request->getUri())) {
10071008
$response->setStatusCode(404, 'Not purged');
10081009
} else {
10091010
$response->setStatusCode(200, 'Purged');

book/internals.rst

+18-2
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ and set a new ``Exception`` object, or do nothing:
380380
.. index::
381381
single: Event Dispatcher
382382

383+
.. _`book-internals-event-dispatcher`:
384+
383385
The Event Dispatcher
384386
--------------------
385387

@@ -403,7 +405,7 @@ Take a simple example from the `Symfony2 HttpKernel component`_. Once a
403405
``Response`` object has been created, it may be useful to allow other elements
404406
in the system to modify it (e.g. add some cache headers) before it's actually
405407
used. To make this possible, the Symfony2 kernel throws an event -
406-
``kernel.response``. Here's how it work:
408+
``kernel.response``. Here's how it works:
407409

408410
* A *listener* (PHP object) tells a central *dispatcher* object that it wants
409411
to listen to the ``kernel.response`` event;
@@ -748,8 +750,16 @@ can be the way to go, especially for optional dependencies.
748750

749751
If you use dependency injection like we did in the two examples above, you
750752
can then use the `Symfony2 Dependency Injection component`_ to elegantly
751-
manage these objects.
753+
manage the injection of the ``event_dispatcher`` service for these objects.
754+
755+
.. code-block:: yaml
752756
757+
# src/Acme/HelloBundle/Resources/config/services.yml
758+
services:
759+
foo_service:
760+
class: Acme/HelloBundle/Foo/FooService
761+
arguments: [@event_dispatcher]
762+
753763
.. index::
754764
single: Event Dispatcher; Event subscribers
755765

@@ -814,6 +824,12 @@ returned by the ``getSubscribedEvents`` method. This method returns an array
814824
indexed by event names and whose values are either the method name to call or
815825
an array composed of the method name to call and a priority.
816826

827+
.. tip::
828+
829+
If you use the Symfony2 MVC framework, subscribers can be registered via
830+
your :ref:`configuration <dic-tags-kernel-event-subscriber>`. As an added
831+
bonus, the subscriber objects are instantiated only when needed.
832+
817833
.. index::
818834
single: Event Dispatcher; Stopping event flow
819835

book/page_creation.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ format you prefer:
721721
722722
# app/config/config.yml
723723
imports:
724-
- { resource: parameters.ini }
724+
- { resource: parameters.yml }
725725
- { resource: security.yml }
726726
727727
framework:
@@ -747,7 +747,7 @@ format you prefer:
747747
748748
<!-- app/config/config.xml -->
749749
<imports>
750-
<import resource="parameters.ini" />
750+
<import resource="parameters.yml" />
751751
<import resource="security.yml" />
752752
</imports>
753753
@@ -769,7 +769,7 @@ format you prefer:
769769
770770
.. code-block:: php
771771
772-
$this->import('parameters.ini');
772+
$this->import('parameters.yml');
773773
$this->import('security.yml');
774774
775775
$container->loadFromExtension('framework', array(

book/routing.rst

+14
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,18 @@ that route. With this information, any URL can easily be generated:
10831083
10841084
In an upcoming section, you'll learn how to generate URLs from inside templates.
10851085

1086+
.. tip::
1087+
1088+
If the frontend of your application uses AJAX requests, you might want
1089+
to be able to generate URLs in JavaScript based on your routing configuration.
1090+
By using the `FOSJsRoutingBundle`_, you can do exactly that:
1091+
1092+
.. code-block:: javascript
1093+
1094+
var url = Routing.generate('blog_show', { "slug": 'my-blog-post});
1095+
1096+
For more information, see the documentation for that bundle.
1097+
10861098
.. index::
10871099
single: Routing; Absolute URLs
10881100
@@ -1172,3 +1184,5 @@ Learn more from the Cookbook
11721184
----------------------------
11731185
11741186
* :doc:`/cookbook/routing/scheme`
1187+
1188+
.. _`FOSJsRoutingBundle`: https://github.com/FriendsOfSymfony/FOSJsRoutingBundle

0 commit comments

Comments
 (0)