Skip to content

Commit e0b8106

Browse files
committed
Merge branch '2.8' into 3.2
* 2.8: [#7907] add some use statements Updating Doctrine syntax for getRepository method Reworded the tip about property_info and Symfony framework remove useless space Add information for enable property_info service Updating doctrine class use [#7909] fix some typos Explained the locateResource() method of HttpKernel Reworded the note about dump() not being available in prod Symfony Installer Instructions for Windows Typo Fixing a typo in the Final Thoughts section Stop recommending the use of "doctrine:generate:entities" Added a help note about translating routes Use a safer code sample for Twig best practices Use the Twig namespaced syntax for all templates Updated the screenshot of deprecation messages
2 parents efc9a0e + 0b78495 commit e0b8106

34 files changed

+195
-189
lines changed
14.2 KB
Loading

best_practices/controllers.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ for the homepage of our app:
9595
9696
namespace AppBundle\Controller;
9797
98+
use AppBundle\Entity\Post;
9899
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
99100
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
100101
@@ -106,7 +107,7 @@ for the homepage of our app:
106107
public function indexAction()
107108
{
108109
$posts = $this->getDoctrine()
109-
->getRepository('AppBundle:Post')
110+
->getRepository(Post::class)
110111
->findLatest();
111112
112113
return $this->render('default/index.html.twig', array(
@@ -170,7 +171,7 @@ manually. In our application, we have this situation in ``CommentController``:
170171
public function newAction(Request $request, $postSlug)
171172
{
172173
$post = $this->getDoctrine()
173-
->getRepository('AppBundle:Post')
174+
->getRepository(Post::class)
174175
->findOneBy(array('slug' => $postSlug));
175176
176177
if (!$post) {

best_practices/security.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ more advanced use-case, you can always do the same security check in PHP:
226226
*/
227227
public function editAction($id)
228228
{
229-
$post = $this->getDoctrine()->getRepository('AppBundle:Post')
229+
$post = $this->getDoctrine()->getRepository(Post::class)
230230
->find($id);
231231
232232
if (!$post) {

best_practices/templates.rst

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,20 @@ Template Locations
3030
Store all your application's templates in ``app/Resources/views/`` directory.
3131

3232
Traditionally, Symfony developers stored the application templates in the
33-
``Resources/views/`` directory of each bundle. Then they used the logical name
34-
to refer to them (e.g. ``AcmeDemoBundle:Default:index.html.twig``).
33+
``Resources/views/`` directory of each bundle. Then they used the Twig namespaced
34+
path to refer to them (e.g. ``@AcmeDemo/Default/index.html.twig``).
3535

3636
But for the templates used in your application, it's much more convenient
3737
to store them in the ``app/Resources/views/`` directory. For starters, this
3838
drastically simplifies their logical names:
3939

40-
================================================= ==================================
41-
Templates Stored inside Bundles Templates Stored in ``app/``
42-
================================================= ==================================
43-
``AcmeDemoBundle:Default:index.html.twig`` ``default/index.html.twig``
44-
``::layout.html.twig`` ``layout.html.twig``
45-
``AcmeDemoBundle::index.html.twig`` ``index.html.twig``
46-
``AcmeDemoBundle:Default:subdir/index.html.twig`` ``default/subdir/index.html.twig``
47-
``AcmeDemoBundle:Default/subdir:index.html.twig`` ``default/subdir/index.html.twig``
48-
================================================= ==================================
40+
============================================ ==================================
41+
Templates Stored inside Bundles Templates Stored in ``app/``
42+
============================================ ==================================
43+
``@AcmeDemo/index.html.twig`` ``index.html.twig``
44+
``@AcmeDemo/Default/index.html.twig`` ``default/index.html.twig``
45+
``@AcmeDemo/Default/subdir/index.html.twig`` ``default/subdir/index.html.twig``
46+
============================================ ==================================
4947

5048
Another advantage is that centralizing your templates simplifies the work
5149
of your designers. They don't need to look for templates in lots of directories
@@ -131,7 +129,7 @@ service in the constructor of the Twig extension:
131129
new \Twig_SimpleFilter(
132130
'md2html',
133131
array($this, 'markdownToHtml'),
134-
array('is_safe' => array('html'))
132+
array('is_safe' => array('html'), 'pre_escape' => 'html')
135133
),
136134
);
137135
}

bundles/best_practices.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,21 @@ The ``composer.json`` file should include at least the following metadata:
422422
In order to make it easier for developers to find your bundle, register it on
423423
`Packagist`_, the official repository for Composer packages.
424424

425+
Resources
426+
---------
427+
428+
If the bundle references any resources (config files, translation files, etc.),
429+
don't use physical paths (e.g. ``__DIR__/config/services.xml``) but logical
430+
paths (e.g. ``@AppBundle/Resources/config/services.xml``).
431+
432+
The logical paths are required because of the bundle overriding mechanism that
433+
lets you override any resource/file of any bundle. See :ref:`http-kernel-resource-locator`
434+
for more details about transforming physical paths into logical paths.
435+
436+
Beware that templates use a simplified version of the logical path shown above.
437+
For example, an ``index.html.twig`` template located in the ``Resources/views/Default/``
438+
directory of the AppBundle, is referenced as ``@App/Default/index.html.twig``.
439+
425440
Learn more
426441
----------
427442

bundles/override.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ How to Override any Part of a Bundle
77
This document is a quick reference for how to override different parts of
88
third-party bundles.
99

10+
.. tip::
11+
12+
The bundle overriding mechanism means that you cannot use physical paths to
13+
refer to bundle's resources (e.g. ``__DIR__/config/services.xml``). Always
14+
use logical paths in your bundles (e.g. ``@AppBundle/Resources/config/services.xml``)
15+
and call the :ref:`locateResource() method <http-kernel-resource-locator>`
16+
to turn them into physical paths when needed.
17+
1018
Templates
1119
---------
1220

components/form.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ is created from the form factory.
418418
->add('dueDate', DateType::class)
419419
->getForm();
420420
421-
return $this->render('AcmeTaskBundle:Default:new.html.twig', array(
421+
return $this->render('@AcmeTask/Default/new.html.twig', array(
422422
'form' => $form->createView(),
423423
));
424424
}

components/http_kernel.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,32 @@ look like this::
742742
// ...
743743
}
744744

745+
.. _http-kernel-resource-locator:
746+
747+
Locating Resources
748+
------------------
749+
750+
The HttpKernel component is responsible of the bundle mechanism used in Symfony
751+
applications. The key feature of the bundles is that they allow to override any
752+
resource used by the application (config files, templates, controllers,
753+
translation files, etc.)
754+
755+
This overriding mechanism works because resources are referenced not by their
756+
physical path but by their logical path. For example, the ``services.xml`` file
757+
stored in the ``Resources/config/`` directory of a bundle called AppBundle is
758+
referenced as ``@AppBundle/Resources/config/services.xml``. This logical path
759+
will work when the application overrides that file and even if you change the
760+
directory of AppBundle.
761+
762+
The HttpKernel component provides a method called :method:`Symfony\\Component\\HttpKernel\\Kernel::locateResource`
763+
which can be used to transform logical paths into physical paths::
764+
765+
use Symfony\Component\HttpKernel\HttpKernel;
766+
767+
// ...
768+
$kernel = new HttpKernel($dispatcher, $resolver);
769+
$path = $kernel->locateResource('@AppBundle/Resources/config/services.xml');
770+
745771
Learn more
746772
----------
747773

components/property_info.rst

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,8 +348,17 @@ Using PHP reflection, the :class:`Symfony\\Component\\PropertyInfo\\Extractor\\R
348348
provides list, type and access information from setter and accessor methods.
349349
It can also provide return and scalar types for PHP 7+.
350350

351-
This service is automatically registered with the ``property_info`` service in
352-
the Symfony Framework.
351+
.. note::
352+
353+
When using the Symfony framework, this service is automatically registered
354+
when the ``property_info`` feature is enabled:
355+
356+
.. code-block:: yaml
357+
358+
# app/config/config.yml
359+
framework:
360+
property_info:
361+
enabled: true
353362
354363
.. code-block:: php
355364

components/security/authorization.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ on a "remember-me" cookie, or even authenticated anonymously?
110110
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
111111
112112
$anonymousClass = AnonymousToken::class;
113-
$rememberMeClass = RememberMeToken::Class;
113+
$rememberMeClass = RememberMeToken::class;
114114
115115
$trustResolver = new AuthenticationTrustResolver($anonymousClass, $rememberMeClass);
116116

controller/service.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ Symfony's base controller::
174174
public function indexAction($name)
175175
{
176176
return $this->render(
177-
'AppBundle:Hello:index.html.twig',
177+
'@App/Hello/index.html.twig',
178178
array('name' => $name)
179179
);
180180
}
@@ -210,7 +210,7 @@ service and use it directly::
210210
public function indexAction($name)
211211
{
212212
return $this->templating->renderResponse(
213-
'AppBundle:Hello:index.html.twig',
213+
'@App/Hello/index.html.twig',
214214
array('name' => $name)
215215
);
216216
}

doctrine.rst

Lines changed: 13 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -445,56 +445,8 @@ Even though Doctrine now knows how to persist a ``Product`` object to the
445445
database, the class itself isn't really useful yet. Since ``Product`` is just
446446
a regular PHP class with ``private`` properties, you need to create ``public``
447447
getter and setter methods (e.g. ``getName()``, ``setName($name)``) in order
448-
to access its properties in the rest of your application's code. Fortunately,
449-
the following command can generate these boilerplate methods automatically:
450-
451-
.. code-block:: terminal
452-
453-
$ php bin/console doctrine:generate:entities AppBundle/Entity/Product
454-
455-
This command makes sure that all the getters and setters are generated
456-
for the ``Product`` class. This is a safe command - you can run it over and
457-
over again: it only generates getters and setters that don't exist (i.e. it
458-
doesn't replace your existing methods).
459-
460-
.. caution::
461-
462-
Keep in mind that Doctrine's entity generator produces simple getters/setters.
463-
You should review the generated methods and add any logic, if necessary,
464-
to suit the needs of your application.
465-
466-
.. sidebar:: More about ``doctrine:generate:entities``
467-
468-
With the ``doctrine:generate:entities`` command you can:
469-
470-
* generate getter and setter methods in entity classes;
471-
472-
* generate repository classes on behalf of entities configured with the
473-
``@ORM\Entity(repositoryClass="...")`` annotation;
474-
475-
* generate the appropriate constructor for 1:n and n:m relations.
476-
477-
The ``doctrine:generate:entities`` command saves a backup of the original
478-
``Product.php`` named ``Product.php~``. In some cases, the presence of
479-
this file can cause a "Cannot redeclare class" error. It can be safely
480-
removed. You can also use the ``--no-backup`` option to prevent generating
481-
these backup files.
482-
483-
Note that you don't *need* to use this command. You could also write the
484-
necessary getters and setters by hand. This option simply exists to save
485-
you time, since creating these methods is often a common task during
486-
development.
487-
488-
You can also generate all known entities (i.e. any PHP class with Doctrine
489-
mapping information) of a bundle or an entire namespace:
490-
491-
.. code-block:: terminal
492-
493-
# generates all entities in the AppBundle
494-
$ php bin/console doctrine:generate:entities AppBundle
495-
496-
# generates all entities of bundles in the Acme namespace
497-
$ php bin/console doctrine:generate:entities Acme
448+
to access its properties in the rest of your application's code. Add these
449+
methods manually or with your own IDE.
498450

499451
.. _doctrine-creating-the-database-tables-schema:
500452

@@ -634,7 +586,7 @@ on its ``id`` value::
634586
public function showAction($productId)
635587
{
636588
$product = $this->getDoctrine()
637-
->getRepository('AppBundle:Product')
589+
->getRepository(Product::class)
638590
->find($productId);
639591

640592
if (!$product) {
@@ -658,18 +610,18 @@ job is to help you fetch entities of a certain class. You can access the
658610
repository object for an entity class via::
659611

660612
$repository = $this->getDoctrine()
661-
->getRepository('AppBundle:Product');
613+
->getRepository(Product::class);
662614

663615
.. note::
664616

665-
The ``AppBundle:Product`` string is a shortcut you can use anywhere
617+
You can also use ``AppBundle:Product`` syntax. This string is a shortcut you can use anywhere
666618
in Doctrine instead of the full class name of the entity (i.e. ``AppBundle\Entity\Product``).
667619
As long as your entity lives under the ``Entity`` namespace of your bundle,
668620
this will work.
669621

670622
Once you have a repository object, you can access all sorts of helpful methods::
671623

672-
$repository = $this->getDoctrine()->getRepository('AppBundle:Product');
624+
$repository = $this->getDoctrine()->getRepository(Product::class);
673625

674626
// query for a single product by its primary key (usually "id")
675627
$product = $repository->find($productId);
@@ -692,7 +644,7 @@ Once you have a repository object, you can access all sorts of helpful methods::
692644
You can also take advantage of the useful ``findBy()`` and ``findOneBy()`` methods
693645
to easily fetch objects based on multiple conditions::
694646

695-
$repository = $this->getDoctrine()->getRepository('AppBundle:Product');
647+
$repository = $this->getDoctrine()->getRepository(Product::class);
696648

697649
// query for a single product matching the given name and price
698650
$product = $repository->findOneBy(
@@ -725,10 +677,13 @@ Updating an Object
725677
Once you've fetched an object from Doctrine, updating it is easy. Suppose
726678
you have a route that maps a product id to an update action in a controller::
727679

680+
use AppBundle\Entity\Post;
681+
// ...
682+
728683
public function updateAction($productId)
729684
{
730685
$em = $this->getDoctrine()->getManager();
731-
$product = $em->getRepository('AppBundle:Product')->find($productId);
686+
$product = $em->getRepository(Product::class)->find($productId);
732687

733688
if (!$product) {
734689
throw $this->createNotFoundException(
@@ -774,7 +729,7 @@ Querying for Objects
774729
You've already seen how the repository object allows you to run basic queries
775730
without any work::
776731

777-
$repository = $this->getDoctrine()->getRepository('AppBundle:Product');
732+
$repository = $this->getDoctrine()->getRepository(Product::class);
778733

779734
$product = $repository->find($productId);
780735
$product = $repository->findOneByName('Keyboard');
@@ -835,7 +790,7 @@ depends on dynamic conditions, as your code soon becomes hard to read with
835790
DQL as you start to concatenate strings::
836791

837792
$repository = $this->getDoctrine()
838-
->getRepository('AppBundle:Product');
793+
->getRepository(Product::class);
839794

840795
// createQueryBuilder() automatically selects FROM AppBundle:Product
841796
// and aliases it to "p"

doctrine/associations.rst

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,8 @@ own a collection of its related ``Product`` objects.
189189
namespace as the targetEntity.
190190

191191
Now that you've added new properties to both the ``Product`` and ``Category``
192-
classes, tell Doctrine to generate the missing getter and setter methods for you:
193-
194-
.. code-block:: terminal
195-
196-
$ php bin/console doctrine:generate:entities AppBundle
192+
classes, you must generate the missing getter and setter methods manually or
193+
using your own IDE.
197194

198195
Ignore the Doctrine metadata for a moment. You now have two classes - ``Product``
199196
and ``Category``, with a natural many-to-one relationship. The ``Product``
@@ -276,10 +273,13 @@ When you need to fetch associated objects, your workflow looks just like it
276273
did before. First, fetch a ``$product`` object and then access its related
277274
``Category`` object::
278275

276+
use AppBundle\Entity\Post;
277+
// ...
278+
279279
public function showAction($productId)
280280
{
281281
$product = $this->getDoctrine()
282-
->getRepository('AppBundle:Product')
282+
->getRepository(Product::class)
283283
->find($productId);
284284

285285
$categoryName = $product->getCategory()->getName();
@@ -306,7 +306,7 @@ You can also query in the other direction::
306306
public function showProductsAction($categoryId)
307307
{
308308
$category = $this->getDoctrine()
309-
->getRepository('AppBundle:Category')
309+
->getRepository(Category::class)
310310
->find($categoryId);
311311

312312
$products = $category->getProducts();
@@ -327,7 +327,7 @@ to the given ``Category`` object via their ``category_id`` value.
327327
example::
328328

329329
$product = $this->getDoctrine()
330-
->getRepository('AppBundle:Product')
330+
->getRepository(Product::class)
331331
->find($productId);
332332

333333
$category = $product->getCategory();
@@ -388,7 +388,7 @@ object and its related ``Category`` with just one query::
388388
public function showAction($productId)
389389
{
390390
$product = $this->getDoctrine()
391-
->getRepository('AppBundle:Product')
391+
->getRepository(Product::class)
392392
->findOneByIdJoinedToCategory($productId);
393393

394394
$category = $product->getCategory();

0 commit comments

Comments
 (0)