Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1936cff

Browse files
committed
Merge remote-tracking branch 'upstream/2.3' into cache_csrf_form
2 parents 8164304 + f43e923 commit 1936cff

File tree

304 files changed

+11809
-6640
lines changed

Some content is hidden

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

304 files changed

+11809
-6640
lines changed

.gitignore

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,2 @@
11
/_build
2-
/bundles/DoctrineFixturesBundle
3-
/bundles/DoctrineMigrationsBundle
4-
/bundles/DoctrineMongoDBBundle
5-
/bundles/SensioFrameworkExtraBundle
6-
/bundles/SensioGeneratorBundle
7-
/cmf
82
/_exts

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ language: python
33
python:
44
- "2.7"
55

6+
sudo: false
7+
68
install:
7-
- "bash install.sh"
89
- "pip install -q -r requirements.txt --use-mirrors"
910

1011
script: sphinx-build -nW -b html -d _build/doctrees . _build/html

best_practices/business-logic.rst

Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
Organizing Your Business Logic
2+
==============================
3+
4+
In computer software, **business logic** or domain logic is "the part of the
5+
program that encodes the real-world business rules that determine how data can
6+
be created, displayed, stored, and changed" (read `full definition`_).
7+
8+
In Symfony applications, business logic is all the custom code you write for
9+
your app that's not specific to the framework (e.g. routing and controllers).
10+
Domain classes, Doctrine entities and regular PHP classes that are used as
11+
services are good examples of business logic.
12+
13+
For most projects, you should store everything inside the ``AppBundle``.
14+
Inside here, you can create whatever directories you want to organize things:
15+
16+
.. code-block:: text
17+
18+
symfony2-project/
19+
├─ app/
20+
├─ src/
21+
│ └─ AppBundle/
22+
│ └─ Utils/
23+
│ └─ MyClass.php
24+
├─ vendor/
25+
└─ web/
26+
27+
Storing Classes Outside of the Bundle?
28+
--------------------------------------
29+
30+
But there's no technical reason for putting business logic inside of a bundle.
31+
If you like, you can create your own namespace inside the ``src/`` directory
32+
and put things there:
33+
34+
.. code-block:: text
35+
36+
symfony2-project/
37+
├─ app/
38+
├─ src/
39+
│ ├─ Acme/
40+
│ │ └─ Utils/
41+
│ │ └─ MyClass.php
42+
│ └─ AppBundle/
43+
├─ vendor/
44+
└─ web/
45+
46+
.. tip::
47+
48+
The recommended approach of using the ``AppBundle`` directory is for
49+
simplicity. If you're advanced enough to know what needs to live in
50+
a bundle and what can live outside of one, then feel free to do that.
51+
52+
Services: Naming and Format
53+
---------------------------
54+
55+
The blog application needs a utility that can transform a post title (e.g.
56+
"Hello World") into a slug (e.g. "hello-world"). The slug will be used as
57+
part of the post URL.
58+
59+
Let's, create a new ``Slugger`` class inside ``src/AppBundle/Utils/`` and
60+
add the following ``slugify()`` method:
61+
62+
.. code-block:: php
63+
64+
// src/AppBundle/Utils/Slugger.php
65+
namespace AppBundle\Utils;
66+
67+
class Slugger
68+
{
69+
public function slugify($string)
70+
{
71+
return preg_replace(
72+
'/[^a-z0-9]/', '-', strtolower(trim(strip_tags($string)))
73+
);
74+
}
75+
}
76+
77+
Next, define a new service for that class.
78+
79+
.. code-block:: yaml
80+
81+
# app/config/services.yml
82+
services:
83+
# keep your service names short
84+
app.slugger:
85+
class: AppBundle\Utils\Slugger
86+
87+
Traditionally, the naming convention for a service involved following the
88+
class name and location to avoid name collisions. Thus, the service
89+
*would have been* called ``app.utils.slugger``. But by using short service names,
90+
your code will be easier to read and use.
91+
92+
.. best-practice::
93+
94+
The name of your application's services should be as short as possible,
95+
but unique enough that you can search your project for the service if
96+
you ever need to.
97+
98+
Now you can use the custom slugger in any controller class, such as the
99+
``AdminController``:
100+
101+
.. code-block:: php
102+
103+
public function createAction(Request $request)
104+
{
105+
// ...
106+
107+
if ($form->isSubmitted() && $form->isValid()) {
108+
$slug = $this->get('app.slugger')->slugify($post->getTitle());
109+
$post->setSlug($slug);
110+
111+
// ...
112+
}
113+
}
114+
115+
Service Format: YAML
116+
--------------------
117+
118+
In the previous section, YAML was used to define the service.
119+
120+
.. best-practice::
121+
122+
Use the YAML format to define your own services.
123+
124+
This is controversial, and in our experience, YAML and XML usage is evenly
125+
distributed among developers, with a slight preference towards YAML.
126+
Both formats have the same performance, so this is ultimately a matter of
127+
personal taste.
128+
129+
We recommend YAML because it's friendly to newcomers and concise. You can
130+
of course use whatever format you like.
131+
132+
Service: No Class Parameter
133+
---------------------------
134+
135+
You may have noticed that the previous service definition doesn't configure
136+
the class namespace as a parameter:
137+
138+
.. code-block:: yaml
139+
140+
# app/config/services.yml
141+
142+
# service definition with class namespace as parameter
143+
services:
144+
app.slugger:
145+
class: AppBundle\Utils\Slugger
146+
147+
This practice is cumbersome and completely unnecessary for your own services:
148+
149+
.. best-practice::
150+
151+
Don't define parameters for the classes of your services.
152+
153+
This practice was wrongly adopted from third-party bundles. When Symfony
154+
introduced its service container, some developers used this technique to easily
155+
allow overriding services. However, overriding a service by just changing its
156+
class name is a very rare use case because, frequently, the new service has
157+
different constructor arguments.
158+
159+
Using a Persistence Layer
160+
-------------------------
161+
162+
Symfony is an HTTP framework that only cares about generating an HTTP response
163+
for each HTTP request. That's why Symfony doesn't provide a way to talk to
164+
a persistence layer (e.g. database, external API). You can choose whatever
165+
library or strategy you want for this.
166+
167+
In practice, many Symfony applications rely on the independent
168+
`Doctrine project`_ to define their model using entities and repositories.
169+
Just like with business logic, we recommend storing Doctrine entities in
170+
the ``AppBundle``
171+
172+
The three entities defined by our sample blog application are a good example:
173+
174+
.. code-block:: text
175+
176+
symfony2-project/
177+
├─ ...
178+
└─ src/
179+
└─ AppBundle/
180+
└─ Entity/
181+
├─ Comment.php
182+
├─ Post.php
183+
└─ User.php
184+
185+
.. tip::
186+
187+
If you're more advanced, you can of course store them under your own
188+
namespace in ``src/``.
189+
190+
Doctrine Mapping Information
191+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
192+
193+
Doctrine Entities are plain PHP objects that you store in some "database".
194+
Doctrine only knows about your entities through the mapping metadata configured
195+
for your model classes. Doctrine supports four metadata formats: YAML, XML,
196+
PHP and annotations.
197+
198+
.. best-practice::
199+
200+
Use annotations to define the mapping information of the Doctrine entities.
201+
202+
Annotations are by far the most convenient and agile way of setting up and
203+
looking for mapping information:
204+
205+
.. code-block:: php
206+
207+
namespace AppBundle\Entity;
208+
209+
use Doctrine\ORM\Mapping as ORM;
210+
use Doctrine\Common\Collections\ArrayCollection;
211+
212+
/**
213+
* @ORM\Entity
214+
*/
215+
class Post
216+
{
217+
const NUM_ITEMS = 10;
218+
219+
/**
220+
* @ORM\Id
221+
* @ORM\GeneratedValue
222+
* @ORM\Column(type="integer")
223+
*/
224+
private $id;
225+
226+
/**
227+
* @ORM\Column(type="string")
228+
*/
229+
private $title;
230+
231+
/**
232+
* @ORM\Column(type="string")
233+
*/
234+
private $slug;
235+
236+
/**
237+
* @ORM\Column(type="text")
238+
*/
239+
private $content;
240+
241+
/**
242+
* @ORM\Column(type="string")
243+
*/
244+
private $authorEmail;
245+
246+
/**
247+
* @ORM\Column(type="datetime")
248+
*/
249+
private $publishedAt;
250+
251+
/**
252+
* @ORM\OneToMany(
253+
* targetEntity="Comment",
254+
* mappedBy="post",
255+
* orphanRemoval=true
256+
* )
257+
* @ORM\OrderBy({"publishedAt" = "ASC"})
258+
*/
259+
private $comments;
260+
261+
public function __construct()
262+
{
263+
$this->publishedAt = new \DateTime();
264+
$this->comments = new ArrayCollection();
265+
}
266+
267+
// getters and setters ...
268+
}
269+
270+
All formats have the same performance, so this is once again ultimately a
271+
matter of taste.
272+
273+
Data Fixtures
274+
~~~~~~~~~~~~~
275+
276+
As fixtures support is not enabled by default in Symfony, you should execute
277+
the following command to install the Doctrine fixtures bundle:
278+
279+
.. code-block:: bash
280+
281+
$ composer require "doctrine/doctrine-fixtures-bundle"
282+
283+
Then, enable the bundle in ``AppKernel.php``, but only for the ``dev`` and
284+
``test`` environments:
285+
286+
.. code-block:: php
287+
288+
use Symfony\Component\HttpKernel\Kernel;
289+
290+
class AppKernel extends Kernel
291+
{
292+
public function registerBundles()
293+
{
294+
$bundles = array(
295+
// ...
296+
);
297+
298+
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
299+
// ...
300+
$bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle();
301+
}
302+
303+
return $bundles;
304+
}
305+
306+
// ...
307+
}
308+
309+
We recommend creating just *one* `fixture class`_ for simplicity, though
310+
you're welcome to have more if that class gets quite large.
311+
312+
Assuming you have at least one fixtures class and that the database access
313+
is configured properly, you can load your fixtures by executing the following
314+
command:
315+
316+
.. code-block:: bash
317+
318+
$ php app/console doctrine:fixtures:load
319+
320+
Careful, database will be purged. Do you want to continue Y/N ? Y
321+
> purging database
322+
> loading AppBundle\DataFixtures\ORM\LoadFixtures
323+
324+
Coding Standards
325+
----------------
326+
327+
The Symfony source code follows the `PSR-1`_ and `PSR-2`_ coding standards that
328+
were defined by the PHP community. You can learn more about
329+
:doc:`the Symfony Coding standards </contributing/code/standards>` and even
330+
use the `PHP-CS-Fixer`_, which is a command-line utility that can fix the
331+
coding standards of an entire codebase in a matter of seconds.
332+
333+
.. _`full definition`: http://en.wikipedia.org/wiki/Business_logic
334+
.. _`Doctrine project`: http://www.doctrine-project.org/
335+
.. _`fixture class`: http://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html#writing-simple-fixtures
336+
.. _`PSR-1`: http://www.php-fig.org/psr/psr-1/
337+
.. _`PSR-2`: http://www.php-fig.org/psr/psr-2/
338+
.. _`PHP-CS-Fixer`: https://github.com/FriendsOfPHP/PHP-CS-Fixer

0 commit comments

Comments
 (0)