Skip to content

Commit 72d40a8

Browse files
committed
Merge branch '2.4'
2 parents db1cda5 + b0e07b4 commit 72d40a8

File tree

7 files changed

+144
-65
lines changed

7 files changed

+144
-65
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ python:
44
- "2.7"
55

66
install:
7-
- "git submodule update --init"
87
- "bash install.sh"
98
- "pip install -q -r requirements.txt --use-mirrors"
109

book/installation.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ If there are any issues, correct them now before moving on.
233233
$ rm -rf app/cache/*
234234
$ rm -rf app/logs/*
235235
236-
$ APACHEUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data' | grep -v root | head -1 | cut -d\ -f1`
236+
$ APACHEUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1`
237237
$ sudo chmod +a "$APACHEUSER allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs
238238
$ sudo chmod +a "`whoami` allow delete,write,append,file_inherit,directory_inherit" app/cache app/logs
239239
@@ -248,7 +248,7 @@ If there are any issues, correct them now before moving on.
248248

249249
.. code-block:: bash
250250
251-
$ APACHEUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data' | grep -v root | head -1 | cut -d\ -f1`
251+
$ APACHEUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1`
252252
$ sudo setfacl -Rn -m u:"$APACHEUSER":rwX -m u:`whoami`:rwX app/cache app/logs
253253
$ sudo setfacl -dRn -m u:"$APACHEUSER":rwX -m u:`whoami`:rwX app/cache app/logs
254254

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
.. index::
2+
single: Console; Commands as Services
3+
4+
How to Define Commands as Services
5+
==================================
6+
7+
.. versionadded:: 2.4
8+
Support for registering commands in the service container was introduced in
9+
version 2.4.
10+
11+
By default, Symfony will take a look in the ``Command`` directory of each
12+
bundle and automatically register your commands. If a command extends the
13+
:class:`Symfony\\Bundle\\FrameworkBundle\\Command\\ContainerAwareCommand`,
14+
Symfony will even inject the container.
15+
While making life easier, this has some limitations:
16+
17+
* Your command must live in the ``Command`` directory;
18+
* There's no way to conditionally register your service based on the environment
19+
or availability of some dependencies;
20+
* You can't access the container in the ``configure()`` method (because
21+
``setContainer`` hasn't been called yet);
22+
* You can't use the same class to create many commands (i.e. each with
23+
different configuration).
24+
25+
To solve these problems, you can register your command as a service and tag it
26+
with ``console.command``:
27+
28+
.. configuration-block::
29+
30+
.. code-block:: yaml
31+
32+
# app/config/config.yml
33+
services:
34+
acme_hello.command.my_command:
35+
class: Acme\HelloBundle\Command\MyCommand
36+
tags:
37+
- { name: console.command }
38+
39+
.. code-block:: xml
40+
41+
<!-- app/config/config.xml -->
42+
<?xml version="1.0" encoding="UTF-8" ?>
43+
<container xmlns="http://symfony.com/schema/dic/services"
44+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
45+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
46+
47+
<services>
48+
<service id="acme_hello.command.my_command"
49+
class="Acme\HelloBundle\Command\MyCommand">
50+
<tag name="console.command" />
51+
</service>
52+
</services>
53+
</container>
54+
55+
.. code-block:: php
56+
57+
// app/config/config.php
58+
$container
59+
->register('acme_hello.command.my_command', 'Acme\HelloBundle\Command\MyCommand')
60+
->addTag('console.command')
61+
;
62+
63+
Using Dependencies and Parameters to Set Default Values for Options
64+
-------------------------------------------------------------------
65+
66+
Imagine you want to provide a default value for the ``name`` option. You could
67+
pass one of the following as the 5th argument of ``addOption()``:
68+
69+
* a hardcoded string;
70+
* a container parameter (e.g. something from parameters.yml);
71+
* a value computed by a service (e.g. a repository).
72+
73+
By extending ``ContainerAwareCommand``, only the first is possible, because you
74+
can't access the container inside the ``configure()`` method. Instead, inject
75+
any parameter or service you need into the constructor. For example, suppose you
76+
have some ``NameRepository`` service that you'll use to get your default value::
77+
78+
// src/Acme/DemoBundle/Command/GreetCommand.php
79+
namespace Acme\DemoBundle\Command;
80+
81+
use Acme\DemoBundle\Entity\NameRepository;
82+
use Symfony\Component\Console\Command\Command;
83+
use Symfony\Component\Console\Input\InputInterface;
84+
use Symfony\Component\Console\Input\InputOption;
85+
use Symfony\Component\Console\Output\OutputInterface;
86+
87+
class GreetCommand extends Command
88+
{
89+
protected $nameRepository;
90+
91+
public function __construct(NameRepository $nameRepository)
92+
{
93+
$this->nameRepository = $nameRepository;
94+
}
95+
96+
protected function configure()
97+
{
98+
$defaultName = $this->nameRepository->findLastOne();
99+
100+
$this
101+
->setName('demo:greet')
102+
->setDescription('Greet someone')
103+
->addOption('name', '-n', InputOption::VALUE_REQUIRED, 'Who do you want to greet?', $defaultName)
104+
;
105+
}
106+
107+
protected function execute(InputInterface $input, OutputInterface $output)
108+
{
109+
$name = $input->getOption('name');
110+
111+
$output->writeln($name);
112+
}
113+
}
114+
115+
Now, just update the arguments of your service configuration like normal to
116+
inject the ``NameRepository``. Great, you now have a dynamic default value!
117+
118+
.. caution::
119+
120+
Be careful not to actually do any work in ``configure`` (e.g. make database
121+
queries), as your code will be run, even if you're using the console to
122+
execute a different command.

cookbook/console/console_command.rst

Lines changed: 4 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -65,55 +65,11 @@ This command will now automatically be available to run:
6565
.. _cookbook-console-dic:
6666

6767
Register Commands in the Service Container
68-
------------------------------------------
69-
70-
.. versionadded:: 2.4
71-
Support for registering commands in the service container was added in
72-
version 2.4.
73-
74-
Instead of putting your command in the ``Command`` directory and having Symfony
75-
auto-discover it for you, you can register commands in the service container
76-
using the ``console.command`` tag:
77-
78-
.. configuration-block::
79-
80-
.. code-block:: yaml
81-
82-
# app/config/config.yml
83-
services:
84-
acme_hello.command.my_command:
85-
class: Acme\HelloBundle\Command\MyCommand
86-
tags:
87-
- { name: console.command }
88-
89-
.. code-block:: xml
90-
91-
<!-- app/config/config.xml -->
92-
<?xml version="1.0" encoding="UTF-8" ?>
93-
<container xmlns="http://symfony.com/schema/dic/services"
94-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
95-
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
96-
97-
<service id="acme_hello.command.my_command"
98-
class="Acme\HelloBundle\Command\MyCommand">
99-
<tag name="console.command" />
100-
</service>
101-
</container>
102-
103-
.. code-block:: php
104-
105-
// app/config/config.php
106-
107-
$container
108-
->register('acme_hello.command.my_command', 'Acme\HelloBundle\Command\MyCommand')
109-
->addTag('console.command')
110-
;
111-
112-
.. tip::
68+
-------------------------------------------
11369

114-
Registering your command as a service gives you more control over its
115-
location and the services that are injected into it. But, there are no
116-
functional advantages, so you don't need to register your command as a service.
70+
Just like controllers, commands can be declared as services. See the
71+
:doc:`dedicated cookbook entry </cookbook/console/commands_as_services>`
72+
for details.
11773

11874
Getting Services from the Service Container
11975
-------------------------------------------

cookbook/console/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ Console
88
usage
99
sending_emails
1010
logging
11+
commands_as_services

cookbook/form/dynamic_form_modification.rst

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ creating that particular field is delegated to an event listener::
9999
{
100100
$builder->add('price');
101101

102-
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
102+
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
103103
// ... adding the name field if needed
104104
});
105105
}
@@ -116,7 +116,7 @@ the event listener might look like the following::
116116
public function buildForm(FormBuilderInterface $builder, array $options)
117117
{
118118
// ...
119-
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
119+
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
120120
$product = $event->getData();
121121
$form = $event->getForm();
122122

@@ -249,7 +249,7 @@ Using an event listener, your form might look like this::
249249
->add('subject', 'text')
250250
->add('body', 'textarea')
251251
;
252-
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
252+
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
253253
// ... add a choice list of friends of the current application user
254254
});
255255
}
@@ -325,13 +325,13 @@ and fill in the listener logic::
325325

326326
$builder->addEventListener(
327327
FormEvents::PRE_SET_DATA,
328-
function(FormEvent $event) use ($user) {
328+
function (FormEvent $event) use ($user) {
329329
$form = $event->getForm();
330330

331331
$formOptions = array(
332332
'class' => 'Acme\DemoBundle\Entity\User',
333333
'property' => 'fullName',
334-
'query_builder' => function(EntityRepository $er) use ($user) {
334+
'query_builder' => function (EntityRepository $er) use ($user) {
335335
// build a custom query
336336
// return $er->createQueryBuilder('u')->addOrderBy('fullName', 'DESC');
337337

@@ -491,7 +491,7 @@ sport like this::
491491

492492
$builder->addEventListener(
493493
FormEvents::PRE_SET_DATA,
494-
function(FormEvent $event) {
494+
function (FormEvent $event) {
495495
$form = $event->getForm();
496496

497497
// this would be your entity, i.e. SportMeetup
@@ -556,7 +556,7 @@ The type would now look like::
556556
));
557557
;
558558

559-
$formModifier = function(FormInterface $form, Sport $sport = null) {
559+
$formModifier = function (FormInterface $form, Sport $sport = null) {
560560
$positions = null === $sport ? array() : $sport->getAvailablePositions();
561561

562562
$form->add('position', 'entity', array(
@@ -568,7 +568,7 @@ The type would now look like::
568568

569569
$builder->addEventListener(
570570
FormEvents::PRE_SET_DATA,
571-
function(FormEvent $event) use ($formModifier) {
571+
function (FormEvent $event) use ($formModifier) {
572572
// this would be your entity, i.e. SportMeetup
573573
$data = $event->getData();
574574

@@ -578,7 +578,7 @@ The type would now look like::
578578

579579
$builder->get('sport')->addEventListener(
580580
FormEvents::POST_SUBMIT,
581-
function(FormEvent $event) use ($formModifier) {
581+
function (FormEvent $event) use ($formModifier) {
582582
// It's important here to fetch $event->getForm()->getData(), as
583583
// $event->getData() will get you the client data (that is, the ID)
584584
$sport = $event->getForm()->getData();
@@ -730,7 +730,7 @@ all of this, use a listener::
730730

731731
public function buildForm(FormBuilderInterface $builder, array $options)
732732
{
733-
$builder->addEventListener(FormEvents::POST_SUBMIT, function($event) {
733+
$builder->addEventListener(FormEvents::POST_SUBMIT, function ($event) {
734734
$event->stopPropagation();
735735
}, 900); // Always set a higher priority than ValidationListener
736736

cookbook/security/voters_data_permission.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ edit a particular object. Here's an example implementation:
6666
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
6767
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
6868
use Symfony\Component\Security\Core\User\UserInterface;
69-
use Acme\DemoBundle\Entity\Post;
7069
7170
class PostVoter implements VoterInterface
7271
{
@@ -81,9 +80,11 @@ edit a particular object. Here's an example implementation:
8180
));
8281
}
8382
84-
public function supportsClass($obj)
83+
public function supportsClass($class)
8584
{
86-
return $obj instanceof Post;
85+
$supportedClass = 'Acme\DemoBundle\Entity\Post';
86+
87+
return $supportedClass === $class || is_subclass_of($class, $supportedClass);
8788
}
8889
8990
/**
@@ -92,7 +93,7 @@ edit a particular object. Here's an example implementation:
9293
public function vote(TokenInterface $token, $post, array $attributes)
9394
{
9495
// check if class of this object is supported by this voter
95-
if (!$this->supportsClass($post)) {
96+
if (!$this->supportsClass(get_class($post))) {
9697
return VoterInterface::ACCESS_ABSTAIN;
9798
}
9899

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy