Skip to content

Commit 80c8e65

Browse files
committed
Merge branch '2.0' into 2.1
Conflicts: book/installation.rst
2 parents b59c01f + 65b316a commit 80c8e65

File tree

12 files changed

+294
-28
lines changed

12 files changed

+294
-28
lines changed

book/installation.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ one of the following commands (replacing ``###`` with your actual filename):
110110
If you've downloaded "without vendors", you'll definitely need to read the
111111
next section.
112112

113+
.. note::
114+
115+
You can easily override the default directory structure. See
116+
:doc:`/cookbook/configuration/override_dir_structure` for more
117+
information.
118+
113119
.. _installation-updating-vendors:
114120

115121
Updating Vendors

components/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ The Components
1717
locale
1818
process
1919
routing
20+
serializer
2021
templating
2122
yaml
2223

components/map.rst.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666

6767
* :doc:`/components/routing`
6868

69+
* **The Serializer Component**
70+
71+
* :doc:`/components/serializer`
72+
6973
* **The Templating Component**
7074

7175
* :doc:`/components/templating`

components/serializer.rst

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
.. index::
2+
single: Serializer
3+
single: Components; Serializer
4+
5+
The Serializer Component
6+
========================
7+
8+
The Serializer Component is meant to be used to turn objects into a
9+
specific format (XML, JSON, Yaml, ...) and the other way around.
10+
11+
In order to do so, the Serializer Component follows the following
12+
simple schema.
13+
14+
.. image:: /images/components/serializer/serializer_workflow.png
15+
16+
As you can see in the picture above, an array is used as a man in
17+
the middle. This way, Encoders will only deal with turning specific
18+
**formats** into **arrays** and vice versa. The same way, Normalizers
19+
will deal with turning specific **objects** into **arrays** and vice versa.
20+
21+
Serialization is a complicated topic, and while this component may not work
22+
in all cases, it can be a useful tool while developing tools to serialize
23+
and deserialize your objects.
24+
25+
Installation
26+
------------
27+
28+
You can install the component in many different ways:
29+
30+
* Use the official Git repository (https://github.com/symfony/Serializer);
31+
* Install it via PEAR ( `pear.symfony.com/Serializer`);
32+
* Install it via Composer (`symfony/serializer` on Packagist).
33+
34+
Usage
35+
-----
36+
37+
Using the Serializer component is really simple. We just need to set up
38+
the :class:`Symfony\\Component\\Serializer\\Serializer` specifying
39+
which Encoders and Normalizer are going to be available::
40+
41+
use Symfony\Component\Serializer\Serializer;
42+
use Symfony\Component\Serializer\Encoder\XmlEncoder;
43+
use Symfony\Component\Serializer\Encoder\JsonEncoder;
44+
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
45+
46+
$encoders = array(new XmlEncoder(), new JsonEncoder());
47+
$normalizers = array(new GetSetMethodNormalizer());
48+
49+
$serializer = new Serializer($normalizers, $encoders);
50+
51+
Serializing an object
52+
~~~~~~~~~~~~~~~~~~~~~
53+
54+
For the sake of this example, let's assume the following class already
55+
exists in our project::
56+
57+
namespace Acme;
58+
59+
class Person
60+
{
61+
private $age;
62+
private $name;
63+
64+
// Getters
65+
public function getName()
66+
{
67+
return $this->name;
68+
}
69+
70+
public function getAge()
71+
{
72+
return $this->age;
73+
}
74+
75+
// Setters
76+
public function setName($name)
77+
{
78+
$this->name = $name;
79+
}
80+
81+
public function setAge($age)
82+
{
83+
$this->age = $age;
84+
}
85+
}
86+
87+
Now, if we want to serialize this object into JSON, we only need to
88+
use the Serializer service created before::
89+
90+
$person = new Acme\Person();
91+
$person->setName('foo');
92+
$person->setAge(99);
93+
94+
$serializer->serialize($person, 'json'); // Output: {"name":"foo","age":99}
95+
96+
The first parameter of the :method:`Symfony\\Component\\Serializer\\Serializer::serialize`
97+
is the object to be serialized and the second is used to choose the proper encoder,
98+
in this case :class:`Symfony\\Component\\Serializer\\Encoder\\JsonEncoder`.
99+
100+
Deserializing an Object
101+
~~~~~~~~~~~~~~~~~~~~~~~
102+
103+
Let's see now how to do the exactly the opposite. This time, the information
104+
of the `People` class would be encoded in XML format::
105+
106+
$data = <<<EOF
107+
<person>
108+
<name>foo</name>
109+
<age>99</age>
110+
</person>
111+
EOF;
112+
113+
$person = $serializer->deserialize($data,'Acme\Person','xml');
114+
115+
In this case, :method:`Symfony\\Component\\Serializer\\Serializer::deserialize`
116+
needs three parameters:
117+
118+
1. The information to be decoded
119+
2. The name of the class this information will be decoded to
120+
3. The encoder used to convert that information into an array
121+
122+
JMSSerializationBundle
123+
----------------------
124+
125+
A popular third-party bundle, `JMSSerializationBundle`_ exists and extends
126+
(and sometimes replaces) the serialization functionality. This includes the
127+
ability to configure how your objects should be serialize/deserialized via
128+
annotations (as well as YML, XML and PHP), integration with the Doctrine ORM,
129+
and handling of other complex cases (e.g. circular references).
130+
131+
.. _`JMSSerializationBundle`: https://github.com/schmittjoh/JMSSerializerBundle

cookbook/configuration/environments.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,11 @@ includes the following:
338338

339339
* ``twig/`` - this directory contains all the cached Twig templates.
340340

341+
.. note::
342+
343+
You can easily change the directory location and name. For more information
344+
read the article :doc:`/cookbook/configuration/override_dir_structure`.
345+
341346

342347
Going Further
343348
-------------

cookbook/configuration/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Configuration
55
:maxdepth: 2
66

77
environments
8+
override_dir_structure
89
external_parameters
910
pdo_session_storage
1011
apache_router
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
.. index::
2+
single: Override Symfony
3+
4+
How to override Symfony's Default Directory Structure
5+
=====================================================
6+
7+
Symfony automatically ships with a default directory structure. You can
8+
easily override this directory structure to create your own. The default
9+
directory structure is:
10+
11+
.. code-block:: text
12+
13+
app/
14+
cache/
15+
config/
16+
logs/
17+
...
18+
src/
19+
...
20+
vendor/
21+
...
22+
web/
23+
app.php
24+
...
25+
26+
Override the ``cache`` directory
27+
--------------------------------
28+
29+
You can override the cache directory by overriding the ``getCacheDir`` method
30+
in the ``AppKernel`` class of you application::
31+
32+
// app/AppKernel.php
33+
34+
// ...
35+
class AppKernel extends Kernel
36+
{
37+
// ...
38+
39+
public function getCacheDir()
40+
{
41+
return $this->rootDir.'/'.$this->environment.'/cache/';
42+
}
43+
}
44+
45+
``$this->rootDir`` is the absolute path to the ``app`` directory and ``$this->environment``
46+
is the current environment (i.e. ``dev``). In this case we have changed
47+
the location of the cache directory to ``app/{environment}/cache``.
48+
49+
.. warning::
50+
51+
You should keep the ``cache`` directory different for each environment,
52+
otherwise some unexpected behaviour may happen. Each environment generates
53+
its own cached config files, and so each needs its own directory to store
54+
those cache files.
55+
56+
Override the ``logs`` directory
57+
-------------------------------
58+
59+
Overriding the ``logs`` directory is the same as overriding the ``cache``
60+
directory, the only difference is that you need to override the ``getLogDir``
61+
method::
62+
63+
// app/AppKernel.php
64+
65+
// ...
66+
class AppKernel extends Kernel
67+
{
68+
// ...
69+
70+
public function getLogDir()
71+
{
72+
return $this->rootDir.'/'.$this->environment.'/logs/';
73+
}
74+
}
75+
76+
Here we have changed the location of the directory to ``app/{environment}/logs``.
77+
78+
Override the ``web`` directory
79+
------------------------------
80+
81+
If you need to rename or move your ``web`` directory, the only thing you
82+
need to guarantee is that the path to the ``app`` directory is still correct
83+
in your ``app.php`` and ``app_dev.php`` front controllers. If you simply
84+
renamed the directory, you're fine. But if you moved it in some way, you
85+
may need to modify the paths inside these files::
86+
87+
require_once __DIR__.'/../Symfony/app/bootstrap.php.cache';
88+
require_once __DIR__.'/../Symfony/app/AppKernel.php';
89+
90+
.. tip::
91+
92+
Some shared hosts have a ``public_html`` web directory root. Renaming
93+
your web directory from ``web`` to ``public_html`` is one way to make
94+
your Symfony project work on your shared host. Another way is to deploy
95+
your application to a directory outside of your web root, delete your
96+
``public_html`` directory, and then replace it with a symbolic link to
97+
the ``web`` in your project.
98+
99+
.. note::
100+
101+
If you use the AsseticBundle you need to configure this, so it can use
102+
the correct ``web`` directory:
103+
104+
.. code-block:: yaml
105+
106+
# app/config/config.yml
107+
108+
# ...
109+
assetic:
110+
# ...
111+
read_from: %kernel.root_dir%/../../public_html
112+
113+
Now you just need to dump the assets again and your application should
114+
work:
115+
116+
.. code-block:: bash
117+
118+
$ php app/console assetic:dump --env=prod --no-debug

cookbook/doctrine/file_uploads.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ Next, refactor the ``Document`` class to take advantage of these callbacks::
266266
{
267267
if (null !== $this->file) {
268268
// do whatever you want to generate a unique name
269-
$this->path = uniqid().'.'.$this->file->guessExtension();
269+
$this->path = sha1(uniqid(mt_rand(), true)).'.'.$this->file->guessExtension();
270270
}
271271
}
272272

cookbook/map.rst.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* :doc:`/cookbook/configuration/index`
2020

2121
* :doc:`/cookbook/configuration/environments`
22+
* :doc:`/cookbook/configuration/override_dir_structure`
2223
* :doc:`/cookbook/configuration/external_parameters`
2324
* :doc:`/cookbook/configuration/pdo_session_storage`
2425
* :doc:`/cookbook/configuration/apache_router`

cookbook/security/custom_authentication_provider.rst

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ set an authenticated token in the security context if successful.
106106
use Symfony\Component\Security\Core\Exception\AuthenticationException;
107107
use Symfony\Component\Security\Core\SecurityContextInterface;
108108
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
109-
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
110109
use Acme\DemoBundle\Security\Authentication\Token\WsseUserToken;
111110
112111
class WsseListener implements ListenerInterface
@@ -124,35 +123,35 @@ set an authenticated token in the security context if successful.
124123
{
125124
$request = $event->getRequest();
126125
127-
if ($request->headers->has('x-wsse')) {
126+
$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/';
127+
if (!$request->headers->has('x-wsse') || 1 !== preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches)) {
128+
return;
129+
}
128130
129-
$wsseRegex = '/UsernameToken Username="([^"]+)", PasswordDigest="([^"]+)", Nonce="([^"]+)", Created="([^"]+)"/';
131+
$token = new WsseUserToken();
132+
$token->setUser($matches[1]);
130133
131-
if (preg_match($wsseRegex, $request->headers->get('x-wsse'), $matches)) {
132-
$token = new WsseUserToken();
133-
$token->setUser($matches[1]);
134+
$token->digest = $matches[2];
135+
$token->nonce = $matches[3];
136+
$token->created = $matches[4];
134137
135-
$token->digest = $matches[2];
136-
$token->nonce = $matches[3];
137-
$token->created = $matches[4];
138+
try {
139+
$authToken = $this->authenticationManager->authenticate($token);
138140
139-
try {
140-
$returnValue = $this->authenticationManager->authenticate($token);
141+
$this->securityContext->setToken($authToken);
142+
} catch (AuthenticationException $failed) {
143+
// ... you might log something here
141144
142-
if ($returnValue instanceof TokenInterface) {
143-
return $this->securityContext->setToken($returnValue);
144-
} elseif ($returnValue instanceof Response) {
145-
return $event->setResponse($returnValue);
146-
}
147-
} catch (AuthenticationException $e) {
148-
// you might log something here
149-
}
150-
}
151-
}
145+
// To deny the authentication clear the token. This will redirect to the login page.
146+
// $this->securityContext->setToken(null);
147+
// return;
152148
153-
$response = new Response();
154-
$response->setStatusCode(403);
155-
$event->setResponse($response);
149+
// Deny authentication with a '403 Forbidden' HTTP response
150+
$response = new Response();
151+
$response->setStatusCode(403);
152+
$event->setResponse($response);
153+
154+
}
156155
}
157156
}
158157

0 commit comments

Comments
 (0)