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

Updated the Best Practices for Symfony 4 and Flex #8599

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 12, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Updated the Best Practices for Symfony 4 and Flex
  • Loading branch information
javiereguiluz committed Nov 10, 2017
commit b997c1e101ce13cfa9f3ada290417f11cc137ef4
57 changes: 7 additions & 50 deletions 57 best_practices/business-logic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ The blog application needs a utility that can transform a post title (e.g.
"Hello World") into a slug (e.g. "hello-world"). The slug will be used as
part of the post URL.

Let's create a new ``Slugger`` class inside ``src/Utils/`` and
add the following ``slugify()`` method:
Let's create a new ``Slugger`` class inside ``src/Utils/`` and add the following
``slugify()`` method:

.. code-block:: php

Expand All @@ -50,22 +50,9 @@ add the following ``slugify()`` method:
}
}

Next, define a new service for that class.

.. code-block:: yaml

# config/services.yaml
services:
# ...

# use the fully-qualified class name as the service id
App\Utils\Slugger:
public: false

.. note::

If you're using the :ref:`default services.yml configuration <service-container-services-load-example>`,
the class is auto-registered as a service.
If you're using the :ref:`default services.yaml configuration <service-container-services-load-example>`,
this class is auto-registered as a service whose ID is ``App\Utils\Slugger`` (or
simply ``Slugger::class`` if the class is already imported in your code).

Traditionally, the naming convention for a service was a short, but unique
snake case key - e.g. ``app.utils.slugger``. But for most services, you should now
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove this paragraph.

Expand All @@ -77,8 +64,8 @@ use the class name.
except when you have multiple services configured for the same class (in that
case, use a snake case id).

Now you can use the custom slugger in any controller class, such as the
``AdminController``:
Now you can use the custom slugger in any other service or controller class,
such as the ``AdminController``:

.. code-block:: php

Expand Down Expand Up @@ -127,36 +114,6 @@ personal taste.
We recommend YAML because it's friendly to newcomers and concise. You can
of course use whatever format you like.

Service: No Class Parameter
---------------------------

You may have noticed that the previous service definition doesn't configure
the class namespace as a parameter:

.. code-block:: yaml

# config/services.yaml

# service definition with class namespace as parameter
parameters:
slugger.class: App\Utils\Slugger

services:
app.slugger:
class: '%slugger.class%'

This practice is cumbersome and completely unnecessary for your own services.

.. best-practice::

Don't define parameters for the classes of your services.

This practice was wrongly adopted from third-party bundles. When Symfony
introduced its service container, some developers used this technique to easily
allow overriding services. However, overriding a service by just changing its
class name is a very rare use case because, frequently, the new service has
different constructor arguments.

Using a Persistence Layer
-------------------------

Expand Down
142 changes: 27 additions & 115 deletions 142 best_practices/creating-the-project.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,36 @@ Creating the Project
Installing Symfony
------------------

In the past, Symfony projects were created with `Composer`_, the dependency manager
for PHP applications. However, the current recommendation is to use the **Symfony
Installer**, which has to be installed before creating your first project.

.. best-practice::

Use the Symfony Installer to create new Symfony-based projects.
Use the `Symfony Skeleton`_ and `Composer`_ to create new Symfony-based projects.

Read the :doc:`/setup` article learn how to install and use the Symfony
Installer.
The **Symfony Skeleton** is a minimal and empty Symfony project which you can
base your new projects on. Unlike past Symfony versions, this skeleton installs
the absolute bare minimum amount of dependencies to make a fully working Symfony
project. Read the :doc:`/setup` article to learn more about installing Symfony.

.. _linux-and-mac-os-x-systems:
.. _windows-systems:

Creating the Blog Application
-----------------------------

Now that everything is correctly set up, you can create a new project based on
Symfony. In your command console, browse to a directory where you have permission
to create files and execute the following commands:
In your command console, browse to a directory where you have permission to
create files and execute the following commands:

.. code-block:: terminal

$ cd projects/
$ symfony new blog

# Windows
c:\> cd projects/
c:\projects\> php symfony new blog

.. note::

If the installer doesn't work for you or doesn't output anything, make sure
that the `Phar extension`_ is installed and enabled on your computer.
$ composer create-project symfony/skeleton blog

This command creates a new directory called ``blog`` that contains a fresh new
project based on the most recent stable Symfony version available. In addition,
the installer checks if your system meets the technical requirements to execute
Symfony applications. If not, you'll see the list of changes needed to meet those
requirements.
project based on the most recent stable Symfony version available.

.. tip::

Symfony releases are digitally signed for security reasons. If you want to
verify the integrity of your Symfony installation, take a look at the
`public checksums repository`_ and follow `these steps`_ to verify the
signatures.
The technical requirements to run Symfony are simple. If you want to check
if your system meets those requirements, read :doc:`/reference/requirements`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about recommending using the req-checker for that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree! The linked article (https://symfony.com/doc/master/reference/requirements.html) was revamped recently to remove everything and just explain how to use req-checker.


Structuring the Application
---------------------------
Expand All @@ -61,47 +44,29 @@ number of files and directories generated automatically:
.. code-block:: text

blog/
├─ app/
│ ├─ config/
│ └─ Resources/
├─ bin
├─ bin/
│ └─ console
├─ config/
└─ public/
│ └─ index.php
├─ src/
│ └─ AppBundle/
│ └─ Kernel.php
├─ var/
│ ├─ cache/
│ ├─ logs/
│ └─ sessions/
├─ tests/
│ └─ AppBundle/
├─ vendor/
└─ web/
│ └─ log/
└─ vendor/

This file and directory hierarchy is the convention proposed by Symfony to
structure your applications. The recommended purpose of each directory is the
following:

* ``app/config/``, stores all the configuration defined for any environment;
* ``app/Resources/``, stores all the templates and the translation files for the
application;
* ``src/AppBundle/``, stores the Symfony specific code (controllers and routes),
your domain code (e.g. Doctrine classes) and all your business logic;
* ``var/cache/``, stores all the cache files generated by the application;
* ``var/log/``, stores all the log files generated by the application;
* ``var/sessions/``, stores all the session files generated by the application;
* ``tests/AppBundle/``, stores the automatic tests (e.g. Unit tests) of the
application.
* ``vendor/``, this is the directory where Composer installs the application's
dependencies and you should never modify any of its contents;
* ``web/``, stores all the front controller files and all the web assets, such
as stylesheets, JavaScript files and images.
structure your applications. It's recommended to keep this structure because it's
easy to navigate and most directory names are self-explanatory, but you can
:doc:`override the location of any Symfony directory </configuration/override_dir_structure>`:

Application Bundles
~~~~~~~~~~~~~~~~~~~

When Symfony 2.0 was released, most developers naturally adopted the symfony
1.x way of dividing applications into logical modules. That's why many Symfony
apps use bundles to divide their code into logical features: UserBundle,
apps used bundles to divide their code into logical features: UserBundle,
ProductBundle, InvoiceBundle, etc.

But a bundle is *meant* to be something that can be reused as a stand-alone
Expand All @@ -111,64 +76,11 @@ ProductBundle, then there's no advantage to having two separate bundles.

.. best-practice::

Create only one bundle called AppBundle for your application logic.

Implementing a single AppBundle bundle in your projects will make your code
more concise and easier to understand.

.. note::

There is no need to prefix the AppBundle with your own vendor (e.g.
AcmeAppBundle), because this application bundle is never going to be
shared.

.. note::

Another reason to create a new bundle is when you're overriding something
in a vendor's bundle (e.g. a controller). See :doc:`/bundles/inheritance`.

All in all, this is the typical directory structure of a Symfony application
that follows these best practices:

.. code-block:: text

blog/
├─ app/
│ ├─ config/
│ └─ Resources/
├─ bin/
│ └─ console
├─ src/
│ └─ AppBundle/
├─ tests/
│ └─ AppBundle/
├─ var/
│ ├─ cache/
│ ├─ logs/
└─ sessions/
├─ vendor/
└─ web/
├─ app.php
└─ app_dev.php

.. tip::

If your Symfony installation doesn't come with a pre-generated AppBundle,
you can generate it by hand executing this command:

.. code-block:: terminal

$ php bin/console generate:bundle --namespace=AppBundle --dir=src --format=annotation --no-interaction

Extending the Directory Structure
---------------------------------
Don't create any bundle to organize your application logic.

If your project or infrastructure requires some changes to the default directory
structure of Symfony, you can
:doc:`override the location of the main directories </configuration/override_dir_structure>`:
``cache/``, ``logs/`` and ``web/``.
Symfony applications can still use third-party bundles (installed in ``vendor/``)
to add features, but you should use PHP namespaces instead of bundles to organize
your own code.

.. _`Symfony Skeleton`: https://github.com/symfony/skeleton
.. _`Composer`: https://getcomposer.org/
.. _`Phar extension`: http://php.net/manual/en/intro.phar.php
.. _`public checksums repository`: https://github.com/sensiolabs/checksums
.. _`these steps`: http://fabien.potencier.org/signing-project-releases.html
40 changes: 13 additions & 27 deletions 40 best_practices/forms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ Building Forms

Define your forms as PHP classes.

The Form component allows you to build forms right inside your controller
code. This is perfectly fine if you don't need to reuse the form somewhere else.
But for organization and reuse, we recommend that you define each
form in its own PHP class::
The Form component allows you to build forms right inside your controller code.
This is perfectly fine if you don't need to reuse the form somewhere else. But
for organization and reuse, we recommend that you define each form in its own
PHP class::

namespace App\Form;

Expand Down Expand Up @@ -67,14 +67,6 @@ To use the class, use ``createForm()`` and pass the fully qualified class name::
// ...
}

Registering Forms as Services
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can also :ref:`register your form type as a service <form-field-service>`.
This is only needed if your form type requires some dependencies to be injected
by the container, otherwise it is unnecessary overhead and therefore *not*
recommended to do this for all form type classes.

Form Button Configuration
-------------------------

Expand All @@ -98,7 +90,7 @@ scope of that form:
{
$builder
// ...
->add('save', SubmitType::class, array('label' => 'Create Post'))
->add('save', SubmitType::class, ['label' => 'Create Post'])
;
}

Expand Down Expand Up @@ -127,7 +119,7 @@ some developers configure form buttons in the controller::
$form = $this->createForm(PostType::class, $post);
$form->add('submit', SubmitType::class, array(
'label' => 'Create',
'attr' => array('class' => 'btn btn-default pull-right'),
'attr' => ['class' => 'btn btn-default pull-right'],
));

// ...
Expand All @@ -144,8 +136,7 @@ view layer:
{{ form_start(form) }}
{{ form_widget(form) }}

<input type="submit" value="Create"
class="btn btn-default pull-right" />
<input type="submit" class="btn" value="Create" />
{{ form_end(form) }}

Rendering the Form
Expand All @@ -161,7 +152,7 @@ all of the fields:

.. code-block:: html+twig

{{ form_start(form, {'attr': {'class': 'my-form-class'} }) }}
{{ form_start(form, {attr: {class: 'my-form-class'} }) }}
{{ form_widget(form) }}
{{ form_end(form) }}

Expand Down Expand Up @@ -197,13 +188,8 @@ Handling a form submit usually follows a similar template:
// render the template
}

There are really only two notable things here. First, we recommend that you
use a single action for both rendering the form and handling the form submit.
For example, you *could* have a ``newAction()`` that *only* renders the form
and a ``createAction()`` that *only* processes the form submit. Both those
actions will be almost identical. So it's much simpler to let ``newAction()``
handle everything.

Second, is it required to call ``$form->isSubmitted()`` in the ``if`` statement
before calling ``isValid()``. Calling ``isValid()`` with an unsubmitted form
is deprecated since version 3.2 and will throw an exception in 4.0.
We recommend that you use a single action for both rendering the form and
handling the form submit. For example, you *could* have a ``newAction()`` that
*only* renders the form and a ``createAction()`` that *only* processes the form
submit. Both those actions will be almost identical. So it's much simpler to let
``newAction()`` handle everything.
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.