<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Maico Orazio</title>
    <description>The latest articles on Forem by Maico Orazio (@mainick).</description>
    <link>https://forem.com/mainick</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F52402%2F513628e5-8cbc-459f-bafc-79a50c71e8d4.jpg</url>
      <title>Forem: Maico Orazio</title>
      <link>https://forem.com/mainick</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mainick"/>
    <language>en</language>
    <item>
      <title>Using Symfony Messenger to Manage Message Queues in Symfony</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Mon, 06 May 2024 12:37:02 +0000</pubDate>
      <link>https://forem.com/mainick/using-symfony-messenger-to-manage-message-queues-in-symfony-2o68</link>
      <guid>https://forem.com/mainick/using-symfony-messenger-to-manage-message-queues-in-symfony-2o68</guid>
      <description>&lt;p&gt;&lt;strong&gt;Symfony&lt;/strong&gt;, the famous PHP framework, offers a wide range of powerful tools and components for developers of all levels. One of these tools is &lt;strong&gt;Symfony Messenger&lt;/strong&gt;, a bundle that &lt;strong&gt;greatly simplifies message handling within Symfony applications&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Symfony Messenger?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://symfony.com/doc/current/messenger.html"&gt;Symfony Messenger&lt;/a&gt; is a bundle that provides everything you need to consume messages from a message queue. &lt;strong&gt;This approach is extremely useful for improving the performance of our applications by allowing us to separate heavy tasks and handle them through a separate worker&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of Message Queuing
&lt;/h3&gt;

&lt;p&gt;Message queuing allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Improve application performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handle heavy tasks asynchronously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain a fast response time for users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are not familiar with message queuing, I recommend delving into the topic to fully understand its benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case
&lt;/h2&gt;

&lt;p&gt;To better understand the usefulness of Symfony Messenger, let's consider a common use case: managing orders and shipments in an application.&lt;/p&gt;

&lt;p&gt;Let's imagine having to perform several tasks every time an order is updated, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Updating the order status on the website.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sending a confirmation email to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perhaps, sending a notification via SMS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Executing other internal scripts.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these tasks require calls to different services, which can take a lot of time, and our goal is to have the shortest response time possible.&lt;/p&gt;

&lt;p&gt;By using Symfony Messenger, we could &lt;strong&gt;delegate these tasks to a separate worker&lt;/strong&gt;, significantly improving the overall performance of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction and Installation
&lt;/h2&gt;

&lt;p&gt;To start using Symfony Messenger, we need to first install the package via Composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require symfony/messenger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This package provides everything needed to create and manage messages and message handlers within our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Messages and Handlers
&lt;/h2&gt;

&lt;p&gt;The core of Symfony Messenger revolves around messages and message handlers. &lt;strong&gt;A message represents the data to be processed, while a message handler contains the logic to process that message&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, suppose we need to send a registration confirmation email to a user who has just registered on our site. We will create a message called &lt;code&gt;SendRegistrationEmailMessage&lt;/code&gt; which will contain the user ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendRegistrationEmailMessage&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$userId&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getUserId&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of executing everything at the exact moment the registration request is sent, we will queue a message containing the user ID. This way, our controller no longer needs to handle an exception, and we could send a "OK" (200) response much faster.&lt;/p&gt;

&lt;p&gt;Next, we will create a message handler called &lt;code&gt;SendRegistrationEmailMessageHandler&lt;/code&gt; that will retrieve the user from the ID and send the confirmation email.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\MessageHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Entity\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Messenger\Attribute\AsMessageHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="na"&gt;#[AsMessageHandler]&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendRegistrationEmailMessageHandler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;EntityManagerInterface&lt;/span&gt; &lt;span class="nv"&gt;$entityManager&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SendRegistrationEmailMessage&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUserId&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="k"&gt;instanceOf&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Handle entity not found case&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Send the email&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Symfony Messenger simplifies this process, allowing us to focus on business logic without worrying about implementation details.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Let's see how.
&lt;/h3&gt;

&lt;p&gt;Symfony Messenger comes with a PHP attribute &lt;code&gt;#[AsMessageHandler]&lt;/code&gt;, so that Symfony considers this service as a message handler to route the correct messages to.&lt;/p&gt;

&lt;p&gt;The type of the message to consume is declared in the &lt;code&gt;__invoke&lt;/code&gt; method.&lt;br&gt;
This means that for each message, we should create a message handler, with the correct type in the &lt;code&gt;__invoke&lt;/code&gt; method, and the routing will be handled automatically by Symfony.&lt;/p&gt;
&lt;h2&gt;
  
  
  Message Transport and Routing
&lt;/h2&gt;

&lt;p&gt;Symfony Messenger supports various types of transports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AMQP&lt;/strong&gt; services (like RabbitMQ). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Doctrine&lt;/strong&gt; (storing messages in an SQL table).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cache services (like &lt;strong&gt;Redis&lt;/strong&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First of all, if we intend to use an AMQP protocol, we need to install the package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; composer require symfony/amqp-messenger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we intend to use Doctrine, we need to install the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; composer require symfony/doctrine-messenger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, if we want to use Redis as our transport, this is the package we need to install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; composere require symfony/redis-messenger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to learn more about other transports, you can take a look at the &lt;a href="https://symfony.com/doc/current/messenger.html#transport-configuration"&gt;relevant documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We can easily configure the desired transport in the &lt;code&gt;messenger.yaml&lt;/code&gt; configuration file, which we will find in &lt;code&gt;config/packages&lt;/code&gt; along with all the other configuration files of installed packages.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;transport&lt;/code&gt; key contains all the configuration regarding message handling (consumption).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;failure-transport&lt;/code&gt; key contains the name of the transport to be used in case of issues (exception thrown during handling).&lt;br&gt;
If something goes wrong here, the stack trace and exception details will be saved in the message and can be retrieved later to be properly handled.&lt;/p&gt;

&lt;p&gt;We can also configure the consumer to perform x retries before sending an error message to the "&lt;em&gt;failed&lt;/em&gt;" queue and manage different priorities for each queue.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;routing&lt;/code&gt; part explains how to route a specific instance of the message to the transport.&lt;/p&gt;

&lt;p&gt;Here is an example of how our configuration file for the above case might look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;framework&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;messenger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;transports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;registration_email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;dsn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%env(MESSENGER_TRANSPORT_DSN)%'&lt;/span&gt;
                &lt;span class="na"&gt;failure_transport&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registration_email_failed&lt;/span&gt;
                &lt;span class="na"&gt;retry_strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;max_retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
                    &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;
                    &lt;span class="na"&gt;multiplier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
                    &lt;span class="na"&gt;max_delay&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
                &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;exchange&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registration_email&lt;/span&gt;
                    &lt;span class="na"&gt;queues&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                        &lt;span class="na"&gt;registration_email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~&lt;/span&gt;

            &lt;span class="na"&gt;registration_email_failed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;dsn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%env(MESSENGER_TRANSPORT_DSN)%'&lt;/span&gt;
                &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                    &lt;span class="na"&gt;exchange&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registration_email_failed&lt;/span&gt;
                    &lt;span class="na"&gt;queues&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                        &lt;span class="na"&gt;registration_email_failed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~&lt;/span&gt;

        &lt;span class="na"&gt;routing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;App\Message\SendRegistrationEmailMessage'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;registration_email&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dispatching the Message
&lt;/h2&gt;

&lt;p&gt;Dispatching a message is as simple as calling the &lt;code&gt;MessageBus&lt;/code&gt; service provided by Symfony Messenger and passing the message to dispatch. The bus will take care of the rest, routing the message to the appropriate handler for processing.&lt;/p&gt;

&lt;p&gt;Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Message\SendEMailRegistrationEmailMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyExampleService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;MessageBusInterface&lt;/span&gt; &lt;span class="nv"&gt;$messageBus&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Any logic...&lt;/span&gt;

        &lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SendEMailRegistrationEmailMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;# This will dispatch the message to the correct transport&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;messageBus&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The architecture of Symfony Messenger is well-structured and involves the use of a publisher (controller, service, command, etc.) that sends a message to the bus. If the bus is synchronous, the message is consumed directly by a handler. If the bus is asynchronous, the message is sent via a transport to a queuing system, where it is processed by a separate worker.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the transport is asynchronous, the &lt;strong&gt;message must be serialized in order to be interpreted and consumed correctly by the worker&lt;/strong&gt;. Symfony natively supports two serialization modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;PHP's native serialization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Serialization via the &lt;a href="https://symfony.com/doc/current/components/serializer.html"&gt;Serializer component&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default, PHP's native serialization is used, which &lt;strong&gt;represents the class itself of the message&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If another application consumes the same message queue, it may not have this class, so it will be impossible to deserialize the message. For this reason, we will use a more traditional exchange format. Usually JSON, but we could use XML, Protobuf, or any other &lt;strong&gt;interoperable serialization&lt;/strong&gt; language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Symfony Messenger is a powerful tool for message handling within Symfony applications. With its support for various transport types and its simple architecture, it allows us to improve application performance and provide a better user experience.&lt;/p&gt;

&lt;p&gt;I hope this article has provided you with a comprehensive overview of Symfony Messenger and inspired you to use it in your future Symfony applications! If you want to receive updates on future articles, feel free to follow my account on Medium!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good work! 👨‍💻&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>symfony</category>
      <category>symfonymessenger</category>
      <category>php</category>
    </item>
    <item>
      <title>KeycloakClientBundle 2.0: added integration with Symfony's Security component</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Wed, 24 Apr 2024 08:19:37 +0000</pubDate>
      <link>https://forem.com/mainick/release-announcement-keycloakclientbundle-v20-3oga</link>
      <guid>https://forem.com/mainick/release-announcement-keycloakclientbundle-v20-3oga</guid>
      <description>&lt;p&gt;I am thrilled to announce the long-awaited release of version v2.0 of my Symfony bundle for Keycloak authentication, the &lt;strong&gt;KeycloakClientBundle&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;In this new release, I has introduced a series of significant improvements, with a particular focus on integration with &lt;strong&gt;Symfony's Security component&lt;/strong&gt;. &lt;a href="https://symfony.com/components/Security%20Bundle"&gt;Symfony's Security component&lt;/a&gt; offers a powerful and flexible framework for managing &lt;strong&gt;authentication&lt;/strong&gt;, &lt;strong&gt;authorization&lt;/strong&gt;, and other &lt;strong&gt;security aspects in Symfony applications&lt;/strong&gt;. With KeycloakClientBundle v2.0, I has made it possible to directly integrate with Symfony's Security component for protecting the application's UI using &lt;strong&gt;the OAuth 2 authorization code flow&lt;/strong&gt;. Now, you can enable Keycloak authentication directly through Symfony's firewall, leveraging the powerful security management features offered by the Security component.&lt;/p&gt;

&lt;p&gt;Here are some of the key benefits and features of KeycloakClientBundle v2.0:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Full integration with Symfony's Security component&lt;/strong&gt;: Enable Keycloak authentication through Symfony's firewall, using the OAuth 2 authorization code flow to protect the application's UI.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance enhancements&lt;/strong&gt;: Optimizations to ensure greater efficiency and speed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bug fixes&lt;/strong&gt;: Resolving issues reported by the community for an even more stable experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can't wait for you to try out all the new features and improvements we've introduced in this version. For more information and to contribute to the project KeycloakClientBundle, visit our &lt;a href="https://github.com/mainick/KeycloakClientBundle"&gt;GitHub repository&lt;/a&gt; today!&lt;/p&gt;

&lt;p&gt;Thank you for your continued support and feedback. Stay tuned for further updates and future developments!&lt;/p&gt;

</description>
      <category>symfony</category>
      <category>keycloak</category>
      <category>oauth</category>
      <category>php</category>
    </item>
    <item>
      <title>DTO vs VO in PHP</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Sat, 10 Feb 2024 18:01:13 +0000</pubDate>
      <link>https://forem.com/mainick/dto-vs-vo-in-php-4adi</link>
      <guid>https://forem.com/mainick/dto-vs-vo-in-php-4adi</guid>
      <description>&lt;p&gt;&lt;strong&gt;Data Transfer Objects (DTOs)&lt;/strong&gt; and &lt;strong&gt;Value Objects (VOs)&lt;/strong&gt; are particularly useful when working with dynamically typed languages like PHP, where switching to the use of more structured types is essential to improve the quality of our applications, as well as the readability of the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a DTO (Data Transfer Object)?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A DTO is an object that contains data and defines the structure of that data. The schema is defined by the names of the fields and their types.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It can only guarantee that all or some data are present, simply by relying on the rigidity of the programming language: if a constructor has a required string type parameter, you must pass a string to instantiate the object. However, &lt;strong&gt;a DTO does not provide any guarantee on the validity of that data&lt;/strong&gt;: strings could be empty, integers could be negative, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ADtoExample&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
   What is a VO (Value Object)?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A VO is an object that provides a guarantee of validity on the data it contains. They are immutable representations of data, aware of the specific domain business rules.&lt;/strong&gt; They help us write more robust and readable code, minimizing bugs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A value object is an object that represents a concept in the domain of an application. It is immutable, has no identity, and encapsulates a value.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnVoExample&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fromValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;\InvalidArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'value is empty'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A VO offers several advantages, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain specificity:&lt;/strong&gt; They can be used to represent domain-specific values. For example, the EmailAddress class can be used to represent only email addresses. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error reduction:&lt;/strong&gt; They help to reduce errors because they encapsulate values and apply business rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better clarity:&lt;/strong&gt; They make the code clearer and more understandable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better testability:&lt;/strong&gt; They are easier to test than primitive data types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;While a DTO deals with the structure of data, a VO also provides proof that the data meets expectations.&lt;/strong&gt; When the VO class is used as a parameter, property, or return type, we know that we are dealing with a valid value.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use these types of objects?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  DTO
&lt;/h3&gt;

&lt;p&gt;A DTO should only be used in two places: where data &lt;em&gt;enters the application&lt;/em&gt; or where data &lt;em&gt;leaves the application&lt;/em&gt;. They help to encapsulate data, making it easier to manipulate and pass between different parts of the codebase.&lt;/p&gt;

&lt;p&gt;Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a controller receives an HTTP POST request, the request data can be in any form: we can use a DTO to have the data with a known schema (keys and types verified).&lt;/li&gt;
&lt;li&gt;When we make an HTTP POST request to a web service: we can first collect the input data in a DTO and then serialize it into a request body that our HTTP client can send to the service.&lt;/li&gt;
&lt;li&gt;For queries: we can use a DTO to represent the query result.&lt;/li&gt;
&lt;li&gt;When we receive an HTTP GET request: we can first deserialize the API response into a DTO, so that we can apply a known schema to it instead of accessing the array keys directly and guessing the types.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  VO
&lt;/h3&gt;

&lt;p&gt;A VO is used whenever we want to verify that a value meets our expectations and do not want to verify it again.&lt;/p&gt;

&lt;p&gt;They are particularly useful for representing the input and output data of an API. In this way, we can be sure that the data received from the API is valid and that the data sent to the API is correct.&lt;/p&gt;

&lt;p&gt;We can also use it to create behaviors related to a particular value. For example, if we have a VO EmailAddress, we know that the value has already been verified to be a valid email address, so we do not need to check it again in other places. We can also add methods to the object that extract, for example, the username or hostname from the email address.&lt;/p&gt;

&lt;p&gt;Let's take an example of an application where we need to manage prices. Without the use of VOs, our code might be full of functions that receive values (such as number amount and string currency) and each of them would have to repeat validation on the values to prevent errors. Skimping on these checks makes your code cleaner but introduces the risk of bugs. This is where VOs shine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Currency&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Dollar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'USD'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Euro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'EUR'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Price&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Stringable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;Currency&lt;/span&gt; &lt;span class="nv"&gt;$currency&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InvalidPriceAmountException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'amount is negative'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__toString&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;number_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getAmount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getCurrency&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'$'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Invalid Argument Exception&lt;/span&gt;
&lt;span class="nv"&gt;$price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Currency&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nc"&gt;Dollar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// InvalidPriceAmountException&lt;/span&gt;

&lt;span class="nv"&gt;$price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;29.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Currency&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nc"&gt;Dollar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 29.99 USD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time you want to represent a price in your code, you can create a Price VO and trust the internal validation performed during instantiation. This means that for the lifecycle of that object in your code, you don't need to revalidate it wherever it's passed between functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;In conclusion, DTO and VO are &lt;strong&gt;two design patterns that are useful for improving code quality and readability&lt;/strong&gt; in PHP.&lt;/p&gt;

&lt;p&gt;DTOs are objects that contain data and define the structure of that data. They are useful for transferring data between different parts of an application.&lt;/p&gt;

&lt;p&gt;VOs are objects that provide assurance of data validity. They are useful for representing domain-specific values and applying business rules.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good work! 👨‍💻&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>php</category>
      <category>dto</category>
      <category>cleancoding</category>
    </item>
    <item>
      <title>KeycloakClientBundle: A Symfony Bundle for Integrating with Keycloak</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Sat, 14 Oct 2023 10:03:35 +0000</pubDate>
      <link>https://forem.com/mainick/keycloakclientbundle-a-symfony-bundle-for-integrating-with-keycloak-3el3</link>
      <guid>https://forem.com/mainick/keycloakclientbundle-a-symfony-bundle-for-integrating-with-keycloak-3el3</guid>
      <description>&lt;p&gt;&lt;strong&gt;Keycloak&lt;/strong&gt; is an open source identity and access management (IAM) solution that provides &lt;strong&gt;single sign-on&lt;/strong&gt; (SSO), &lt;strong&gt;user management&lt;/strong&gt;, and &lt;strong&gt;role-based access control&lt;/strong&gt; (RBAC). It is a popular choice for &lt;strong&gt;enterprise applications&lt;/strong&gt; that need to securely manage user access.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;KeycloakClientBundle is a Symfony bundle&lt;/strong&gt; that makes it easy to integrate your Symfony application with Keycloak.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It provides a set of services and classes that allow you to &lt;strong&gt;authenticate users&lt;/strong&gt; against Keycloak, &lt;strong&gt;retrieve user information&lt;/strong&gt;, and &lt;strong&gt;manage user roles&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;KeycloakClientBundle includes the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User authentication&lt;/strong&gt;: The bundle provides a service that allows you to authenticate users against Keycloak.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User information&lt;/strong&gt;: The bundle provides a service that allows you to retrieve user information from Keycloak.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User roles&lt;/strong&gt;: The bundle provides a service that allows you to manage user roles in Keycloak.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please refer to the documentation on the repository page for how to proceed with installation and use. &lt;/p&gt;

&lt;p&gt;Learn more and contribute to the &lt;a href="https://github.com/mainick/KeycloakClientBundle"&gt;project on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>symfony</category>
      <category>keycloak</category>
      <category>oauth</category>
      <category>php</category>
    </item>
    <item>
      <title>Date Analysis Using date_parse() and date_parse_from_format() Functions</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Mon, 09 Oct 2023 15:30:00 +0000</pubDate>
      <link>https://forem.com/mainick/date-analysis-using-dateparse-and-dateparsefromformat-functions-2mdh</link>
      <guid>https://forem.com/mainick/date-analysis-using-dateparse-and-dateparsefromformat-functions-2mdh</guid>
      <description>&lt;p&gt;The &lt;strong&gt;&lt;code&gt;date_parse()&lt;/code&gt; function&lt;/strong&gt; is used to obtain detailed information about a specific date.&lt;/p&gt;

&lt;p&gt;This function returns an associative array containing more details about the parsed date, or it returns &lt;code&gt;false&lt;/code&gt; in case of an error. It accepts a single argument specifying the date in a format accepted by the &lt;code&gt;strtotime()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$date_parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date_parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2023-06-22T07:30:09+01:00'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$date_parsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example given above returns the following information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Array
&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;year] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 2023
    &lt;span class="o"&gt;[&lt;/span&gt;month] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 6
    &lt;span class="o"&gt;[&lt;/span&gt;day] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 22
    &lt;span class="o"&gt;[&lt;/span&gt;hour] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 7
    &lt;span class="o"&gt;[&lt;/span&gt;minute] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 30
    &lt;span class="o"&gt;[&lt;/span&gt;second] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 9
    &lt;span class="o"&gt;[&lt;/span&gt;fraction] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
    &lt;span class="o"&gt;[&lt;/span&gt;warning_count] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
    &lt;span class="o"&gt;[&lt;/span&gt;warnings] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Array
        &lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="o"&gt;[&lt;/span&gt;error_count] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
    &lt;span class="o"&gt;[&lt;/span&gt;errors] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Array
        &lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="o"&gt;[&lt;/span&gt;is_localtime] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 1
    &lt;span class="o"&gt;[&lt;/span&gt;zone_type] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 1
    &lt;span class="o"&gt;[&lt;/span&gt;zone] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 3600
    &lt;span class="o"&gt;[&lt;/span&gt;is_dst] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can perform date analysis starting from a specific format.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;date_parse_from_format()&lt;/code&gt; function&lt;/strong&gt; is used to obtain detailed information about the specified date based on the specified format.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;date_parse_from_format()&lt;/code&gt; function accepts, as its first argument, a string representing the format and then the date. It returns, like &lt;code&gt;date_parse()&lt;/code&gt;, an associative array of detailed information about the date in the specified format, or it returns &lt;code&gt;false&lt;/code&gt; in case of an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$date_parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date_parse_from_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'d/m/Y H:i:s T'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'22/06/2023 07:30:09 Europe/Rome'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$date_parsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example given above returns the following information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Array
&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;year] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 2023
    &lt;span class="o"&gt;[&lt;/span&gt;month] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 6
    &lt;span class="o"&gt;[&lt;/span&gt;day] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 22
    &lt;span class="o"&gt;[&lt;/span&gt;hour] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 7
    &lt;span class="o"&gt;[&lt;/span&gt;minute] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 30
    &lt;span class="o"&gt;[&lt;/span&gt;second] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 9
    &lt;span class="o"&gt;[&lt;/span&gt;fraction] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
    &lt;span class="o"&gt;[&lt;/span&gt;warning_count] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
    &lt;span class="o"&gt;[&lt;/span&gt;warnings] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Array
        &lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="o"&gt;[&lt;/span&gt;error_count] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
    &lt;span class="o"&gt;[&lt;/span&gt;errors] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Array
        &lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="o"&gt;[&lt;/span&gt;is_localtime] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 1
    &lt;span class="o"&gt;[&lt;/span&gt;zone_type] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 3
    &lt;span class="o"&gt;[&lt;/span&gt;tz_id] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Europe/Rome
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try to specify an incorrect format, we get an incorrect result where the related errors are also listed in &lt;code&gt;errors&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$date_parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date_parse_from_format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y-m-d H:i:s T'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'22/06/2023 07:30:09 Europe/Rome'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$date_parsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Array
&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;year] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 22
    &lt;span class="o"&gt;[&lt;/span&gt;month] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 6
    &lt;span class="o"&gt;[&lt;/span&gt;day] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 20
    &lt;span class="o"&gt;[&lt;/span&gt;hour] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 23
    &lt;span class="o"&gt;[&lt;/span&gt;minute] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 7
    &lt;span class="o"&gt;[&lt;/span&gt;second] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 30
    &lt;span class="o"&gt;[&lt;/span&gt;fraction] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
    &lt;span class="o"&gt;[&lt;/span&gt;warning_count] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
    &lt;span class="o"&gt;[&lt;/span&gt;warnings] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Array
        &lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="o"&gt;[&lt;/span&gt;error_count] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 8
    &lt;span class="o"&gt;[&lt;/span&gt;errors] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Array
        &lt;span class="o"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;[&lt;/span&gt;2] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Unexpected data found.
            &lt;span class="o"&gt;[&lt;/span&gt;5] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Unexpected data found.
            &lt;span class="o"&gt;[&lt;/span&gt;10] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Unexpected data found.
            &lt;span class="o"&gt;[&lt;/span&gt;16] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; Trailing data
        &lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="o"&gt;[&lt;/span&gt;is_localtime] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 1
    &lt;span class="o"&gt;[&lt;/span&gt;zone_type] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 0
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Good work 👨‍💻&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>php</category>
      <category>date</category>
    </item>
    <item>
      <title>In PHP, function parameters</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Fri, 06 Oct 2023 15:30:00 +0000</pubDate>
      <link>https://forem.com/mainick/in-php-function-parameters-3ne0</link>
      <guid>https://forem.com/mainick/in-php-function-parameters-3ne0</guid>
      <description>&lt;p&gt;In this article, we will discuss &lt;strong&gt;function arguments&lt;/strong&gt;, &lt;strong&gt;default values&lt;/strong&gt;, &lt;strong&gt;type unions&lt;/strong&gt;, &lt;strong&gt;argument unpacking&lt;/strong&gt;, &lt;strong&gt;pass by value or reference&lt;/strong&gt;, and finally, introduced in PHP 8, &lt;strong&gt;named arguments&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  To define function parameters
&lt;/h2&gt;

&lt;p&gt;We can define function parameters within the parentheses of the function definition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we call the &lt;code&gt;foo()&lt;/code&gt; function, we need to pass two arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parameters are the variables listed in the function definition, while arguments are the actual values we pass to the function when we invoke it; in the example above, &lt;code&gt;$x&lt;/code&gt; and &lt;code&gt;$y&lt;/code&gt; are the function's parameters, and &lt;code&gt;5&lt;/code&gt; and &lt;code&gt;10&lt;/code&gt; are the passed arguments, i.e., the values assigned to the parameters of the &lt;code&gt;foo()&lt;/code&gt; function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type Hinting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Type Hinting&lt;/strong&gt; is a feature introduced by PHP starting from version 5, which allows specifying the type of object/data passed as an argument to a function or method.&lt;/p&gt;

&lt;p&gt;Starting from PHP version 7, in addition to the &lt;em&gt;weak mode&lt;/em&gt;, there is also the &lt;em&gt;strict mode&lt;/em&gt;. By enabling this mode, we force PHP to interpret variable types, and if the type is not satisfied, we will receive a fatal error.&lt;/p&gt;

&lt;p&gt;So, if in the example above, we want to be more restrictive and accept only the &lt;code&gt;int&lt;/code&gt; type and no others, we should declare it at the top of the code using the &lt;code&gt;declare&lt;/code&gt; statement followed by &lt;code&gt;strict_types=1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if we try to pass an argument of type &lt;code&gt;float&lt;/code&gt; or &lt;code&gt;string&lt;/code&gt;, we will receive an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'10'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Fatal error: Uncaught TypeError: foo(): Argument #1 must be of type int, float given, called in ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Union of types
&lt;/h2&gt;

&lt;p&gt;Starting from PHP version 8, it is possible to accept multiple data types. We can specify &lt;strong&gt;type unions&lt;/strong&gt; using the &lt;code&gt;|&lt;/code&gt; character.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we can invoke the &lt;code&gt;foo()&lt;/code&gt; function by passing both integers and decimals as arguments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default values
&lt;/h2&gt;

&lt;p&gt;For every parameter listed in the function definition, it is necessary to pass an argument; otherwise, we will receive a fatal error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// Fatal error: Uncaught ArgumentCountError: Too few arguments to function foo(), 1 passed in ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is possible to set &lt;strong&gt;default values for parameters&lt;/strong&gt; to assign a value in case it is not passed as an argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 50&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can assign scalar arrays and &lt;code&gt;null&lt;/code&gt; values as default values, but not a function call or an object; it must be a constant expression. &lt;/p&gt;

&lt;p&gt;Another important thing is that optional parameters must be defined after any required parameter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pass arguments by value vs by reference
&lt;/h2&gt;

&lt;p&gt;As a default, arguments for &lt;strong&gt;required parameters are passed by value&lt;/strong&gt;. You can specify to &lt;strong&gt;pass an argument by reference&lt;/strong&gt; using the &lt;code&gt;&amp;amp;&lt;/code&gt; character in the parameter definition.&lt;/p&gt;

&lt;p&gt;For example, let's define a &lt;code&gt;foo()&lt;/code&gt; function that takes 2 arguments and returns the multiplication of the arguments, dividing the first argument by 2 if it is an even number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 21&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// float(6) int(7)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have mentioned that by default, arguments are passed by value. In fact, modifying the value of &lt;code&gt;$x&lt;/code&gt; (&lt;code&gt;$x /= 2;&lt;/code&gt;), which is the first argument passed to the function, does not affect the original variable &lt;code&gt;$a&lt;/code&gt;, which still holds the value &lt;code&gt;float(6)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we change the definition of the first argument to pass the reference to the variable &lt;code&gt;$a&lt;/code&gt;, in this case, modifying the parameter &lt;code&gt;$x&lt;/code&gt; also affects the value of the original variable &lt;code&gt;$a&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 21&lt;/span&gt;
&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// float(3) int(7)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Decompression of topics
&lt;/h2&gt;

&lt;p&gt;We want to define a function that returns the sum of 2 or more arguments. We can change the function definition as we add an argument, or we can use the &lt;strong&gt;spread operator&lt;/strong&gt; that will capture any arguments passed to the function in an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$sum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;//return array_sum($numbers);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 48&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the spread operator even after a fixed number of parameters, in which case only the arguments passed after the fixed ones will be added to the array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 48&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, &lt;code&gt;$x&lt;/code&gt; and &lt;code&gt;$y&lt;/code&gt; are equal to &lt;code&gt;6.0&lt;/code&gt; and &lt;code&gt;7&lt;/code&gt;, respectively, and all the remaining arguments passed to the function are captured within the &lt;code&gt;$numbers&lt;/code&gt; array.&lt;/p&gt;

&lt;p&gt;We can specify the type of the extra arguments passed to the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'8'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Fatal error: Uncaught TypeError: sum(): Argument #5 must be of type int|float, string given, called in ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we receive an error because the last argument passed to the function is a string.&lt;/p&gt;

&lt;p&gt;The spread operator can also be used to unpack an array into the list of arguments to be passed to a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;array_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 56&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
   named arguments
&lt;/h2&gt;

&lt;p&gt;In PHP 8.0, we have the ability to specify the name of the argument to be passed to the function, regardless of the order listed in the function definition.&lt;/p&gt;

&lt;p&gt;Let's define a function where, if the first parameter &lt;code&gt;$x&lt;/code&gt; is divisible by the second parameter &lt;code&gt;$y&lt;/code&gt;, it returns their division; otherwise, it returns the value of &lt;code&gt;$x&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happens if we change the order of the arguments passed to the function?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get the value of &lt;code&gt;$b&lt;/code&gt; because it's no longer divisible. This new feature in PHP 8 effectively allows us to name the argument to indicate the value of the respective parameter declared in the function, regardless of the order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feature proves to be very useful in various use cases. For example, if we want to change the order of parameter definitions, we would have to search throughout the code where the function is used and update the order of how we pass arguments. With named arguments, we no longer need to worry about updating existing functions because the order is not important. However, if we change the name of a parameter, we still need to update the name in every part of the code where it is used.&lt;/p&gt;

&lt;p&gt;Another very valid use case is when you have a series of parameters with default values. For example, PHP has a function called &lt;code&gt;setcookie()&lt;/code&gt; that has many parameters with default values. If we wanted to pass only the &lt;code&gt;name&lt;/code&gt; and the last argument, we would still have to pass all the others defined before the last one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
method signature
setcookie (
 string $name,
 string $value = "",
 int $expires = 0,
 string $path = "",
 string $domain = "",
 bool $secure = false,
 bool $httponly = false,
) : bool
*/&lt;/span&gt;

&lt;span class="nb"&gt;setcookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// named arguments&lt;/span&gt;
&lt;span class="nb"&gt;setcookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httponly&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing the same argument multiple times results in an error because it overwrites the previous argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Fatal error: Uncaught Error: Named parameter $x overwrites previous argoument in ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can combine named arguments with positional arguments as long as the named arguments come after the positional ones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing &lt;code&gt;x&lt;/code&gt; again conflicts because we already have an argument for the &lt;code&gt;$x&lt;/code&gt; parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Fatal error: Uncaught Error: Named parameter $x overwrites previous argoument in ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another thing to note is that if we use argument unpacking and the array contains keys, those keys will be treated as argument names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'y'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Good work 👨‍💻&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>php8</category>
      <category>php</category>
      <category>functional</category>
    </item>
    <item>
      <title>How to test a private service in Symfony</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Wed, 04 Oct 2023 15:30:00 +0000</pubDate>
      <link>https://forem.com/mainick/how-to-test-a-private-service-in-symfony-2m91</link>
      <guid>https://forem.com/mainick/how-to-test-a-private-service-in-symfony-2m91</guid>
      <description>&lt;p&gt;In Symfony 3.4, they made all services private by default, which means you can no longer call &lt;code&gt;$this-&amp;gt;get('my_service_id')&lt;/code&gt; in your controllers to quickly obtain a service.&lt;/p&gt;

&lt;p&gt;This change was made because &lt;strong&gt;direct usage of services from the container is considered a bad practice&lt;/strong&gt;. That's why controllers allow services to be injected using &lt;a href="https://symfony.com/doc/current/service_container.html#fetching-and-using-services"&gt;Type Hinting&lt;/a&gt; in their methods and constructors. &lt;/p&gt;

&lt;p&gt;The only remaining inconvenience is that when running tests, we get the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; bin/phpunit
&lt;span class="c"&gt;# Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: The "App\Service\S" service or alias has&lt;/span&gt;
&lt;span class="c"&gt;# been removed or inlined when the container was compiled. You should either make it public, or stop using the container&lt;/span&gt;
&lt;span class="c"&gt;# directly and use dependency injection instead.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;We want to create a service and test it before integrating it with the rest of the project (standard &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;&lt;strong&gt;TDD&lt;/strong&gt;&lt;/a&gt; approach).&lt;/p&gt;

&lt;p&gt;I have a repository &lt;code&gt;R&lt;/code&gt; that implements the &lt;code&gt;RInterface&lt;/code&gt; interface. The &lt;code&gt;RInterface&lt;/code&gt; interface is used in the &lt;code&gt;S&lt;/code&gt; service (type hinted constructor). The &lt;code&gt;S&lt;/code&gt; service is used in the &lt;code&gt;C&lt;/code&gt; controller (again, as a constructor parameter).&lt;/p&gt;

&lt;p&gt;When we run the test for the &lt;code&gt;S&lt;/code&gt; service...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;STest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;KernelTestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testGetItems&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;bootKernel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$kernel&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getContainer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$container&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;S&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// ... other&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see the following message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; bin/phpunit
&lt;span class="c"&gt;# Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: The "App\Service\S" service or alias has&lt;/span&gt;
&lt;span class="c"&gt;# been removed or inlined when the container was compiled. You should either make it public, or stop using the container&lt;/span&gt;
&lt;span class="c"&gt;# directly and use dependency injection instead.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reason
&lt;/h3&gt;

&lt;p&gt;The service can be integrated when &lt;a href="https://github.com/symfony/dependency-injection/blob/6.1/Compiler/InlineServiceDefinitionsPass.php#L158"&gt;certain conditions are met&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To check if the &lt;code&gt;S&lt;/code&gt; service is present in the test container, we type the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; bin/console debug:container &lt;span class="s1"&gt;'App\Service\S'&lt;/span&gt; &lt;span class="nt"&gt;--env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the message we will see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Information &lt;span class="k"&gt;for &lt;/span&gt;Service &lt;span class="s2"&gt;"App&lt;/span&gt;&lt;span class="se"&gt;\C&lt;/span&gt;&lt;span class="s2"&gt;ore&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s2"&gt;ervice&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;=========================================================&lt;/span&gt;

 &lt;span class="nt"&gt;----------------&lt;/span&gt; &lt;span class="nt"&gt;---------------------------------&lt;/span&gt;
  Option           Value
 &lt;span class="nt"&gt;----------------&lt;/span&gt; &lt;span class="nt"&gt;---------------------------------&lt;/span&gt;
  Service ID       App&lt;span class="se"&gt;\S&lt;/span&gt;ervice&lt;span class="se"&gt;\S&lt;/span&gt;
  Class            App&lt;span class="se"&gt;\S&lt;/span&gt;ervice&lt;span class="se"&gt;\S&lt;/span&gt;
  Tags             -
  Public           no
  Synthetic        no
  Lazy             no
  Shared           &lt;span class="nb"&gt;yes
  &lt;/span&gt;Abstract         no
  Autowired        &lt;span class="nb"&gt;yes
  &lt;/span&gt;Autoconfigured   &lt;span class="nb"&gt;yes&lt;/span&gt;
 &lt;span class="nt"&gt;----------------&lt;/span&gt; &lt;span class="nt"&gt;---------------------------------&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned in the received message when running the test, the &lt;code&gt;S&lt;/code&gt; service appears as private (&lt;code&gt;Public: no&lt;/code&gt;). It's important to note that due to how the Symfony container works, &lt;strong&gt;unused services are removed from the container&lt;/strong&gt;. This means that if you have a private service not used by any other service, Symfony removes it, and you cannot retrieve it from the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;The solution is to explicitly define the &lt;code&gt;S&lt;/code&gt; service as &lt;code&gt;public&lt;/code&gt; so that Symfony does not remove it. The most appropriate solution would be to create a public alias only in the test environment for the service you want to test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/services_test.yaml&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;test_alias.service:s:&lt;/span&gt;
    &lt;span class="s"&gt;alias&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;App\Service\S'&lt;/span&gt;
    &lt;span class="na"&gt;public&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Good work 👨‍💻&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>symfony</category>
      <category>php</category>
      <category>tdd</category>
      <category>testing</category>
    </item>
    <item>
      <title>PHP Match Expression - Match vs Switch</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Mon, 02 Oct 2023 15:30:00 +0000</pubDate>
      <link>https://forem.com/mainick/php-match-expression-match-vs-switch-3j5b</link>
      <guid>https://forem.com/mainick/php-match-expression-match-vs-switch-3j5b</guid>
      <description>&lt;p&gt;The &lt;strong&gt;Match&lt;/strong&gt; expression is essentially the same as the Switch statement and was introduced in PHP 8.&lt;/p&gt;

&lt;p&gt;The keyword is match, so let's recreate the switch statement below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$paymentStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$paymentStatus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Paid'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Payment Declined'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Pending Payment'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Unknown Payment Status'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the curly braces, we form pairs of values where the key is the individual conditional expression, and the value is the return expression.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$paymentStatusDisplay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$paymentStatus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Paid'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Payment Declined'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Pending Payment'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Unknown Payment Status'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$paymentStatusDisplay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Let's talk about the differences
&lt;/h3&gt;

&lt;p&gt;The first difference is that the &lt;code&gt;match&lt;/code&gt; expression is actually an expression and evaluates to a value, so it can be assigned to a variable. It can be practically any type of expression; for example, we could use a function that returns a value.&lt;/p&gt;

&lt;p&gt;The second difference is that &lt;code&gt;switch&lt;/code&gt; requires the use of &lt;code&gt;break&lt;/code&gt; to avoid some unexpected outcomes, such as the evaluation of other &lt;code&gt;case&lt;/code&gt; statements, while the &lt;code&gt;match&lt;/code&gt; statement returns a value once a match is found.&lt;/p&gt;

&lt;p&gt;The third difference is that in the &lt;code&gt;switch&lt;/code&gt; statement, the &lt;code&gt;default&lt;/code&gt; value is not required, whereas a fatal error is generated in &lt;code&gt;match&lt;/code&gt; if a corresponding match is not found in any of the listed cases and the default value is not specified.&lt;/p&gt;

&lt;p&gt;The fourth difference is that the &lt;code&gt;match&lt;/code&gt; expression performs a strict comparison while the &lt;code&gt;switch&lt;/code&gt; statement performs loose comparison. Both sides are expressions, and we could have complex expressions, function calls, logical operators used within a conditional expression.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$paymentStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// switch print 'Pending Payment'&lt;/span&gt;
&lt;span class="c1"&gt;// match print 'Unknown Payment Status'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing to note is that the &lt;code&gt;match&lt;/code&gt; expression does not deprecate the &lt;code&gt;switch&lt;/code&gt; statement as it still has its use cases. For example, &lt;code&gt;match&lt;/code&gt; returns a value once a match is found, whereas with &lt;code&gt;switch&lt;/code&gt;, you can execute multiple statements.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good work 👨‍💻&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>php8</category>
      <category>php</category>
    </item>
    <item>
      <title>Using array_merge in a PHP loop is considered bad practice</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Sat, 30 Sep 2023 09:56:42 +0000</pubDate>
      <link>https://forem.com/mainick/using-arraymerge-in-a-php-loop-is-considered-bad-practice-3bgd</link>
      <guid>https://forem.com/mainick/using-arraymerge-in-a-php-loop-is-considered-bad-practice-3bgd</guid>
      <description>&lt;p&gt;To use the &lt;code&gt;array_merge&lt;/code&gt; function in a &lt;code&gt;for&lt;/code&gt; / &lt;code&gt;foreach&lt;/code&gt; / &lt;code&gt;while&lt;/code&gt; loop, do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$arraysToMerge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$arraysMerged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arraysToMerge&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$arraysMerged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arraysMerged&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$array&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a poor practice 😱 because it is a &lt;strong&gt;performance drain&lt;/strong&gt; (especially on memory).&lt;/p&gt;

&lt;p&gt;Since PHP 5.6, there is a new operator, the &lt;strong&gt;spread operator&lt;/strong&gt;,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$arraysToMerge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$arraysMerged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$arraysToMerge&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arraysMerged&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Array
&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;0] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 1
    &lt;span class="o"&gt;[&lt;/span&gt;1] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 2
    &lt;span class="o"&gt;[&lt;/span&gt;2] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 2
    &lt;span class="o"&gt;[&lt;/span&gt;3] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 3
    &lt;span class="o"&gt;[&lt;/span&gt;4] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 5
    &lt;span class="o"&gt;[&lt;/span&gt;5] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 8
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which automatically expands the array without the need to loop through it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No more performance issues &lt;/li&gt;
&lt;li&gt;No &lt;code&gt;for&lt;/code&gt; / &lt;code&gt;foreach&lt;/code&gt; / &lt;code&gt;while&lt;/code&gt; loops&lt;/li&gt;
&lt;li&gt;Processed in a single line of code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A more complex example can be represented by the following case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have a list of students&lt;/li&gt;
&lt;li&gt;For each of them, I need to retrieve their used books&lt;/li&gt;
&lt;li&gt;I need to store them in a new array structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is possible to use the spread operator, but an intermediate process is required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// student data model&lt;/span&gt;
&lt;span class="nv"&gt;$students&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;

&lt;span class="c1"&gt;// retrieve used books by student ID&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;searchUsedBooksByStudent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'italian'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'history'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'mathematics'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'latin'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nv"&gt;$arrayUsedBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$students&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$student&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$books&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;searchUsedBooksByStudent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$student&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;$arrayUsedBooks&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$books&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;$arraysMerged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_merge&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$arrayUsedBooks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arraysMerged&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; Array
&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;0] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; italian
    &lt;span class="o"&gt;[&lt;/span&gt;1] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;history&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;2] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; mathematics
    &lt;span class="o"&gt;[&lt;/span&gt;3] &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; latin
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope these examples are helpful. Now, look at your code to see what you can improve!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good work 👨‍💻&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>php</category>
      <category>loop</category>
      <category>performance</category>
    </item>
    <item>
      <title>Guida ai React Hooks</title>
      <dc:creator>Maico Orazio</dc:creator>
      <pubDate>Fri, 11 Dec 2020 08:00:00 +0000</pubDate>
      <link>https://forem.com/mainick/guida-ai-react-hooks-1aii</link>
      <guid>https://forem.com/mainick/guida-ai-react-hooks-1aii</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--soAtB7kc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xlw4n53uat3zd5tpu0yq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--soAtB7kc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xlw4n53uat3zd5tpu0yq.png" alt="Ract Hooks" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se fai un lavoro come il mio, l’approfondimento è una delle regole da seguire nel quotidiano. Nell’ultimo periodo mi è capitato di approfondire i &lt;strong&gt;React Hooks&lt;/strong&gt; e ho deciso di scrivere per il blog dell’azienda in cui lavoro una guida su questo tema. La &lt;strong&gt;guida ai React Hooks&lt;/strong&gt; , divisa in 3 parti nella quale ho presentato alcuni hooks di uso più comune e qualche altro utile al fine di migliorare le prestazioni delle vostre app in React.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Grazie agli Hooks siamo in grado di usare lo stato nei componenti funzionali stateless senza creare necessariamente un componente di classe per utilizzarlo&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Nella &lt;a href="https://medium.com/webeetle/guida-ai-react-hooks-parte-1-510693ea60f8"&gt;prima parte della guida ai React Hook&lt;/a&gt; approfondisco il perché e il come sono stati introdotti gli hooks e l’utilizzo dei più comuni &lt;em&gt;useState&lt;/em&gt; e &lt;em&gt;useEffect&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;L’ &lt;strong&gt;hook useState&lt;/strong&gt; consente di gestire lo stato locale nei componente funzionali.&lt;/p&gt;

&lt;p&gt;L’ &lt;strong&gt;hook useEffect&lt;/strong&gt; viene utilizzato per gestire gli &lt;a href="https://it.wikipedia.org/wiki/Effetto_collaterale_(informatica)"&gt;effetti collaterali&lt;/a&gt; nei componenti funzionali.&lt;/p&gt;




&lt;p&gt;Nella &lt;a href="https://medium.com/webeetle/guida-ai-react-hooks-parte-2-c4cce979a65d"&gt;seconda parte della guida ai React Hooks&lt;/a&gt; presento altri due hooks utili alla gestione dello stato.&lt;/p&gt;

&lt;p&gt;L’ &lt;strong&gt;hook useReducer&lt;/strong&gt; può essere utilizzato in alternativa a &lt;em&gt;useState&lt;/em&gt;, è ideale per la gestione di stato e transazioni di stato più complessi.&lt;/p&gt;

&lt;p&gt;L’ &lt;strong&gt;hook useContext&lt;/strong&gt; ti fa risparmiare lo stress di dover fare affidamento su un consumer &lt;em&gt;&lt;a href="https://it.reactjs.org/docs/context.html"&gt;Context&lt;/a&gt;&lt;/em&gt; e ha un’API più semplice rispetto all’API di &lt;em&gt;&lt;a href="https://it.reactjs.org/docs/render-props.html"&gt;render props&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;Nell’&lt;a href="https://medium.com/webeetle/guida-ai-react-hooks-parte-3-8541657ff5d5"&gt;ultima parte della guida ai React Hooks&lt;/a&gt; introduco altri due hooks utili per ottimizzare le prestazioni delle app in React.&lt;/p&gt;

&lt;p&gt;L’ &lt;strong&gt;hook useMemo&lt;/strong&gt; usato per memorizzare i valori.&lt;/p&gt;

&lt;p&gt;L’ &lt;strong&gt;hook useCallback&lt;/strong&gt; usato per memorizzare le funzioni.&lt;/p&gt;

&lt;p&gt;All’interno della guida ho condiviso esempi di codice per ogni hook illustrato e per i quali ho inserito i link ai relativi repository.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Buona lettura!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The post &lt;a href="https://www.mainickweb.com/guida-ai-react-hooks/"&gt;Guida ai React Hooks&lt;/a&gt; appeared first on &lt;a href="https://www.mainickweb.com"&gt;MaiNick Web&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>reacthooks</category>
    </item>
  </channel>
</rss>
