-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[WCM] Revamped the Quick Start tutorial #4374
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
Changes from 3 commits
531fc24
4725c16
fe20efd
1ca388e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,17 +13,17 @@ Understanding the Directory Structure | |
The directory structure of a Symfony :term:`application` is rather flexible, | ||
but the recommended structure is as follows: | ||
|
||
* ``app/``: the application configuration; | ||
* ``src/``: the project's PHP code; | ||
* ``app/``: the application configuration and templates; | ||
* ``src/``: the project's PHP code; | ||
* ``vendor/``: the third-party dependencies; | ||
* ``web/``: the web root directory. | ||
* ``web/``: the web root directory. | ||
|
||
The ``web/`` Directory | ||
~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
The web root directory is the home of all public and static files like images, | ||
stylesheets, and JavaScript files. It is also where each :term:`front controller` | ||
lives:: | ||
lives, such as the production controller shown here:: | ||
|
||
// web/app.php | ||
require_once __DIR__.'/../app/bootstrap.php.cache'; | ||
|
@@ -33,7 +33,9 @@ lives:: | |
|
||
$kernel = new AppKernel('prod', false); | ||
$kernel->loadClassCache(); | ||
$kernel->handle(Request::createFromGlobals())->send(); | ||
$request = Request::createFromGlobals(); | ||
$response = $kernel->handle($request); | ||
$response->send(); | ||
|
||
The controller first bootstraps the application using a kernel class (``AppKernel`` | ||
in this case). Then, it creates the ``Request`` object using the PHP's global | ||
|
@@ -51,8 +53,7 @@ configuration and as such, it is stored in the ``app/`` directory. | |
This class must implement two methods: | ||
|
||
* ``registerBundles()`` must return an array of all bundles needed to run the | ||
application; | ||
|
||
application, as explained in the next section; | ||
* ``registerContainerConfiguration()`` loads the application configuration | ||
|
||
|
@@ -73,12 +74,21 @@ A bundle is kind of like a plugin in other software. So why is it called a | |
Symfony, from the core framework features to the code you write for your | ||
application. | ||
|
||
All the code you write for your application is organized in bundles. In Symfony | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this first sentence puts people on the wrong path. It'll put beginners in the limited view of: If something is not in bundle, it won't work with Symfony. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this is the quick tour, we need to keep things on the simpler side. We could have people put their integration code in a bundle and their model-ish code just in a namespaced directory in BUT, I do think this sentence is a bit out-dated. The bundle (or technically There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now I see we have a sentence below about how you could later split your |
||
speak, a bundle is a structured set of files (PHP files, stylesheets, JavaScripts, | ||
images, ...) that implements a single feature (a blog, a forum, ...) and which | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. implement (it refers to files, doesn't it?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the same phrase use originally in the tutorial. I think it's correct because "implements" refers to the bundle, not the files. But maybe the wording is confusing and we could change it. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine so. |
||
can be easily shared with other developers. | ||
|
||
Bundles are first-class citizens in Symfony. This gives you the flexibility | ||
to use pre-built features packaged in third-party bundles or to distribute your | ||
own bundles. It makes it easy to pick and choose which features to enable in | ||
your application and optimize them the way you want. And at the end of the day, | ||
your application code is just as *important* as the core framework itself. | ||
|
||
Symfony already includes an ``AppBundle`` that you may use to start developing | ||
your application. Then, if you need to split the application into reusable | ||
components, you can create your own bundles. | ||
|
||
Registering a Bundle | ||
~~~~~~~~~~~~~~~~~~~~ | ||
|
||
|
@@ -98,10 +108,10 @@ a single ``Bundle`` class that describes it:: | |
new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), | ||
new Symfony\Bundle\AsseticBundle\AsseticBundle(), | ||
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), | ||
new AppBundle\AppBundle(); | ||
); | ||
|
||
if (in_array($this->getEnvironment(), array('dev', 'test'))) { | ||
$bundles[] = new Acme\DemoBundle\AcmeDemoBundle(); | ||
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); | ||
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); | ||
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); | ||
|
@@ -110,23 +120,23 @@ a single ``Bundle`` class that describes it:: | |
return $bundles; | ||
} | ||
|
||
In addition to the AcmeDemoBundle that was already talked about, notice | ||
that the kernel also enables other bundles such as the FrameworkBundle, | ||
DoctrineBundle, SwiftmailerBundle and AsseticBundle bundle. They are all part | ||
of the core framework. | ||
In addition to the AppBundle that was already talked about, notice that the | ||
kernel also enables other bundles such as the FrameworkBundle, DoctrineBundle, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need the |
||
SwiftmailerBundle and AsseticBundle. They are all part of the core framework. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. technically, they are not. FrameworkBundle, TwigBundle, SecurityBundle, WebProfilerBundle and DebugBundle are the only bundles being in the core framework: https://github.com/symfony/symfony/tree/master/src/Symfony/Bundle There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. part of the standard distribution. Only 2 of them are part of the core framework. |
||
|
||
Configuring a Bundle | ||
~~~~~~~~~~~~~~~~~~~~ | ||
|
||
Each bundle can be customized via configuration files written in YAML, XML, or | ||
PHP. Have a look at the default Symfony configuration: | ||
PHP. Have a look at this sample of the default Symfony configuration: | ||
|
||
.. code-block:: yaml | ||
|
||
# app/config/config.yml | ||
imports: | ||
- { resource: parameters.yml } | ||
- { resource: security.yml } | ||
- { resource: services.yml } | ||
|
||
framework: | ||
#esi: ~ | ||
|
@@ -138,7 +148,7 @@ PHP. Have a look at the default Symfony configuration: | |
form: true | ||
csrf_protection: true | ||
validation: { enable_annotations: true } | ||
templating: { engines: ['twig'] } #assets_version: SomeVersionScheme | ||
templating: { engines: ['twig'] } | ||
default_locale: "%locale%" | ||
trusted_proxies: ~ | ||
session: ~ | ||
|
@@ -148,34 +158,6 @@ PHP. Have a look at the default Symfony configuration: | |
debug: "%kernel.debug%" | ||
strict_variables: "%kernel.debug%" | ||
|
||
# Assetic Configuration | ||
assetic: | ||
debug: "%kernel.debug%" | ||
use_controller: false | ||
bundles: [ ] | ||
#java: /usr/bin/java | ||
filters: | ||
cssrewrite: ~ | ||
#closure: | ||
# jar: "%kernel.root_dir%/Resources/java/compiler.jar" | ||
#yui_css: | ||
# jar: "%kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar" | ||
|
||
# Doctrine Configuration | ||
doctrine: | ||
dbal: | ||
driver: "%database_driver%" | ||
host: "%database_host%" | ||
port: "%database_port%" | ||
dbname: "%database_name%" | ||
user: "%database_user%" | ||
password: "%database_password%" | ||
charset: UTF8 | ||
|
||
orm: | ||
auto_generate_proxy_classes: "%kernel.debug%" | ||
auto_mapping: true | ||
|
||
# Swift Mailer Configuration | ||
swiftmailer: | ||
transport: "%mailer_transport%" | ||
|
@@ -184,9 +166,11 @@ PHP. Have a look at the default Symfony configuration: | |
password: "%mailer_password%" | ||
spool: { type: memory } | ||
|
||
Each first level entry like ``framework``, ``twig`` or ``doctrine`` defines the | ||
configuration for a specific bundle. For example, ``framework`` configures the | ||
FrameworkBundle while ``swiftmailer`` configures the SwiftmailerBundle. | ||
# ... | ||
|
||
Each first level entry like ``framework``, ``twig`` or ``swiftmailer`` defines | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or -> and ? |
||
the configuration for a specific bundle. For example, ``framework`` configures | ||
the FrameworkBundle while ``swiftmailer`` configures the SwiftmailerBundle. | ||
|
||
Each :term:`environment` can override the default configuration by providing a | ||
specific configuration file. For example, the ``dev`` environment loads the | ||
|
@@ -207,64 +191,42 @@ and then modifies it to add some debugging tools: | |
toolbar: true | ||
intercept_redirects: false | ||
|
||
monolog: | ||
handlers: | ||
main: | ||
type: stream | ||
path: "%kernel.logs_dir%/%kernel.environment%.log" | ||
level: debug | ||
firephp: | ||
type: firephp | ||
level: info | ||
|
||
assetic: | ||
use_controller: true | ||
# ... | ||
|
||
Extending a Bundle | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
In addition to being a nice way to organize and configure your code, a bundle | ||
can extend another bundle. Bundle inheritance allows you to override any existing | ||
bundle in order to customize its controllers, templates, or any of its files. | ||
This is where the logical names (e.g. ``@AcmeDemoBundle/Controller/SecuredController.php``) | ||
come in handy: they abstract where the resource is actually stored. | ||
|
||
Logical File Names | ||
.................. | ||
|
||
When you want to reference a file from a bundle, use this notation: | ||
``@BUNDLE_NAME/path/to/file``; Symfony will resolve ``@BUNDLE_NAME`` | ||
to the real path to the bundle. For instance, the logical path | ||
``@AcmeDemoBundle/Controller/DemoController.php`` would be converted to | ||
``src/Acme/DemoBundle/Controller/DemoController.php``, because Symfony knows | ||
the location of the AcmeDemoBundle. | ||
``@AppBundle/Controller/DefaultController.php`` would be converted to | ||
``src/AppBundle/Controller/DefaultController.php``, because Symfony knows | ||
the location of the AppBundle. | ||
|
||
Logical Controller Names | ||
........................ | ||
|
||
For controllers, you need to reference method names using the format | ||
For controllers, you need to reference actions using the format | ||
``BUNDLE_NAME:CONTROLLER_NAME:ACTION_NAME``. For instance, | ||
``AcmeDemoBundle:Welcome:index`` maps to the ``indexAction`` method from the | ||
``Acme\DemoBundle\Controller\WelcomeController`` class. | ||
|
||
Logical Template Names | ||
...................... | ||
|
||
For templates, the logical name ``AcmeDemoBundle:Welcome:index.html.twig`` is | ||
converted to the file path ``src/Acme/DemoBundle/Resources/views/Welcome/index.html.twig``. | ||
Templates become even more interesting when you realize they don't need to be | ||
stored on the filesystem. You can easily store them in a database table for | ||
instance. | ||
``AppBundle:Default:index`` maps to the ``indexAction`` method from the | ||
``AppBundle\Controller\DefaultController`` class. | ||
|
||
Extending Bundles | ||
................. | ||
|
||
If you follow these conventions, then you can use :doc:`bundle inheritance</cookbook/bundles/inheritance>` | ||
to "override" files, controllers or templates. For example, you can create | ||
a bundle - AcmeNewBundle - and specify that it overrides AcmeDemoBundle. | ||
When Symfony loads the ``AcmeDemoBundle:Welcome:index`` controller, it will | ||
first look for the ``WelcomeController`` class in AcmeNewBundle and, if | ||
it doesn't exist, then look inside AcmeDemoBundle. This means that one bundle | ||
If you follow these conventions, then you can use :doc:`bundle inheritance </cookbook/bundles/inheritance>` | ||
to override files, controllers or templates. For example, you can create | ||
a bundle - NewBundle - and specify that it overrides AppBundle. | ||
When Symfony loads the ``AppBundle:Default:index`` controller, it will | ||
first look for the ``DefaultController`` class in NewBundle and, if | ||
it doesn't exist, then look inside AppBundle. This means that one bundle | ||
can override almost any part of another bundle! | ||
|
||
Do you understand now why Symfony is so flexible? Share your bundles between | ||
|
@@ -276,22 +238,28 @@ Using Vendors | |
------------- | ||
|
||
Odds are that your application will depend on third-party libraries. Those | ||
should be stored in the ``vendor/`` directory. This directory already contains | ||
the Symfony libraries, the SwiftMailer library, the Doctrine ORM, the Twig | ||
templating system, and some other third party libraries and bundles. | ||
should be stored in the ``vendor/`` directory and managed by Composer. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [...] and are managed by Composer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your proposal is better, but I think it doesn't convey the meaning that I was thinking of. It's not only that Composer manages There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just: "should be stored in the |
||
This directory already contains the Symfony libraries, the SwiftMailer library, | ||
the Doctrine ORM, the Twig templating system and some other third party | ||
libraries and bundles. | ||
|
||
Understanding the Cache and Logs | ||
-------------------------------- | ||
|
||
Symfony is probably one of the fastest full-stack frameworks around. But how | ||
can it be so fast if it parses and interprets tens of YAML and XML files for | ||
each request? The speed is partly due to its cache system. The application | ||
Symfony applications can contain tens of configuration files defined in several | ||
formats (YAML, XML, PHP, etc.) Instead of parsing and combining all those files | ||
for each request, Symfony uses its own cache system. In fact, the application | ||
configuration is only parsed for the very first request and then compiled down | ||
to plain PHP code stored in the ``app/cache/`` directory. In the development | ||
environment, Symfony is smart enough to flush the cache when you change a | ||
file. But in the production environment, to speed things up, it is your | ||
responsibility to clear the cache when you update your code or change its | ||
configuration. | ||
to plain PHP code stored in the ``app/cache/`` directory. | ||
|
||
In the development environment, Symfony is smart enough to update the cache when | ||
you change a file. But in the production environment, to speed things up, it is | ||
your responsibility to clear the cache when you update your code or change its | ||
configuration. Execute this command to clear the cache in the ``prod`` environment: | ||
|
||
.. code-block:: bash | ||
|
||
$ php app/console cache:clear --env=prod | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need to add a caution somewhere (not sure quick tour is the best place) that the cache clearing done by |
||
|
||
When developing a web application, things can go wrong in many ways. The log | ||
files in the ``app/logs/`` directory tell you everything about the requests | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
translations too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1. There are also probably some other things, but I think 3 is enough - it gives you the right idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but these three are important in my opinion as they are all explained in the Best Practices book.