diff --git a/bundles/configuration.rst b/bundles/configuration.rst index 2521aa53274..0e8220eadce 100644 --- a/bundles/configuration.rst +++ b/bundles/configuration.rst @@ -429,7 +429,9 @@ Assuming the XSD file is called ``hello-1.0.xsd``, the schema location will be diff --git a/bundles/prepend_extension.rst b/bundles/prepend_extension.rst index 923796fc42e..5c32d206629 100644 --- a/bundles/prepend_extension.rst +++ b/bundles/prepend_extension.rst @@ -122,9 +122,14 @@ The above would be the equivalent of writing the following into the xmlns:acme-something="http://example.org/schema/dic/acme_something" xmlns:acme-other="http://example.org/schema/dic/acme_other" xsi:schemaLocation="http://symfony.com/schema/dic/services - https://symfony.com/schema/dic/services/services-1.0.xsd"> + https://symfony.com/schema/dic/services/services-1.0.xsd + http://example.org/schema/dic/acme_something + https://example.org/schema/dic/acme_something/acme_something-1.0.xsd + http://example.org/schema/dic/acme_other + https://example.org/schema/dic/acme_something/acme_other-1.0.xsd"> + non_default diff --git a/cache.rst b/cache.rst index 9912b879e93..c10c90f4e51 100644 --- a/cache.rst +++ b/cache.rst @@ -65,7 +65,9 @@ adapter (template) they use by using the ``app`` and ``system`` key like: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:framework="http://symfony.com/schema/dic/symfony" xsi:schemaLocation="http://symfony.com/schema/dic/services - https://symfony.com/schema/dic/services/services-1.0.xsd"> + https://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony + https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> + https://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony + https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> + + https://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony + https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> @@ -276,7 +283,9 @@ For advanced configurations it could sometimes be useful to use a pool as an ada xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:framework="http://symfony.com/schema/dic/symfony" xsi:schemaLocation="http://symfony.com/schema/dic/services - https://symfony.com/schema/dic/services/services-1.0.xsd"> + https://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony + https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> @@ -354,7 +363,9 @@ and use that when configuring the pool. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:framework="http://symfony.com/schema/dic/symfony" xsi:schemaLocation="http://symfony.com/schema/dic/services - https://symfony.com/schema/dic/services/services-1.0.xsd"> + https://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony + https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> @@ -364,6 +375,7 @@ and use that when configuring the pool. + redis://localhost 2 @@ -376,6 +388,8 @@ and use that when configuring the pool. .. code-block:: php // app/config/config.php + use Symfony\Component\Cache\Adapter\RedisAdapter; + $container->loadFromExtension('framework', [ 'cache' => [ 'pools' => [ @@ -387,12 +401,14 @@ and use that when configuring the pool. ], ]); - $container->getDefinition('app.my_custom_redis_provider', \Redis::class) + $container->register('app.my_custom_redis_provider', \Redis::class) + ->setFactory([RedisAdapter::class, 'createConnection']) ->addArgument('redis://localhost') ->addArgument([ 'retry_interval' => 2, 'timeout' => 10 - ]); + ]) + ; Creating a Cache Chain ---------------------- @@ -448,7 +464,9 @@ Symfony stores the item automatically in all the missing pools. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:framework="http://symfony.com/schema/dic/symfony" xsi:schemaLocation="http://symfony.com/schema/dic/services - https://symfony.com/schema/dic/services/services-1.0.xsd"> + https://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony + https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> @@ -474,6 +492,9 @@ Symfony stores the item automatically in all the missing pools. .. code-block:: php // app/config/config.php + use Symfony\Component\Cache\Adapter\ChainAdapter; + use Symfony\Component\DependencyInjection\Reference; + $container->loadFromExtension('framework', [ 'cache' => [ 'pools' => [ @@ -495,13 +516,14 @@ Symfony stores the item automatically in all the missing pools. ], ]); - $container->getDefinition('app.my_cache_chain_adapter', \Symfony\Component\Cache\Adapter\ChainAdapter::class) + $container->register('app.my_cache_chain_adapter', ChainAdapter::class) ->addArgument([ new Reference('cache.array'), new Reference('cache.apcu'), new Reference('cache.my_redis'), ]) - ->addArgument(31536000); + ->addArgument(31536000) + ; .. note:: diff --git a/configuration.rst b/configuration.rst index 49b5589cee8..f089e89dc25 100644 --- a/configuration.rst +++ b/configuration.rst @@ -84,7 +84,7 @@ The main configuration file is called ``config.yml``: // Twig Configuration $container->loadFromExtension('twig', [ - 'debug' => '%kernel.debug%', + 'debug' => '%kernel.debug%', 'strict_variables' => '%kernel.debug%', ]); @@ -196,14 +196,8 @@ can also load XML files or PHP files. + https://symfony.com/schema/dic/services/services-1.0.xsd"> diff --git a/configuration/environments.rst b/configuration/environments.rst index 2d78e6c56da..9fb3a6712bb 100644 --- a/configuration/environments.rst +++ b/configuration/environments.rst @@ -231,6 +231,7 @@ this code and changing the environment string. + @@ -395,7 +395,7 @@ Symfony provides the following env var processors: 10.0.0.1 %env(HOST)% - http://%sentry_host%/project + https://%sentry_host%/project @@ -406,7 +406,7 @@ Symfony provides the following env var processors: // app/config/config.php $container->setParameter('env(HOST)', '10.0.0.1'); $container->setParameter('sentry_host', '%env(HOST)%'); - $container->setParameter('env(SENTRY_DSN)', 'http://%sentry_host%/project'); + $container->setParameter('env(SENTRY_DSN)', 'https://%sentry_host%/project'); $container->loadFromExtension('sentry', [ 'dsn' => '%env(resolve:SENTRY_DSN)%', ]); @@ -420,9 +420,12 @@ Symfony provides the following env var processors: # app/config/config.yml parameters: - env(AUTH_FILE): '../config/auth.json' - google: - auth: '%env(file:AUTH_FILE)%' + env(AUTH_FILE): '../auth.json' + + services: + some_authenticator: + arguments: + $auth: '%env(file:AUTH_FILE)%' .. code-block:: xml @@ -430,26 +433,30 @@ Symfony provides the following env var processors: - ../config/auth.json + ../auth.json - + + + "%env(file:AUTH_FILE)%" + + .. code-block:: php // app/config/config.php - $container->setParameter('env(AUTH_FILE)', '../config/auth.json'); - $container->loadFromExtension('google', [ - 'auth' => '%env(file:AUTH_FILE)%', - ]); + $container->setParameter('env(AUTH_FILE)', __DIR__.'/../auth.json'); + + $container->register('some_authenticator') + ->setArgument('$auth', '%env(file:AUTH_FILE)%') + ; It is also possible to combine any number of processors: @@ -457,12 +464,15 @@ It is also possible to combine any number of processors: parameters: env(AUTH_FILE): "%kernel.project_dir%/config/auth.json" - google: - # 1. gets the value of the AUTH_FILE env var - # 2. replaces the values of any config param to get the config path - # 3. gets the content of the file stored in that path - # 4. JSON-decodes the content of the file and returns it - auth: '%env(json:file:resolve:AUTH_FILE)%' + + services: + some_authenticator: + arguments: + # 1. gets the value of the AUTH_FILE env var + # 2. replaces the values of any config param to get the config path + # 3. gets the content of the file stored in that path + # 4. JSON-decodes the content of the file and returns it + $auth: '%env(json:file:resolve:AUTH_FILE)%' Custom Environment Variable Processors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -550,3 +560,4 @@ the Symfony service container:: // app/config/parameters.php include_once('/path/to/drupal/sites/default/settings.php'); $container->setParameter('drupal.database.url', $db_url); + diff --git a/configuration/using_parameters_in_dic.rst b/configuration/using_parameters_in_dic.rst index 13a179d1133..f39bf1726d2 100644 --- a/configuration/using_parameters_in_dic.rst +++ b/configuration/using_parameters_in_dic.rst @@ -51,7 +51,11 @@ Now, examine the results to see this closely: + xmlns:my-bundle="http://example.org/schema/dic/my_bundle" + xsi:schemaLocation="http://symfony.com/schema/dic/services + https://symfony.com/schema/dic/services/services-1.0.xsd + http://example.org/schema/dic/my_bundle + https://example.org/schema/dic/my_bundle/my_bundle-1.0.xsd"> diff --git a/console/commands_as_services.rst b/console/commands_as_services.rst index 30ba7265f23..394fdc26a3a 100644 --- a/console/commands_as_services.rst +++ b/console/commands_as_services.rst @@ -96,20 +96,22 @@ Or set the ``command`` attribute on the ``console.command`` tag in your service .. code-block:: yaml services: + # ... AppBundle\Command\SunshineCommand: tags: - { name: 'console.command', command: 'app:sunshine' } - # ... .. code-block:: xml + xsi:schemaLocation="http://symfony.com/schema/dic/services + https://symfony.com/schema/dic/services/services-1.0.xsd"> + @@ -124,8 +126,7 @@ Or set the ``command`` attribute on the ``console.command`` tag in your service // ... - $container - ->register(SunshineCommand::class) + $container->register(SunshineCommand::class) ->addTag('console.command', ['command' => 'app:sunshine']) ; diff --git a/console/input.rst b/console/input.rst index c9d934ff725..b05f4d7bfac 100644 --- a/console/input.rst +++ b/console/input.rst @@ -74,7 +74,8 @@ to greet all your friends). Only the last argument can be a list:: 'names', InputArgument::IS_ARRAY, 'Who do you want to greet (separate multiple names with a space)?' - ); + ) + ; To use this, just specify as many names as you want: @@ -111,7 +112,8 @@ You can combine ``IS_ARRAY`` with ``REQUIRED`` and ``OPTIONAL`` like this:: 'names', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Who do you want to greet (separate multiple names with a space)?' - ); + ) + ; Using Command Options --------------------- @@ -135,7 +137,8 @@ how many times in a row the message should be printed:: InputOption::VALUE_REQUIRED, 'How many times should the message be printed?', 1 - ); + ) + ; Next, use this in the command to print the message multiple times:: @@ -177,7 +180,8 @@ flag: InputOption::VALUE_REQUIRED, 'How many times should the message be printed?', 1 - ); + ) + ; Note that to comply with the `docopt standard`_, long options can specify their values after a white space or an ``=`` sign (e.g. ``--iterations 5`` or @@ -221,7 +225,8 @@ You can combine ``VALUE_IS_ARRAY`` with ``VALUE_REQUIRED`` or InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Which colors do you like?', ['blue', 'red'] - ); + ) + ; Options with optional arguments ------------------------------- @@ -239,7 +244,8 @@ optionally accepts a value, but it's a bit tricky. Consider this example:: null, InputOption::VALUE_OPTIONAL, 'Should I yell while greeting?' - ); + ) + ; This option can be used in 3 ways: ``--yell``, ``yell=louder``, and not passing the option at all. However, it's hard to distinguish between passing the option @@ -258,7 +264,8 @@ To solve this issue, you have to set the option's default value to ``false``:: InputOption::VALUE_OPTIONAL, 'Should I yell while greeting?', false // this is the new default value, instead of null - ); + ) + ; Now check the value of the option and keep in mind that ``false !== null``:: diff --git a/controller.rst b/controller.rst index c035f192507..9cbb20101cc 100644 --- a/controller.rst +++ b/controller.rst @@ -295,7 +295,7 @@ the argument by its name: # explicitly configure the service AppBundle\Controller\LuckyController: - public: true + tags: [controller.service_arguments] bind: # for any $logger argument, pass this specific service $logger: '@monolog.logger.doctrine' @@ -313,7 +313,8 @@ the argument by its name: - + + register(LuckyController::class) - ->setPublic(true) + ->addTag('controller.service_arguments') ->setBindings([ '$logger' => new Reference('monolog.logger.doctrine'), ]) @@ -341,7 +342,7 @@ in your controllers. .. caution:: You can *only* pass *services* to your controller arguments in this way. It's not - possible, for example, to pass a service parameter as a controller argument, + possible, for example, to pass a config parameter as a controller argument, even by using ``bind``. If you need a parameter, use the ``$this->getParameter('kernel.debug')`` shortcut or pass the value through your controller's ``__construct()`` method and specify its value with ``bind``. diff --git a/controller/argument_value_resolver.rst b/controller/argument_value_resolver.rst index 61239377dcb..70f0ea58610 100644 --- a/controller/argument_value_resolver.rst +++ b/controller/argument_value_resolver.rst @@ -101,7 +101,9 @@ type-hinted method arguments: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sensio-framework-extra="http://symfony.com/schema/dic/symfony_extra" xsi:schemaLocation="http://symfony.com/schema/dic/services - https://symfony.com/schema/dic/services/services-1.0.xsd"> + https://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony_extra + https://symfony.com/schema/dic/symfony_extra/symfony_extra-1.0.xsd"> @@ -191,12 +193,8 @@ and adding a priority. # app/config/services.yml services: - _defaults: - # ... be sure autowiring is enabled - autowire: true - # ... - AppBundle\ArgumentResolver\UserValueResolver: + autowire: true tags: - { name: controller.argument_value_resolver, priority: 50 } @@ -206,14 +204,11 @@ and adding a priority. + xsi:schemaLocation="http://symfony.com/schema/dic/services + https://symfony.com/schema/dic/services/services-1.0.xsd"> - - - - - + @@ -226,7 +221,8 @@ and adding a priority. use AppBundle\ArgumentResolver\UserValueResolver; $container->autowire(UserValueResolver::class) - ->addTag('controller.argument_value_resolver', ['priority' => 50]); + ->addTag('controller.argument_value_resolver', ['priority' => 50]) + ; While adding a priority is optional, it's recommended to add one to make sure the expected value is injected. The ``RequestAttributeValueResolver`` has a diff --git a/doctrine.rst b/doctrine.rst index cb1a77ba304..79efbebbd58 100644 --- a/doctrine.rst +++ b/doctrine.rst @@ -102,10 +102,10 @@ information. By convention, this information is usually configured in an // app/config/config.php $container->loadFromExtension('doctrine', [ 'dbal' => [ - 'driver' => 'pdo_mysql', - 'host' => '%database_host%', - 'dbname' => '%database_name%', - 'user' => '%database_user%', + 'driver' => 'pdo_mysql', + 'host' => '%database_host%', + 'dbname' => '%database_name%', + 'user' => '%database_user%', 'password' => '%database_password%', ], ]); @@ -250,8 +250,8 @@ can automatically generate an empty ``test_project`` database for you: // app/config/config.php $container->loadFromExtension('doctrine', [ 'dbal' => [ - 'driver' => 'pdo_sqlite', - 'path' => '%kernel.project_dir%/app/sqlite.db', + 'driver' => 'pdo_sqlite', + 'path' => '%kernel.project_dir%/app/sqlite.db', 'charset' => 'UTF-8', ], ]); diff --git a/email.rst b/email.rst index 0e60f8b520f..35795e83dc2 100644 --- a/email.rst +++ b/email.rst @@ -47,7 +47,8 @@ already included: xmlns:swiftmailer="http://symfony.com/schema/dic/swiftmailer" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd - http://symfony.com/schema/dic/swiftmailer https://symfony.com/schema/dic/swiftmailer/swiftmailer-1.0.xsd"> + http://symfony.com/schema/dic/swiftmailer + https://symfony.com/schema/dic/swiftmailer/swiftmailer-1.0.xsd"> autowire(ExceptionListener::class) + $container->register(ExceptionListener::class) ->addTag('kernel.event_listener', ['event' => 'kernel.exception']) ; diff --git a/logging.rst b/logging.rst index af5b72f2ba9..5663fd83921 100644 --- a/logging.rst +++ b/logging.rst @@ -130,17 +130,15 @@ to write logs using the :phpfunction:`syslog` function: https://symfony.com/schema/dic/monolog/monolog-1.0.xsd"> - + - + + + level="error"/> @@ -149,13 +147,17 @@ to write logs using the :phpfunction:`syslog` function: // app/config/config.php $container->loadFromExtension('monolog', [ 'handlers' => [ + // this "file_log" key could be anything 'file_log' => [ 'type' => 'stream', + // log to var/logs/(environment).log 'path' => '%kernel.logs_dir%/%kernel.environment%.log', + // log *all* messages (debug is lowest level) 'level' => 'debug', ], 'syslog_handler' => [ 'type' => 'syslog', + // log error-level messages and higher 'level' => 'error', ], ], @@ -209,20 +211,22 @@ one of the messages reaches an ``action_level``. Take this example: https://symfony.com/schema/dic/monolog/monolog-1.0.xsd"> - + - + - + @@ -236,14 +240,19 @@ one of the messages reaches an ``action_level``. Take this example: 'handlers' => [ 'filter_for_errors' => [ 'type' => 'fingers_crossed', + // if *one* log is error or higher, pass *all* to file_log 'action_level' => 'error', 'handler' => 'file_log', ], + + // now passed *all* logs, but only if one log is error or higher 'file_log' => [ 'type' => 'stream', 'path' => '%kernel.logs_dir%/%kernel.environment%.log', 'level' => 'debug', ], + + // still passed *all* logs, and still only logs error or higher 'syslog_handler' => [ 'type' => 'syslog', 'level' => 'error', diff --git a/routing.rst b/routing.rst index 74597a3b6e3..cd271898bce 100644 --- a/routing.rst +++ b/routing.rst @@ -100,8 +100,8 @@ the same features and performance, so choose the one you prefer: AppBundle:Blog:list - - + AppBundle:Blog:show @@ -119,7 +119,7 @@ the same features and performance, so choose the one you prefer: '_controller' => 'AppBundle:Blog:list', ])); // Matches /blog/* - // but not /blog/slug/extra-part + // but not /blog/slug/extra-part $routes->add('blog_show', new Route('/blog/{slug}', [ '_controller' => 'AppBundle:Blog:show', ])); @@ -253,8 +253,10 @@ To fix this, add a *requirement* that the ``{page}`` wildcard can *only* match n $routes = new RouteCollection(); $routes->add('blog_list', new Route('/blog/{page}', [ + // defaults '_controller' => 'AppBundle:Blog:list', ], [ + // requirements 'page' => '\d+' ])); @@ -347,10 +349,12 @@ So how can you make ``blog_list`` once again match when the user visits $routes->add('blog_list', new Route( '/blog/{page}', [ + // defaults '_controller' => 'AppBundle:Blog:list', 'page' => 1, ], [ + // requirements 'page' => '\d+' ] )); @@ -440,9 +444,11 @@ With all of this in mind, check out this advanced example: $routes->add( 'article_show', new Route('/articles/{_locale}/{year}/{slug}.{_format}', [ + // defaults '_controller' => 'AppBundle:Article:show', '_format' => 'html', ], [ + // requirements '_locale' => 'en|fr', '_format' => 'html|rss', 'year' => '\d+', diff --git a/service_container.rst b/service_container.rst index 0513559aaf9..b0298073182 100644 --- a/service_container.rst +++ b/service_container.rst @@ -210,11 +210,13 @@ each time you ask for it. https://symfony.com/schema/dic/services/services-1.0.xsd"> - + - - + + @@ -223,17 +225,23 @@ each time you ask for it. // app/config/services.php use Symfony\Component\DependencyInjection\Definition; - // To use as default template - $definition = new Definition(); - - $definition + // To use as default configuration for services in *this* file + $defaults = new Definition(); + $defaults ->setAutowired(true) ->setAutoconfigured(true) ->setPublic(false) ; // $this is a reference to the current loader - $this->registerClasses($definition, 'AppBundle\\', '../../src/AppBundle/*', '../../src/AppBundle/{Entity,Repository}'); + $this->registerClasses( + $defaults, + // makes classes in src/AppBundle available to be used as services + 'AppBundle\\', + '../../src/AppBundle/*', + // excludes some directory or files + '../../src/AppBundle/{Entity,Repository}' + ); .. tip:: @@ -457,9 +465,8 @@ pass here. No problem! In your configuration, you can explicitly set this argume # app/config/services.yml services: - # ... + # ... same as before - # same as before AppBundle\: resource: '../../src/AppBundle/*' exclude: '../../src/AppBundle/{Entity,Repository}' @@ -479,12 +486,13 @@ pass here. No problem! In your configuration, you can explicitly set this argume https://symfony.com/schema/dic/services/services-1.0.xsd"> - + - - + - + manager@example.com @@ -497,20 +505,21 @@ pass here. No problem! In your configuration, you can explicitly set this argume use AppBundle\Updates\SiteUpdateManager; use Symfony\Component\DependencyInjection\Definition; - // Same as before - $definition = new Definition(); - - $definition - ->setAutowired(true) - ->setAutoconfigured(true) - ->setPublic(false) - ; - - $this->registerClasses($definition, 'AppBundle\\', '../../src/AppBundle/*', '../../src/AppBundle/{Entity,Repository}'); + // ... same as before - // Explicitly configure the service + // $this is a reference to the current loader + $this->registerClasses( + $defaults, + 'AppBundle\\', + '../../src/AppBundle/*', + // excludes + '../../src/AppBundle/{Entity,Repository}' + ); + + // explicitly configure the service $container->getDefinition(SiteUpdateManager::class) - ->setArgument('$adminEmail', 'manager@example.com'); + ->setArgument('$adminEmail', 'manager@example.com') + ; .. versionadded:: 3.3 @@ -544,7 +553,7 @@ and reference it with the ``%parameter_name%`` syntax: admin_email: manager@example.com services: - # ... + # ... same as before AppBundle\Updates\SiteUpdateManager: arguments: @@ -564,7 +573,7 @@ and reference it with the ``%parameter_name%`` syntax: - + %admin_email% @@ -576,11 +585,14 @@ and reference it with the ``%parameter_name%`` syntax: // app/config/services.php use AppBundle\Updates\SiteUpdateManager; + + // ... same as before + $container->setParameter('admin_email', 'manager@example.com'); - $container->autowire(SiteUpdateManager::class) - // ... - ->setArgument('$adminEmail', '%admin_email%'); + $container->getDefinition(SiteUpdateManager::class) + ->setArgument('$adminEmail', '%admin_email%') + ; Actually, once you define a parameter, it can be referenced via the ``%parameter_name%`` syntax in *any* other service configuration file - like ``config.yml``. Many parameters @@ -671,7 +683,7 @@ But, you can control this and pass in a different logger: - + @@ -684,10 +696,12 @@ But, you can control this and pass in a different logger: use AppBundle\Service\MessageGenerator; use Symfony\Component\DependencyInjection\Reference; - $container->autowire(MessageGenerator::class) - ->setAutoconfigured(true) - ->setPublic(false) - ->setArgument('$logger', new Reference('monolog.logger.request')); + // ... same as before + + // explicitly configure the service + $container->getDefinition(MessageGenerator::class) + ->setArgument('$logger', new Reference('monolog.logger.request')) + ; This tells the container that the ``$logger`` argument to ``__construct`` should use service whose id is ``monolog.logger.request``. @@ -756,15 +770,26 @@ You can also use the ``bind`` keyword to bind specific arguments by name or type .. code-block:: php // config/services.php - use App\Controller\LuckyController; use Psr\Log\LoggerInterface; + use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; - $container->register(LuckyController::class) - ->setPublic(true) - ->setBindings([ + $defaults = new Definition(); + $defaults + ->setAutowired(true) + ->setAutoconfigured(true) + ->setPublic(false) + ->setBinds([ + // pass this value to any $adminEmail argument for any service + // that's defined in this file (including controller arguments) '$adminEmail' => 'manager@example.com', - '$requestLogger' => new Reference('monolog.logger.request'), + + // pass this service to any $requestLogger argument for any + // service that's defined in this file + '$requestLogger' => new Reference('@monolog.logger.request'), + + // pass this service for any LoggerInterface type-hint for any + // service that's defined in this file LoggerInterface::class => new Reference('monolog.logger.request'), ]) ; @@ -840,8 +865,10 @@ as a service, and :doc:`tag ` it with ``twig.extension` // app/config/services.php use AppBundle\Twig\MyTwigExtension; - $container->autowire(MyTwigExtension::class) - ->addTag('twig.extension'); + // ... + $container->getDefinition(MyTwigExtension::class) + ->addTag('twig.extension') + ; But, with ``autoconfigure: true``, you don't need the tag. In fact, if you're using the :ref:`Symfony Standard Edition services.yml config `, @@ -887,6 +914,21 @@ this file is ``public: false`` by default: + .. code-block:: php + + // app/config/services.php + setPublic(false) + ; + + What does this mean? When a service is **not** public, you cannot access it directly from the container:: @@ -932,6 +974,19 @@ need to make your service public, just override this setting: + .. code-block:: php + + // app/config/services.php + getDefinition(MessageGenerator::class) + ->setPublic(true) + ; + .. _service-psr4-loader: Importing Many Services at once with resource @@ -946,7 +1001,7 @@ key. For example, the default Symfony configuration contains this: # app/config/services.yml services: - # ... + # ... same as before # the namespace prefix for classes (must end in \) AppBundle\: @@ -955,11 +1010,10 @@ key. For example, the default Symfony configuration contains this: # ...except for the classes located in these directories exclude: '../../src/AppBundle/{Entity,Repository}' - # these were imported above, but we want to add some extra config + # these were imported above, but we want to add the tag AppBundle\Controller\: resource: '../../src/AppBundle/Controller' # apply some configuration to these services - public: true tags: ['controller.service_arguments'] .. code-block:: xml @@ -972,10 +1026,16 @@ key. For example, the default Symfony configuration contains this: https://symfony.com/schema/dic/services/services-1.0.xsd"> - + - + + + + @@ -985,27 +1045,27 @@ key. For example, the default Symfony configuration contains this: .. code-block:: php // app/config/services.php - use Symfony\Component\DependencyInjection\Definition; - - // To use as default template - $definition = new Definition(); - - $definition - ->setAutowired(true) - ->setAutoconfigured(true) - ->setPublic(false) - ; - - $this->registerClasses($definition, 'AppBundle\\', '../../src/AppBundle/*', '../../src/AppBundle/{Entity,Repository}'); - - // Changes default config - $definition - ->setPublic(true) - ->addTag('controller.service_arguments') - ; + // ... same as before // $this is a reference to the current loader - $this->registerClasses($definition, 'AppBundle\\Controller\\', '../../src/AppBundle/Controller/*'); + $this->registerClasses( + $defaults, + // the namespace prefix for classes (must end in \) + 'AppBundle\\', + // create services for all the classes found in this directory... + '../../src/AppBundle/*', + '../../src/AppBundle/{Entity,Repository}' + ); + + // changes default config + $defaults->addTag('controller.service_arguments'); + + // these were imported above, but we want to the tag + $this->registerClasses( + $defaults, + 'AppBundle\\Controller\\', + '../../src/AppBundle/Controller/*' + ); .. tip:: @@ -1045,30 +1105,119 @@ If you define services using the YAML config format, the PHP namespace is used as the key of each configuration, so you can't define different service configs for classes under the same namespace: -.. code-block:: yaml +.. configuration-block:: + + .. code-block:: yaml + + # app/config/services.yml + services: + AppBundle\Domain\: + resource: '../../src/AppBundleDomain/*' - # app/config/services.yml - services: - App\Domain\: - resource: '../../src/Domain/*' # ... + .. code-block:: xml + + + + + + + + + + + + + + .. code-block:: php + + // app/config/services.php + use Symfony\Component\DependencyInjection\Definition; + + $defaults = new Definition(); + + // $this is a reference to the current loader + $this->registerClasses( + $defaults, + 'AppBundle\\Domain\\', + '../../src/AppBundle/Domain/*' + ); + + // ... + In order to have multiple definitions, add the ``namespace`` option and use any unique string as the key of each service config: -.. code-block:: yaml +.. configuration-block:: - # app/config/services.yml - services: - command_handlers: - namespace: App\Domain\ - resource: '../../src/Domain/*/CommandHandler' - tags: [command_handler] + .. code-block:: yaml - event_subscribers: - namespace: App\Domain\ - resource: '../../src/Domain/*/EventSubscriber' - tags: [event_subscriber] + # app/config/services.yml + services: + command_handlers: + namespace: App\Domain\ + resource: '../../src/Domain/*/CommandHandler' + tags: [command_handler] + + event_subscribers: + namespace: App\Domain\ + resource: '../../src/Domain/*/EventSubscriber' + tags: [event_subscriber] + + # ... + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + .. code-block:: php + + // app/config/services.php + use Symfony\Component\DependencyInjection\Definition; + + $commandHandlers = new Definition(); + $commandHandlers->addTag('command_handler'); + + // $this is a reference to the current loader + $this->registerClasses( + $commandHandlers, + 'AppBundle\\Domain\\', + '../../src/AppBundle/Domain/*/CommandHandler' + ); + + $eventSubscribers = new Definition(); + $eventSubscribers->addTag('event_subscriber'); + + $this->registerClasses( + $eventSubscribers, + 'AppBundle\\Domain\\', + '../../src/AppBundle/Domain/*/EventSubscriber' + ); .. _services-explicitly-configure-wire-services: @@ -1127,18 +1276,26 @@ admin email. In this case, each needs to have a unique service id: - + + + superadmin@example.com - + contact@example.com + @@ -1150,13 +1307,17 @@ admin email. In this case, each needs to have a unique service id: use AppBundle\Updates\SiteUpdateManager; use Symfony\Component\DependencyInjection\Reference; + // register the service by its id $container->register('site_update_manager.superadmin', SiteUpdateManager::class) + // you CAN still use autowiring: we just want to show what it looks like without ->setAutowired(false) + // manually wire all arguments ->setArguments([ new Reference(MessageGenerator::class), new Reference('mailer'), 'superadmin@example.com' - ]); + ]) + ; $container->register('site_update_manager.normal_users', SiteUpdateManager::class) ->setAutowired(false) @@ -1164,8 +1325,11 @@ admin email. In this case, each needs to have a unique service id: new Reference(MessageGenerator::class), new Reference('mailer'), 'contact@example.com' - ]); + ]) + ; + // Create an alias, so that - by default - if you type-hint SiteUpdateManager, + // the site_update_manager.superadmin will be used $container->setAlias(SiteUpdateManager::class, 'site_update_manager.superadmin') In this case, *two* services are registered: ``site_update_manager.superadmin`` diff --git a/translation.rst b/translation.rst index 5c3ff5553ad..9a9effd3527 100644 --- a/translation.rst +++ b/translation.rst @@ -263,14 +263,14 @@ Sometimes, a message containing a variable needs to be translated:: public function indexAction($name) { - $translated = $this->get('translator')->trans('Hello '.$name); + $translated = $this->get('translator')->trans('Hello '.$name.'!'); // ... } However, creating a translation for this string is impossible since the translator will try to look up the exact message, including the variable portions -(e.g. *"Hello Ryan"* or *"Hello Fabien"*). Instead of writing a translation +(e.g. *"Hello Ryan!"* or *"Hello Fabien!"*). Instead of writing a translation for every possible iteration of the ``$name`` variable, you can replace the variable with a "placeholder":: @@ -291,7 +291,7 @@ is done just as before: .. code-block:: yaml - 'Hello %name%': Bonjour %name% + 'Hello %name%!': Bonjour %name% ! .. code-block:: xml @@ -300,8 +300,8 @@ is done just as before: - Hello %name% - Bonjour %name% + Hello %name%! + Bonjour %name% ! @@ -310,7 +310,7 @@ is done just as before: .. code-block:: php return [ - 'Hello %name%' => 'Bonjour %name%', + 'Hello %name%!' => 'Bonjour %name% !', ]; .. note:: @@ -717,8 +717,7 @@ if you're generating translations with specialized programs or teams. xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony - https://symfony.com/schema/dic/symfony/symfony-1.0.xsd" - > + https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> diff --git a/workflow.rst b/workflow.rst index 890225c6efd..82afcba8cb5 100644 --- a/workflow.rst +++ b/workflow.rst @@ -60,14 +60,17 @@ like this: + xsi:schemaLocation="http://symfony.com/schema/dic/services + https://symfony.com/schema/dic/services/services-1.0.xsd + http://symfony.com/schema/dic/symfony + https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> + + currentPlace @@ -102,8 +105,9 @@ like this: .. code-block:: php // app/config/config.php + use AppBundle\Entity\BlogPost; + $container->loadFromExtension('framework', [ - // ... 'workflows' => [ 'blog_publishing' => [ 'type' => 'workflow', // or 'state_machine' @@ -114,7 +118,7 @@ like this: 'type' => 'multiple_state', // or 'single_state' 'arguments' => ['currentPlace'] ], - 'supports' => ['AppBundle\Entity\BlogPost'], + 'supports' => [BlogPost::class], 'places' => [ 'draft', 'reviewed', @@ -163,8 +167,8 @@ As configured, the following property is used by the marking store:: configures the marking store according to the "type" by default, so it's preferable to not configure it. - A single state marking store uses a string to store the data. A multiple - state marking store uses an array to store the data. + A single state marking store uses a ``string`` to store the data. A multiple + state marking store uses an ``array`` to store the data. .. tip:: @@ -414,29 +418,109 @@ Alternatively, you can define a ``guard`` configuration option for the transition. The value of this option is any valid expression created with the :doc:`ExpressionLanguage component `: -.. code-block:: yaml - - # config/packages/workflow.yaml - framework: - workflows: - blog_publishing: - # previous configuration - transitions: - to_review: - # the transition is allowed only if the current user has the ROLE_REVIEWER role. - guard: "is_granted('ROLE_REVIEWER')" - from: draft - to: reviewed - publish: - # or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted" - guard: "is_authenticated" - from: reviewed - to: published - reject: - # or any valid expression language with "subject" referring to the post - guard: "has_role('ROLE_ADMIN') and subject.isStatusReviewed()" - from: reviewed - to: rejected +.. configuration-block:: + + .. code-block:: yaml + + # config/packages/workflow.yaml + framework: + workflows: + blog_publishing: + # ... previous configuration + + transitions: + to_review: + # the transition is allowed only if the current user has the ROLE_REVIEWER role. + guard: "is_granted('ROLE_REVIEWER')" + from: draft + to: reviewed + publish: + # or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted" + guard: "is_authenticated" + from: reviewed + to: published + reject: + # or any valid expression language with "subject" referring to the post + guard: "has_role('ROLE_ADMIN') and subject.isStatusReviewed()" + from: reviewed + to: rejected + + .. code-block:: xml + + + + + + + + + + + + + is_granted("ROLE_REVIEWER") + draft + reviewed + + + + + is_authenticated + reviewed + published + + + + + has_role("ROLE_ADMIN") and subject.isStatusReviewed() + reviewed + rejected + + + + + + + + .. code-block:: php + + // app/config/config.php + use AppBundle\Entity\BlogPost; + + $container->loadFromExtension('framework', [ + 'workflows' => [ + 'blog_publishing' => [ + // ... previous configuration + + 'transitions' => [ + 'to_review' => [ + // the transition is allowed only if the current user has the ROLE_REVIEWER role. + 'guard' => 'is_granted("ROLE_REVIEWER")', + 'from' => 'draft', + 'to' => 'reviewed', + ], + 'publish' => [ + // or "is_anonymous", "is_remember_me", "is_fully_authenticated", "is_granted" + 'guard' => 'is_authenticated', + 'from' => 'reviewed', + 'to' => 'published', + ], + 'reject' => [ + // or any valid expression language with "subject" referring to the post + 'guard' => 'has_role("ROLE_ADMIN") and subject.isStatusReviewed()', + 'from' => 'reviewed', + 'to' => 'rejected', + ], + ], + ], + ], + ]); Usage in Twig -------------