diff --git a/.doctor-rst.yaml b/.doctor-rst.yaml index 2ecd4fc7d2d..a0d74a57714 100644 --- a/.doctor-rst.yaml +++ b/.doctor-rst.yaml @@ -49,6 +49,7 @@ rules: no_namespace_after_use_statements: ~ no_php_open_tag_in_code_block_php_directive: ~ no_space_before_self_xml_closing_tag: ~ + no_typographic_quotes: ~ non_static_phpunit_assertions: ~ only_backslashes_in_namespace_in_php_code_block: ~ only_backslashes_in_use_statements_in_php_code_block: ~ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 497dfd9b430..fa36efbcbcf 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -72,7 +72,7 @@ jobs: key: ${{ runner.os }}-doctor-rst-${{ steps.extract_base_branch.outputs.branch }} - name: "Run DOCtor-RST" - uses: docker://oskarstark/doctor-rst:1.67.0 + uses: docker://oskarstark/doctor-rst:1.68.0 with: args: --short --error-format=github --cache-file=/github/workspace/.cache/doctor-rst.cache diff --git a/best_practices.rst b/best_practices.rst index b887d4d289a..6211d042f0b 100644 --- a/best_practices.rst +++ b/best_practices.rst @@ -95,7 +95,7 @@ Use Secrets for Sensitive Information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When your application has sensitive configuration, like an API key, you should -store those securely via :doc:`Symfony’s secrets management system `. +store those securely via :doc:`Symfony's secrets management system `. Use Parameters for Application Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/cache.rst b/cache.rst index 83bb5b4cedc..35f1404d42a 100644 --- a/cache.rst +++ b/cache.rst @@ -539,6 +539,8 @@ Symfony stores the item automatically in all the missing pools. ; }; +.. _cache-using-cache-tags: + Using Cache Tags ---------------- diff --git a/components/cache.rst b/components/cache.rst index 3c124c7d85e..44ba8b5c151 100644 --- a/components/cache.rst +++ b/components/cache.rst @@ -91,30 +91,61 @@ Creating Sub-Namespaces Cache sub-namespaces were introduced in Symfony 7.3. -All cache adapters provided by the component implement the -:class:`Symfony\\Contracts\\Cache\\NamespacedPoolInterface` to provide the -:method:`Symfony\\Contracts\\Cache\\NamespacedPoolInterface::withSubNamespace` method. -This method allows namespacing cached items by transparently prefixing their keys:: +Sometimes you need to create context-dependent variations of data that should be +cached. For example, the data used to render a dashboard page may be expensive +to generate and unique per user, so you can't cache the same data for everyone. - $subCache = $cache->withSubNamespace('foo'); +In such cases, Symfony allows you to create different cache contexts using +namespaces. A cache namespace is an arbitrary string that identifies a set of +related cache items. All cache adapters provided by the component implement the +:class:`Symfony\\Contracts\\Cache\\NamespacedPoolInterface`, which provides the +:method:`Symfony\\Contracts\\Cache\\NamespacedPoolInterface::withSubNamespace` +method. - $subCache->get('my_cache_key', function (ItemInterface $item): string { +This method allows you to namespace cached items by transparently prefixing their keys:: + + $userCache = $cache->withSubNamespace(sprintf('user-%d', $user->getId())); + + $userCache->get('dashboard_data', function (ItemInterface $item): string { $item->expiresAfter(3600); return '...'; }); -In this example, the cache item will use the ``my_cache_key`` key, but it will be -stored internally under the ``foo`` namespace. This is handled transparently for -you, so you **don't** need to manually prefix keys like ``foo.my_cache_key``. +In this example, the cache item uses the ``dashboard_data`` key, but it will be +stored internally under a namespace based on the current user ID. This is handled +automatically, so you **don't** need to manually prefix keys like ``user-27.dashboard_data``. -This is useful when using namespace-based cache invalidation to isolate or -invalidate a subset of cached data based on some context. Typical examples -include namespacing by user ID, locale, or entity ID and hash:: +There are no guidelines or restrictions on how to define cache namespaces. +You can make them as granular or as generic as your application requires:: - $userCache = $cache->withSubNamespace((string) $userId); $localeCache = $cache->withSubNamespace($request->getLocale()); - $productCache = $cache->withSubNamespace($productId.'_'.$productChecksum); + + $flagCache = $cache->withSubNamespace( + $featureToggle->isEnabled('new_checkout') ? 'checkout-v2' : 'checkout-v1' + ); + + $channel = $request->attributes->get('_route')?->startsWith('api_') ? 'api' : 'web'; + $channelCache = $cache->withSubNamespace($channel); + +.. tip:: + + You can combine cache namespaces with :ref:`cache tags ` + for more advanced needs. + +There is no built-in way to invalidate caches by namespace. Instead, the recommended +approach is to change the namespace itself. For this reason, it's common to include +static or dynamic versioning data in the cache namespace:: + + // for simple applications, an incrementing static version number may be enough + $userCache = $cache->withSubNamespace(sprintf('v1-user-%d', $user->getId())); + + // other applications may use dynamic versioning based on the date (e.g. monthly) + $userCache = $cache->withSubNamespace(sprintf('%s-user-%d', date('Ym'), $user->getId())); + + // or even invalidate the cache when the user data changes + $checksum = hash('xxh128', $user->getUpdatedAt()->format(DATE_ATOM)); + $userCache = $cache->withSubNamespace(sprintf('user-%d-%s', $user->getId(), $checksum)); .. _cache_stampede-prevention: diff --git a/components/config/caching.rst b/components/config/caching.rst index 18620c0d8cf..80e23a4fdfb 100644 --- a/components/config/caching.rst +++ b/components/config/caching.rst @@ -3,7 +3,7 @@ Caching based on Resources When all configuration resources are loaded, you may want to process the configuration values and combine them all in one file. This file acts -like a cache. Its contents don’t have to be regenerated every time the +like a cache. Its contents don't have to be regenerated every time the application runs – only when the configuration resources are modified. For example, the Symfony Routing component allows you to load all routes, diff --git a/components/dependency_injection.rst b/components/dependency_injection.rst index 93e8af711cf..d146f553a0c 100644 --- a/components/dependency_injection.rst +++ b/components/dependency_injection.rst @@ -180,16 +180,16 @@ You can override this behavior as follows:: These are all the possible behaviors: - * ``ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE``: throws an exception - at compile time (this is the **default** behavior); - * ``ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE``: throws an - exception at runtime, when trying to access the missing service; - * ``ContainerInterface::NULL_ON_INVALID_REFERENCE``: returns ``null``; - * ``ContainerInterface::IGNORE_ON_INVALID_REFERENCE``: ignores the wrapping - command asking for the reference (for instance, ignore a setter if the service - does not exist); - * ``ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE``: ignores/returns - ``null`` for uninitialized services or invalid references. +* ``ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE``: throws an exception + at compile time (this is the **default** behavior); +* ``ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE``: throws an + exception at runtime, when trying to access the missing service; +* ``ContainerInterface::NULL_ON_INVALID_REFERENCE``: returns ``null``; +* ``ContainerInterface::IGNORE_ON_INVALID_REFERENCE``: ignores the wrapping + command asking for the reference (for instance, ignore a setter if the service + does not exist); +* ``ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE``: ignores/returns + ``null`` for uninitialized services or invalid references. Avoiding your Code Becoming Dependent on the Container ------------------------------------------------------ diff --git a/contributing/code_of_conduct/code_of_conduct.rst b/contributing/code_of_conduct/code_of_conduct.rst index 6202fdad424..ce14dd5ad0e 100644 --- a/contributing/code_of_conduct/code_of_conduct.rst +++ b/contributing/code_of_conduct/code_of_conduct.rst @@ -34,7 +34,7 @@ Examples of unacceptable behavior include: any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment -* Publishing others’ private information, such as a physical or email address, +* Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting @@ -128,7 +128,7 @@ Attribution This Code of Conduct is adapted from the `Contributor Covenant`_, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html -Community Impact Guidelines were inspired by `Mozilla’s code of conduct enforcement ladder`_. +Community Impact Guidelines were inspired by `Mozilla's code of conduct enforcement ladder`_. Related Documents ----------------- @@ -141,4 +141,4 @@ Related Documents concrete_example_document .. _Contributor Covenant: https://www.contributor-covenant.org -.. _Mozilla’s code of conduct enforcement ladder: https://github.com/mozilla/diversity +.. _Mozilla's code of conduct enforcement ladder: https://github.com/mozilla/diversity diff --git a/contributing/code_of_conduct/concrete_example_document.rst b/contributing/code_of_conduct/concrete_example_document.rst index 60ffe2527db..227a41df4a8 100644 --- a/contributing/code_of_conduct/concrete_example_document.rst +++ b/contributing/code_of_conduct/concrete_example_document.rst @@ -9,7 +9,7 @@ according to the Symfony code of conduct. Concrete Examples ----------------- -* Unwelcome comments regarding a person’s lifestyle choices and practices, +* Unwelcome comments regarding a person's lifestyle choices and practices, including those related to food, health, parenting, drugs, and employment; * Deliberate misgendering or use of `dead names`_ (The birth name of a person who has since changed their name, often a transgender person); diff --git a/contributing/community/review-comments.rst b/contributing/community/review-comments.rst index 5b9bc932205..331352bb5fd 100644 --- a/contributing/community/review-comments.rst +++ b/contributing/community/review-comments.rst @@ -28,7 +28,7 @@ constructive, respectful and helpful reviews and replies. welcoming place for everyone. **You are free to disagree with someone's opinions, but don't be disrespectful.** -It’s important to accept that many programming decisions are opinions. +It's important to accept that many programming decisions are opinions. Discuss trade-offs, which you prefer, and reach a resolution quickly. It's not about being right or wrong, but using what works. diff --git a/contributing/core_team.rst b/contributing/core_team.rst index 7b3d667a14b..d776cd4ed93 100644 --- a/contributing/core_team.rst +++ b/contributing/core_team.rst @@ -197,7 +197,7 @@ Pull Request Merging Policy A pull request **can be merged** if: -* It is a :ref:`unsubstantial change `; +* It is an :ref:`unsubstantial change `; * Enough time was given for peer reviews; * It is a bug fix and at least two **Mergers Team** members voted ``+1`` (only one if the submitter is part of the Mergers team) and no Core diff --git a/contributing/diversity/further_reading.rst b/contributing/diversity/further_reading.rst index 8bb07c39c97..b5f44047159 100644 --- a/contributing/diversity/further_reading.rst +++ b/contributing/diversity/further_reading.rst @@ -9,7 +9,7 @@ Diversity in Open Source `Sage Sharp - What makes a good community? `_ `Ashe Dryden - The Ethics of Unpaid Labor and the OSS Community `_ `Model View Culture - The Dehumanizing Myth of the Meritocracy `_ -`Annalee - How “Good Intent” Undermines Diversity and Inclusion `_ +`Annalee - How "Good Intent" Undermines Diversity and Inclusion `_ `Karolina Szczur - Building Inclusive Communities `_ Code of Conduct @@ -22,7 +22,7 @@ Code of Conduct Inclusive language ------------------ -`Jenée Desmond-Harris - Why I’m finally convinced it's time to stop saying "you guys" `_ +`Jenée Desmond-Harris - Why I'm finally convinced it's time to stop saying "you guys" `_ `inclusive language presentations `_ Other talks and Blog Posts @@ -30,7 +30,7 @@ Other talks and Blog Posts `Lena Reinhard – A Talk About Nothing `_ `Lena Reinhard - A Talk about Everything `_ -`Sage Sharp - SCALE: Improving Diversity with Maslow’s hierarchy `_ +`Sage Sharp - SCALE: Improving Diversity with Maslow's hierarchy `_ `UCSF - Unconscious Bias `_ `Responding to harassment reports `_ `Unconscious bias at work `_ diff --git a/http_client.rst b/http_client.rst index 30379f9a3b3..014fd0f4aa3 100644 --- a/http_client.rst +++ b/http_client.rst @@ -891,7 +891,7 @@ in your requests:: 'extra' => ['trace_content' => false], ]); -This setting won’t affect other clients. +This setting won't affect other clients. Using URI Templates ~~~~~~~~~~~~~~~~~~~ diff --git a/scheduler.rst b/scheduler.rst index 765f60e156a..59dfa121361 100644 --- a/scheduler.rst +++ b/scheduler.rst @@ -579,7 +579,7 @@ In your handler, you can check a condition and, if affirmative, access the { public function getSchedule(): Schedule { - $this->removeOldReports = RecurringMessage::cron(‘3 8 * * 1’, new CleanUpOldSalesReport()); + $this->removeOldReports = RecurringMessage::cron('3 8 * * 1', new CleanUpOldSalesReport()); return $this->schedule ??= (new Schedule()) ->with(