<?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>DEV Community: Doeke Norg</title>
    <description>The latest articles on DEV Community by Doeke Norg (@doekenorg).</description>
    <link>https://dev.to/doekenorg</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%2F671711%2Fa230e275-6db6-4956-ac61-61ff6f798edc.jpeg</url>
      <title>DEV Community: Doeke Norg</title>
      <link>https://dev.to/doekenorg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/doekenorg"/>
    <language>en</language>
    <item>
      <title>Exploring Coroutines in PHP</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Sat, 05 Jul 2025 09:41:22 +0000</pubDate>
      <link>https://dev.to/doekenorg/exploring-coroutines-in-php-h1j</link>
      <guid>https://dev.to/doekenorg/exploring-coroutines-in-php-h1j</guid>
      <description>&lt;p&gt;The term "coroutine" often comes up when talking about asynchronous or non-blocking code, but what does it actually mean? In this post, we will explore coroutines as a concept and see how PHP supports them through Generators and Fibers. Whether you're building pipelines, CLI tools, or preparing to dive into concurrency, understanding coroutines is an essential first step.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Coroutines?
&lt;/h2&gt;

&lt;p&gt;A coroutine is a function. However, where a regular function continuously runs from top to bottom until it is finished, a coroutine can pause/suspend itself and be resumed. It can return a value every time it suspends, and receive a value when it is resumed. While the coroutine is suspended and not yet finished, it will hold on to the current state it is in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Suspend and resume
&lt;/h3&gt;

&lt;p&gt;Once a coroutine is executed, it will start performing its task. During the execution, the coroutine can suspend itself, handing over control to the rest of the code. This means that the suspension of the execution can only originate &lt;em&gt;inside&lt;/em&gt; the coroutine. It has to voluntarily release control (dare I say it should &lt;code&gt;yield&lt;/code&gt;? Spoilers!)&lt;/p&gt;

&lt;p&gt;After that, the fate of the coroutine is in the hands of the rest of the code. It cannot resume itself. The coroutine will have to be explicitly given control back with the instruction to resume. Until then, it waits while the rest of the code runs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The other code could continue and never call the coroutine again, leaving it in its suspended state. Once the other code finishes, the program ends. It will not have to wait for the coroutine to finish.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Return and receive values
&lt;/h3&gt;

&lt;p&gt;When a coroutine suspends its execution, it can provide a value to go with that. This makes the suspension like a return statement. And because a coroutine can resume and suspend multiple times, it can return multiple values.&lt;/p&gt;

&lt;p&gt;A coroutine can also receive a value when it is resumed. It will have this value available immediately after resuming and can act on it. This makes a coroutine bi-directional.&lt;/p&gt;

&lt;p&gt;While returning and receiving values is &lt;strong&gt;possible&lt;/strong&gt; in a coroutine, it is not &lt;em&gt;required&lt;/em&gt;. A coroutine can just suspend its execution without doing anything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hold its state
&lt;/h3&gt;

&lt;p&gt;When a regular function is called, any internal parameters it creates to hold values are released from memory as soon as the function finishes. You can call a function multiple times, but the values from the first call will not be available in the function the second time it is called.&lt;/p&gt;

&lt;p&gt;Since a coroutine is a function that can suspend and resume, values that are scoped inside the coroutine stay available while it hasn't finished. When the coroutine regains control and resumes its execution, it can still reference those variables. Only when the coroutine is finished are its internal variables released from memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Types of coroutines
&lt;/h3&gt;

&lt;p&gt;Coroutines come in a few flavors. They can either be &lt;strong&gt;symmetrical or asymmetrical&lt;/strong&gt;, and &lt;strong&gt;stackless or stackful&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Asymmetrical vs. Symmetrical Coroutines
&lt;/h4&gt;

&lt;p&gt;When it comes to suspending its execution, as we now know, the control must be released by the coroutine. An &lt;strong&gt;asymmetrical&lt;/strong&gt; coroutine can only release control &lt;em&gt;back&lt;/em&gt; to the code that called the coroutine. A &lt;strong&gt;symmetrical&lt;/strong&gt; coroutine can choose to whom it releases control, either a different coroutine or the original caller.&lt;/p&gt;

&lt;p&gt;Let's imagine coroutines are playing a game of &lt;strong&gt;hot potato&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In an &lt;strong&gt;asymmetrical game&lt;/strong&gt;, the main program &lt;strong&gt;always passes the potato to a coroutine&lt;/strong&gt;, which can &lt;strong&gt;only toss it back to the caller&lt;/strong&gt;, not to another coroutine.&lt;/p&gt;

&lt;p&gt;In a &lt;strong&gt;symmetrical game&lt;/strong&gt;, coroutines can &lt;strong&gt;pass the potato among themselves&lt;/strong&gt;, deciding who goes next. The main program will start and end the game, but doesn’t have to control every pass.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Even in a symmetrical coroutine situation, at some point, the control must be released back to the original calling code for the program to finish. Otherwise, it would hang indefinitely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Stackless vs. Stackful Coroutines
&lt;/h4&gt;

&lt;p&gt;Finally, there are stackless and stackful coroutines. The difference lies in where they are allowed to suspend execution.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Stackless Coroutine&lt;/strong&gt; can only yield control from its &lt;em&gt;outermost function&lt;/em&gt;. While it can call other (nested) functions, it cannot suspend from within them.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Stackful Coroutine&lt;/strong&gt;, on the other hand, &lt;em&gt;can&lt;/em&gt; suspend from within nested functions. It will release its control right there, and when it is resumed, it will resume from that exact location.&lt;/p&gt;

&lt;p&gt;As a result, stackful coroutines are more flexible, since they allow suspension inside helper functions. This can reduce verbosity and keep the focus on the core logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  How are coroutines implemented in PHP?
&lt;/h2&gt;

&lt;p&gt;Now that we know the conditions that can make up a coroutine, let's see how PHP implements or facilitates coroutines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coroutines using Generators
&lt;/h3&gt;

&lt;p&gt;The first introduction of Coroutines in PHP came with version 5.5 in the form of &lt;a href="https://www.php.net/manual/en/language.generators.overview.php" rel="noopener noreferrer"&gt;Generators&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, most developers know Generators as memory-preserving iterators. And if you haven't yet, I'd highly recommend reading my earlier post &lt;a href="https://doeken.org/blog/generators-over-arrays" rel="noopener noreferrer"&gt;Generators over Arrays&lt;/a&gt; where I go into detail on how Generators can be used like this. But as we'll see, they are much more than just iterators.&lt;/p&gt;

&lt;p&gt;As a quick reminder, here is an example of a Generator that yields a few values.&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;exampleGenerator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;Generator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Started"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;yield&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;yield&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;yield&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;yield&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="nv"&gt;$generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exampleGenerator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, how is this Generator also a coroutine? Let's examine the conditions we've talked about so far.&lt;/p&gt;

&lt;h4&gt;
  
  
  It can pause its execution
&lt;/h4&gt;

&lt;p&gt;When we call &lt;code&gt;$generator = exampleGenerator()&lt;/code&gt;, it only returns the &lt;code&gt;Generator&lt;/code&gt; instance. The code inside it has not yet been started. The generator will start when any function is called on it.&lt;/p&gt;

&lt;p&gt;If we call &lt;code&gt;$result = $generator-&amp;gt;current()&lt;/code&gt;, for example, the first part of the code will run. It will echo &lt;code&gt;Started&lt;/code&gt;, set the parameter of &lt;code&gt;$value&lt;/code&gt; to &lt;code&gt;4&lt;/code&gt;, and then it will pause its execution and &lt;code&gt;yield&lt;/code&gt; control back.&lt;/p&gt;

&lt;h4&gt;
  
  
  It can return a value
&lt;/h4&gt;

&lt;p&gt;Now that the execution is paused, the generator has also returned the value of &lt;code&gt;1&lt;/code&gt;. We can see that when we dump the value of &lt;code&gt;$result&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  It can be resumed
&lt;/h4&gt;

&lt;p&gt;When the generator is paused, we can do anything we want in our calling code. Send an email, write a log, &lt;code&gt;sleep&lt;/code&gt; for a bit. But we can also resume the generator by calling &lt;code&gt;$generator-&amp;gt;next()&lt;/code&gt;. At this point, the generator will resume its code until it hits the next pause or &lt;code&gt;yield&lt;/code&gt; keyword. If we call &lt;code&gt;$generator-&amp;gt;current()&lt;/code&gt; again, it will have a value of &lt;code&gt;null&lt;/code&gt;, because the next &lt;code&gt;yield&lt;/code&gt; keyword does not specify a value to be returned. It simply pauses execution.&lt;/p&gt;

&lt;h4&gt;
  
  
  It remembers its state
&lt;/h4&gt;

&lt;p&gt;If we were to call &lt;code&gt;$generator-&amp;gt;next()&lt;/code&gt; two more times, it would be at the &lt;code&gt;yield $value&lt;/code&gt; line. To prove that it has remembered its earlier state of the &lt;code&gt;$value&lt;/code&gt; parameter, we can inspect &lt;code&gt;$generator-&amp;gt;current()&lt;/code&gt; and lo and behold, it will have the value &lt;code&gt;4&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When using a Generator as an iterator with &lt;code&gt;foreach($generator as $key =&amp;gt; $result)&lt;/code&gt;, internally it will also use these methods. After calling &lt;code&gt;$generator-&amp;gt;rewind()&lt;/code&gt; once, it will call these methods for every iteration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$generator-&amp;gt;valid()&lt;/code&gt; - to make sure it has more values&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$generator-&amp;gt;key()&lt;/code&gt; - to return the value to &lt;code&gt;$key&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$generator-&amp;gt;current()&lt;/code&gt; - to return the value to &lt;code&gt;$result&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The body of the foreach loop runs&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$generator-&amp;gt;next()&lt;/code&gt; - to resume to the next &lt;code&gt;yield&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the full code so far if you want to try it out:&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;exampleGenerator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;Generator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Started"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;yield&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;yield&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;yield&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;yield&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="nv"&gt;$generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exampleGenerator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$generator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;current&lt;/span&gt;&lt;span class="p"&gt;();&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;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// int(1)&lt;/span&gt;
&lt;span class="c1"&gt;// Other code, send email, log, sleep...&lt;/span&gt;

&lt;span class="nv"&gt;$generator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Restart coroutine&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;$generator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;current&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// NULL&lt;/span&gt;

&lt;span class="nv"&gt;$generator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Current value = 3&lt;/span&gt;
&lt;span class="nv"&gt;$generator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&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;$generator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;current&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// int(4)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  It can receive a value (?!)
&lt;/h4&gt;

&lt;p&gt;Wait, what? Yes, it can. Well, our current example can't, but a Generator in general &lt;strong&gt;can&lt;/strong&gt; receive a value when it resumes. To let the generator receive a value, it must be called with &lt;code&gt;$generator-&amp;gt;send($value)&lt;/code&gt;. So, where does this value enter the coroutine? Right after the last &lt;code&gt;yield&lt;/code&gt;. Or better yet, "before". Let me explain with 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="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;coroutine&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;Generator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nv"&gt;$received&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s1"&gt;'Hello from the Coroutine'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;"Received: "&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$received&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="nv"&gt;$coroutine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;coroutine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$coroutine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;current&lt;/span&gt;&lt;span class="p"&gt;();&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;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Hello from the Coroutine&lt;/span&gt;

&lt;span class="nv"&gt;$next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$coroutine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Greetings from the code'&lt;/span&gt;&lt;span class="p"&gt;);&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;$next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Received: Greetings from the code.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the Generator will be started by the &lt;code&gt;current()&lt;/code&gt; method and immediately paused. During its suspension, the value the Generator returns will be &lt;code&gt;Hello from the Coroutine&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Generator::send()&lt;/code&gt; method not only sends the value, but it also instructs the Generator to resume its execution. At that point, the Generator will set the value of &lt;code&gt;$received&lt;/code&gt; to the value it received from &lt;code&gt;send()&lt;/code&gt; and &lt;code&gt;yield&lt;/code&gt; it back prefixed by &lt;code&gt;Received:&lt;/code&gt;. The result of the &lt;code&gt;-&amp;gt;send()&lt;/code&gt; will therefore be: &lt;code&gt;Received: Greetings from the Coroutine&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also use &lt;code&gt;-&amp;gt;throw(\Throwable $exception)&lt;/code&gt; to throw an exception back into the Generator. It will be as if the &lt;br&gt;
current &lt;code&gt;yield&lt;/code&gt; statement were replaced by that exception.&lt;/p&gt;

&lt;p&gt;So, to summarize, the &lt;code&gt;yield&lt;/code&gt; keyword can be used in different ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;yield;&lt;/code&gt; Suspends the execution, returns nothing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yield $value;&lt;/code&gt; Suspends and returns &lt;code&gt;$value&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$received = yield;&lt;/code&gt; Suspends, returns nothing, able to receive either a value to &lt;code&gt;$received&lt;/code&gt;, or an exception&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$received = yield $value;&lt;/code&gt; Suspends, returns &lt;code&gt;$value&lt;/code&gt;, able to receive either a value to &lt;code&gt;$received&lt;/code&gt;, or an exception&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  It is Asymmetrical and Stackless
&lt;/h4&gt;

&lt;p&gt;As we've seen, the &lt;code&gt;yield&lt;/code&gt; keyword makes a function a coroutine, because it pauses the execution and releases control. However, it can not release control to any other coroutine. This would require a &lt;code&gt;yield to&lt;/code&gt; syntax, which doesn't exist.&lt;/p&gt;

&lt;p&gt;While a generator can start (and consume) a different generator, this isn't technically symmetrical because it is not releasing its control. It only starts the other generator, while it also still runs itself. This makes a generator an &lt;strong&gt;Asymmetric Coroutine&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Finally, a generator cannot be suspended from a nested function. This is because the &lt;code&gt;yield&lt;/code&gt; keyword inside a function will make it return a &lt;code&gt;Generator&lt;/code&gt;. So, when you call &lt;code&gt;yield&lt;/code&gt; in a nested function, it becomes a generator, instead of suspending the parent. This lack of call stack awareness makes the generator a &lt;strong&gt;Stackless Coroutine&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Coroutines using Fibers
&lt;/h3&gt;

&lt;p&gt;If you are anything like me, when PHP 8.1 introduced &lt;a href="https://www.php.net/manual/en/language.fibers.php" rel="noopener noreferrer"&gt;Fibers&lt;/a&gt;, you might have read about them and thought &lt;em&gt;"🤯 this isn't for me"&lt;/em&gt;. And to be honest, it might very well not be. However, I think with the context of coroutines and generators, it is much easier to understand and see their use cases.&lt;/p&gt;

&lt;p&gt;Where a &lt;code&gt;Generator&lt;/code&gt; itself is a stackless coroutine, Fibers represent a toolbox that you can use to implement a stackful coroutine. Let's take a look at our last example,  written with Fibers.&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;$coroutine&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;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nv"&gt;$received&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello from the Coroutine'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Received: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$received&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;  

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$coroutine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&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;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Hello from the Coroutine&lt;/span&gt;
&lt;span class="nv"&gt;$next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$coroutine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello from the code'&lt;/span&gt;&lt;span class="p"&gt;);&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;$next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Received: Hello from the code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Fibers, the coroutine is now wrapped inside a &lt;code&gt;Fiber&lt;/code&gt; instance. After that, you need to explicitly &lt;code&gt;start()&lt;/code&gt; the &lt;code&gt;Fiber&lt;/code&gt; instance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: any arguments you pass to the &lt;code&gt;start()&lt;/code&gt; method will be provided to the callback function, just like it would when you call a generator function with arguments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Suspending and resuming
&lt;/h4&gt;

&lt;p&gt;Just like in our previous generator example, a fiber can suspend its execution. Where the generator uses more iterator function names, because it is mostly used as such, a fiber's methods are very semantic: &lt;code&gt;Fiber::suspend()&lt;/code&gt; and &lt;code&gt;$fiber-&amp;gt;resume()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So why is &lt;code&gt;::suspend()&lt;/code&gt; a static method, and &lt;code&gt;-&amp;gt;resume()&lt;/code&gt; a non-static method? This has to do with the call stack.&lt;br&gt;
Unlike a generator, a &lt;code&gt;Fiber&lt;/code&gt; has its own call stack. This means that suspension can happen deep within nested functions, not just at the top level. However, neither those nested functions nor the callback that starts the fiber have access to a &lt;code&gt;$this&lt;/code&gt; variable representing the currently running instance.&lt;/p&gt;

&lt;p&gt;This is where the static &lt;code&gt;Fiber::suspend()&lt;/code&gt; function comes in. Because a fiber knows its call stack, &lt;code&gt;Fiber::suspend&lt;/code&gt; can determine the closest instance it is being called in, and suspend it.&lt;/p&gt;

&lt;p&gt;And because a coroutine can't resume itself, the instance must be resumed from the outside. This is why the instance has a public non-static method &lt;code&gt;resume()&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Returning and Receiving values &amp;amp; Exceptions
&lt;/h4&gt;

&lt;p&gt;Just like a generator, a Fiber can return multiple values. Whenever you call &lt;code&gt;Fiber::suspend($value)&lt;/code&gt;, you can provide a value that will be returned. A fiber will receive any value that is provided to the &lt;code&gt;$fiber-&amp;gt;resume($value)&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;You can also resume a fiber by throwing a &lt;code&gt;Throwable $exception&lt;/code&gt; at it. This allows the Fiber to respond to different types of communication. You can send the fiber an exception by calling &lt;code&gt;$fiber-&amp;gt;throw($exception)&lt;/code&gt;. Inside your callback function, you should guard against this by wrapping (at least) the current &lt;code&gt;Fiber::suspend()&lt;/code&gt; call in a &lt;strong&gt;try-catch&lt;/strong&gt; block.&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;$coroutine&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;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello from the fiber.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nv"&gt;$received&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Give me something.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
       &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'You gave me a value of "%s": '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$received&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\Throwable&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
       &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'You gave me this exception: "%s".'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&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;span class="nv"&gt;$hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$coroutine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&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;$hello&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Hello from the fiber.  &lt;/span&gt;

&lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$coroutine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello from the code'&lt;/span&gt;&lt;span class="p"&gt;);&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;$message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Give me something.  &lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$coroutine&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="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'Exception from the code'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&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;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// You gave me this exception: "Exception from the code".&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: While a local catch is possible, a better approach would be to wrap your entire callback function body. Because an exception is always thrown from the outside, the callback does not control the exceptions, so it should always expect them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Nested suspension
&lt;/h4&gt;

&lt;p&gt;We have seen that a Generator cannot be suspended from a nested function, as that would become a Generator itself. With Fibers, however, it &lt;strong&gt;is possible&lt;/strong&gt; to have a nested function call that will suspend the current Fiber. This allows you to use helper functions, which can keep your code more DRY, more semantic, and easier to understand.&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;Logger&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;warning&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;$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="k"&gt;echo&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;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;get_logger&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;?Logger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
       &lt;span class="nv"&gt;$logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'Waiting for a logger instance...'&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;$logger&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$logger&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Throwable&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="kc"&gt;null&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;$coroutine&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;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&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;=&lt;/span&gt; &lt;span class="s1"&gt;'I am a message that needs to be logged.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

    &lt;span class="nv"&gt;$logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_logger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
    &lt;span class="nv"&gt;$logger&lt;/span&gt;&lt;span class="o"&gt;?-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;warning&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="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$coroutine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&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;$message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Waiting for a logger instance...  &lt;/span&gt;

&lt;span class="nv"&gt;$coroutine&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// I am a message that needs to be logged.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we can see that the Fiber callback function does not explicitly suspend its execution. However, the &lt;code&gt;get_logger&lt;/code&gt; helper function does. The code is suspended right there, and the control is handed off to the caller. When the caller resumes the coroutine with a new &lt;code&gt;Logger&lt;/code&gt;, the coroutine also resumes right there in the nested function. It validates the input, returns the logger, and the coroutine continues. This makes the Fiber a &lt;strong&gt;Stackful Coroutine&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fibers are also Asymmetrical
&lt;/h4&gt;

&lt;p&gt;It would be cool if it all came full circle, and I told you that Fibers were also symmetrical. But unfortunately, that's not the case. Just like the &lt;code&gt;yield&lt;/code&gt; keyword, the &lt;code&gt;Fiber::suspend()&lt;/code&gt; method does not allow for suspending to a specific coroutine. It, too, can only release control to the caller, making the use of Fibers an &lt;strong&gt;Asymmetric Coroutine&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Just like in a Generator, calling &lt;code&gt;start()&lt;/code&gt; or &lt;code&gt;resume()&lt;/code&gt; on a different coroutine does not pause the current one. Here is a quick example that proves that:&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;$a&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;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Fiber&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$a&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="s2"&gt;"starting B&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&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;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&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="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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Fiber&lt;/span&gt; &lt;span class="nv"&gt;$a&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="s2"&gt;"Resuming A&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// FiberError: Cannot resume a fiber that is not suspended  &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;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, &lt;code&gt;$a&lt;/code&gt; starts &lt;code&gt;$b&lt;/code&gt;, and in turn, &lt;code&gt;$b&lt;/code&gt; wants to resume &lt;code&gt;$a&lt;/code&gt;. But because there was no handoff of control and suspension, &lt;code&gt;$a&lt;/code&gt; is still running, resulting in an exception.&lt;/p&gt;

&lt;p&gt;However, just because Fibers aren’t symmetrical doesn’t mean they’re useless or no better than Generators. Their stackful nature and added expressiveness make them a powerful tool in their own right.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparing Generators and Fibers
&lt;/h3&gt;

&lt;p&gt;Now that we've explored both, let's compare Generators and Fibers side by side to see how they differ.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Generator&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Fibers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Suspend / Resume&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;yield&lt;/code&gt;, &lt;code&gt;-&amp;gt;next()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;Fiber::suspend()&lt;/code&gt;, &lt;code&gt;-&amp;gt;resume()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Return Values&lt;/td&gt;
&lt;td&gt;✅ via &lt;code&gt;yield $value&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅ via &lt;code&gt;Fiber::suspend($value)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Receive Values&lt;/td&gt;
&lt;td&gt;✅ via &lt;code&gt;-&amp;gt;send($value)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅ via &lt;code&gt;-&amp;gt;resume($value)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exception Handling&lt;/td&gt;
&lt;td&gt;✅ via &lt;code&gt;-&amp;gt;throw($exception)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅ via &lt;code&gt;-&amp;gt;throw($exception)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Symmetrical&lt;/td&gt;
&lt;td&gt;❌ Always resumes to original caller&lt;/td&gt;
&lt;td&gt;❌ Always resumes to original caller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stackful&lt;/td&gt;
&lt;td&gt;❌ Cannot suspend in nested functions&lt;/td&gt;
&lt;td&gt;✅ Can suspend from within nested functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iterator Integration&lt;/td&gt;
&lt;td&gt;✅ Implements &lt;code&gt;Iterator&lt;/code&gt; (great for &lt;code&gt;foreach&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;❌ Not iterable — requires manual handling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What are Coroutines useful for in PHP?
&lt;/h2&gt;

&lt;p&gt;The ability to pause code execution, have bidirectional I/O, and retain its current state makes coroutines a good candidate for various use cases. Let's have a look at some possibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  State processing
&lt;/h3&gt;

&lt;p&gt;Because coroutines can retain their state between invocations, they are useful as state machines, chatbots, pipelines, and command-line (CLI) tools.&lt;/p&gt;

&lt;p&gt;Let's look at a simple command-line tool that asks some questions to produce a final output.&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;$cli&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nv"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s1"&gt;'What is your name?'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'age'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s1"&gt;'How old are you?'&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;$state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;

&lt;span class="nv"&gt;$cli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;rewind&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$cli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;current&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;$prompt&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;STDIN&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nv"&gt;$cli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$cli&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getReturn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Display the collected information&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Collected information:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Name: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Age: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'age'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the Generator will return a few questions. We display every question and use &lt;code&gt;fgets(STDIN)&lt;/code&gt; to input an answer. This answer will be sent back to the generator, and it will proceed to the next question. When the Generator finishes, we return the recorded state. We can use &lt;code&gt;-&amp;gt;getReturn()&lt;/code&gt; to get that value from the generator.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can only use &lt;code&gt;getReturn&lt;/code&gt; on a Generator or Fiber that has finished. Otherwise, it will throw an exception.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Lazy iteration
&lt;/h3&gt;

&lt;p&gt;Being able to return multiple values is what makes coroutines great at being lazy iterators. Because the data it returns does not need to exist before the iteration starts, it can save a lot of memory. In PHP, generators are perfect for this kind of job, since they implement the &lt;code&gt;Iterator&lt;/code&gt; interface and plug right into &lt;code&gt;foreach&lt;/code&gt; loops. If you’re curious to see this in action, check out my post on &lt;a href="https://doeken.org/blog/generators-over-arrays" rel="noopener noreferrer"&gt;Generators over arrays&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cooperative Multitasking (Concurrency)
&lt;/h3&gt;

&lt;p&gt;Concurrency is a concept of multiple tasks running at the same time. This can be achieved through &lt;em&gt;parallelism&lt;/em&gt;, where tasks run on separate threads simultaneously, or through &lt;strong&gt;cooperative multitasking&lt;/strong&gt;, where tasks take turns running by explicitly yielding control.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Because coroutines simply yield their control, you need a manager that determines which coroutine runs next. This is often implemented with something called an &lt;strong&gt;Event Loop&lt;/strong&gt;, which will manage and schedule coroutines based on I/O events and timers. Out of the box, PHP does not provide this, but there are various projects like &lt;a href="https://revolt.run" rel="noopener noreferrer"&gt;Revolt&lt;/a&gt; and &lt;a href="https://reactphp.org" rel="noopener noreferrer"&gt;ReactPHP&lt;/a&gt; that do. We will touch on them in a different post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine a chef preparing a meal. Instead of cooking the entire dish and cleaning everything afterward, the chef alternates between cooking steps and quick cleaning tasks. While both routes would have the same result, alternating makes for a cleaner work environment.&lt;/p&gt;

&lt;p&gt;Here is what that could look like in code, using Fibers.&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;$cooking&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;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$steps&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Meal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Ready to cook.'&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;$steps&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$step&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="c1"&gt;// Perform step.  &lt;/span&gt;
        &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$step&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;" finished"&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Meal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;  

&lt;span class="nv"&gt;$cleaning&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;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Waiting for something to clean.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

    &lt;span class="k"&gt;while&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="c1"&gt;// Cleaning.&lt;/span&gt;
        &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Finished cleaning'&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;$cooking&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'chopping'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mixing'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'cooking'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'plating'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Ready to cook.&lt;/span&gt;
&lt;span class="nv"&gt;$cleaning&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Waiting for something to clean.&lt;/span&gt;

&lt;span class="c1"&gt;// Alternate between cooking and cleaning.&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$cooking&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isTerminated&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"[Cooking] %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$cooking&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"[Cleaning] %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$cleaning&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$meal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$cooking&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getReturn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this could happen in code, too. Code uses memory, which can routinely be freed up to keep memory usage low. Especially when you are processing a lot of data, this constant switching between processing and cleaning can drastically improve your code's efficiency.&lt;/p&gt;

&lt;p&gt;Where cooperative multitasking really shines is when you combine it with background processing. Instead of waiting for a function to finish its computation, you could allow the calling code to perform other tasks, while in the background the computation is finished. Then the function could pick up where it left off at a later moment, when the computation is completed.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR (but scrolled here anyway)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Coroutines are functions that can pause and resume execution while retaining internal state.&lt;/li&gt;
&lt;li&gt;PHP supports coroutines through &lt;strong&gt;Generators&lt;/strong&gt; (asymmetric, stackless) and &lt;strong&gt;Fibers&lt;/strong&gt; (asymmetric, stackful).&lt;/li&gt;
&lt;li&gt;Use Generators for iteration and memory efficiency.&lt;/li&gt;
&lt;li&gt;Use Fibers for cooperative multitasking and nested suspension.&lt;/li&gt;
&lt;li&gt;Real-world applications include CLI tools, state machines, and async workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Coming Up: Coroutines in Practice
&lt;/h2&gt;

&lt;p&gt;Now that we've explored what coroutines are and how PHP supports them through Generators and Fibers, the next step is putting them to work. In a next post, we’ll dive into &lt;em&gt;concurrency&lt;/em&gt; in PHP, exploring event loops like &lt;a href="https://revolt.run" rel="noopener noreferrer"&gt;Revolt&lt;/a&gt;, coroutine schedulers, and async libraries like &lt;a href="https://reactphp.org" rel="noopener noreferrer"&gt;ReactPHP&lt;/a&gt;. We’ll see how coroutines fit into the bigger picture of building responsive, non-blocking PHP applications.&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>generators</category>
      <category>programming</category>
    </item>
    <item>
      <title>Reading bundle configuration inside Symfony Compiler Passes</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Thu, 04 May 2023 15:29:20 +0000</pubDate>
      <link>https://dev.to/doekenorg/reading-bundle-configuration-inside-symfony-compiler-passes-27nn</link>
      <guid>https://dev.to/doekenorg/reading-bundle-configuration-inside-symfony-compiler-passes-27nn</guid>
      <description>&lt;p&gt;When creating a Symfony bundle, you'll often want to use a custom &lt;code&gt;Configuration&lt;/code&gt; to configure, or even add, various services during the compilation of the service container. Symfony provides this option by implementing an &lt;a href="https://symfony.com/doc/current/bundles/extension.html" rel="noopener noreferrer"&gt;Extension&lt;/a&gt;. While an &lt;code&gt;Extension&lt;/code&gt; provides a lot of options to do so, a big configuration can easily create a massive extension class that does way too much.&lt;/p&gt;

&lt;p&gt;An alternative to this approach is using &lt;strong&gt;Compiler Passes&lt;/strong&gt; to split up all the logic into separate steps. A big drawback however is that by default these compiler passes don't have access to the final compiled configuration.&lt;/p&gt;

&lt;p&gt;To get around this problem, an often used solution is to store (parts of) the configuration in a temporary transient parameter on the service container. Because the compiler pass has access to (a copy) of the container, you can read that parameter and remove it from the container before compiling is completed.&lt;/p&gt;

&lt;p&gt;Although this is a viable option, the use of these temporary values always seemed a bit off to me; plus the developer must be very conscious of removing the values afterwards. Let's look at a great alternative option of providing this configuration to the compiler passes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Injecting the extension into the compiler passes
&lt;/h2&gt;

&lt;p&gt;Because the &lt;code&gt;Extension&lt;/code&gt; is &lt;em&gt;the&lt;/em&gt; location where the configurations of that bundle are aggregated and combined, it should serve as the only trustworthy source for the configuration. That means we should only retrieve the configuration from the extension class.&lt;/p&gt;

&lt;p&gt;As luck would have it; you initialize and add a compiler pass in the &lt;code&gt;build()&lt;/code&gt; method on the bundle class. This class also has access to the extension, by use of the &lt;code&gt;getContainerExtension()&lt;/code&gt; method. That means we can inject the &lt;br&gt;
extension into our compiler pass like this:&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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\HttpKernel\Bundle\Bundle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyEpicBundle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Bundle&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;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ContainerBuilder&lt;/span&gt; &lt;span class="nv"&gt;$container&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;$extension&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="nf"&gt;getContainerExtension&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;$extension&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;MyEpicExtension&lt;/span&gt;&lt;span class="p"&gt;)&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;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addCompilerPass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyEpicCompilerPass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$extension&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;p&gt;To accept the extension in the compiler pass, we need to make sure to receive it as its first 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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface&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\DependencyInjection\ContainerBuilder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyEpicCompilerPass&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;CompilerPassInterface&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;MyEpicExtension&lt;/span&gt; &lt;span class="nv"&gt;$extension&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;function&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ContainerBuilder&lt;/span&gt; &lt;span class="nv"&gt;$container&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;// ... We want our configuration here.&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;
  
  
  Retrieving the configuration from the extension
&lt;/h2&gt;

&lt;p&gt;An extension &lt;strong&gt;has&lt;/strong&gt; to implement a &lt;code&gt;load()&lt;/code&gt; method that receives all provided configurations (e.g. from the project or other bundles that need to configure this bundle), as well as a copy of the container. To compile all these configurations into a final configuration array you can either use a &lt;code&gt;Processor&lt;/code&gt;, or use the &lt;code&gt;Extension::processConfiguration()&lt;/code&gt; method if you extend the base &lt;code&gt;Extension&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In either case, you will probably want to avoid processing the configuration multiple times; so let's add a micro cache that contains the compiled configuration, and retrieves only that.&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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\DependencyInjection\Extension\Extension&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyEpicExtension&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Extension&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;array&lt;/span&gt; &lt;span class="nv"&gt;$config&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;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$configs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ContainerBuilder&lt;/span&gt; &lt;span class="nv"&gt;$contaienr&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;$loader&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;YamlFileLoader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileLocator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/../../config'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nv"&gt;$loader&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'services.yaml'&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="nf"&gt;compileConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$configs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Compiles and stores the configuration once.
     */&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;compileConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$configs&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;$configuration&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;Configuration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// This is our bundle's configuration class.&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;config&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="nf"&gt;processConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$configuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$configs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="cd"&gt;/**  
     * Retrieves the configuration for the bundle.
     */&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;getConfig&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&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;config&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we are able to retrieve the entire bundle configuration in our Compiler Pass by calling the &lt;code&gt;getConfig()&lt;/code&gt; method on the extension.&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;// MyEpicCompilerPass.php&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;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ContainerBuilder&lt;/span&gt; &lt;span class="nv"&gt;$container&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;$config&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;extension&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getConfig&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/symfony/http-kernel/blob/6.2/DependencyInjection/MergeExtensionConfigurationPass.php" rel="noopener noreferrer"&gt;compiling of the extension configurations&lt;/a&gt; is actually done in a compiler pass. This is called the &lt;em&gt;Merge Pass&lt;/em&gt; and is the &lt;a href="https://github.com/symfony/dependency-injection/blob/6.2/Compiler/PassConfig.php#L108" rel="noopener noreferrer"&gt;first compiler pass to be processed&lt;/a&gt;. Because of this, once our custom compiler pass reads the configuration of off the extension, we can be sure it is already compiled, cached and ready for use.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it
&lt;/h2&gt;

&lt;p&gt;As I said; there are alternative ways of using configuration inside a compiler pass. And a compiler pass might not even be necessary in some cases. A small configuration could very well be processed inside the bundle extension. Like always "it depends"; but this too is a nice thing to have in your tool belt.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope you enjoyed reading this post! If so, please leave a 👍 reaction or a 💬 comment and consider subscribing to my newsletter! You can also follow me on 🐦 &lt;a href="https://twitter.com/intent/follow?screen_name=doekenorg" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; for more content and the occasional tip.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>symfony</category>
      <category>php</category>
      <category>tip</category>
    </item>
    <item>
      <title>How the PHP Middleware Pattern works and can easily be applied</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Wed, 04 May 2022 05:24:58 +0000</pubDate>
      <link>https://dev.to/doekenorg/how-the-php-middleware-pattern-works-and-can-easily-be-applied-2hb6</link>
      <guid>https://dev.to/doekenorg/how-the-php-middleware-pattern-works-and-can-easily-be-applied-2hb6</guid>
      <description>&lt;p&gt;In this post we'll be looking at Middleware in PHP. This pattern is most common in the handling of requests and responses. But the Middleware Pattern can also be applied in various other places. We'll look into what middleware is, how middleware works, when middleware can be useful and what an alternative to middleware might be.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; The middleware pattern is not part of the patterns introduced by the &lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Design_Patterns" rel="noopener noreferrer"&gt;Gang of Four&lt;/a&gt;, but I personally still view it as a pattern, as it can be applied in various situations.&lt;/em&gt; &lt;/p&gt;
&lt;h2&gt;
  
  
  What is Middleware?
&lt;/h2&gt;

&lt;p&gt;Middleware in PHP is a layer of actions / callables that are wrapped around a piece of core logic in an application. These middlewares provide the ability to change either the input or the output of this logic. So they "live" between the input and the output, right in the &lt;em&gt;middle&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;While these short explanations are obviously very easy to follow and &lt;em&gt;click&lt;/em&gt; instantly, let me illustrate this with a small 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="nv"&gt;$input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="nv"&gt;$output&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="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, a Middleware layer is able to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;change &lt;code&gt;$input&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; it is injected into &lt;code&gt;$this-&amp;gt;action()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;change &lt;code&gt;$output&lt;/code&gt; &lt;em&gt;after&lt;/em&gt; it was returned by &lt;code&gt;$this-&amp;gt;action()&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's look at how it does this.&lt;/p&gt;

&lt;h3&gt;
  
  
  How middleware works
&lt;/h3&gt;

&lt;p&gt;The Middleware layer consists of a stack of middleware callables. These can be either a simple &lt;code&gt;Closure&lt;/code&gt;, an invokable class or a method on a class.&lt;/p&gt;

&lt;p&gt;Each one of the middleware callables is wrapped around the core action. Alright, I'll say it; it's like an &lt;em&gt;onion&lt;/em&gt;, or a present with multiple layers of wrapping paper. The input gets injected into the first middleware (or most outer layer). The middleware can do something with the input, and then pass that (changed) input along to the next middleware, and the next, and the next, until it reaches the final action (the core). By this time, the input maybe changed a little or a lot.&lt;/p&gt;

&lt;p&gt;Then the core action is executed and returns its output to the last middleware, which returns its output back to the previous middleware, all the way back to the first middleware. On its way back, every middleware can now change the output before it gets returned.&lt;/p&gt;

&lt;p&gt;Before we look at some examples, let's first explore the different types of middleware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of middleware
&lt;/h2&gt;

&lt;p&gt;While the concept of middleware is pretty much the same between them, there are actually &lt;em&gt;two&lt;/em&gt; common types of middleware: &lt;em&gt;Single Pass Middleware&lt;/em&gt; &amp;amp; &lt;em&gt;Double Pass Middleware&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Pass middleware
&lt;/h3&gt;

&lt;p&gt;The most common type of middleware is &lt;em&gt;Single Pass Middleware&lt;/em&gt;. With this type every middleware callable receives two parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the input (e.g. a request, message, DTO or scalar value)&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;callable&lt;/code&gt; to invoke the next middleware in the chain, that also receives a &lt;em&gt;single&lt;/em&gt; parameter: the input.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In some conventions the callable parameter is called &lt;code&gt;$next&lt;/code&gt; to indicate the invocation of the next middleware.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This type of middleware can change the input and forward that modified version to the next middleware. To affect the output; it will first call the next middleware and retrieve its output. It can then modify that output and return this instead.&lt;/p&gt;

&lt;p&gt;Here is a small example middleware to illustrate the full behavior.&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="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Receive the input and change it.&lt;/span&gt;
  &lt;span class="nv"&gt;$input&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="nf"&gt;changeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Call the next middleware or final action with the changed input, and receive the output.&lt;/span&gt;
  &lt;span class="nv"&gt;$output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

  &lt;span class="c1"&gt;// Change the output, and return it to the previous middleware or final consumer.&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="nf"&gt;changeOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$output&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;h3&gt;
  
  
  Double Pass Middleware
&lt;/h3&gt;

&lt;p&gt;The second type of middleware is &lt;em&gt;Double Pass Middleware&lt;/em&gt;. With this type every middleware also receives a default &lt;em&gt;output&lt;/em&gt; object as a parameter. So the "double" part refers to the middleware passing along both the input and an output to the next middleware / final action.&lt;/p&gt;

&lt;p&gt;Why is this useful? In the &lt;em&gt;Single Pass&lt;/em&gt; type a middleware must either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the required output object when short-circuiting (not calling &lt;code&gt;$next&lt;/code&gt; but returning a different result).&lt;/li&gt;
&lt;li&gt;Call the &lt;code&gt;$next&lt;/code&gt; middleware(s) to retrieve an output object, and change that.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Depending on the type of output, it can be cumbersome or even undesirable to make the middleware depend on a service or factory to create that output type. And it can be just as undesirable to call (and possibly instantiate) every other middleware and final action, only to discard everything they do; and change the output object completely.&lt;/p&gt;

&lt;p&gt;So with the &lt;em&gt;Double Pass&lt;/em&gt; a default output object is created beforehand and passed around. This way the middleware already has an output object of the correct type it can use when it wants to short-circuit.&lt;/p&gt;

&lt;p&gt;Here is another small example to illustrate the full behavior.&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="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Quickly return the output object, instead of passing it along.&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasSomeReason&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&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;$output&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Call the next middleware and return that output instead of the default output.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$output&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 we know what a middleware callable looks like, but how can we wrap all these middlewares on top of an action?&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple middleware implementation
&lt;/h2&gt;

&lt;p&gt;Let's dive into some code, and create a very basic &lt;em&gt;Single Pass&lt;/em&gt; middleware implementation. In this example we will prepend &amp;amp; append some value to a string (re-)using a single middleware class.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There are many ways a middleware implementation can be built. This example isn't very optimized, and there is lots of room for improvement. But this example is really to demonstrate the inner workings of middleware as clear as possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As we've seen, we first need a core action (or function) to wrap our middleware around. Our action will simply receive&lt;br&gt;
and return a string.&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;$action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&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;$input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll create an invokable middleware class that we can use multiple times with a different value to prepend and append.&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;ValueMiddleware&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="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="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;string&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$next&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="c1"&gt;// Prepend value to the input.&lt;/span&gt;
        &lt;span class="nv"&gt;$output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$next&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;value&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Append value to the output.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$output&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;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;The middleware class is instantiated with a &lt;code&gt;$value&lt;/code&gt;. This instance will be our middleware callable, since it is an invokable class. Let's create 3 of them:&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;$middlewares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ValueMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ValueMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ValueMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'3'&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 we'll add all of these middlewares as a layer around our &lt;code&gt;$action&lt;/code&gt;, and then we'll examine the code.&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;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$middlewares&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$middleware&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&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;$input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$action&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;Let's look at what is happening in this loop.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At first the &lt;code&gt;$action&lt;/code&gt; closure is our simple callback which returns the &lt;code&gt;$input&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the first loop &lt;code&gt;$action&lt;/code&gt; is overwritten with a new closure that also receives the &lt;code&gt;$input&lt;/code&gt; (just like the initial action). When this closure is executed, it will call the first middleware, and provide that input, as well as our initial &lt;code&gt;$action&lt;/code&gt;. So inside that middleware &lt;code&gt;$next&lt;/code&gt; is now the original action.&lt;/li&gt;
&lt;li&gt;In the second and third loop &lt;code&gt;$action&lt;/code&gt; is overwritten again, but in this middleware the &lt;code&gt;$next&lt;/code&gt; callable is not the original action, but the closure we set at the previous iteration.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; As we can see, &lt;code&gt;$next&lt;/code&gt; never directly refers to a middleware. It can't, because the middleware method signature expects 2 parameters, while &lt;code&gt;$next&lt;/code&gt; only receives one; the input. &lt;code&gt;$next&lt;/code&gt; is always a callable which is responsible for calling the next middleware. So this can also be a method on a middleware handler that contains and keeps track of a list of (applied) middlewares.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And that's it. Our middleware implementation is complete. All we need to do now is run the &lt;code&gt;$action&lt;/code&gt; with a value, and check out the response.&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="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this will of course be: &lt;code&gt;123value123&lt;/code&gt;... wait what? Did you expect &lt;code&gt;123value321&lt;/code&gt;? That would make the whole onion thing make more sense, right? But it is actually correct.&lt;/p&gt;

&lt;p&gt;The middleware that prepends and appends &lt;code&gt;1&lt;/code&gt; is applied first, but is then wrapped with &lt;code&gt;2&lt;/code&gt;, which in turn is wrapped by &lt;code&gt;3&lt;/code&gt;. So middleware 3 is the first to prepend &lt;code&gt;3&lt;/code&gt; on the input, but it is also the &lt;em&gt;last&lt;/em&gt; middleware to append that value. It's a bit of a mind-bender, but when we check out the &lt;code&gt;$input&lt;/code&gt; and &lt;code&gt;return&lt;/code&gt; for every middleware we end up with this list:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Middleware&lt;/th&gt;
&lt;th&gt;$input&lt;/th&gt;
&lt;th&gt;return&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Middleware 3&lt;/td&gt;
&lt;td&gt;value&lt;/td&gt;
&lt;td&gt;123value123&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Middleware 2&lt;/td&gt;
&lt;td&gt;3value&lt;/td&gt;
&lt;td&gt;123value12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Middleware 1&lt;/td&gt;
&lt;td&gt;23value&lt;/td&gt;
&lt;td&gt;123value1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core-action&lt;/td&gt;
&lt;td&gt;123value&lt;/td&gt;
&lt;td&gt;123value&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Working our way down the &lt;code&gt;$input&lt;/code&gt; list, and back up the &lt;code&gt;return&lt;/code&gt; list, we can see what stages the value passes through in this entire middleware flow.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If you want the order of middlewares to be outside-in, where the top of the list is the first one to be called, you should &lt;code&gt;array_reverse&lt;/code&gt; the array, or use a Last-In-First-Out (LIFO) iterator like a &lt;code&gt;Stack&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Request and Response middleware
&lt;/h2&gt;

&lt;p&gt;One of the most common places you'll find middleware being used is within a framework that transforms a &lt;code&gt;Request&lt;/code&gt; object into a &lt;code&gt;Response&lt;/code&gt; object. &lt;a href="https://www.php-fig.org/psr/psr-15/" rel="noopener noreferrer"&gt;PSR-15: HTTP Server Request Handlers&lt;/a&gt; in the PHP Standard Recommendation (PSR), is a recommendation on how a (&lt;a href="https://www.php-fig.org/psr/psr-7/" rel="noopener noreferrer"&gt;PSR-7&lt;/a&gt;) &lt;code&gt;Request&lt;/code&gt; object should be handled and turned into a &lt;code&gt;Response&lt;/code&gt; object. This recommendation also contains the &lt;code&gt;Psr\Http\Server\MiddlewareInterface&lt;/code&gt;. This interface favors the use of a &lt;code&gt;process&lt;/code&gt; method on a middleware class, but the principle is the same. It receives an input (the &lt;code&gt;Request&lt;/code&gt; object), modifies it, and passes it along to &lt;code&gt;RequestHandler&lt;/code&gt; which will trigger the next middleware or final action.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; &lt;a href="https://docs.mezzio.dev/" rel="noopener noreferrer"&gt;Laminas' Mezzio&lt;/a&gt; is a minimal PSR-7 middleware Framework which provides a set of PSR-15 middlewares. And while most frameworks that work with PSR-7 and PSR-15 use &lt;em&gt;Single Pass Middleware&lt;/em&gt; (since that&lt;br&gt;
is what PSR-15 recommends) it also provides a &lt;a href="https://docs.mezzio.dev/mezzio/v3/cookbook/double-pass-middleware/#using-double-pass-middleware" rel="noopener noreferrer"&gt;&lt;em&gt;Double Pass Middleware&lt;/em&gt; Decorator&lt;/a&gt;, so those will also work with these PSRs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://doeken.org/blog/decorator-vs-proxy-pattern" rel="noopener noreferrer"&gt;Learn more about decorators and proxies&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Examples of Request and Response middlewares
&lt;/h3&gt;

&lt;p&gt;Middlewares can be used to perform all kinds of actions and checks during a request, so the main action (controller) can focus on the task at hand. Let's look at a few examples of middleware that can be useful.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cross-site request forgery (CSRF) validation middleware
&lt;/h4&gt;

&lt;p&gt;To prevent a &lt;a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery" rel="noopener noreferrer"&gt;CSRF&lt;/a&gt; attack a framework can choose to add a certain validation to a request. This validation need to happen before the main action is triggered. In this case a middleware can examine the request object. If it deems the request valid, it can pass it along to the next handler. But if the validation fails, the middleware can immediately short-circuit the request, and return a &lt;code&gt;403 Forbidden&lt;/code&gt; response.&lt;/p&gt;

&lt;h4&gt;
  
  
  Multi-tenant middleware
&lt;/h4&gt;

&lt;p&gt;Some applications allow for &lt;a href="https://en.wikipedia.org/wiki/Multitenancy" rel="noopener noreferrer"&gt;multi-tenancy&lt;/a&gt;, which basically means the same source code is used for different customers; e.g. by hooking up a separate database / source per customer. A middleware can inspect the request and figure out (for instance by checking the request URL) what database should be selected, or which customer should be loaded. It can even attach that &lt;code&gt;Customer&lt;/code&gt; entity (if one exists) to the &lt;code&gt;Request&lt;/code&gt; object, so the core action can read the proper information off the request object, instead of having to figure out the correct customer itself.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exception handling middleware
&lt;/h4&gt;

&lt;p&gt;Another great type of middleware is the handling of exceptions. If this middleware is applied as the outermost middleware it can wrap the entire request to response flow in a try-catch block. If an exception is thrown, this middleware can log the exception and then return a properly configured response object which contains information about the exception.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other real world examples of middleware
&lt;/h2&gt;

&lt;p&gt;While middleware is most common in the handling of requests and responses, there are other use cases. Here are a some examples:&lt;/p&gt;

&lt;h3&gt;
  
  
  Symfony Messenger middleware
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://symfony.com/doc/current/messenger.html" rel="noopener noreferrer"&gt;Queue handler of Symfony&lt;/a&gt; &lt;code&gt;symfony/messenger&lt;/code&gt; uses middleware to manipulate the &lt;code&gt;Message&lt;/code&gt; when it is sent to the queue, and when it is read from the queue and handled by the &lt;code&gt;MessageHandler&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One example of these is the &lt;code&gt;router_context&lt;/code&gt; middleware. Because messages are (mostly) handled asynchronous, the original &lt;code&gt;Request&lt;/code&gt; is not available. This middleware stores the original &lt;code&gt;Request&lt;/code&gt; state (things like the host and HTTP port) when it is sent to the queue and restores this when the &lt;code&gt;Message&lt;/code&gt; is handled, so the handler can use this context to build up things like absolute URLs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guzzle middleware
&lt;/h3&gt;

&lt;p&gt;While also somewhat in the realm of Request and Response; the Guzzle HTTP Client also supports the use of &lt;a href="https://docs.guzzlephp.org/en/stable/handlers-and-middleware.html#middleware" rel="noopener noreferrer"&gt;middleware&lt;/a&gt;. These again allow you to change the request and response to and from the HTTP request. This implementation works a bit different, but still revolves around a callback that triggers the next middleware / action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative to middleware
&lt;/h2&gt;

&lt;p&gt;Like we've seen, middleware essentially allows us to change input and output respectively &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; a core action, within a single function / callable. So a great alternative to middleware would be to provide event hooks &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; the core action. With these events you can change the input before it hits the core action, and maybe even return early. And afterwards you can change the output.&lt;/p&gt;

&lt;p&gt;Both of these options work quite well. For instance &lt;a href="https://laravel.com/docs/9.x/middleware#introduction" rel="noopener noreferrer"&gt;Laravel uses middleware&lt;/a&gt; around their Request and Response flow, while &lt;a href="https://symfony.com/doc/current/reference/events.html" rel="noopener noreferrer"&gt;Symfony uses the Events&lt;/a&gt; approach.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you want to learn more about events, you can check out my (quite lengthy) blog post on &lt;a href="https://doeken.org/blog/event-dispatching-exploration" rel="noopener noreferrer"&gt;Event Dispatching&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Thanks for reading
&lt;/h2&gt;

&lt;p&gt;When using middleware you can easily create a separation of concerns within your code. Every middleware has a tiny job to do. It can easily be tested; and the core action can focus on what it does best, without worrying about any possible edge cases or side effects. And while it currently mostly revolves around (PSR-7) Request and Response objects, the pattern can be used widely. Do you have other ideas where this pattern can be useful? Let me know!&lt;/p&gt;

</description>
      <category>php</category>
      <category>designpatterns</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using callbacks to prevent code duplication</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Mon, 11 Apr 2022 11:57:25 +0000</pubDate>
      <link>https://dev.to/doekenorg/using-callbacks-to-prevent-code-duplication-aj7</link>
      <guid>https://dev.to/doekenorg/using-callbacks-to-prevent-code-duplication-aj7</guid>
      <description>&lt;p&gt;Sometimes it can be useful to use a callback function or other &lt;code&gt;callable&lt;/code&gt; to prevent a bunch of code duplication.&lt;/p&gt;

&lt;p&gt;Let's say you have an event subscriber that encrypts and decrypts data in the life cycle of an entity. When the entity is stored, some data will be encrypted; and when the entity is loaded, the data will be decrypted.&lt;/p&gt;

&lt;p&gt;Here is a maybe somewhat contrived but minimal example of this:&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;EncryptionSubscriber&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;CryptographerInterface&lt;/span&gt; &lt;span class="nv"&gt;$cryptographer&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;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getEncryptedProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Entity&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// some code to detect the encrypted properties of the entity.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'encrypted'&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;onSave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="nv"&gt;$event&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;$entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getEntity&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getEncryptedProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$property&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;cryptographer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;encrypt&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;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;onLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="nv"&gt;$event&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;$entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getEntity&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getEncryptedProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$property&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;cryptographer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;decrypt&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;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;While this isn't that bad, the &lt;code&gt;onSave&lt;/code&gt; and &lt;code&gt;onLoad&lt;/code&gt; are practically the same method; only the content of &lt;code&gt;setValue()&lt;/code&gt; is different. And to be honest, with two tiny functions like these; I might not bother. But it often happens that three or even more methods are the same. Or the functions are way more elaborate; while they still only differ by a tiny thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extracting a &lt;code&gt;callback&lt;/code&gt; helper
&lt;/h2&gt;

&lt;p&gt;A solution to this duplication can be to extract one helper method that contains all the logic once. But at the point where the logic is different we call a &lt;code&gt;callable&lt;/code&gt; which is injected. The original &lt;code&gt;onSave&lt;/code&gt; and &lt;code&gt;onLoad&lt;/code&gt; will then defer to that helper method, and provide the &lt;code&gt;callable&lt;/code&gt; to handle the specific difference.&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;EncryptionSubscriber&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;onSave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="nv"&gt;$event&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;processEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cryptographer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;encrypt&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;onLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="nv"&gt;$event&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;processEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cryptographer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;decrypt&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="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;processEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Event&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="nv"&gt;$callback&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;$entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getEntity&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getEncryptedProperties&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$callback&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="c1"&gt;// [tl! highlight]&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;As you can see, we added a &lt;code&gt;processEvent()&lt;/code&gt; method that also receives a &lt;code&gt;callable $callback&lt;/code&gt;. This callback is executed with the current value instead of the previous &lt;code&gt;encrypt&lt;/code&gt; or &lt;code&gt;decrypt&lt;/code&gt; calls. This makes the entire method a very generic implementation. Only the specific difference is handled by the callback.&lt;/p&gt;

&lt;p&gt;If the callback needs more context to do its job, that can be added as additional parameters on the &lt;code&gt;$callback()&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;While the &lt;code&gt;onSave&lt;/code&gt; and &lt;code&gt;onLoad&lt;/code&gt; still have some necessary duplication; the amount is way less and the difference is easier to spot. And with the help of some shorthand &lt;code&gt;fn&lt;/code&gt; it's very readable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts and comments?
&lt;/h2&gt;

&lt;p&gt;Like I said, there is a time and place for things like this. If the duplication is minimal; you might not need to bother with it. But I think it's a nice tool to know. Do you have other nice examples where this would be useful? Please share it with the rest of us. And if you have any other comments, drop them below.&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Heaps explained in PHP | Quick access to the highest or lowest value of a dataset</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Mon, 27 Dec 2021 11:41:34 +0000</pubDate>
      <link>https://dev.to/doekenorg/heaps-explained-in-php-quick-access-to-the-highest-or-lowest-value-of-a-dataset-186a</link>
      <guid>https://dev.to/doekenorg/heaps-explained-in-php-quick-access-to-the-highest-or-lowest-value-of-a-dataset-186a</guid>
      <description>&lt;p&gt;In this article we'll explore the world of Heaps, the data structure. Because some knowledge of Trees is useful I highly suggest you read my &lt;a href="https://doeken.org/blog/tree-traversal-in-php" rel="noopener noreferrer"&gt;Trees and Tree Traversal in PHP&lt;/a&gt; article before diving into this one.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I did my best to provide some visual aid for Heaps, because it can be hard to visualize some steps. If you have trouble understanding the concept through this blog post, I suggest you also watch the videos linked at the end of the post. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is a Heap?
&lt;/h2&gt;

&lt;p&gt;A Heap is a data structure. So it is a way of how data is organized and how it can be accessed in an efficient way. There are many types of data structures, like: (Doubly) Linked Lists, Graphs, Stacks, Queues, Arrays and HashMaps. Each of these data types can be used for various use cases; but some are more performant than others in certain situations.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎄 A Heap is a Binary Tree
&lt;/h3&gt;

&lt;p&gt;The data structure of a Heap is a Binary Tree. Starting with a Root-node, every node has a maximum of two children; left &amp;amp; right. But there are two rules these trees have to follow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heap rule #1: The parent node has a lower value (MinHeap) or a higher value (MaxHeap) than its children
&lt;/h3&gt;

&lt;p&gt;There are two types of heaps: a &lt;em&gt;MinHeap&lt;/em&gt; and a &lt;em&gt;MaxHeap&lt;/em&gt;. The difference between these are the order in which the nodes are placed inside the Tree.&lt;/p&gt;

&lt;p&gt;The children of a node in a &lt;em&gt;MinHeap&lt;/em&gt; have a higher value then their parent, while the children of a node in a &lt;em&gt;MaxHeap&lt;/em&gt; will have a lower value then their parent. If there are two identical values, a node can have a child with the same value. This behavior flows all the way down the Tree.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The naming of the heaps refers to the value of the top, or Root-node, of the Tree. This means the top of a MinHeap will always be the lowest value (min) of the nodes, and in a MaxHeap it will be the highest value (max).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Heap rule #2: A Heap is a &lt;em&gt;Complete Binary Tree&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;There are 5 types of Binary Trees:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;Full Binary Trees&lt;/em&gt;: every node has zero ór two children; but never one&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Perfect Binary Trees&lt;/em&gt;:  every node has exactly two children&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Balanced Binary Trees&lt;/em&gt;: the left and right sub-branch of a node never vary by more than one node&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Degenerate Binary Trees:&lt;/em&gt; every node has a single child, essentially making it like a single line list&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Complete Binary Tree&lt;/em&gt;: every row of the Tree is filled from left to right, without leaving gaps between nodes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So in a Complete Binary Tree, and thus also a Heap, it is &lt;strong&gt;not possible&lt;/strong&gt; to have a node with only a &lt;em&gt;right&lt;/em&gt; child-node. But it &lt;em&gt;ís&lt;/em&gt; possible to have one with only a &lt;em&gt;left&lt;/em&gt; child node.  &lt;/p&gt;

&lt;h2&gt;
  
  
  🔨 Creating a Heap
&lt;/h2&gt;

&lt;p&gt;Enough theory; let's look at an example of a Heap.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In this example we'll use numbers (integers) that represent the values. But that's mostly for simplicity's sake. These values can be strings, objects, whatever you want; as long as you can compare them and figure out which is the lesser or greater of the two.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's say we have a list of values. I'll put it in a PHP array to make it look pretty:&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;$values&lt;/span&gt; &lt;span class="o"&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;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;36&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;2&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="o"&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;72&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll make this list into a MaxHeap. Remember; in this case the highest value goes at the Root-node, making the values decrease every level of the tree. So in this case our Root-node will be &lt;code&gt;72&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This root-node will have two children. Those values will be &lt;code&gt;36&lt;/code&gt; and &lt;code&gt;18&lt;/code&gt;, because those the next highest two values. The position of these values doesn't really matter at this point, they can both be either left or right.&lt;/p&gt;

&lt;p&gt;Both of these values can have 2 children; so lets find the next 4 values in declining order from the list: &lt;code&gt;5&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;,&lt;code&gt;2&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;. Again there exact position doesn't matter, because they are all lower then &lt;code&gt;18&lt;/code&gt; and &lt;code&gt;36&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And our final remaining number &lt;code&gt;-5&lt;/code&gt; will be the last child; the most left value on the lowest level of the tree. This makes our Complete Binary Tree complete.&lt;/p&gt;

&lt;p&gt;So this is the MaxHeap we created:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Fheaps-explained-in-php%2FMaxHeap.png" class="article-body-image-wrapper"&gt;&lt;img alt="Example of a MaxHeap" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Fheaps-explained-in-php%2FMaxHeap.png" width="706" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The last node&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The node that is the most right node (filled from the left) at the bottom of a Complete Binary Tree is called &lt;em&gt;the last node&lt;/em&gt;. In our example this is &lt;code&gt;-5&lt;/code&gt;. We'll come back to this node when we start extracting nodes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At this point you might be thinking: &lt;em&gt;this feels like cheating&lt;/em&gt;. And yes, I know; we cheated a bit by sorting the integers in our head from largest to smallest first, and then filling out the Heap from left to right. But that is actually the fastest way of creating a MaxHeap. However, what if we didn't know the values up front, or if they came in a random order? How would we fill out this MaxHeap?&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding values to an empty Heap
&lt;/h3&gt;

&lt;p&gt;So now let's create a Heap without sorting the numbers beforehand. In this case it would be a more iterative process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We add the first value to the heap (in our case &lt;code&gt;2&lt;/code&gt;). This will become our root-node by default.&lt;/li&gt;
&lt;li&gt;We insert the second value (&lt;code&gt;18&lt;/code&gt;) at the first available location (left child).&lt;/li&gt;
&lt;li&gt;We compare this value to its parent (the Root-node in this case). If it is bigger that the parent, swap them; otherwise go back to step 2 for the next value. (we need to swap)&lt;/li&gt;
&lt;li&gt;Repeat step 3 until there are no other parents to swap with (there are no other parents)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After this we go back to step 2 and insert the next value: &lt;code&gt;36&lt;/code&gt; (In our case the right child of the Root-node). We compare it to its parent. It is bigger, so we swap. &lt;code&gt;36&lt;/code&gt; is now the root with &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;18&lt;/code&gt; as its children.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This swapping of values with a parent to put the values in the correct spot is referred to as &lt;strong&gt;sifting up&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next value to add will be &lt;code&gt;5&lt;/code&gt;.  Again, we insert it at the first available location in the Tree (step 2). In this case the left child of &lt;code&gt;2&lt;/code&gt;. We compare it to its parent and swap (step 3), because &lt;code&gt;5&lt;/code&gt; is bigger than &lt;code&gt;2&lt;/code&gt;. We repeat step 3, but this parent (&lt;code&gt;36&lt;/code&gt;) is bigger, so we are done. Next!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Boring!&lt;/em&gt; - Ok, let's stop this explanation here. I think you get the point. If you really want a more in-depth visualization; I've added some useful links at the end of this article including a video explanation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extracting a value from a Heap
&lt;/h3&gt;

&lt;p&gt;We've seen how you can add a value to the Heap By injecting it, and then sifting it up. But how can you extract a value? It isn't as simple as removing the node, because that might cut the Tree in half. Take the Root-node for instance. On a Heap it's very likely you want to extract that value. But simply removing it will create two new Trees.&lt;/p&gt;

&lt;p&gt;To avoid this Tree splitting, we need to replace (or swap) the Root-node with &lt;em&gt;the last node&lt;/em&gt;. In a heap the last node can always be removed from a Tree, without corrupting it, because the Tree is already sorted.&lt;/p&gt;

&lt;p&gt;However, when we swap the Root-node with the last node, and extract it, the Tree will no longer be a Heap at that point, because the wrong value will be at the top. So we need to turn this Tree into a Heap again, starting with the Root-node. This process is not as lengthy as turning an entire unsorted Tree into a Heap, because most of the Tree is already in the correct order.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The transforming of a Binary Tree into a Heap, is known as to &lt;strong&gt;Heapify&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of sifting the Root-node &lt;em&gt;up&lt;/em&gt;, we need to sift the Root-node &lt;em&gt;down&lt;/em&gt;. In this case we need to compare the node to both its children, and swap it with the largest of the two. And keep repeating it, until the node is in its correct position. At this point the Tree is once again a Heap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Heap in PHP
&lt;/h2&gt;

&lt;p&gt;Creating a Heap is made easy in PHP by using the &lt;a href="https://www.php.net/manual/en/class.splheap.php" rel="noopener noreferrer"&gt;&lt;code&gt;abstract SplHeap&lt;/code&gt;&lt;/a&gt; class. It contains all methods of an &lt;code&gt;Iterator&lt;/code&gt; as well as a few helper methods that are specific to a Heap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;extract()&lt;/code&gt; - Removes and returns the Root-node from the Heap, and reorders the Heap with a new Root node.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;insert($value)&lt;/code&gt; - Adds a new value to the Heap and reorders it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top()&lt;/code&gt; - Only returns the current Root node value; it does not change the cursor of the iterator or remove the node.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isCorrupted()&lt;/code&gt; - Returns whether the current Heap is in a corrupted state (this happens when the &lt;code&gt;compare()&lt;/code&gt; function throws an exception).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;recoverFromCorruption()&lt;/code&gt; - resets the corrupted state of the heap and allows for further use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then there is also &lt;code&gt;abstract protected function compare($value1, $value2): int&lt;/code&gt;. This function is used inside the Heap algorithm to determine how it should order two values / nodes.&lt;/p&gt;

&lt;p&gt;PHP also provides a &lt;a href="https://www.php.net/manual/en/class.splminheap.php" rel="noopener noreferrer"&gt;&lt;code&gt;SplMinHeap&lt;/code&gt;&lt;/a&gt; and a &lt;a href="https://www.php.net/manual/en/class.splmaxheap.php" rel="noopener noreferrer"&gt;&lt;code&gt;SplMaxHeap&lt;/code&gt;&lt;/a&gt; class that are concrete implementations of the &lt;code&gt;SplHeap&lt;/code&gt;. These classes have an implemented &lt;code&gt;compare()&lt;/code&gt; method. Both classes essentially use the spaceship operator to compare the values.&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;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value2&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="c1"&gt;// SplMaxHeap&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$value1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$value2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// SplMinHeap&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$value2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$value1&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;Knowing all this we can create a MaxHeap from our &lt;code&gt;$values&lt;/code&gt; array like this:&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;$heap&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;\SplMaxHeap&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;$values&lt;/span&gt; &lt;span class="k"&gt;as&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="nv"&gt;$heap&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;insert&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We saw that &lt;code&gt;SplHeap&lt;/code&gt; is also an &lt;code&gt;Iterator&lt;/code&gt;, so we can &lt;code&gt;foreach&lt;/code&gt; over the Heap and have it yield its values in a decreasing 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;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$heap&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;){&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;$value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// int(72), int(36), int(18), int(5), int(2), int(2), int(0), int(-5)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Iterating over the Heap will essentially call &lt;code&gt;extract()&lt;/code&gt; for every value. This means that those values are gone from the heap. If you call &lt;code&gt;::rewind()&lt;/code&gt; on the Heap, this will &lt;strong&gt;not&lt;/strong&gt; return those values. Using &lt;code&gt;::current()&lt;/code&gt; or &lt;code&gt;::top()&lt;/code&gt; will return the current top value without removing it. When you call &lt;code&gt;::next()&lt;/code&gt; however, this &lt;em&gt;will again&lt;/em&gt; extract the current value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Creating a custom MaxHeap in PHP
&lt;/h3&gt;

&lt;p&gt;When using a MaxHeap to sort a list of objects it is possible the value of those objects is calculated through a function. In that case the regular &lt;code&gt;SplMaxHeap&lt;/code&gt; will (probably) not work, but you can create your own MaxHeap by extending &lt;code&gt;splHeap&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Imagine having a shop with product represented by a &lt;code&gt;Product&lt;/code&gt; class. It can store a physical weight in different units of measurements; like pounds (lbs) and grams (g). To put these in a MaxHeap, it needs to be able to compare those different types of measurements. A (very simple) implementation could look like this:&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;Product&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="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$weight_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$weight_amount&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductMaxHeap&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;\SplHeap&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value2&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="nf"&gt;asGrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;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="nf"&gt;asGrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value2&lt;/span&gt;&lt;span class="p"&gt;);&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;asGrams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="nv"&gt;$product&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;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;weight_type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'grams'&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;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;weight_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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;weight_type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'pounds'&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;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;weight_amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;453.59237&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&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;'Product has unknown weight type.'&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;In this example we convert the weight amount of pounds into grams in order to compare the values accordingly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Whenever dealing with types like these, make sure to use constants that represent that type (like &lt;code&gt;public const WEIGHT_TYPE_GRAMS = 'grams';&lt;/code&gt;) or use &lt;code&gt;Enums&lt;/code&gt; when using PHP 8.1 or higher. This provides autocompletion in IDE's and prevents typo's like &lt;code&gt;gram&lt;/code&gt; instead of &lt;code&gt;grams&lt;/code&gt;.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Array Index Algorithm for Heaps
&lt;/h2&gt;

&lt;p&gt;Remember how Heaps are Complete Binary Trees? This is actually a very helpful characteristic of a Heap. If we give every node in the tree a 0-based index key, and moved from top to bottom, left to right, we can actually quite simply figure out what the keys of the children of a specific node are. So we can store a heap as 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="nv"&gt;$heap_as_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="c1"&gt;// Keys added for visual aid&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="mi"&gt;72&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;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;4&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="mi"&gt;5&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="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&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;Assuming &lt;code&gt;$i&lt;/code&gt; represents the current node's key, the algorithm to figure out the left child of that node is: &lt;code&gt;($i * 2) + 1&lt;/code&gt;, and for the right child it is: &lt;code&gt;($i * 2) + 2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's try that out. We want the values for the left and right child of &lt;code&gt;36&lt;/code&gt;.  Its key is &lt;code&gt;1&lt;/code&gt;. So the left key is &lt;code&gt;(1 * 2) + 1 = 3&lt;/code&gt;, and the right key is &lt;code&gt;(1 * 2) + 2 = 4&lt;/code&gt;. Which are respectively the nodes: &lt;code&gt;5&lt;/code&gt; and &lt;code&gt;2&lt;/code&gt;. Which in turn matches our Heap.&lt;/p&gt;

&lt;p&gt;We can also do the reverse and find out the parent of the current node. The algorithm for that is: &lt;code&gt;(int) ($i -1) / 2&lt;/code&gt;.  For the right child of 36 (index: 4) that would be: &lt;code&gt;(4 - 1) / 2) = 1.5&lt;/code&gt;.  The &lt;code&gt;int&lt;/code&gt; of 1.5 = &lt;code&gt;1&lt;/code&gt;. And key &lt;code&gt;1&lt;/code&gt; is indeed the parent node: &lt;code&gt;36&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heapify an 0-based array
&lt;/h3&gt;

&lt;p&gt;Because a Complete Binary Tree can be stored as a 0-based array; we can also see any 0-based array as a Complete Binary Tree. How is this helpful? Because it's very easy and efficient to turn any existing Complete Binary Tree into a Heap.&lt;/p&gt;

&lt;p&gt;When we want to convert a Complete Binary Tree into a Heap, we only have to sort half of it. Because the sorting is done by swapping two nodes, the other half of the Tree will automatically also end up in their correct position.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Since we are working with a 0-based array, &lt;strong&gt;swapping&lt;/strong&gt; means we can just switch the index of these values.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can try this out yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Draw a Complete Binary Tree from the provided array &lt;code&gt;2, 18, 36, 5, 2, 0, -5, 72&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Start at the half of the array: &lt;code&gt;5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sift it down by swapping it with the largest of its children and repeat this until it has no children to swap with (It only has one child: &lt;code&gt;72&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Now work your way back by applying step 3 on every element before &lt;code&gt;5&lt;/code&gt; (So the next will be &lt;code&gt;36&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If done correctly, you end up with a Tree like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         72
       /    \
     18       36
    /  \     /  \
   5    2   0   -5
 /
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, by only sifting down half the array, the other half of the Heap automatically ended up in a correct position.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤷 When are Heaps useful?
&lt;/h2&gt;

&lt;p&gt;Because there are many types of data structures, there are also many ways to solve a problem. Sometimes a simple array is all you need. But Heaps have their time to shine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Direct access to the highest (or lowest) value
&lt;/h3&gt;

&lt;p&gt;A MaxHeap (or MinHeap) has direct access to the highest (or lowest) value of the dataset. So whenever you are working with large datasets for which you need the maximum (or minimum) value; a Heap is a safe bet. As you've seen we only need to sort half the dataset in order to figure out the minimum or maximum value. Which is pretty fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  Working with a lot of inserts and removals
&lt;/h3&gt;

&lt;p&gt;When inserting a new value into a dataset, a Heap is more efficient because it only performs (relatively) a few comparisons to end up in the right spot. In the worst case scenario an array would need to perform a comparison for &lt;em&gt;every&lt;/em&gt; value it has. Because a Heap is a binary tree, the worst case would need exponentially fewer comparisons. Making it a more efficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sorting arrays
&lt;/h3&gt;

&lt;p&gt;An array can be sorted by using a MaxHeap in a process known as &lt;strong&gt;HeapSort&lt;/strong&gt;.&lt;br&gt;
Because a MaxHeap continuously has the highest value at the top, you can extract that value and place it at it to the beginning of an array. By adding the next value, and the next, and the next, at the beginning of the array, it ends up sorted from lowest to highest.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Although this technically qualifies as HeapSort this isn't the most efficient way. We'll cover HeapSort more in-depth in an upcoming post where we'll make it more efficient.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Priority Queues
&lt;/h3&gt;

&lt;p&gt;While also a topic for a future blog post, queues are essentially a First-In First-Out system that adds new values at the end of a list, and extracts values from the start of the list.&lt;/p&gt;

&lt;p&gt;A variant on this is where you use a MaxHeap that contains a &lt;code&gt;priority&lt;/code&gt; value for a certain object. When adding this object to the Heap, it will end up higher or lower depending on its priority. This type of queue is called a &lt;strong&gt;Priority Queue&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fun fact:&lt;/strong&gt; Did you know the letters &lt;code&gt;ueue&lt;/code&gt; in &lt;code&gt;Queue&lt;/code&gt; are not silent, but are actually just waiting their turn? &lt;em&gt;- I'll let myself out; sorry.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because this is such a frequently used case for MaxHeaps, PHP actually provides a &lt;a href="https://www.php.net/manual/en/class.splpriorityqueue.php" rel="noopener noreferrer"&gt;&lt;code&gt;SplPriorityQueue&lt;/code&gt;&lt;/a&gt; based on a MaxHeap.&lt;/p&gt;

&lt;p&gt;Instead of updating your object to contain a priority, you can insert the object &lt;em&gt;with&lt;/em&gt; a priority.&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;$queue&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;SplPriorityQueue&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'task 1'&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="nv"&gt;$queue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'task 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="nv"&gt;$queue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'task 3'&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="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// string(6) "task 2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And because we only need to partially sort a Heap find the highest priority, this too is a lot more efficient that sorting an array-queue after every insertion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real world example
&lt;/h2&gt;

&lt;p&gt;A very nice real world example of a Heap implemented with a PHP array &lt;a href="https://github.com/revoltphp/event-loop/blob/a928073cc74501c1852fd9d8c8b02e550cb56517/src/EventLoop/Internal/TimerQueue.php" rel="noopener noreferrer"&gt;can be found&lt;/a&gt; in the &lt;code&gt;revolt/event-loop&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;In this example they implemented a queue of callbacks based on an expiry time. Whenever the expiry time has passed, the callback will be extracted. So this is an example of a Priority Queue, but it's based on a MinHeap instead of a MaxHeap; because the lowest expiry time has to be on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative for the Standard PHP Library (SPL)
&lt;/h2&gt;

&lt;p&gt;As &lt;a href="https://www.reddit.com/r/PHP/comments/rj57h6/heaps_explained_in_php/hp1xzzd/?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3" rel="noopener noreferrer"&gt;u/sproingie pointed out on Reddit&lt;/a&gt; The SPL data structures are not great. They are a great jumping of point in getting started with other data structures. But if you want / need more performance you could install the &lt;a href="https://www.php.net/manual/en/book.ds.php" rel="noopener noreferrer"&gt;Data Structures&lt;/a&gt; extension. While it has a Priority Queue, there is no generic Heap implementation. But you might be able to build this yourself using the &lt;a href="https://www.php.net/manual/en/class.ds-vector.php" rel="noopener noreferrer"&gt;&lt;code&gt;DS\Vector&lt;/code&gt; class&lt;/a&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Useful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/class.splheap.php" rel="noopener noreferrer"&gt;&lt;code&gt;SplHeap&lt;/code&gt; documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/class.splminheap.php" rel="noopener noreferrer"&gt;&lt;code&gt;SplMinHeap&lt;/code&gt; documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/class.splmaxheap.php" rel="noopener noreferrer"&gt;&lt;code&gt;SplMaxHeap&lt;/code&gt; documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/class.splpriorityqueue.php" rel="noopener noreferrer"&gt;&lt;code&gt;SplPriorityQueue&lt;/code&gt; documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.upgrad.com/blog/5-types-of-binary-tree/#Types_of_Binary_Trees" rel="noopener noreferrer"&gt;5 Types of Binary Tree Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net/manual/en/book.ds.php" rel="noopener noreferrer"&gt;Data Structures PHP extension &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=BHB0B1jFKQc" rel="noopener noreferrer"&gt;Video: Binary Tree Bootcamp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=g9YK6sftDi0" rel="noopener noreferrer"&gt;Video: Implement A Binary Heap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Thanks for reading
&lt;/h2&gt;

&lt;p&gt;Like I stated at the beginning of the post; Trees and Heaps are very visual things and not everything is as easily explained with a bunch of text. I do hope after reading this post you understand the gist of it. If you have any questions please leave a comment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope you enjoyed reading this article! If so, please leave a ❤️ or a 🦄 and consider subscribing! I write posts on PHP almost every week. You can also follow me on &lt;a href="https://twitter.com/intent/follow?screen_name=doekenorg" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; for more content and the occasional tip. If you want to be the first to read my next blog; consider &lt;a href="https://doeken.org" rel="noopener noreferrer"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>programming</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>The Visitor Pattern in PHP</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Fri, 12 Nov 2021 06:19:17 +0000</pubDate>
      <link>https://dev.to/doekenorg/the-visitor-pattern-in-php-2fa8</link>
      <guid>https://dev.to/doekenorg/the-visitor-pattern-in-php-2fa8</guid>
      <description>&lt;p&gt;The Visitor Pattern isn't used often. This is because there are few situations in which it is applicable or even makes sense. However, it's a nice pattern to know and to have in your tool belt when the time comes. Let's look at how this pattern can be applied in a PHP environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛑 The problem
&lt;/h2&gt;

&lt;p&gt;Like a few other patterns, the Visitor Pattern tries to solve the problem of adding functionality to an entity without changing it (much...). In addition to this very generic problem, it provides a way of adding the functionality to &lt;em&gt;multiple similar&lt;/em&gt; entities, which can't be completely handled in the same way.&lt;/p&gt;

&lt;p&gt;So let's make the problem a bit more practical. Imagine you have two entities: &lt;code&gt;Book&lt;/code&gt; and &lt;code&gt;Document&lt;/code&gt;. And for both of these entities we want to know how many pages there are. Our &lt;code&gt;Document&lt;/code&gt; has a &lt;code&gt;public function getPageCount(): int&lt;/code&gt; which returns the number of pages, while the &lt;code&gt;Book&lt;/code&gt; consists of an array of &lt;code&gt;Chapter&lt;/code&gt; entities, which also have this 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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Document&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;int&lt;/span&gt; &lt;span class="nv"&gt;$page_count&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;getPageCount&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;page_count&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Chapter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Document&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Chapter specific code &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;Book&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;getChapters&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Chapter&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Chapter&lt;/span&gt;&lt;span class="p"&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;new&lt;/span&gt; &lt;span class="nc"&gt;Chapter&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="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;To streamline the process of returning the page count for either of these entity types, we create a &lt;code&gt;PageCountDumper&lt;/code&gt;. A (somewhat naive) implementation of this could look like this:&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;PageCountDumper&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;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$entity&lt;/span&gt;&lt;span class="p"&gt;)&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;$entity&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&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;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getPageCount&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$entity&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$count&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;$entity&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getChapters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$chapter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$chapter&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getPageCount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&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;$count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&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;'PaperCalculator can not handle the provided type.'&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;p&gt;And we can call it like this:&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;$document&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;Document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$book&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;Book&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$dumper&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;PageCountDumper&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$dumper&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$document&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// int(20)&lt;/span&gt;
&lt;span class="nv"&gt;$dumper&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$book&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// int(14)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;PageCountDumper&lt;/code&gt; has a &lt;code&gt;handle()&lt;/code&gt; function that can handle both the &lt;code&gt;Book&lt;/code&gt; and the &lt;code&gt;Document&lt;/code&gt; entity, and will &lt;code&gt;var_dump&lt;/code&gt; the proper page count for both. There are however a few things that stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Because there is no shared interface or abstraction between &lt;code&gt;Document&lt;/code&gt; and &lt;code&gt;Book&lt;/code&gt;, the &lt;code&gt;handle()&lt;/code&gt; function receives a &lt;code&gt;mixed $entity&lt;/code&gt; and contains the logic for either situation. When adding on more entities, this type checking will pile on and can become quite cumbersome and unreadable.&lt;/li&gt;
&lt;li&gt;  We throw an exception when the entity type is unknown to avoid improper use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can do better!&lt;/p&gt;

&lt;h2&gt;
  
  
  👋 The Visitor Pattern Solution
&lt;/h2&gt;

&lt;p&gt;So the Visitor Pattern provides a solution for this particular problem. It will remove the need for the &lt;code&gt;instanceOf&lt;/code&gt; type checks, while keeping the reference to the entity type intact. And it will remove the need to explicitly throw an exception. Let's see how the Visitor pattern tackles these issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entity specific functions
&lt;/h3&gt;

&lt;p&gt;First off, to remove the &lt;code&gt;instanceOf&lt;/code&gt; checks, it requires a method for every possible entity type. For convention's sake, we'll call these methods: &lt;code&gt;visitBook(Book $book)&lt;/code&gt; and &lt;code&gt;visitDocument(Document $document)&lt;/code&gt;. And because we are creating a &lt;code&gt;Visitor&lt;/code&gt; let's rename the calculator to: &lt;code&gt;PageCountVisitor&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PageCountVisitor&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;visitBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Book&lt;/span&gt; &lt;span class="nv"&gt;$book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$count&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;$book&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getChapters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$chapter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$chapter&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getPageCount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&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;$count&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;visitDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Document&lt;/span&gt; &lt;span class="nv"&gt;$document&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&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;$document&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getPageCount&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;By implementing separate methods, with type-hinted arguments, we've removed the need for the &lt;code&gt;instanceOf&lt;/code&gt; checks. And because we can only call these methods with the appropriate type, there is no need to throw an exception. PHP would already do so when we provide an invalid argument.&lt;/p&gt;

&lt;p&gt;If there is another entity in the future that needs its pages to be counted, let's say a &lt;code&gt;Report&lt;/code&gt;, we can add a &lt;code&gt;pubilc function visitReport(Report $report)&lt;/code&gt; and implement that logic separately.&lt;/p&gt;

&lt;p&gt;But, you might be thinking: &lt;em&gt;This isn't better. I still need to know what type my entity is in order to call the correct method!&lt;/em&gt;. And you would be correct. But hold on, this refactoring is only half of the visitor pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accepting a visitor
&lt;/h3&gt;

&lt;p&gt;Remember when I said the entities the visitor works on should not be changed &lt;strong&gt;much&lt;/strong&gt;? Yeah, well; there is &lt;em&gt;one&lt;/em&gt; change that is needed on every entity to make the Visitor Pattern work. But only one, and this will make it accept any visitor, and therefore add any (future) functionality.&lt;/p&gt;

&lt;p&gt;To avoid the &lt;code&gt;instanceOf&lt;/code&gt; check, there is only one context in which we can be sure the entity is of a certain type: &lt;em&gt;within the entity itself&lt;/em&gt;. Only when we are inside a (non-static) method of a class, we know for certain that &lt;code&gt;$this&lt;/code&gt; is an instance of that type. That is why the Visitor Pattern uses a technique called &lt;strong&gt;Double Dispatch&lt;/strong&gt;, in which the entity calls the correct function on the visitor, while providing itself as the argument.&lt;/p&gt;

&lt;p&gt;To implement this double dispatch we need a generic method that receives the visitor, and relays the call to the correct method on the visitor. By convention this method is called: &lt;code&gt;accept()&lt;/code&gt;. This method will receive the visitor as its argument. In order to accept other visitors in the future, we first extract a &lt;code&gt;VisitorInterface&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="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;VisitorInterface&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;visitBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Book&lt;/span&gt; &lt;span class="nv"&gt;$book&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;visitDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Document&lt;/span&gt; &lt;span class="nv"&gt;$document&lt;/span&gt;&lt;span class="p"&gt;);&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;PageCountVisitor&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;VisitorInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Make sure the visitor implements the interface&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we create a &lt;code&gt;VisitableInterface&lt;/code&gt;  and apply it on &lt;code&gt;Book&lt;/code&gt; and &lt;code&gt;Document&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="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;VisitableInterface&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;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;VisitorInterface&lt;/span&gt; &lt;span class="nv"&gt;$visitor&lt;/span&gt;&lt;span class="p"&gt;);&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;Book&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;VisitableInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;VisitorInterface&lt;/span&gt; &lt;span class="nv"&gt;$visitor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$visitor&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;visitBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Document&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;VisitableInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;VisitorInterface&lt;/span&gt; &lt;span class="nv"&gt;$visitor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$visitor&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;visitDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&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;Here you can see the &lt;em&gt;double dispatch&lt;/em&gt; in action. The &lt;code&gt;Book&lt;/code&gt; class calls the &lt;code&gt;visitBook()&lt;/code&gt; method on the visitor and &lt;code&gt;Document&lt;/code&gt; calls &lt;code&gt;visitDocument()&lt;/code&gt;. Both are providing themselves as the parameter. Because of this minor change to the entity we can now apply all kinds of different visitors that provide a certain functionality for every entity.&lt;/p&gt;

&lt;p&gt;To use the visitor on the entities we need to adjust our calling code like this:&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;$document&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;Document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$book&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;Book&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$visitor&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;PageCountVisitor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$document&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$visitor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// int(20)&lt;/span&gt;
&lt;span class="nv"&gt;$book&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$visitor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// int(14)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With all the pieces now in place, we are free to create more visitors that implement the &lt;code&gt;VisitorInterface&lt;/code&gt; and can perform a certain feature for both &lt;code&gt;Book&lt;/code&gt; and &lt;code&gt;Document&lt;/code&gt;. A &lt;code&gt;WordCountVisitor&lt;/code&gt; for example.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note:&lt;/strong&gt; I'm well aware what this is a contrived example, and that in this case it would be way easier to implement a &lt;code&gt;Countable&lt;/code&gt; interface a make use of the &lt;code&gt;count()&lt;/code&gt; function. This example is merely for demonstration purposes, and to make it easier to understand. However, when stacking on more and more actions, a class would need more and more interfaces. So please keep in mind that this would be a beneficial pattern when &lt;em&gt;multiple&lt;/em&gt; actions are required, and possibly even new actions in the future.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Pros &amp;amp; cons
&lt;/h2&gt;

&lt;p&gt;Like many other patterns, the Visitor Pattern isn't the one pattern to rule them all. There are multiple solutions to different problems. The Visitor Pattern is just that; a possible solution to a specific problem. Let's look at some reasons you might use it, and some reasons you might not.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔️ Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  You can add functionality to any entity by implementing the &lt;code&gt;VisitableInterface&lt;/code&gt; once. This makes the entity more extendable.&lt;/li&gt;
&lt;li&gt;  By adding visitors the functionality you enforce separation of concern.&lt;/li&gt;
&lt;li&gt;  The entity is in control whether the visitor is accepted. You can omit the relay and cut the double dispatch.&lt;/li&gt;
&lt;li&gt;  The individual visitors are easier to test.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  The double dispatch can be confusing and make the code harder to understand.&lt;/li&gt;
&lt;li&gt;  The &lt;code&gt;accept()&lt;/code&gt; and &lt;code&gt;visit...()&lt;/code&gt; methods usually don't return anything, so you need to keep records on the visitor itself.&lt;/li&gt;
&lt;li&gt;  All Visitors need every method on the &lt;code&gt;VisitorInterface&lt;/code&gt; while it might not have an implementation for it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real world examples
&lt;/h2&gt;

&lt;p&gt;Realistically, you aren't likely to find this pattern much in the wild. However, it is a common practice in combination with Trees and Tree Traversal.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are unfamiliar with &lt;a href="https://doeken.org/blog/tree-traversal-in-php" rel="noopener noreferrer"&gt;Trees &amp;amp; Tree Traversal&lt;/a&gt;, you can check out my previous blog on that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When traversing a Tree, you are iterating over a continuous stream of Nodes. We can perform an action for every node in that Tree. This is called &lt;em&gt;visiting&lt;/em&gt;... coincidence? These nodes are usually just an entity holding a value. Instead of adding a bunch of methods to these nodes; it's actually a nice way of adding different features to these otherwise &lt;em&gt;dumb&lt;/em&gt; entities.&lt;/p&gt;

&lt;p&gt;Some tree implementations I've seen actually have A &lt;code&gt;PreOderVisitor&lt;/code&gt; and a &lt;code&gt;PostOrderVisistor&lt;/code&gt;. These will then return an array of nodes in that order. While that is a perfectly acceptable visitor, I believe a Visitor should not dictate the order in which it is applied to the tree. For some features it might not even matter what the traversal order is, while in some cases it might.&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://doeken.org/blog/tree-traversal-in-php" rel="noopener noreferrer"&gt;Trees &amp;amp; Tree Traversal&lt;/a&gt; post I gave the example of a document inside a tree structure. When traversing that tree in &lt;code&gt;PreOrder&lt;/code&gt; you get a logical flow of the document; starting at the cover page. Some visitors we might want to build for that tree are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;RenderPdfVisitor&lt;/code&gt; which could render every node as a PDF file.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;TableOfContentsVisitor&lt;/code&gt; which could create a table of contents with the correct page numbering.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;CombinePdfVisitor&lt;/code&gt; which could combine every previously rendered PDF into a single PDF document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And basically every example from that blog post can be build as a visitor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks for reading
&lt;/h2&gt;

&lt;p&gt;Like I said, the Visitor Pattern isn't very common, but it's nice to have up your sleeve. Do you have any experience with this pattern? Please let me know in the comments. I'm curious to hear what you think of it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope you enjoyed reading this article! If so, please leave a ❤️ or a 🦄 and consider subscribing! I write posts on PHP almost every week. You can also follow me on &lt;a href="https://twitter.com/intent/follow?screen_name=doekenorg" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; for more content and the occasional tip. If you want to be the first to read my next blog; consider &lt;a href="https://doeken.org" rel="noopener noreferrer"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Trees and Tree Traversal in PHP</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Mon, 18 Oct 2021 07:04:07 +0000</pubDate>
      <link>https://dev.to/doekenorg/how-to-climb-trees-walk-on-branches-in-php-516f</link>
      <guid>https://dev.to/doekenorg/how-to-climb-trees-walk-on-branches-in-php-516f</guid>
      <description>&lt;p&gt;In this post I want to introduce you to Tree structures. What they are, how you can use them, and in which situation they can be helpful.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please note that this is a&lt;/em&gt; &lt;strong&gt;basic&lt;/strong&gt; &lt;em&gt;introduction, and by no means the entire story. I might even be wrong somewhere, and if you believe I've screwed up: let me know in the comments or send me a &lt;a href="https://twitter.com/messages/compose?recipient_id=23949599&amp;amp;text=You+are+wrong!" rel="noopener noreferrer"&gt;DM&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  🌳 What is a Tree?
&lt;/h2&gt;

&lt;p&gt;To answer this question, we first have to look at &lt;code&gt;Graphs&lt;/code&gt;. In &lt;a href="https://en.wikipedia.org/wiki/Graph_theory" rel="noopener noreferrer"&gt;Graph theory&lt;/a&gt; a &lt;code&gt;Graph&lt;/code&gt; is a (visual) structure of data points (or &lt;code&gt;Nodes&lt;/code&gt;) that are in some way related to each other. This relation can, for example, be a &lt;strong&gt;parent&lt;/strong&gt; with a &lt;strong&gt;child&lt;/strong&gt; or &lt;strong&gt;siblings&lt;/strong&gt;. The relation between these &lt;code&gt;Nodes&lt;/code&gt; is shown by a line / vertex (or edge). Within a "normal" Graph these relationships can be all over the place. Every node can be connected to another or even multiple nodes. Edges can zigzag everywhere.&lt;/p&gt;

&lt;p&gt;So what is a &lt;code&gt;Tree&lt;/code&gt;? It is a subset of a Graph that only allows any two nodes to be connected by &lt;strong&gt;one&lt;/strong&gt; path, rather than unlimited paths.&lt;/p&gt;

&lt;h3&gt;
  
  
  Graph vs. Tree
&lt;/h3&gt;

&lt;p&gt;For example; If we have a &lt;code&gt;Parent&lt;/code&gt; node with 2 child nodes: &lt;code&gt;Child 1&lt;/code&gt; and &lt;code&gt;Child 2&lt;/code&gt;, a &lt;strong&gt;Graph&lt;/strong&gt; would allow these relations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Parent &amp;lt;-&amp;gt; Child 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Parent &amp;lt;-&amp;gt; Child 2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Child 1 &amp;lt;-&amp;gt; Child 2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also called a &lt;strong&gt;cyclic graph&lt;/strong&gt; because it has a &lt;em&gt;cycle&lt;/em&gt; in it (multiple nodes are connected to the same nodes creating cycles in the representation).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Graphs don't &lt;em&gt;have&lt;/em&gt; to be cyclic, but they &lt;em&gt;can&lt;/em&gt; be.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;strong&gt;Tree&lt;/strong&gt; on the other hand would only allow something like these relations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Parent &amp;lt;-&amp;gt; Child 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Parent &amp;lt;-&amp;gt; Child 2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Parent &amp;lt;-&amp;gt; Child 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Child 1 &amp;lt;-&amp;gt; Child 2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because a picture is worth a thousand words; lets look a (simple) Graph vs. a Tree.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Ftree-traversal-in-php%2Fgraph-vs-tree.png" class="article-body-image-wrapper"&gt;&lt;img alt="Image of a graph and a tree" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Ftree-traversal-in-php%2Fgraph-vs-tree.png" width="760" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that in the Tree each pair of nodes is only connected by &lt;strong&gt;one&lt;/strong&gt; edge, Therefore there can never be any &lt;em&gt;cycles&lt;/em&gt;. That's why Trees are &lt;strong&gt;acyclic graphs&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What elements make up a tree?
&lt;/h3&gt;

&lt;p&gt;As we can see in the image above, a &lt;em&gt;Tree&lt;/em&gt; always has a single &lt;em&gt;Node&lt;/em&gt; at the top. This called the &lt;strong&gt;Root Node&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;Node&lt;/em&gt; can have a value, but is not forced to. It also may or may not have any child nodes. If a node does &lt;em&gt;not&lt;/em&gt; have any children it is called a &lt;strong&gt;Leaf&lt;/strong&gt; 🍃 .&lt;/p&gt;

&lt;p&gt;Any node can have multiple children, but some Trees only allow a maximum amount of children per node. These are called &lt;strong&gt;N-ary Trees&lt;/strong&gt;, in which &lt;strong&gt;N&lt;/strong&gt; stands for the &lt;em&gt;maximum amount&lt;/em&gt; of children per node. Probably the most famous of these Tree types is the &lt;strong&gt;Binary Tree&lt;/strong&gt; which allows only 2 child nodes; &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;right&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There is  a lot more to tell about a Tree structures, but for a basic understanding; this should be enough. Let's move on to some action!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚶 Traversing a Tree
&lt;/h2&gt;

&lt;p&gt;Trees are nice as a visual representation, but you can also walk the complete structure of a Tree and use the data of every node. When we &lt;em&gt;Traverse a Tree&lt;/em&gt; we &lt;strong&gt;visit&lt;/strong&gt; every node in the Tree &lt;strong&gt;once&lt;/strong&gt;. And &lt;em&gt;visiting&lt;/em&gt; is just a fancy word for: "preforming an action on". This action can be anything you want: print it, save it or change it. Whatever you want to do to a node, you get &lt;strong&gt;one&lt;/strong&gt; visit per node per traversal.&lt;/p&gt;

&lt;p&gt;There are lots of ways to traverse a Tree. You can Zig-zag, pick a random order; but there are 2 broad spectrum types of Tree Traversal: &lt;em&gt;Depth-First&lt;/em&gt; &amp;amp; &lt;em&gt;Breadth-First&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ↙️ Depth-First Tree Traversal
&lt;/h3&gt;

&lt;p&gt;A Depth-First Tree Traversal is an &lt;em&gt;algorithm&lt;/em&gt; of traversing a Tree, by picking a specific branch; and keep moving downward into that branch until it reaches the end. Only then will It go back up to find another branch.&lt;/p&gt;

&lt;p&gt;Within the realm of Depth-First Tree Traversal there are several types of traversal; three of wich are the most common: &lt;em&gt;PreOrder&lt;/em&gt;, &lt;em&gt;InOrder&lt;/em&gt; and &lt;em&gt;PostOrder&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;These algorithms are recursive; meaning they will start again on the child nodes, and their child nodes, and so on.&lt;/p&gt;

&lt;p&gt;In every upcoming example we will be returning the value of every node from the following Binary Tree.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Ftree-traversal-in-php%2Fsorted-binary-tree.png" class="article-body-image-wrapper"&gt;&lt;img alt="Image of a sorted binary tree" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Ftree-traversal-in-php%2Fsorted-binary-tree.png" width="760" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A PHP representation of this tree can look like this:&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;$root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'value'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'children'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'value'&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;'children'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'value'&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="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'value'&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="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'value'&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="s1"&gt;'children'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'value'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'value'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;7&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;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Helper function to visualize the visiting of a node.&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$node&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;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'value'&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;h4&gt;
  
  
  PreOrder Traversal (node, left (to), right)
&lt;/h4&gt;

&lt;p&gt;When traversing a Tree we start at the &lt;em&gt;Root Node&lt;/em&gt; and then apply the algorithm.&lt;/p&gt;

&lt;p&gt;In the PreOrder algorithm a &lt;em&gt;node&lt;/em&gt; will be visited &lt;em&gt;first&lt;/em&gt;, and then it's children from &lt;em&gt;left&lt;/em&gt; to &lt;em&gt;right&lt;/em&gt;. This process is recursive; meaning it will start again on its children, and so on.&lt;/p&gt;

&lt;p&gt;The output of this Traversal will therefore be: &lt;code&gt;4, 2, 1, 3, 6, 5, 7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First we visit &lt;code&gt;4&lt;/code&gt;, and then move on to its first (left) child, and apply the same algorithm again. So from that point we first visit &lt;code&gt;2&lt;/code&gt;, and then go to its first (left) child, and apply the algorithm again. When we reach &lt;code&gt;1&lt;/code&gt; we hit a &lt;strong&gt;Leaf&lt;/strong&gt;. It has no children, and therefore no output for a &lt;code&gt;left&lt;/code&gt; or a &lt;code&gt;right&lt;/code&gt; node. &lt;em&gt;We've hit the maximum depth of this branch.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So now we backtrack to previous node &lt;code&gt;2&lt;/code&gt; and finish its algorithm. We go &lt;em&gt;right&lt;/em&gt;: &lt;code&gt;3&lt;/code&gt;. This node is also a &lt;strong&gt;Leaf&lt;/strong&gt;. So we backtrack to the previous node: &lt;code&gt;2&lt;/code&gt;. This is now finished; so we backtrack even further to &lt;code&gt;4&lt;/code&gt;. We go &lt;em&gt;right&lt;/em&gt; and visit: &lt;code&gt;6&lt;/code&gt; and the algorithm repeats: Go left: &lt;code&gt;5&lt;/code&gt;; backtrack and go right: &lt;code&gt;7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A PHP implementation of the PreOrder traversal can look like this:&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;preOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// First we visit the node itself.&lt;/span&gt;
    &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Then apply the algorithm to every child from left -&amp;gt; right.&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;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'children'&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="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;preOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$child&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="nb"&gt;implode&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="nv"&gt;$output&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;preOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 4, 2, 1, 3, 6, 5, 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  InOrder Traversal (left, node, right)
&lt;/h4&gt;

&lt;p&gt;The algorithm for an InOrder Traversal makes most sense on a Binary tree. This is because we first go &lt;em&gt;left&lt;/em&gt;, then visit the &lt;code&gt;node&lt;/code&gt; itself and then go &lt;em&gt;right&lt;/em&gt;. If we had 3 children we'd need to make a choice what to do with the middle node; befóre or áfter the node itself.&lt;/p&gt;

&lt;p&gt;Running this algorithm would produce the following output: &lt;code&gt;1,2,3,4,5,6,7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because this algorithm first visits the &lt;em&gt;left&lt;/em&gt; node, we traverse all the way down until we hit the lowest left node &lt;code&gt;1&lt;/code&gt;. Because it has no children, we can't go left anymore. Therefore, we visit the node itself. We can't go right either; so we backtrack to the previous node: &lt;code&gt;2&lt;/code&gt;. This has now exhausted its complete left branch, so we visit the node itself. Then we go to the right node and repeat the algorithm..., etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A PHP implementation of the InOrder traversal can look like this:&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;inOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We extract a possible left and right node for clarity.&lt;/span&gt;
    &lt;span class="nv"&gt;$left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'children'&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="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'children'&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// We'll apply the algorithm on the left node first.&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;$left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$left&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Now we visit the node itself.&lt;/span&gt;
    &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// And apply the algorithm on the right node.&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;$right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$right&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="nb"&gt;implode&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="nv"&gt;$output&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;inOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1, 2, 3, 4, 5, 6, 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The name &lt;em&gt;InOrder&lt;/em&gt; is (most likely) based on the fact that it visits every node in ascending order. But this only works for a so-called &lt;strong&gt;Sorted Binary Tree&lt;/strong&gt;. In this type of tree, every left child is less than the node itself, and the right side is more than the node itself. Just like in our example tree.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  PostOrder Traversal (left (to), right, node)
&lt;/h4&gt;

&lt;p&gt;In the PostOrder Traversal we visit the children from a node first (from left to right) and then the node itself. Because of the recursion of this algorithm the output will be: &lt;code&gt;1,3,2,5,7,6,4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Since we already had two (exhausting) walk-throughs of the other algorithms, and this one is almost the same process as **PreOrder&lt;/em&gt;&lt;em&gt;,  I'll let you try this one out on your own.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A PHP implementation of the PostOrder traversal can look like this:&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;postOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// First we'll apply the algorithm on every child from left -&amp;gt; right.&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;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'children'&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="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;postOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$child&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Then we visit the node itself.&lt;/span&gt;
    &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$node&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;implode&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="nv"&gt;$output&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;postOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1, 3, 2, 5, 7, 6, 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ↔️ Breadth-First Tree Traversal
&lt;/h3&gt;

&lt;p&gt;In a Breadth-First Tree Traversal we start at the Root Node, and then visit the children. But unlike the Depth-First approach, this algorithm is not applied recursively; but more linear. It goes level by level, and therefore it's also called &lt;strong&gt;LevelOrder&lt;/strong&gt;. This algorithm is usually used when the depth of a Tree is unknown or even dynamic. &lt;/p&gt;

&lt;h4&gt;
  
  
  LevelOrder Tree Traversal
&lt;/h4&gt;

&lt;p&gt;The algorithm for LevelOrder is pretty much the same as &lt;strong&gt;PreOrder&lt;/strong&gt;, but because it is &lt;em&gt;Breadth-First&lt;/em&gt; we actually visit the child nodes before visiting the next level of child nodes. So first it will visit the root &lt;code&gt;4&lt;/code&gt;, then its children: &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;6&lt;/code&gt;, then the children of &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;6&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;To put this into perspective, the output of a &lt;em&gt;LevelOrder&lt;/em&gt; traversal would be: &lt;code&gt;4,2,6,1,3,5,7&lt;/code&gt;. Every level is visited before moving on to the next level.&lt;/p&gt;

&lt;p&gt;To implement this behavior you can use a &lt;strong&gt;Queue&lt;/strong&gt;. This is a simple list or array that we append every child node to when a node is visited. You start by adding the Root Node to the queue, and then start a recursive function on the queue which visits the first Node of the queue; adds its children to the queue and then starts over; until the entire queue is empty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example code&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A PHP implementation of LevelOrder traversal can look like this:&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;levelOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$output&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="c1"&gt;// If the queue is empty, return the output.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="p"&gt;)&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="nb"&gt;implode&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="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Take the first item from the queue and visit it.&lt;/span&gt;
    &lt;span class="nv"&gt;$node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Add any children to the queue.&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;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'children'&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="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Repeat the algorithm with the rest of the queue.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;levelOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Put the root on the queue.&lt;/span&gt;
&lt;span class="nv"&gt;$queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$root&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;levelOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$queue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 4, 2, 6, 1, 3, 5, 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🤔 What can Tree Traversal be used for?
&lt;/h2&gt;

&lt;p&gt;If you're anything like me, you like learning stuff like this; but also want / need a practical reason to use it. So let's explore that a bit further.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You absolutely do not &lt;em&gt;NEED&lt;/em&gt; a tree for this example. Just like most things in life, you can choose to use it; if you feel like it. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Example: Building a document
&lt;/h3&gt;

&lt;p&gt;Let's say we have a Content Management System (CMS) to create a hierarchy of chapters for a document (or book). It has the following parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A cover page (C)&lt;/li&gt;
&lt;li&gt;A table of contents (TOC)&lt;/li&gt;
&lt;li&gt;Chapters 1 - 3 with various (nested) sub-chapters &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since there is nesting and a hierarchy, your CMS probably already has a tree-like structure. So let's embrace that and put it all in a Tree like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Ftree-traversal-in-php%2Fdocument-tree.png" class="article-body-image-wrapper"&gt;&lt;img alt="Image of a tree with a document hierarchy" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Ftree-traversal-in-php%2Fdocument-tree.png" width="760" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since a Tree needs a &lt;strong&gt;Root Node&lt;/strong&gt; we'll pick the cover page. Its child nodes will be the Table of contents, and every main chapter. The main chapters all have child sub-chapters.&lt;/p&gt;

&lt;h4&gt;
  
  
  Rendering the complete document (PreOrder)
&lt;/h4&gt;

&lt;p&gt;If we want to combine every part into a single logical flowing document we can visit the nodes using the &lt;strong&gt;PreOrder Traversal&lt;/strong&gt;. Why? Because we first visit the node itself, and then visit its children from left to right with a Depth-First algorithm. This means the output will be &lt;code&gt;C, TOC, 1, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another common task to use PreOrder for is &lt;em&gt;cloning a tree&lt;/em&gt;. Since we visit every node in the correct order you can completely clone every node, and set the correct parent (because it already exists).&lt;/p&gt;

&lt;h4&gt;
  
  
  Removing a page from the Tree (PostOrder)
&lt;/h4&gt;

&lt;p&gt;Let's say we don't need the main chapter &lt;code&gt;2&lt;/code&gt;, but we do need its children &lt;code&gt;2.1&lt;/code&gt; and &lt;code&gt;2.2&lt;/code&gt; (and their possible (grand-) children). If we were to use the PreOrder traversal, we would visit the main node first. If we were to remove that node; you'd lose al the sub-children as well. To prevent this we can use the &lt;strong&gt;PostOrder Traversal&lt;/strong&gt;. Since this essentially works &lt;em&gt;bottom-up&lt;/em&gt; we can move &lt;code&gt;2.1&lt;/code&gt; and &lt;code&gt;2.2&lt;/code&gt; up a level (by updating the parent), and then safely remove chapter &lt;code&gt;2&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Indexing a website (LevelOrder)
&lt;/h3&gt;

&lt;p&gt;For this example we are going to index a website. Our &lt;strong&gt;Root Node&lt;/strong&gt; is the homepage of the website. Because we don't know how many links we are going to encounter, we also can't know what the depth of the Tree is going to be. In these cases it's better to use a &lt;strong&gt;Breadth-First&lt;/strong&gt; traversal. Because this traverses a Tree level-by-level; we can stop the process if it goes to deep. We can set a maximum depth. A Depth-First approach can possibly send you down a very deep branch before it ever comes up again. Not ideal.&lt;/p&gt;

&lt;p&gt;When we start at the Root Node, we visit (aka index) it. Then we find every (internal) link on the page and add those pages to the queue; and repeat the process, until the queue is empty.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To prevent a possible infinite loop, because a link can be on multiple pages &amp;amp; linked back to those pages, you need to keep track of every node that has been visited, and only add it to the queue if it hasn't been visited yet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🔗 Useful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📺 If you want to learn more about Graphs and Tree Traversal I can recommend &lt;a href="https://www.youtube.com/channel/UCmJz2DV1a3yfgrR7GqRtUUA" rel="noopener noreferrer"&gt;Back to Back SWE&lt;/a&gt; on YouTube.&lt;/li&gt;
&lt;li&gt;📤 PHP has some helper classes working with Data Structures. For example this &lt;a href="https://www.php.net/manual/en/class.splqueue.php" rel="noopener noreferrer"&gt;SplQueue&lt;/a&gt; you can use to implement &lt;em&gt;Breadth-First Traversal&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Thanks for reading
&lt;/h2&gt;

&lt;p&gt;While this article isn't very PHP related; I think it's good to have a basic understanding of the tree principe and the traversal algorithms. You never know in what situation you end up needing this.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope you enjoyed reading this article! If so, please leave a ❤️ or a 🦄 and consider subscribing! I write posts on PHP almost every week. You can also follow me on &lt;a href="https://twitter.com/intent/follow?screen_name=doekenorg" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; for more content and the occasional tip. If you want to be the first to read my next blog; consider &lt;a href="https://doeken.org" rel="noopener noreferrer"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>computerscience</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Adapter Pattern vs. Bridge Pattern</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Mon, 04 Oct 2021 07:05:29 +0000</pubDate>
      <link>https://dev.to/doekenorg/adapter-pattern-vs-bridge-pattern-11nd</link>
      <guid>https://dev.to/doekenorg/adapter-pattern-vs-bridge-pattern-11nd</guid>
      <description>&lt;p&gt;The Adapter pattern and the Bridge Pattern have brought along a lot of confusion. In this post we're going to look at what they are, what their differences are &amp;amp; where they might be similar.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔌 Adapter Pattern
&lt;/h2&gt;

&lt;p&gt;The Adapter Pattern tries to solve the problem of making two (or more) &lt;em&gt;incompatible&lt;/em&gt; classes &lt;strong&gt;compatible&lt;/strong&gt;, by using an intermediate class that implements a predefined interface.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;- Wait what? Let's try this again!&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;Imagine a single &lt;code&gt;Feed&lt;/code&gt; that wants to display the latest topics from multiple sources, like: Reddit &amp;amp; Hacker News. For these sources we have two API clients: &lt;code&gt;RedditApi&lt;/code&gt; and &lt;code&gt;HackerNewsApi&lt;/code&gt;. Both return a list of topics, but their APIs are not the same.&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;RedditApi&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;fetchTopicItems&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;RedditFeedIterator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Returns a `RedditFeedIterator` that provides `Topic` objects, that hold a `title`, `date` and `url`.&lt;/span&gt;
    &lt;span class="p"&gt;}&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;HackerNewsApi&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;getTopics&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// returns an array of ['topic_title' =&amp;gt; '...', 'topic_date' =&amp;gt; '...', 'topic_url' =&amp;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;We don't want to make our feed know about the different implementations, because we might want to add another source in the future and that would mean adding even more code to the feed. Instead, we'll apply the Adapter Pattern. &lt;/p&gt;

&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;The Adapter Pattern consists of these 4 elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🙋 &lt;strong&gt;Client:&lt;/strong&gt; This is the class that want's to connect to multiple sources. This would be &lt;code&gt;Feed&lt;/code&gt; in our example.&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;Adaptee:&lt;/strong&gt; A source the &lt;em&gt;Client&lt;/em&gt; wants to connect to. In our example we have two: &lt;code&gt;RedditApi&lt;/code&gt; &amp;amp; &lt;code&gt;HackerNewsApi&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Target:&lt;/strong&gt; An interface or contract that defines a single API the &lt;em&gt;Client&lt;/em&gt; will connect to.&lt;/li&gt;
&lt;li&gt;🔌 &lt;strong&gt;Adapter:&lt;/strong&gt; A class that implements the &lt;em&gt;Target&lt;/em&gt; interface and delegates to an &lt;em&gt;Adaptee&lt;/em&gt; source and formats its output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First let's settle on a &lt;em&gt;Target&lt;/em&gt; interface; we'll call it &lt;code&gt;TopicAdapterInterface&lt;/code&gt; and it will have a &lt;code&gt;getTopics()&lt;/code&gt; method that returns an &lt;code&gt;iterable&lt;/code&gt; of topics, where every topic is an array with &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt;. So it can be an array of arrays, or a Generator/Iterator of arrays.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you aren't familiar with Generators or Iterators, then please check out my &lt;a href="https://doeken.org/blog/generators-over-arrays" rel="noopener noreferrer"&gt;Generators over arrays&lt;/a&gt; post.&lt;/em&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="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;TopicAdapterInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @return iterable Iterable of topic array ['title' =&amp;gt; '...', 'date' =&amp;gt; '...', 'url' =&amp;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;getTopics&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;iterable&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 we can create a &lt;code&gt;Feed&lt;/code&gt; class that uses these adapters. We'll loop over every adapter, and &lt;code&gt;yield&lt;/code&gt; their results, so we get a single continuous stream of topics as a &lt;code&gt;Generator&lt;/code&gt;. This of course doesn't take a date into consideration, but it's enough for this 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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Feed&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @param TopicAdapterInterface[] $adapters The adapters.
     */&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="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$adapters&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;getAllTopics&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;iterable&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;adapters&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$adapter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;$adapter&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTopics&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;p&gt;So we have a &lt;em&gt;Client&lt;/em&gt; &lt;code&gt;Feed&lt;/code&gt;, a &lt;em&gt;Target&lt;/em&gt; &lt;code&gt;TopicAdapterInterface&lt;/code&gt; and two &lt;em&gt;Adaptees&lt;/em&gt; &lt;code&gt;RedditApi&lt;/code&gt; &amp;amp; &lt;code&gt;HackerNewsApi&lt;/code&gt;. That means that we are only missing two &lt;em&gt;Adapters&lt;/em&gt;. We'll create these first, and then we'll look at what makes them tick.&lt;/p&gt;

&lt;p&gt;To make it a bit easier working with the Iterators, I'll be using the &lt;code&gt;iterator_map()&lt;/code&gt; function from my &lt;a href="https://github.com/doekenorg/iterator-functions" rel="noopener noreferrer"&gt;&lt;code&gt;doekenorg/iterator-functions&lt;/code&gt;&lt;/a&gt; package.&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;RedditTopicAdapter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;TopicAdapterInterface&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="kt"&gt;RedditApi&lt;/span&gt; &lt;span class="nv"&gt;$reddit_api&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;getTopics&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;iterable&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;iterator_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Topic&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="s1"&gt;'date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;getDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y-m-d H:i:s'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'url'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUrl&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;reddit_api&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fetchTopicItems&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;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HackerNewsTopicAdapter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;TopicAdapterInterface&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="kt"&gt;HackerNewsApi&lt;/span&gt; &lt;span class="nv"&gt;$hacker_news_api&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;getTopics&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;iterable&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;iterator_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'topic_title'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="s1"&gt;'date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;\DateTime&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;createFromFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'H:i:s Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'topic_date'&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;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y-m-d H:i:s'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'url'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'topic_url'&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;hacker_news_api&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTopics&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;p&gt;Here you can see our two adapters: &lt;code&gt;RedditTopicAdapter&lt;/code&gt; and &lt;code&gt;HackerNewsTopicAdapter&lt;/code&gt;. Both of these classes implement the &lt;code&gt;TopicAdapterInterface&lt;/code&gt; and provide the required &lt;code&gt;getTopics()&lt;/code&gt; method. They each get their own &lt;em&gt;Adaptee&lt;/em&gt; injected as a dependency, and use this to retrieve topics and format it to the required array.&lt;/p&gt;

&lt;p&gt;This means that our &lt;code&gt;Feed&lt;/code&gt; can now use these adapters by injecting them in its constructor. To connect this all together it could look a little something like this:&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;$hacker_news_adapter&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;HackerNewsAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HackerNewsApi&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nv"&gt;$reddit_adapter&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;RedditTopicAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RedditApi&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nv"&gt;$feed&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;Feed&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;$hacker_news_adapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$reddit_adapter&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;$feed&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getAllTopics&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&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;$topic&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// arrays of [`title`, `date` and `url`]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Benefits of the Adapter Pattern
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🔄 You can plug in an extra &lt;em&gt;Adapter&lt;/em&gt; at a later time, without having to change he &lt;em&gt;Client&lt;/em&gt; implementation.&lt;/li&gt;
&lt;li&gt;🖖 Only the &lt;em&gt;Adapter&lt;/em&gt; needs to know about the &lt;em&gt;Adaptee&lt;/em&gt; which enforces separation of concerns.&lt;/li&gt;
&lt;li&gt;🔬 The &lt;em&gt;Client&lt;/em&gt; code is easily testable, because it only relies on a &lt;em&gt;Target&lt;/em&gt; interface.&lt;/li&gt;
&lt;li&gt;📦 When working with an IoC container you can usually get / tag all services with a specific interface, making it very easy to find and inject or auto-wire all &lt;em&gt;Adapters&lt;/em&gt; into the &lt;em&gt;Client&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real world examples
&lt;/h3&gt;

&lt;p&gt;The Adapter Pattern is one of the most used patterns, because of its extendability. It can even be extended by other packages without the original packages having to change. Here are some real world examples of this.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cache adapters
&lt;/h4&gt;

&lt;p&gt;Most frameworks have a caching system that has a single API for working with it, while providing adapters for different implementations, like: redis, memcache or a filesystem cache. Laravel calls these adapters a &lt;code&gt;Store&lt;/code&gt; and you can find these stores in &lt;a href="https://github.com/illuminate/cache" rel="noopener noreferrer"&gt;&lt;code&gt;illuminate/cache&lt;/code&gt;&lt;/a&gt;. They provide the &lt;em&gt;Target&lt;/em&gt; interface for such a store in the &lt;a href="https://github.com/illuminate/contracts/blob/master/Cache/Store.php" rel="noopener noreferrer"&gt;&lt;code&gt;illuminate/contracts&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
repository.&lt;/p&gt;
&lt;h4&gt;
  
  
  Filesystem adapters
&lt;/h4&gt;

&lt;p&gt;Another common thing is to write data to files. Files that may be located somewhere else, like: an FTP server, a Dropbox folder or Google Drive. One of the most used packages for writing data to files is &lt;a href="https://github.com/thephpleague/flysystem" rel="noopener noreferrer"&gt;&lt;code&gt;thephpleague/flysystem&lt;/code&gt;&lt;/a&gt;. This packages provides a &lt;a href="https://github.com/thephpleague/flysystem/blob/2.x/src/FilesystemAdapter.php" rel="noopener noreferrer"&gt;FilesystemAdapter&lt;/a&gt; interface that can have specific implementations. And because of this &lt;em&gt;Target&lt;/em&gt; interface, others can build 3rd-party packages that provide another Filesystem; like: &lt;a href="https://github.com/spatie/flysystem-dropbox" rel="noopener noreferrer"&gt;&lt;code&gt;spatie/flysystem-dropbox&lt;/code&gt;&lt;/a&gt; by Spatie.&lt;/p&gt;
&lt;h2&gt;
  
  
  🔀 Bridge Pattern
&lt;/h2&gt;

&lt;p&gt;The Bridge Pattern is often confused with the Adapter Pattern, and with good reasons. Let's look at what problem this pattern tries to solve and how it is different from the Adapter Pattern.&lt;/p&gt;
&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;Let's say we have two editors: a &lt;code&gt;MarkdownEditor&lt;/code&gt; and a &lt;code&gt;WysiwygEditor&lt;/code&gt;. Both editors can read and format some file and update the source on that file. The &lt;code&gt;MarkdownEditor&lt;/code&gt; obviously returns Markdown text, while the &lt;code&gt;WysiwygEditor&lt;/code&gt; returns HTML.&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;WysiwygEditor&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="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;format&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="s1"&gt;'&amp;lt;h1&amp;gt;Source&amp;lt;/h1&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The formatted source.&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;read&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;file_get_contents&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;file_path&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;store&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="nb"&gt;file_put_contents&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;file_path&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="nf"&gt;format&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MarkdownEditor&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="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;format&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="s1"&gt;'# Source'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The formatted source.&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;read&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;file_get_contents&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;file_path&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;store&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="nb"&gt;file_put_contents&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;file_path&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="nf"&gt;format&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;At some point in time, we need a Markdown editor and a WYSIWYG editor that can read &amp;amp; store files on an FTP server. We could create a new editor that extends the &lt;code&gt;MarkdownEditor&lt;/code&gt; or &lt;code&gt;WysiwygEditor&lt;/code&gt; and overwrites the &lt;code&gt;read()&lt;/code&gt; and &lt;code&gt;store()&lt;/code&gt; method. However, this will likely introduce a lot of duplicate code between the two. Instead, we'll use the Bridge Pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;The Bridge Pattern also consist of 4 elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎨 &lt;strong&gt;Abstraction:&lt;/strong&gt; An abstract base class that delegates some predefined functions to a &lt;em&gt;Implementor&lt;/em&gt;. In our example this will be an &lt;code&gt;AbstractEditor&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;🧑‍🎨 &lt;strong&gt;Refined Abstraction:&lt;/strong&gt; A specific implementation of the &lt;em&gt;Abstraction&lt;/em&gt;. In our example this will be &lt;code&gt;MarkdownEditor&lt;/code&gt; and &lt;code&gt;WysiwygEditor&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;🖌️ &lt;strong&gt;Implementor:&lt;/strong&gt; An interface that the &lt;em&gt;Abstraction&lt;/em&gt; uses for delegation. In our example this will be a &lt;code&gt;FileSystemInterface&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🖼️ &lt;strong&gt;Concrete Implementor:&lt;/strong&gt; A specific implementation of the &lt;em&gt;Implementor&lt;/em&gt; that actually does the work. In our example this will be &lt;code&gt;LocalFileSystem&lt;/code&gt; and a &lt;code&gt;FtpFileSystem&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is at this point, I think one of the things that makes this pattern hard to grasp is this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Fthere-is-no-bridge.jpg" class="article-body-image-wrapper"&gt;&lt;img alt="There is no bridge" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdoeken.org%2Fassets%2Fimg%2Fthere-is-no-bridge.jpg" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlike the Adapter Pattern, where there is an actual &lt;em&gt;Adapter&lt;/em&gt;; the Bridge Pattern does &lt;em&gt;not&lt;/em&gt; have a &lt;em&gt;Bridge&lt;/em&gt;. But no worries, we'll see the thing that makes this the &lt;em&gt;Bridge&lt;/em&gt; soon enough!&lt;/p&gt;

&lt;h4&gt;
  
  
  Refactoring the code
&lt;/h4&gt;

&lt;p&gt;Let's refactor our example code by implementing the Bridge Pattern. We'll start by extracting the &lt;em&gt;Abstraction&lt;/em&gt; from our two Editors.&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;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractEditor&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="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;format&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;read&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;file_get_contents&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;file_path&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;store&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="nb"&gt;file_put_contents&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;file_path&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="nf"&gt;format&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WysiwygEditor&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractEditor&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;format&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="s1"&gt;'&amp;lt;h1&amp;gt;Source&amp;lt;/h1&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The formatted source.&lt;/span&gt;
    &lt;span class="p"&gt;}&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;MarkdownEditor&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractEditor&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;format&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="s1"&gt;'# Source'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The formatted source.&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;In this refactoring we've created an &lt;code&gt;AbstractEditor&lt;/code&gt; that now contains all the duplicate code there was between the editors, and made the editors extend this abstraction. This way the editors, or &lt;em&gt;Refined Abstractions&lt;/em&gt;, are only focussing on what they do best: formatting the source of the file.&lt;/p&gt;

&lt;p&gt;But remember, we still don't have a &lt;em&gt;Implementor&lt;/em&gt; or a &lt;em&gt;Refined Implementor&lt;/em&gt; and we really want to use multiple file systems. So let's create the &lt;em&gt;Implementor&lt;/em&gt; and a &lt;code&gt;LocalFileSystem&lt;/code&gt; as the first &lt;em&gt;Refined Implementor&lt;/em&gt;. Then we'll update the &lt;code&gt;AbstractEditor&lt;/code&gt; to use the &lt;em&gt;Implementor&lt;/em&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="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FilesystemInterface&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;read&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;$file_path&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&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;$file_path&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;$file_contents&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalFileSystem&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;FilesystemInterface&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;read&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;$file_path&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;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file_path&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;store&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;$file_path&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;$file_contents&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="nb"&gt;file_put_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$file_contents&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;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractEditor&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;FilesystemInterface&lt;/span&gt; &lt;span class="nv"&gt;$filesystem&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;string&lt;/span&gt; &lt;span class="nv"&gt;$file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;format&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;read&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;filesystem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;read&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;file_path&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;store&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;filesystem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;store&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;file_path&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="nf"&gt;format&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;So here is the &lt;em&gt;"Bridge"&lt;/em&gt;. It's the connection between the &lt;em&gt;Abstraction&lt;/em&gt; and the &lt;em&gt;Implementor&lt;/em&gt;. It connects one editor to one filesystem. But now the two can vary independently. We can add multiple editors that all have their own formatting, like &lt;code&gt;yaml&lt;/code&gt;, &lt;code&gt;json&lt;/code&gt; or &lt;code&gt;csv&lt;/code&gt;. And all these editors can use any filesystem to read and store those files.&lt;/p&gt;

&lt;p&gt;So now we can create a &lt;code&gt;FtpFileSystem&lt;/code&gt; that reads and stores the formatted content on an FTP server.&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;FtpFileSystem&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;FilesystemInterface&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;read&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;$file_path&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="c1"&gt;// Imagine the ultimate FTP file reading code here.&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;store&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;$file_path&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;$file_contents&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;// Imagine the ultimate FTP file writing code here.&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;By using the Bridge Pattern we've made it possible to make 4 different implementation combinations:&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;// 1. A local markdown file editor&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MardownEditor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LocalFileSystem&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'local-file.md'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 2. An FTP markdown file editor&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MardownEditor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FtpFileSystem&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'ftp-file.md'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 3. A local WYSIWYG file editor&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WysiwygEditor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LocalFileSystem&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'local-file.html'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// 4. An FTP WYSIWYG file editor&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WysiwygEditor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FtpFileSystem&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'ftp-file.html'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we were to add another &lt;code&gt;AbstractEditor&lt;/code&gt; and another &lt;code&gt;FileSystem&lt;/code&gt; we'd have 9 possible combination, while only adding 2 classes 🤯!&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of the Bridge Pattern
&lt;/h3&gt;

&lt;p&gt;As we've seen there are some benefits to using the Bridge Pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💧 The code is more DRY (Don't Repeat Yourself) by extracting the &lt;em&gt;Abstraction&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;🧱 It is more extendable by creating two separate abstractions that can vary independently.&lt;/li&gt;
&lt;li&gt;🔬 The individual classes are smaller and therefore easier to test and understand.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Similarities with Adapter Pattern
&lt;/h3&gt;

&lt;p&gt;Another reason why some have trouble understanding the difference between the Bridge Pattern and the Adapter Pattern is that the connecting part of the "bridge" actually looks like an &lt;em&gt;Adapter&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Client&lt;/strong&gt; could be seen as the &lt;strong&gt;Abstraction&lt;/strong&gt; as that also delegates to an interface.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Target&lt;/strong&gt; could be seen as the &lt;strong&gt;Implementor&lt;/strong&gt; as this also defines an interface to adhere to.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Adapter&lt;/strong&gt; could be seen as the &lt;strong&gt;Refined Implementor&lt;/strong&gt; because this implements the interface and fulfills the requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last one is probably the most confusing; as a &lt;em&gt;Refined Implementor&lt;/em&gt; can actually &lt;em&gt;be&lt;/em&gt; an &lt;em&gt;Adapter&lt;/em&gt; to a dependency or &lt;em&gt;Adaptee&lt;/em&gt;, but this is not required. The &lt;em&gt;Refined Implementor&lt;/em&gt; will often be a class on its own, while an &lt;em&gt;Adapter&lt;/em&gt; will always delegate. But the two are indeed not mutually exclusive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks for reading
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I hope you enjoyed reading this article! If so, please leave a ❤️ or a 🦄 and consider subscribing! I write posts on PHP almost every week. You can also follow me on &lt;a href="https://twitter.com/intent/follow?screen_name=doekenorg" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; for more content and the occasional tip.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What happens when we clone?</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Fri, 24 Sep 2021 16:54:54 +0000</pubDate>
      <link>https://dev.to/doekenorg/what-happens-when-we-clone-jdi</link>
      <guid>https://dev.to/doekenorg/what-happens-when-we-clone-jdi</guid>
      <description>&lt;p&gt;It can sometimes be more useful to create a copy of an &lt;code&gt;object&lt;/code&gt; and only change the relevant parts, then to completely recreate it. For example, when the &lt;code&gt;object&lt;/code&gt; has a lot of dependencies or parameters you need to provide; while a second copy might only differ by &lt;em&gt;one&lt;/em&gt; value.&lt;/p&gt;

&lt;p&gt;To create such a copy you can use the &lt;code&gt;clone&lt;/code&gt; keyword in PHP. When you make such a clone however, you are possibly not getting a full copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shallow copies
&lt;/h2&gt;

&lt;p&gt;When cloning a simple &lt;code&gt;stdClass&lt;/code&gt; with a few scalar variables, a clone will be almost identical, but it will be a separate instance. So when we update a value on the second copy it will only be updated on that instance.&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;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Object title'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;;&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;$object&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true, they are equivalent&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;$object&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false, they not the same instance&lt;/span&gt;

&lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Clone title'&lt;/span&gt;&lt;span class="p"&gt;;&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;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false, the title are no longer identical&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, when &lt;code&gt;clone&lt;/code&gt; copies the object it will make what is known as a &lt;strong&gt;Shallow copy&lt;/strong&gt;. This means it will keep all references that object has intact. So when you have an object or reference stored on a parameter, the instance of that reference will be the same for both copies.&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;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Object title'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$inner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nv"&gt;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// The title parameter is now a reference to $title&lt;/span&gt;
    &lt;span class="s1"&gt;'inner'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$inner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Clone title'&lt;/span&gt;&lt;span class="p"&gt;;&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;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Clone title"&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;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true, the same instance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is important  to keep in mind when working with clones. Because this could very well be annoying oversight or a very useful advantage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep copies
&lt;/h2&gt;

&lt;p&gt;If you need your nested objects to be a new instance as well, you need what is known as a &lt;strong&gt;Deep copy&lt;/strong&gt;. This means that every reference will be a new instance of that reference as well.&lt;/p&gt;

&lt;p&gt;To help with this you can use the magic &lt;code&gt;__clone()&lt;/code&gt; method on the object you are cloning. This method is called on the object &lt;em&gt;after the copy is made&lt;/em&gt;, but also &lt;em&gt;before the object is returned&lt;/em&gt;. So you can use it to alter any parameters.&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;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;\stdClass&lt;/span&gt; &lt;span class="nv"&gt;$inner&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="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;inner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;object&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;function&lt;/span&gt; &lt;span class="n"&gt;__clone&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;inner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;clone&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;inner&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;$clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;;&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;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true, equivalent&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;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false, not the same instance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example we updated the &lt;code&gt;$inner&lt;/code&gt; parameter with a new copy of itself. So now we are no longer referencing the same object. This means we now have a deep copy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Did you notice we referenced &lt;code&gt;$this&lt;/code&gt; inside the &lt;code&gt;__clone()&lt;/code&gt; method? The context bound to that method is not the current instance,  but &lt;code&gt;$this&lt;/code&gt; is actually referring to the clone!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A clone is not constructed
&lt;/h2&gt;

&lt;p&gt;Another thing to be aware of is that the &lt;code&gt;__construct()&lt;/code&gt; method is never called when an object is cloned. Just as with &lt;code&gt;unserialize()&lt;/code&gt; the cloned object is recreated from the state of the original object; so there is no need to call the constructor.&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;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$title&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="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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Object title'&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;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'New title'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="p"&gt;;&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;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "New title"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the new title on the clone is copied as well, while we might expect the cloned object to have &lt;code&gt;Object title&lt;/code&gt; as its title.&lt;/p&gt;

&lt;h2&gt;
  
  
  Factories
&lt;/h2&gt;

&lt;p&gt;Not calling the &lt;code&gt;__construct()&lt;/code&gt; when cloning can be a powerful asset. It is used in a lot of factory classes to avoid possible heavy calls from being made. Imagine some heavy dependency that is created in the constructor. That same dependency can very likely be the same instance for every clone. This way the call is only made once, and then the instance is shared between every clone.&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;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;HeavyDependency&lt;/span&gt; &lt;span class="nv"&gt;$heavy_dependency&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="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;heavy_dependency&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;HeavyDependency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserFactory&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;User&lt;/span&gt; &lt;span class="nv"&gt;$prototype&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;create&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;User&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;clone&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;prototype&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;User&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;In this example we create a &lt;code&gt;new&lt;/code&gt; instance of the &lt;code&gt;User&lt;/code&gt; class on the &lt;em&gt;first&lt;/em&gt; &lt;code&gt;UserFactory::create()&lt;/code&gt; call.  We then return a clone of that instance. Any subsequent calls to the &lt;code&gt;create()&lt;/code&gt; method will already have the User instance, so we only return a clone. This cloning of a single instance to copy its dependencies is also known as the &lt;strong&gt;Prototype Pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set private variables on a clone without &lt;code&gt;__clone()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;One final cool trick is that you can actually create a clone and then set &lt;code&gt;private&lt;/code&gt; variables on that clone, without the use of a &lt;code&gt;__clone()&lt;/code&gt; method. To do this you must create a method on the object class that creates the clone and returns it. Inside this method you can still update private variables of the cloned instance.&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;$object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&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;string&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Object title'&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;getTitle&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;title&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;getClone&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;$title&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="nv"&gt;$clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;clone&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$title&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;$clone&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;$clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$object&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'New title'&lt;/span&gt;&lt;span class="p"&gt;);&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;$clone&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTitle&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// "New title"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contrary to popular believe, a &lt;code&gt;private&lt;/code&gt; variable is not private to the &lt;em&gt;instance&lt;/em&gt; but to the &lt;em&gt;class&lt;/em&gt; of that instance 🤯. So within the context of the same class, you can reference and update any private variable on such an instance.&lt;/p&gt;

&lt;p&gt;As you can see this is useful for creating a clone, while also updating some of its values within the same call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks for reading
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I hope you enjoyed reading this article! If so, please leave a ❤️ or a 🦄 and consider subscribing! I write posts on PHP almost every week. You can also follow me on &lt;a href="https://twitter.com/intent/follow?screen_name=doekenorg" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; for more content and the occasional tip.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Decorator Pattern vs. Proxy Pattern</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Sat, 18 Sep 2021 14:09:19 +0000</pubDate>
      <link>https://dev.to/doekenorg/decorator-pattern-vs-proxy-pattern-3bb5</link>
      <guid>https://dev.to/doekenorg/decorator-pattern-vs-proxy-pattern-3bb5</guid>
      <description>&lt;p&gt;There are two patterns in PHP that are very similar; The Decorator Pattern and The Proxy Pattern. Because they are so similar, you can quickly mistake one for the other. Does that matter? Maybe not, but I think it's good to know the differences when communicating about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Similarities between Decorators and Proxies
&lt;/h2&gt;

&lt;p&gt;Both the Decorator Pattern and the Proxy Pattern revolve around the idea of wrapping an instance of an existing interface (let's call that the &lt;strong&gt;inner instance&lt;/strong&gt;) with a class that implements that same interface and delegates their function calls to the same functions on their inner instance.&lt;/p&gt;

&lt;p&gt;These patterns are very useful for adding or changing functionality of an instance without breaking encapsulation. It can also change or extend functionalities of &lt;code&gt;final&lt;/code&gt; functions and classes. And because they usually serve one purpose they can easily be tested.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SubscriberInterface&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;subscribe&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;$email&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SubscriberDecorator&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;SubscriberInterface&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;SubscriberInterface&lt;/span&gt; &lt;span class="nv"&gt;$inner_subscriber&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;subscribe&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;$email&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inner_subscriber&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$email&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;In this example you can see that our &lt;code&gt;SubscriberDecorator&lt;/code&gt; implements the &lt;code&gt;SubscriberInterface&lt;/code&gt; and it also requires some instance of the &lt;code&gt;SubscriberInterface&lt;/code&gt;. After that it delegates the &lt;code&gt;subcribe()&lt;/code&gt; function to the same function on that instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Differences between Decorators and Proxies
&lt;/h2&gt;

&lt;p&gt;When it comes to naming a class a Decorator or a Proxy you have to look at its intent. What is the class actually doing with the instance it is wrapping?&lt;/p&gt;

&lt;h3&gt;
  
  
  Required vs. Optional dependency
&lt;/h3&gt;

&lt;p&gt;You might have noticed I didn't include a &lt;code&gt;__construct()&lt;/code&gt; method in the previous example. This was intentional, because this is where the first difference can be apparent.&lt;/p&gt;

&lt;p&gt;A Decorator &lt;strong&gt;requires&lt;/strong&gt; an instance of the interface it is wrapping, while a Proxy does &lt;strong&gt;not require&lt;/strong&gt; such an instance. A Proxy &lt;em&gt;can&lt;/em&gt; receive an instance, but is also allowed to create this instance itself. So you can create a &lt;code&gt;new&lt;/code&gt; Proxy on its own, while a Decorator &lt;em&gt;needs&lt;/em&gt; another instance as dependency.&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;// Decorator&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="kt"&gt;SubscriberInterface&lt;/span&gt; &lt;span class="nv"&gt;$inner_subscriber&lt;/span&gt;&lt;span class="p"&gt;){}&lt;/span&gt;

&lt;span class="c1"&gt;// Proxy&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="kt"&gt;?SubscriberInterface&lt;/span&gt; &lt;span class="nv"&gt;$inner_subscriber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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;inner_subscriber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$inner_subscriber&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;InnerSubscriber&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;h3&gt;
  
  
  Additive vs. Restrictive
&lt;/h3&gt;

&lt;p&gt;Decorators are additive; meaning they only add new functionality by wrapping the function call and returning the original value. It can however do anything before or after that call. You can for example log every value when a function is called or dispatch an event. Just make sure to return the original value.&lt;/p&gt;

&lt;p&gt;Proxies are restrictive; meaning they can change the behavior of a function or even restrict calling a specific function by throwing an exception.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Both Decorators and Proxies are allowed to add any extra functions or parameters. It can therefore be wise to implement some magic &lt;code&gt;__isset()&lt;/code&gt;, &lt;code&gt;__get()&lt;/code&gt; and &lt;code&gt;__call()&lt;/code&gt; methods on the Decorator or Proxy to pass these calls along to the inner instance as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  General purpose vs. Specific purpose
&lt;/h3&gt;

&lt;p&gt;Decorators serve a general purpose. It will add some functionality regardless of the instance it is wrapping. This means that multiple decorators should be able to be applied on top of one another in any random order and still produce the same result and added functionality.&lt;/p&gt;

&lt;p&gt;Proxies serve a more specific purpose. It will mostly be used to change or append functionality to a specific instance of the interface. Proxies also aren't commonly stacked on top of one another as a single proxy is usually enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips for Decorators and Proxies
&lt;/h2&gt;

&lt;p&gt;Here are a few tips you might consider when working with Decorators and Proxies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make a base abstraction
&lt;/h3&gt;

&lt;p&gt;If you create multiple Decorators or Proxies of the same interface it can be beneficial to create an &lt;code&gt;abstract class&lt;/code&gt; of the interface or a &lt;code&gt;trait&lt;/code&gt; that satisfies the interface, where every function is already deferred to the function on the inner instance. If you are a package creator, you might even consider providing this implementation inside the package. This way a Decorator or Proxy can &lt;code&gt;extend&lt;/code&gt; or &lt;code&gt;use&lt;/code&gt; this implementation and only (re)declare the functions it needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single responsibility Decorators
&lt;/h3&gt;

&lt;p&gt;It might be tempting to slap on multiple features onto a Decorator, but the beauty of them is that they can be added or removed without changing the underlying code. So try to make tiny Decorators that focus on one thing and apply these on top of each other. Again, this simpleness makes them easier to test as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;You can find a couple of nice examples of Decorators and Proxies in Symfony.&lt;/p&gt;

&lt;p&gt;Their developer toolbar shows a lot of information regarding events and cache, for example. They log this information by decorating the current EventDispatcher with a &lt;a href="https://symfony.com/doc/current/components/event_dispatcher/traceable_dispatcher.html" rel="noopener noreferrer"&gt;TraceableEventDispatcher&lt;/a&gt; and the current cache adapter with a &lt;a href="https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php" rel="noopener noreferrer"&gt;TraceableAdapter&lt;/a&gt; within the &lt;code&gt;dev&lt;/code&gt; environment.&lt;/p&gt;

&lt;p&gt;An example of a Proxy can be found in the &lt;a href="https://github.com/symfony/cache/blob/5.3/Marshaller/DeflateMarshaller.php" rel="noopener noreferrer"&gt;DeflateMarshaller&lt;/a&gt; of the &lt;code&gt;symfony/cache&lt;/code&gt; package. This Marshaller is restrictive due to its dependency on &lt;code&gt;gzinflate()&lt;/code&gt; &amp;amp; &lt;code&gt;gzdeflate()&lt;/code&gt; and its changes to the output of the inner instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks for reading
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I hope you enjoyed reading this article! If so, please leave a ❤️ or a 🦄 and consider subscribing! I write posts on PHP almost every week. You can also follow me on &lt;a href="https://twitter.com/intent/follow?screen_name=doekenorg" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; for more content and the occasional tip.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to use symfony/mailer without the Symfony framework</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Sat, 11 Sep 2021 10:07:14 +0000</pubDate>
      <link>https://dev.to/doekenorg/how-to-use-symfony-mailer-without-the-symfony-framework-123g</link>
      <guid>https://dev.to/doekenorg/how-to-use-symfony-mailer-without-the-symfony-framework-123g</guid>
      <description>&lt;p&gt;On August 19, 2021, Fabien Potencier officially announced &lt;a href="https://symfony.com/blog/the-end-of-swiftmailer" rel="noopener noreferrer"&gt;the end of maintenance for Swiftmailer&lt;/a&gt;. Swiftmailer is being replaced by the &lt;code&gt;symfony/mailer&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;Because of the name, you might think this package can only be used inside a Symfony project, but that's not the case. The naming only implies the package is created by Symfony. So let's take a look at this package and how we can use it inside a project without any framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing the components
&lt;/h2&gt;

&lt;p&gt;To email a recipient you need three things; a mailer service, a transporter and, (of course) a message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mailer
&lt;/h3&gt;

&lt;p&gt;As you might expect, the &lt;code&gt;symfony/mailer&lt;/code&gt; package provides a &lt;code&gt;MailerInterface&lt;/code&gt; with a corresponding &lt;code&gt;Mailer&lt;/code&gt; service. The &lt;code&gt;Mailer&lt;/code&gt; service contains the main API and is responsible for sending the message to the appropriate receiver. The interface only has &lt;em&gt;one&lt;/em&gt; method: &lt;code&gt;send()&lt;/code&gt;. So the API is very basic and easy to understand. To set up the mailer service a &lt;em&gt;transporter&lt;/em&gt; is required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transporter
&lt;/h3&gt;

&lt;p&gt;A transporter is responsible for actually sending a message using a particular protocol. The service must implement the &lt;code&gt;TransporterInterface&lt;/code&gt;, which also only contains a &lt;code&gt;send()&lt;/code&gt; method. When you call the &lt;code&gt;Mailer::send()&lt;/code&gt; method, it will delegate this request to the provided &lt;code&gt;TransportInterface::send()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Because there are many ways a mail can be sent, there are also many transporters available. By default, this package includes the two most common transporters: &lt;code&gt;sendmail&lt;/code&gt; and &lt;code&gt;smtp&lt;/code&gt;. There are however many 3rd party transport services available. A full list of these services can be found on &lt;a href="https://symfony.com/doc/current/mailer.html#using-a-3rd-party-transport" rel="noopener noreferrer"&gt;the documentation site&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Message
&lt;/h3&gt;

&lt;p&gt;The most important part of sending a message is of course the message itself. Symfony Mailer uses the &lt;code&gt;symfony/mime&lt;/code&gt; package. This package provides a few handy objects for creating messages that follow the &lt;a href="https://en.wikipedia.org/wiki/MIME" rel="noopener noreferrer"&gt;MIME standard&lt;/a&gt;. One of these classes is &lt;code&gt;Email&lt;/code&gt;, which provides a high-level API to quickly create an email message. An &lt;code&gt;Email&lt;/code&gt; is a data object that contains the message, the recipient, and any other useful headers. This class is also &lt;a href="https://www.php.net/manual/en/class.serializable.php" rel="noopener noreferrer"&gt;Serializable&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Now that we are familiar with the underlying components, let's create a PHP program that sends an email via the &lt;code&gt;sendmail&lt;/code&gt; protocol.&lt;/p&gt;

&lt;p&gt;We'll create a new project by making an empty folder and running the following command inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer init &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; symfony-mailer-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a tiny &lt;code&gt;composer.json&lt;/code&gt; file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"symfony-mailer-test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use &lt;code&gt;symfony/mailer&lt;/code&gt; inside our project, we need to require it:&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/mailer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll create an &lt;code&gt;index.php&lt;/code&gt; file, and require the &lt;code&gt;vendor/autoload.php&lt;/code&gt; file.&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;require_once&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll create the email message we want to send.&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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Mime\Email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Email&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;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sender@example.test'&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;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'your-email@here.test'&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;priority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PRIORITY_HIGHEST&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;subject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'My first mail using Symfony Mailer'&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;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'This is an important message!'&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;html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;strong&amp;gt;This is an important message!&amp;lt;/strong&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the API for creating an &lt;code&gt;Email&lt;/code&gt; is very verbose and easy to understand. You might have noticed we provided the content twice; as text and as HTML. When the email client used to read the mail supports HTML, it will show that version, otherwise it will fall back to the text only version.&lt;/p&gt;

&lt;p&gt;Now that our &lt;code&gt;Email&lt;/code&gt; is done. We can add our transport service and the mailer instance.&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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Mailer\Mailer&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\Mailer\Transport\SendmailTransport&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$transport&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;SendmailTransport&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$mailer&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;Mailer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$transport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$mailer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we should be able to send this message. We can try it out by running it from the command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php index.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it. You've just sent a mail using &lt;code&gt;symfony/mailer&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a DSN
&lt;/h3&gt;

&lt;p&gt;There is one more thing I'd like to show you, and that is creating a transporter based on a &lt;a href="https://en.wikipedia.org/wiki/Data_source_name" rel="noopener noreferrer"&gt;DSN&lt;/a&gt;. If you are unfamiliar with the term, DSN stands for &lt;em&gt;Data Source Name&lt;/em&gt;. It is a string that represents the location of a data source. This data source can be anything like a file location, a database connection, or in our case a mail transport driver.&lt;/p&gt;

&lt;p&gt;There is no real definitive format for a DSN, other than: it is a string. Symfony however has chosen to make their DSNs mirror a URI. So this format should be pretty familiar to you. If I were to say to you for example: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a url based on the &lt;code&gt;ftp&lt;/code&gt; protocol, for the &lt;code&gt;doeken.org&lt;/code&gt; domain, with username: &lt;code&gt;john&lt;/code&gt; and password: &lt;code&gt;doe&lt;/code&gt; on port &lt;code&gt;21&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You would probably give me a string like this: &lt;code&gt;ftp://john:doe@doeken.org:21&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In the case of a transporter DSN, the protocol is the name of the sender, so in our case: &lt;code&gt;sendmail&lt;/code&gt;. So that would make our DSN &lt;code&gt;sendmail://&lt;/code&gt; This is however not a valid URI because there is no &lt;code&gt;domain&lt;/code&gt;. To fix this, we can add a random string, but most prefer &lt;code&gt;default&lt;/code&gt;. That means the final DSN is &lt;code&gt;sendmail://default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can now use the &lt;code&gt;Transport::fromDSN()&lt;/code&gt; method to automatically create the appropriate transport 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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Mailer\Transport\Transport&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Transport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;fromDsn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sendmail://default'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$transport&lt;/code&gt; will now still hold a &lt;code&gt;SendmailTransport&lt;/code&gt; instance, and the sending of the mail will still work.&lt;/p&gt;

&lt;p&gt;If you wanted to send a mail using the &lt;code&gt;smtp&lt;/code&gt; protocol you can provide a similar DSN. I like using &lt;a href="https://usehelo.com/" rel="noopener noreferrer"&gt;HELO&lt;/a&gt; to debug my emails. A DSN for this could be: &lt;code&gt;smtp://symfony-mailer@127.0.0.1:2500&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;For testing purposes &lt;code&gt;symfony/mailer&lt;/code&gt; includes a &lt;code&gt;NullTransport&lt;/code&gt; service. This transporter will not send any mail, but it will trigger all the appropriate events. You can create this transporter using the &lt;code&gt;null://default&lt;/code&gt; DSN.&lt;/p&gt;

&lt;h3&gt;
  
  
  Events
&lt;/h3&gt;

&lt;p&gt;I won't be covering events in this blog post, but this is something that &lt;code&gt;symfony/mailer&lt;/code&gt; supports. As of version &lt;code&gt;5.3&lt;/code&gt; the only event dispatcher package you can use is &lt;code&gt;symfony/event-dispatcher&lt;/code&gt;. When &lt;code&gt;5.4&lt;/code&gt; is released, and Swiftmailer will officially be retired, you can use any &lt;a href="https://www.php-fig.org/psr/psr-14/" rel="noopener noreferrer"&gt;PSR-14&lt;/a&gt; event dispatcher.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do you want to learn more about event dispatching?&lt;/strong&gt;&lt;br&gt;
Then you should check out my in-depth post on &lt;a href="https://doeken.org/blog/event-dispatching-exploration" rel="noopener noreferrer"&gt;Event Dispatching&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;If you want to learn more about the &lt;code&gt;symfony/mailer&lt;/code&gt; package I highly recommend &lt;a href="https://symfony.com/doc/current/mailer.html" rel="noopener noreferrer"&gt;reading the docs&lt;/a&gt;. It goes into a lot of detail on the possible transport services, as well as using multiple transports at the same time, or even sending mails asynchronous by using a message queue.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hope you enjoyed reading this article! If so, please leave a ❤️ or a 🦄 and consider subscribing! I write posts on PHP most every week.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A simple PSR-4 autoloader</title>
      <dc:creator>Doeke Norg</dc:creator>
      <pubDate>Fri, 03 Sep 2021 19:27:36 +0000</pubDate>
      <link>https://dev.to/doekenorg/a-simple-psr-4-autoloader-4635</link>
      <guid>https://dev.to/doekenorg/a-simple-psr-4-autoloader-4635</guid>
      <description>&lt;p&gt;Have you even used a &lt;code&gt;composer.json&lt;/code&gt; file purely for the need of registering a PSR-4 autoloader? I have, and it always felt a little weird to require such a hunk of code for such a simple task. It adds a &lt;code&gt;vendor&lt;/code&gt; folder and a bunch of empty files. I don't like that overhead when it's not necessary.&lt;/p&gt;

&lt;p&gt;So here is a drop-in alternative. You can for example use this in a WordPress theme or plugin.&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="nb"&gt;spl_autoload_register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&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;$class_name&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;// Map the namespace to the corresponding folder&lt;/span&gt;
    &lt;span class="nv"&gt;$namespace_mapping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'DoekeNorg\\BlogTheme'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'src'&lt;/span&gt;&lt;span class="p"&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;$namespace_mapping&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$namespace&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$directory&lt;/span&gt;&lt;span class="p"&gt;)&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="nb"&gt;strpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$class_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$namespace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$namespace&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="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;realpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="no"&gt;DIRECTORY_SEPARATOR&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;DIRECTORY_SEPARATOR&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;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Class name doesn't match or the directory doesn't exist&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Require the file&lt;/span&gt;
        &lt;span class="nv"&gt;$class_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$directory&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;str_replace&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;$namespace&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="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;DIRECTORY_SEPARATOR&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$class_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'.php'&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="nb"&gt;file_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$class_file&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="nv"&gt;$class_file&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;
  
  
  How to use this autoloader
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Save this file as &lt;code&gt;autoload.php&lt;/code&gt; for example, and fill out the correct values for &lt;code&gt;$namespace_mapping&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;require&lt;/code&gt; this file inside your bootstrap file or theme/plugin entry file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. Now you can reference any class with that namespace, and the autoloader will require the correct file.&lt;/p&gt;

&lt;p&gt;The mapping is relative to the location of the &lt;code&gt;autoload.php&lt;/code&gt; file, so you can also do things like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- blog-theme
    |-- src
    |-- vendor
        |-- autoload.php &amp;lt;- the autoloader 
    |-- public
        |-- index.php &amp;lt;- entry file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you require &lt;code&gt;vendor/autoload.php&lt;/code&gt; inside &lt;code&gt;public/index.php&lt;/code&gt; you can adjust your mapping to the following,&lt;br&gt;
and the resolving will still work.&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;$namespace_mapping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'DoekeNorg\\BlogTheme'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'../src'&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;&lt;strong&gt;Couldn't you make this into a nice class?&lt;/strong&gt;&lt;br&gt;
Of course, but would that &lt;em&gt;really&lt;/em&gt; be better?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it a big win over Composer?&lt;/strong&gt;&lt;br&gt;
No, a big win it is not, a small one; maybe. It's also not ment to replace Composer in any way, because that is way more optimized. It's just that for a simple plugin or theme you don't need the overhead Composer creates.&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>programming</category>
      <category>wordpress</category>
    </item>
  </channel>
</rss>
