<?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: Antonio Silva</title>
    <description>The latest articles on DEV Community by Antonio Silva (@xxzeroxx).</description>
    <link>https://dev.to/xxzeroxx</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%2F1151667%2F51f5fc62-cc13-4a03-8bc8-41ab6665d31c.png</url>
      <title>DEV Community: Antonio Silva</title>
      <link>https://dev.to/xxzeroxx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xxzeroxx"/>
    <language>en</language>
    <item>
      <title>Primeiro Livro Publicado</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Wed, 15 Apr 2026 16:44:26 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/primeiro-livro-publicado-2b03</link>
      <guid>https://dev.to/xxzeroxx/primeiro-livro-publicado-2b03</guid>
      <description>&lt;p&gt;🚀 Publiquei meu primeiro livro na Amazon!&lt;/p&gt;

&lt;p&gt;📘 PHP do Zero: Guia Completo para Iniciantes&lt;/p&gt;

&lt;p&gt;Depois de muito trabalho, lancei um guia completo para quem quer aprender PHP do zero, com explicações claras e práticas.&lt;/p&gt;

&lt;p&gt;Se você está começando na programação ou quer reforçar os fundamentos, esse livro é pra você.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.amazon.com.br/dp/B0GX3BQPH5" rel="noopener noreferrer"&gt;https://www.amazon.com.br/dp/B0GX3BQPH5&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23zte0bmrxsr55n30c4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23zte0bmrxsr55n30c4b.png" alt="capa" width="800" height="1131"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Responsive Images in HTML</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sat, 15 Nov 2025 21:28:52 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/responsive-images-in-html-3pf6</link>
      <guid>https://dev.to/xxzeroxx/responsive-images-in-html-3pf6</guid>
      <description>&lt;p&gt;In a world where a large portion of traffic comes from mobile devices, &lt;strong&gt;making your images responsive&lt;/strong&gt; is essential for delivering a great user experience. Poorly sized images can break layouts, waste bandwidth, and even harm your page performance.&lt;/p&gt;

&lt;p&gt;In this post, you’ll learn &lt;strong&gt;what responsive images are&lt;/strong&gt;, why they matter, and &lt;strong&gt;how to implement them&lt;/strong&gt; in HTML using modern best practices.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Responsive Images?
&lt;/h2&gt;

&lt;p&gt;Responsive images are images that &lt;strong&gt;automatically adjust to the size of the screen or the element they’re placed in&lt;/strong&gt;. This ensures that the image:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Doesn’t overflow the layout&lt;/li&gt;
&lt;li&gt;Scales proportionally&lt;/li&gt;
&lt;li&gt;Improves loading on different devices&lt;/li&gt;
&lt;li&gt;Avoids unnecessary bandwidth usage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic Responsiveness with CSS
&lt;/h2&gt;

&lt;p&gt;The most basic yet very effective way to make an image responsive is through CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"image.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Image description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&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;Why this works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;max-width: 100%&lt;/code&gt;&lt;br&gt;
Tells the browser:&lt;br&gt;
👉 “this image should never be wider than its container.”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;height: auto&lt;/code&gt;&lt;br&gt;
Keeps the aspect ratio intact.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;display: block&lt;/code&gt;&lt;br&gt;
Removes the small whitespace that images have by default (because they’re inline elements).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
The image shrinks smoothly on small screens without distortion.&lt;/p&gt;
&lt;h2&gt;
  
  
  Smart Responsiveness with &lt;code&gt;srcset&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Now we use &lt;strong&gt;native HTML5 features&lt;/strong&gt;. If you want to give the browser &lt;strong&gt;multiple resolution options&lt;/strong&gt; and let it choose the best one, use srcset.&lt;/p&gt;

&lt;p&gt;The browser will &lt;strong&gt;automatically choose the best image&lt;/strong&gt; depending on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;screen width&lt;/li&gt;
&lt;li&gt;pixel density&lt;/li&gt;
&lt;li&gt;layout rules you define
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; 
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"img-800.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
        img-400.jpg 400w,
        img-800.jpg 800w,
        img-1600.jpg 1600w
    "&lt;/span&gt;
    &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 600px) 400px,
           (max-width: 1200px) 800px,
           1600px"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Image description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;How the browser decides which file to load&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It evaluates:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;screen size&lt;/li&gt;
&lt;li&gt;device pixel ratio (1x, 2x, 3x)&lt;/li&gt;
&lt;li&gt;rules in sizes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small phones → load img-400.jpg&lt;/li&gt;
&lt;li&gt;Tablets/laptops → load img-800.jpg&lt;/li&gt;
&lt;li&gt;Large monitors → load img-1600.jpg&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;faster loading&lt;/li&gt;
&lt;li&gt;less bandwidth&lt;/li&gt;
&lt;li&gt;better battery usage&lt;/li&gt;
&lt;li&gt;improved SEO (Google Lighthouse loves this)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Using the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; Element (The Modern &amp;amp; Powerful Approach)
&lt;/h2&gt;

&lt;p&gt;To deliver &lt;strong&gt;different images depending on the device&lt;/strong&gt; (screen size, resolution, or format), HTML provides the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 600px)"&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo-mobile.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 1200px)"&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"photo-tablet.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"photo-desktop.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Fully responsive photo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On screens up to 600px → loads &lt;code&gt;photo-mobile.jpg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;On screens up to 1200px → loads &lt;code&gt;photo-tablet.jpg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Otherwise → loads &lt;code&gt;photo-desktop.jpg&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This boosts performance&lt;/strong&gt;, as each device loads only what it needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When this is essential:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vertical image on mobile.&lt;/li&gt;
&lt;li&gt;Horizontal version on desktops.&lt;/li&gt;
&lt;li&gt;Using modern formats with fallback.&lt;/li&gt;
&lt;li&gt;Art direction (different compositions per device).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Difference Between &lt;code&gt;srcset&lt;/code&gt; Using w and x
&lt;/h2&gt;

&lt;p&gt;There are two ways to write responsive image sets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A) Width-based (&lt;code&gt;w&lt;/code&gt;) — Modern and recommended&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"img-800.jpg"&lt;/span&gt;
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"img-400.jpg 400w, img-800.jpg 800w, img-1600.jpg 1600w"&lt;/span&gt;
     &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"100vw"&lt;/span&gt;
     &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The browser calculates the final display width.&lt;/li&gt;
&lt;li&gt;Selects the most appropriate file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;B) Pixel-density-based (&lt;code&gt;x&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"img.jpg"&lt;/span&gt;
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"img.jpg 1x, img@2x.jpg 2x, img@3x.jpg 3x"&lt;/span&gt;
     &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;logos&lt;/li&gt;
&lt;li&gt;icons&lt;/li&gt;
&lt;li&gt;UI images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;A 3x retina screen → loads &lt;code&gt;img@3x.jpg&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues and How to Avoid Them
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Image overflows outside the screen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&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;2. Image looks stretched&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;→ Remove fixed &lt;code&gt;width&lt;/code&gt; or &lt;code&gt;height&lt;/code&gt; in the HTML.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Images look blurry on mobile&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;→ Use &lt;code&gt;srcset&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Image appears smaller than expected&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;→ Ensure the container doesn’t have a too-small &lt;code&gt;max-width&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use Each Technique
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Best Technique&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Only want the image to shrink on small screens&lt;/td&gt;
&lt;td&gt;CSS &lt;code&gt;max-width: 100%&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Want performance and smaller downloads on mobile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;srcset + sizes&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Want completely different images per screen size&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Want WebP/AVIF with fallback&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Want high-resolution images for retina screens&lt;/td&gt;
&lt;td&gt;&lt;code&gt;srcset 1x, 2x, 3x&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Responsive images are essential for building modern, fast, and adaptable websites. With a few lines of HTML and CSS, you ensure your images display properly on any device from smartphones to 4K screens.&lt;/p&gt;

&lt;p&gt;If you want to go further, &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;, &lt;code&gt;srcset&lt;/code&gt;, and &lt;code&gt;sizes&lt;/code&gt; offer fine-grained control over performance, quality, and compatibility.&lt;/p&gt;

</description>
      <category>html</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How to create and publish your own packages on Packagist</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sat, 08 Nov 2025 20:48:08 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/how-to-create-and-publish-your-own-packages-on-packagist-2ho3</link>
      <guid>https://dev.to/xxzeroxx/how-to-create-and-publish-your-own-packages-on-packagist-2ho3</guid>
      <description>&lt;h2&gt;
  
  
  What Is Packagist?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://packagist.org/" rel="noopener noreferrer"&gt;Packagist.org&lt;/a&gt; is the official package repository for &lt;strong&gt;Composer&lt;/strong&gt;, PHP’s dependency manager. It’s where packages are published so anyone can install them easily using:&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 yourusername/yourpackage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;Before you start, you’ll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; account&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://packagist.org/" rel="noopener noreferrer"&gt;Packagist.org&lt;/a&gt; account&lt;/li&gt;
&lt;li&gt;PHP installed&lt;/li&gt;
&lt;li&gt;Composer installed (&lt;code&gt;composer --version&lt;/code&gt; to check)&lt;/li&gt;
&lt;li&gt;Basic understanding of PHP namespaces and classes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 — Basic Package Structure
&lt;/h2&gt;

&lt;p&gt;Create a folder for your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;MyPackage
&lt;span class="nb"&gt;cd &lt;/span&gt;MyPackage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside it, create this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;MyPackage&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nt"&gt;Greeting&lt;/span&gt;&lt;span class="nc"&gt;.php&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nt"&gt;composer&lt;/span&gt;&lt;span class="nc"&gt;.json&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nt"&gt;README&lt;/span&gt;&lt;span class="nc"&gt;.md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example of &lt;code&gt;src/Greeting.php&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyPackage&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;Greeting&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&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="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&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;
  
  
  Step 2 — Create the &lt;code&gt;composer.json&lt;/code&gt; File
&lt;/h2&gt;

&lt;p&gt;In the root directory, create a file named &lt;code&gt;composer.json&lt;/code&gt; with this 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;"yourusername/my-package"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A simple greeting package in PHP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"autoload"&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="nl"&gt;"psr-4"&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="nl"&gt;"MyPackage\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/"&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;span class="nl"&gt;"authors"&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;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;"Your Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"youremail@example.com"&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;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;blockquote&gt;
&lt;p&gt;⚠️ The &lt;code&gt;"name"&lt;/code&gt; field must follow the pattern &lt;code&gt;username/package&lt;/code&gt;, matching your GitHub username.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3 — Test the Autoload Locally
&lt;/h2&gt;

&lt;p&gt;Before publishing, test the autoload to make sure everything works.&lt;/p&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a &lt;code&gt;test.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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;require&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;'/vendor/autoload.php'&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;MyPackage\Greeting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nc"&gt;Greeting&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"MyPackage"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello, MyPackage!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4 — Push the Project to GitHub
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Create a public repository on GitHub (e.g., my-package).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Initialize the local repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"First version of the package"&lt;/span&gt;
git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
git remote add origin https://github.com/yourusername/my-package.git
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Create a version tag (Packagist uses tags to detect releases):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag v1.0.0
git push origin v1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5 — Publish on Packagist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Go to &lt;a href="https://packagist.org/packages/submit" rel="noopener noreferrer"&gt;https://packagist.org/packages/submit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Paste your GitHub repository URL, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://github.com/yourusername/my-package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Click Check, then Submit.&lt;/p&gt;

&lt;p&gt;Done 🎉 — your package is now public on Packagist!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 — Enable Automatic Updates via GitHub Hook
&lt;/h2&gt;

&lt;p&gt;After publishing, you can enable &lt;strong&gt;automatic updates&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your package page on Packagist.&lt;/li&gt;
&lt;li&gt;Click “&lt;strong&gt;Maintain&lt;/strong&gt;”.&lt;/li&gt;
&lt;li&gt;Under “GitHub Hook”, click “&lt;strong&gt;Connect&lt;/strong&gt;” to allow Packagist to auto-update your package whenever you push changes to GitHub.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 7 — Using Your Package in Another Project
&lt;/h2&gt;

&lt;p&gt;In any other PHP project, just run:&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 yourusername/my-package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And use 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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;MyPackage\Greeting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nc"&gt;Greeting&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;semantic versioning&lt;/strong&gt; (&lt;strong&gt;semver&lt;/strong&gt;) (&lt;code&gt;v1.0.0&lt;/code&gt;, &lt;code&gt;v1.1.0&lt;/code&gt;, &lt;code&gt;v2.0.0&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Keep a clear &lt;strong&gt;README.md&lt;/strong&gt; explaining usage.&lt;/li&gt;
&lt;li&gt;Add unit tests with &lt;strong&gt;PHPUnit&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;GitHub Actions&lt;/strong&gt; for automated testing.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>Module 5: Advanced Topics and Best Practices</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sat, 01 Nov 2025 22:41:12 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/module-5-advanced-topics-and-best-practices-48go</link>
      <guid>https://dev.to/xxzeroxx/module-5-advanced-topics-and-best-practices-48go</guid>
      <description>&lt;p&gt;Congratulations on reaching the final module of our course! You've come a long way, from the initial setup of PHPUnit to mastering the use of Mocks and Stubs. Now it's time to refine your skills, ensure your tests are a sustainable asset for your project, and integrate this practice into your professional development workflow.&lt;/p&gt;

&lt;p&gt;In this module, we will cover code coverage analysis, integration with CI/CD pipelines, and the best practices that separate a junior developer from a senior one when it comes to testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Code Coverage Analysis: What are your tests not seeing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Writing tests is great, but how do you know if you're testing enough parts of your code? &lt;strong&gt;Code coverage&lt;/strong&gt; is a metric that answers this question. It measures, as a percentage, how many lines or "branches" (such as &lt;code&gt;if/else&lt;/code&gt; statements) of your production code were executed during your test suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is it important?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identifies Untested Code:&lt;/strong&gt; Code coverage is a fantastic tool for visualizing which parts of your application lack tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increases Confidence:&lt;/strong&gt; High code coverage gives the team more confidence to perform refactoring and add new features, knowing that there is a safety net to detect regressions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a Silver Bullet:&lt;/strong&gt; It's crucial to understand that &lt;strong&gt;100% coverage doesn't mean 100% quality&lt;/strong&gt;. It's possible to execute a line of code without actually testing its logic correctly (for example, without adequate assertions). Coverage is a guide, not a blind end goal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to Generate a Coverage Report:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To generate coverage reports, PHPUnit needs a code coverage driver such as &lt;strong&gt;Xdebug&lt;/strong&gt; or &lt;strong&gt;PCOV&lt;/strong&gt;. Xdebug is more common in development environments, while PCOV is lighter and faster, making it an excellent option for automation pipelines.&lt;/p&gt;

&lt;p&gt;Once you have a driver installed and activated, you can generate an HTML report, which is very visual and easy to navigate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Project structure&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;coverage/
├── src/
│   └── Calculator.php
├── tests/
│   └── CalculatorTest.php
├── composer.json
└── phpunit.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Source code – &lt;code&gt;src/Calculator.php&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App&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;Calculator&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;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$b&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;$a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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;subtract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$b&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;$a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;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;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="s2"&gt;"Division by zero"&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;$a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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;3. Teste PHPUnit – &lt;code&gt;tests/CalculatorTest.php&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Calculator&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;CalculatorTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&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;testSum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$calc&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;Calculator&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;assertEquals&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="nv"&gt;$calc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testSubtract&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$calc&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;Calculator&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;assertEquals&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;$calc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;subtract&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testDivide&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$calc&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;Calculator&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;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$calc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;divide&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="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;testDivideByZero&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="nf"&gt;expectException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\InvalidArgumentException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$calc&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;Calculator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$calc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;divide&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;0&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;&lt;strong&gt;4. PHPUnit configuration – &lt;code&gt;phpunit.xml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;phpunit&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
         &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"https://schema.phpunit.de/12.0/phpunit.xsd"&lt;/span&gt;
         &lt;span class="na"&gt;bootstrap=&lt;/span&gt;&lt;span class="s"&gt;"vendor/autoload.php"&lt;/span&gt;
         &lt;span class="na"&gt;colors=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;testsuites&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;testsuite&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Testes da Calculadora"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;directory&amp;gt;&lt;/span&gt;tests&lt;span class="nt"&gt;&amp;lt;/directory&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/testsuite&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/testsuites&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;source&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;include&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;directory&amp;gt;&lt;/span&gt;src&lt;span class="nt"&gt;&amp;lt;/directory&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/include&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/source&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/phpunit&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt; tag (in more recent versions of PHPUnit) or &lt;code&gt;&amp;lt;coverage&amp;gt;/&amp;lt;filter&amp;gt;&lt;/code&gt; (in older versions) specifies that only the code within the &lt;strong&gt;src&lt;/strong&gt; directory should be considered for coverage analysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Run PHPUnit with the coverage flag.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the terminal, execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vendor/bin/phpunit &lt;span class="nt"&gt;--coverage-html&lt;/span&gt; coverage-report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will run your tests and create a detailed HTML report in a new folder, &lt;code&gt;coverage-report&lt;/code&gt;. Open the &lt;code&gt;index.html&lt;/code&gt; file in that folder in your browser. You will see an overview of your project's coverage and can navigate through specific files and lines, seeing exactly what was and what was not executed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Continuous Integration (CI/CD): Automating Your Safety Net&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Continuous Integration (CI) is the practice of automatically integrating code changes from multiple contributors into a single software repository. A key part of CI is the automatic execution of tests with each new integration (for example, on every &lt;code&gt;git push&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why integrate tests into a CI/CD pipeline?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast Feedback:&lt;/strong&gt; Developers know almost immediately if their change broke some part of the application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Regression Prevention:&lt;/strong&gt; Ensures that faulty code doesn’t reach the main branch of your project, let alone production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistent Quality:&lt;/strong&gt; Maintains a quality standard by ensuring all tests pass before any code merge.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools like &lt;strong&gt;GitHub Actions&lt;/strong&gt;, &lt;strong&gt;GitLab CI/CD&lt;/strong&gt;, and &lt;strong&gt;Jenkins&lt;/strong&gt; make it easy to set up a pipeline that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Checks out your code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Installs dependencies with &lt;code&gt;composer install&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Runs your test suite with &lt;code&gt;./vendor/bin/phpunit&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;(Optional)&lt;/em&gt; Fails the build if any test fails.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;(Optional)&lt;/em&gt; Publishes coverage reports for analysis.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your PHPUnit test suite becomes the &lt;strong&gt;first automated line of defense&lt;/strong&gt; for your project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Refactoring for Testability&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sometimes, testing a class is difficult. This is usually not a problem with the testing tool itself, but rather a sign that the class design could be improved. Writing tests forces us to think about &lt;strong&gt;coupling&lt;/strong&gt; and &lt;strong&gt;cohesion&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Principles for Testable Code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dependency Injection:&lt;/strong&gt; Instead of creating dependencies inside a class (with the &lt;code&gt;new&lt;/code&gt; operator), &lt;em&gt;inject&lt;/em&gt; them through the constructor. This allows you to easily replace real dependencies with mocks or stubs in your tests. (We’ve done this in modules 3 and 4!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Responsibility Principle (SRP):&lt;/strong&gt; Classes that “do too many things” are hard to test. Break them down into smaller, more focused classes. If your class name contains the word &lt;em&gt;“And”&lt;/em&gt;, it may be violating SRP (e.g., &lt;code&gt;UserCreatorAndEmailSender&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid Global State and Singletons:&lt;/strong&gt; Functions and classes that rely on global state are a nightmare to test since one test’s result can affect another.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Program to an Interface, Not an Implementation:&lt;/strong&gt; Depending on interfaces rather than concrete classes (as we did with &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Translator&lt;/code&gt;) makes your code more flexible and easier to mock in tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Testing Patterns and Antipatterns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices (Patterns):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One Test, One Logical Assertion:&lt;/strong&gt; Ideally, each test method should verify one thing. There can be multiple physical asserts, but they should all check the same logical concept.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Arrange, Act, Assert (AAA):&lt;/strong&gt; Structure your tests into three clear sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arrange:&lt;/strong&gt; Prepare the environment, create objects and stubs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act:&lt;/strong&gt; Execute the method being tested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assert:&lt;/strong&gt; Verify that the result is as expected.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Descriptive Names:&lt;/strong&gt; &lt;code&gt;testSumShouldThrowExceptionWhenArgumentIsNotNumeric()&lt;/code&gt; is much better than &lt;code&gt;testSum()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast Tests:&lt;/strong&gt; Unit tests should be extremely fast. Avoid interacting with the file system, network, or database—use test doubles for that.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mistakes to Avoid (Antipatterns):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dependent Tests:&lt;/strong&gt; A test that only passes if another test has run before it. Use &lt;code&gt;setUp()&lt;/code&gt; and &lt;code&gt;tearDown()&lt;/code&gt; to ensure isolation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Slow Tests:&lt;/strong&gt; Tests that take too long to run will eventually be ignored by the team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fragile Tests:&lt;/strong&gt; Tests that break with any small refactor in production code. This often happens when you test implementation instead of behavior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing Trivial Logic:&lt;/strong&gt; Don’t waste time testing simple getters and setters that contain no logic. Focus on complex behavior.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Course Conclusion&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You’ve reached the end of our PHPUnit journey! Now, you not only know &lt;em&gt;how&lt;/em&gt; to write tests, but also &lt;em&gt;why&lt;/em&gt; each technique matters. You’ve learned how to isolate your code, test complex interactions, measure your test effectiveness through coverage, and integrate everything into a professional workflow.&lt;/p&gt;

&lt;p&gt;The next step is to apply this knowledge. Start small: pick a new feature in your project and write tests for it. Take an existing class without tests and try adding them. Constant practice is what will solidify your skills.&lt;/p&gt;

&lt;p&gt;Automated tests are not a waste of time—they’re an &lt;strong&gt;investment&lt;/strong&gt; in your software’s quality, maintainability, and longevity.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Welcome to the world of more reliable and professional software development!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>phpunit</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Module 4: Uncovering Test Doubles (Mocks and Stubs)</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sat, 06 Sep 2025 23:22:54 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/module-4-uncovering-test-doubles-mocks-and-stubs-4f6f</link>
      <guid>https://dev.to/xxzeroxx/module-4-uncovering-test-doubles-mocks-and-stubs-4f6f</guid>
      <description>&lt;p&gt;Welcome to the module that will transform the way you write unit tests. Until now, we have tested classes that were largely independent. In the real world, however, classes collaborate with each other. A &lt;code&gt;UserService&lt;/code&gt; class might need an &lt;code&gt;EmailClient&lt;/code&gt; class to send emails, or a &lt;code&gt;Logger&lt;/code&gt; to record activities.&lt;/p&gt;

&lt;p&gt;How can we test the logic of the &lt;code&gt;UserService&lt;/code&gt; without actually sending an email or writing to a log file every time the test runs? The answer lies in &lt;strong&gt;Test Doubles&lt;/strong&gt;, a fundamental concept for test isolation.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. What are Test Doubles?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A Test Double is a generic term for any object that pretends to be another object for testing purposes. Think of it like a movie stunt double: they step in to replace the main actor in specific situations, allowing the scene to be filmed safely and in a controlled manner.&lt;/p&gt;

&lt;p&gt;In our case, we use doubles to replace the &lt;strong&gt;dependencies&lt;/strong&gt; of the class we are testing (the "Unit Under Test"). This allows us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Isolate the Unit Under Test:&lt;/strong&gt; We ensure our test fails only if there is a problem in the class we are testing, not in its dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control the Environment:&lt;/strong&gt; We can force dependencies to behave in specific ways (e.g., simulate a database connection failure) to test all paths of our code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Speed Up Tests:&lt;/strong&gt; Replacing a slow dependency (like a network call) with an in-memory double makes test execution orders of magnitude faster.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The two most common types of Test Doubles you will use with PHPUnit are &lt;strong&gt;Stubs&lt;/strong&gt; and &lt;strong&gt;Mocks&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Stubs: Simulating Behavior (State Control)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A &lt;strong&gt;Stub&lt;/strong&gt; is a double that provides "canned answers" to method calls made during the test. The main purpose of a stub is to ensure your unit under test receives the data it needs to do its job, allowing the test to continue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use a Stub?&lt;/strong&gt; When you need to simulate the state of a dependency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a &lt;code&gt;WelcomeGenerator&lt;/code&gt; class that depends on a &lt;code&gt;Translator&lt;/code&gt; to get the correct greeting.&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;// src/Translator.php&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Translator&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;getGreeting&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// src/WelcomeGenerator.php&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WelcomeGenerator&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$translator&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;Translator&lt;/span&gt; &lt;span class="nv"&gt;$translator&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;translator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$translator&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;greet&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;$name&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="nv"&gt;$greeting&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;translator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getGreeting&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$greeting&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&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 test the &lt;code&gt;WelcomeGenerator&lt;/code&gt;, we don't want to depend on a real implementation of &lt;code&gt;Translator&lt;/code&gt;. Instead, we create a &lt;strong&gt;stub&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/WelcomeGeneratorTest.php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&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;WelcomeGeneratorTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&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;testGreetingInEnglish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Create a stub for the Translator interface&lt;/span&gt;
        &lt;span class="nv"&gt;$translatorStub&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;createStub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Translator&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Configure the stub: When the 'getGreeting' method is called,&lt;/span&gt;
        &lt;span class="c1"&gt;//    it should return the string 'Hello'.&lt;/span&gt;
        &lt;span class="nv"&gt;$translatorStub&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'getGreeting'&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;willReturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 3. Inject the stub into our class under test&lt;/span&gt;
        &lt;span class="nv"&gt;$generator&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;WelcomeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$translatorStub&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 4. Execute and assert&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="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John'&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;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello, John!'&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="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 test, it doesn't matter &lt;em&gt;how&lt;/em&gt; the translator works. We only care that it provides us with the string "Hello" so we can verify that the &lt;code&gt;WelcomeGenerator&lt;/code&gt; concatenates it correctly with the name.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3. Mocks: Verifying Interactions (Behavior Verification)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A &lt;strong&gt;Mock&lt;/strong&gt; is a "smarter" double. Like a stub, it can return values, but its main purpose is to &lt;strong&gt;verify that certain methods were called&lt;/strong&gt; on the dependency. Mocks are used to test the interaction between objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use a Mock?&lt;/strong&gt; When you need to verify that your class under test is correctly calling the methods of its dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's imagine a &lt;code&gt;UserRegistrar&lt;/code&gt; that, after saving a user, must notify a &lt;code&gt;Logger&lt;/code&gt; service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/Logger.php&lt;/span&gt;
&lt;span class="kd"&gt;interface&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;log&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// src/UserRegistrar.php&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRegistrar&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&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;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Logger&lt;/span&gt; &lt;span class="nv"&gt;$logger&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;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$logger&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;register&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;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Logic to save the user to the database...&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Saving user &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="si"&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="c1"&gt;// Notify the logger&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;logger&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; registered successfully."&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 test needs to ensure that the &lt;code&gt;log&lt;/code&gt; method of the &lt;code&gt;Logger&lt;/code&gt; is called.&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;// tests/UserRegistrarTest.php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&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;UserRegistrarTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&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;testShouldLogMessageOnRegister&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Create a mock for the Logger interface&lt;/span&gt;
        &lt;span class="nv"&gt;$loggerMock&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;createMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Set the expectation: We expect the 'log' method&lt;/span&gt;
        &lt;span class="c1"&gt;//    to be called EXACTLY ONCE.&lt;/span&gt;
        &lt;span class="nv"&gt;$loggerMock&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expects&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;once&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;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'log'&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;with&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;equalTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'User Alice registered successfully.'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;// 3. Inject the mock into our class under test&lt;/span&gt;
        &lt;span class="nv"&gt;$registrar&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;UserRegistrar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$loggerMock&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 4. Execute the method&lt;/span&gt;
        &lt;span class="nv"&gt;$registrar&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Alice'&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;&lt;strong&gt;Analyzing the Mock:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;createMock()&lt;/code&gt;: Creates the mock object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;expects($this-&amp;gt;once())&lt;/code&gt;: This is the expectation. We are telling PHPUnit: "I expect that during the execution of this test, the following method will be called exactly one time." Other options include &lt;code&gt;any()&lt;/code&gt;, &lt;code&gt;never()&lt;/code&gt;, &lt;code&gt;atLeastOnce()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;method('log')&lt;/code&gt;: Specifies the method we are observing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;with(...)&lt;/code&gt;: (Optional) Specifies the exact arguments with which we expect the method to be called.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the &lt;code&gt;log&lt;/code&gt; method is not called, or is called more than once, or is called with a different message, the test will fail, even if there is no explicit &lt;code&gt;assert&lt;/code&gt; at the end. The expectation (&lt;code&gt;expects&lt;/code&gt;) itself is an assertion.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;4. Crucial Differences: Mocks vs. Stubs&lt;/strong&gt;
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Characteristic&lt;/th&gt;
&lt;th&gt;Stub&lt;/th&gt;
&lt;th&gt;Mock&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Main Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provide canned answers (state)&lt;/td&gt;
&lt;td&gt;Verify interactions (behavior)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Test Focus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;On the final state of the object under test&lt;/td&gt;
&lt;td&gt;On the communication between the test object and its dependency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Verification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The test makes assertions against the class under test&lt;/td&gt;
&lt;td&gt;The test verifies that the mock was used as expected (&lt;code&gt;expects&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Analogy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An actor with a fixed script&lt;/td&gt;
&lt;td&gt;An actor being watched by a director who checks their actions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;5. Other Doubles: Fakes and Spies&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Although Mocks and Stubs are the most common, it's worth briefly knowing two other types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fakes:&lt;/strong&gt; These are objects that have a working implementation, but it's much simpler than the production version. A classic example is an in-memory database that replaces a real connection to MySQL or PostgreSQL. It works, but it's simplified for testing purposes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Spies:&lt;/strong&gt; A spy is a double that "spies on" method calls without interfering with them (unless instructed to do so). After the code is executed, you can make assertions about how the spy was used. In PHPUnit, you can often achieve spy-like behavior by using a mock with flexible expectations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Next Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mastering the use of Stubs and Mocks is a giant leap in your ability to write effective and truly "unit" tests. In the next and final module, we will bring together all the knowledge you've acquired and explore advanced topics like code coverage analysis, integrating your tests into a CI/CD workflow, and best practices to ensure your test suite is a valuable asset to your project.&lt;/p&gt;

</description>
      <category>php</category>
      <category>phpunit</category>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>Module 3: Deepening Your Testing Knowledge</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sat, 30 Aug 2025 18:38:05 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/module-3-deepening-your-testing-knowledge-375b</link>
      <guid>https://dev.to/xxzeroxx/module-3-deepening-your-testing-knowledge-375b</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Module 3: Deepening Your Testing Knowledge&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You have now mastered the basics: you know how to set up PHPUnit, write test classes, and use the most important assertions. Now, let's deepen our knowledge with techniques that will make your tests more efficient, organized, and powerful. In this module, you will learn how to run the same test with multiple datasets, how to prepare the "stage" for your tests, and how to organize your test suite professionally.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Data Providers: Test More with Less Code&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Imagine you need to test a sum function with various combinations of numbers: positive, negative, zeros, etc. You could write a test method for each combination, but that would lead to a lot of code duplication.&lt;/p&gt;

&lt;p&gt;This is exactly the problem that &lt;strong&gt;Data Providers&lt;/strong&gt; solve. A data provider is a public method in your test class that returns an array of arrays. Each of these inner arrays contains the arguments for one execution of your test method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a test method that accepts arguments.&lt;/li&gt;
&lt;li&gt;Create a public method that returns an array of arrays (or an &lt;code&gt;Iterator&lt;/code&gt; object). This is your data provider.&lt;/li&gt;
&lt;li&gt;Annotate the test method with the &lt;code&gt;#[DataProvider('method')]&lt;/code&gt; tag.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's test a simple &lt;code&gt;Calculator&lt;/code&gt; class.&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;// src/Calculator.php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App&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;Calculator&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;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$b&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;$a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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, the test with a data provider:&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;// tests/CalculatorTest.php&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\Attributes\DataProvider&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;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Example&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;CalculatorTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;#[DataProvider('sumProvider')]&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;testSumWithDifferentValues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$calculator&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;Calculator&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;$calculator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$expected&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sumProvider&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="s1"&gt;'Sum of two positives'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'Sum of positive with zero'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&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="s1"&gt;'Sum of two negatives'&lt;/span&gt;      &lt;span class="o"&gt;=&amp;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;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="s1"&gt;'Sum of positive with negative'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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;&lt;strong&gt;Analyzing the Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;**use PHPUnit\Framework\Attributes\DataProvider;**&lt;/code&gt;: Imports the &lt;code&gt;DataProvider&lt;/code&gt; attribute, which is a modern way (PHP 8+) of connecting a test method to a data provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;#[DataProvider('sumProvider')]&lt;/code&gt;&lt;/strong&gt;: This attribute is the central piece. It tells PHPUnit: "To run this test, first call the &lt;code&gt;sumProvider()&lt;/code&gt; method to get a set of data. Then, execute this test method &lt;strong&gt;once for each data set&lt;/strong&gt; it provides."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;public function testSumWithDifferentValues(int $a, int $b, int $expected)&lt;/code&gt;&lt;/strong&gt;: This is the test method itself. The parameters &lt;code&gt;$a&lt;/code&gt;, &lt;code&gt;$b&lt;/code&gt;, and &lt;code&gt;$expected&lt;/code&gt; will receive their values from the &lt;code&gt;sumProvider&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;he &lt;code&gt;**sumProvider**&lt;/code&gt; method returns an array. Each item in this array is another array containing the data for one test run: &lt;code&gt;[$a, $b, $expected]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;$this-&amp;gt;assertEquals($expected, $result);&lt;/code&gt;&lt;/strong&gt;: This is the &lt;strong&gt;assertion&lt;/strong&gt; (the check). It compares if the expected result (&lt;code&gt;$expected&lt;/code&gt;) is equal to the actual result (&lt;code&gt;$result&lt;/code&gt;). If they are equal, the test for that data set passes ✅. If not, it fails ❌.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you run this test, PHPUnit will execute &lt;code&gt;testSumWithDifferentValues&lt;/code&gt; four times, once for each dataset provided by &lt;code&gt;sumProvider&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Fixtures and the Test Lifecycle: &lt;code&gt;setUp()&lt;/code&gt; and &lt;code&gt;tearDown()&lt;/code&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In many tests, you need to perform some setup actions before running the test logic and some cleanup actions afterward. For example, you might need to create an object instance before each test or clear a log file after execution. This predefined environment and state is called a &lt;strong&gt;fixture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;PHPUnit provides two special methods to manage your test's lifecycle and ensure that each test runs in a clean, isolated environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;setUp()&lt;/code&gt;: This method is executed &lt;strong&gt;before&lt;/strong&gt; each test method (&lt;code&gt;test*&lt;/code&gt;) in the class. It's the perfect place to instantiate objects or prepare the environment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tearDown()&lt;/code&gt;: This method is executed &lt;strong&gt;after&lt;/strong&gt; each test method. It's used to "clean up the mess," such as closing database connections or removing temporary files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's refactor our &lt;code&gt;CalculatorTest&lt;/code&gt; to use &lt;code&gt;setUp()&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;// tests/CalculatorTest.php
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Calculator&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;CalculatorTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&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;?Calculator&lt;/span&gt; &lt;span class="nv"&gt;$calculator&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;setUp&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;// This line will run before EACH test in this 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;calculator&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;Calculator&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;"Running setUp()&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="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;tearDown&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;// This line will run after EACH test in this class&lt;/span&gt;
        &lt;span class="k"&gt;unset&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;calculator&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;"Running tearDown()&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="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;testSimpleSum&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&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;assertEquals&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="nv"&gt;$result&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;testSumWithNegatives&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sum&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;2&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;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$result&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 using &lt;code&gt;setUp()&lt;/code&gt;, we avoid writing &lt;code&gt;$calculator = new Calculator();&lt;/code&gt; in every test method, making our code cleaner (DRY principle - Don't Repeat Yourself) and ensuring that each test gets a fresh instance of the object. This prevents the result of one test from interfering with another.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3. Organizing Your Tests: The &lt;code&gt;phpunit.xml&lt;/code&gt; File&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;As your project grows, running tests from the terminal by specifying the directory every time becomes repetitive. PHPUnit can be configured through an XML file, usually named &lt;code&gt;phpunit.xml&lt;/code&gt; or &lt;code&gt;phpunit.xml.dist&lt;/code&gt;, in the root of your project.&lt;/p&gt;

&lt;p&gt;This file allows you to define default settings for your test suite, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The directory where the tests are located.&lt;/li&gt;
&lt;li&gt;The "bootstrap" file (a file that is executed before the tests begin, perfect for loading the Composer autoloader).&lt;/li&gt;
&lt;li&gt;Colors in the terminal output.&lt;/li&gt;
&lt;li&gt;And many other advanced options we'll see later, like filters and code coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Creating a basic &lt;code&gt;phpunit.xml&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create the file &lt;code&gt;phpunit.xml&lt;/code&gt; in your project's root directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;phpunit&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt;
         &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"https://schema.phpunit.de/10.0/phpunit.xsd"&lt;/span&gt;
         &lt;span class="na"&gt;bootstrap=&lt;/span&gt;&lt;span class="s"&gt;"vendor/autoload.php"&lt;/span&gt;
         &lt;span class="na"&gt;colors=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;testsuites&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;testsuite&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"Unit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;directory&lt;/span&gt; &lt;span class="na"&gt;suffix=&lt;/span&gt;&lt;span class="s"&gt;"Test.php"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;./tests&lt;span class="nt"&gt;&amp;lt;/directory&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/testsuite&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/testsuites&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/phpunit&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Analyzing the File:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bootstrap="vendor/autoload.php"&lt;/code&gt;: Essential. It ensures the Composer autoloader is loaded before any tests, so your classes can be found automatically.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;colors="true"&lt;/code&gt;: Makes the terminal output nicer, with green bars for success and red for failures.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;testsuites&amp;gt;&lt;/code&gt;: Defines one or more sets of tests.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;testsuite name="Unit"&amp;gt;&lt;/code&gt;: Names our test suite "Unit".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;directory suffix="Test.php"&amp;gt;./tests&amp;lt;/directory&amp;gt;&lt;/code&gt;: The most important directive. It tells PHPUnit to look for files ending with &lt;code&gt;Test.php&lt;/code&gt; inside the &lt;code&gt;./tests&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, to run all the tests in your project, you just need to type in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpunit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHPUnit will automatically find and use the &lt;code&gt;phpunit.xml&lt;/code&gt; file, running your test suite with the defined configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You now know how to write more robust and organized tests. In the next module, we will dive into one of the most powerful and sometimes challenging concepts in the world of unit testing: &lt;strong&gt;Test Doubles&lt;/strong&gt;, better known as &lt;strong&gt;Mocks and Stubs&lt;/strong&gt;. This technique is fundamental for isolating your code and testing units that depend on other complex parts of the system.&lt;/p&gt;

</description>
      <category>php</category>
      <category>phpuni</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Module 2: Writing Basic Tests and Assertions</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sat, 23 Aug 2025 20:24:06 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/module-2-writing-basic-tests-and-assertions-5hgo</link>
      <guid>https://dev.to/xxzeroxx/module-2-writing-basic-tests-and-assertions-5hgo</guid>
      <description>&lt;p&gt;Now that you have your environment set up and have run your first test, it's time to deepen your knowledge of writing tests with PHPUnit. In this module, we will explore the structure of a test in more detail and dive into the world of assertions, which are the heart of any test.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Structure of a Test&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;As we saw in the previous module, every test in PHPUnit is a class that extends PHPUnit\Framework\TestCase. Let's take a closer look at the structure:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c1"&gt;// tests/MathTest.php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&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;MathTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&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;testSumShouldReturnTheCorrectValue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... test body ...&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;testSubtractionShouldWorkCorrectly&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... test body ...&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;Important Conventions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Class Name:&lt;/strong&gt; The test class usually has the same name as the class being tested, with the suffix &lt;code&gt;Test&lt;/code&gt;. For example, to test a &lt;code&gt;Math&lt;/code&gt; class, the test class would be &lt;code&gt;MathTest&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method Name:&lt;/strong&gt; The name of the test method must begin with the prefix &lt;code&gt;test&lt;/code&gt;. A good practice is to make the method name descriptive, indicating what is being tested and what the expected result is. For example, instead of &lt;code&gt;testSum()&lt;/code&gt;, use &lt;code&gt;testSumShouldReturnTheCorrectValue()&lt;/code&gt;. This makes your tests more readable, and when a test fails, the method name already gives you a clue as to what went wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. The Power of Assertions&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Assertions are the methods you use to verify that the result of your code is what you expect. If an assertion fails, PHPUnit stops the execution of that test and marks it as "failed".&lt;/p&gt;

&lt;p&gt;Let's get to know the most common and useful assertions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a) Checking for Equality:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;assertEquals($expected, $actual)&lt;/code&gt;: Checks if two variables are equal in value. This is by far the most used assertion.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testSumShouldReturnTheCorrectValue&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="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertEquals&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="nv"&gt;$result&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;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;assertSame($expected, $actual)&lt;/code&gt;: Checks if two variables are identical, meaning they have the same type and the same value.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testVariableTypes&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="nf"&gt;assertEquals&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="s2"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Passes, because the values are equal&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;assertSame&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="s2"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// Fails, because the types are different (integer vs. string)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;b) Checking Boolean Conditions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;assertTrue($condition)&lt;/code&gt;: Checks if a condition is true.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;assertFalse($condition)&lt;/code&gt;: Checks if a condition is false.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testIsEvenNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$number&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="nv"&gt;$isEven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$number&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertTrue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$isEven&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;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;c) Checking for Nulls:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;assertNull($variable)&lt;/code&gt;: Checks if a variable is null.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;assertNotNull($variable)&lt;/code&gt;: Checks if a variable is not null.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;d) Checking Counts and Arrays:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;assertCount($expectedCount, $array)&lt;/code&gt;: Checks if an array has a specific number of elements.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testArrayHasThreeItems&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'apple'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'banana'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'orange'&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;assertCount&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;$items&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;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;assertArrayHasKey($key, $array)&lt;/code&gt;: Checks if an array contains a given key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;assertContains($value, $array)&lt;/code&gt;: Checks if an array contains a given value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;assertEmpty($variable)&lt;/code&gt;: Checks if a variable is empty (useful for strings, arrays, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;e) Checking Object Types:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;assertInstanceOf($expectedClass, $object)&lt;/code&gt;: Checks if an object is an instance of a given class.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assuming you have a 'User' class&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;testUserCreation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertInstanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$user&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;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;f) Optional: Adding Custom Error Messages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All assertions accept an optional last argument: a custom error message. If the test fails, this message will be displayed, which can help you understand the problem more quickly.&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;testSumWithErrorMessage&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="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertEquals&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="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'The sum of 2 + 2 should be 5, but it was not.'&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;
  
  
  &lt;strong&gt;3. Testing Exceptions&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Sometimes, the expected behavior of your code is to throw an exception. For example, when trying to divide a number by zero. PHPUnit offers an elegant way to test 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="c1"&gt;// In a 'Calculator' class&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;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="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;$b&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;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;'Cannot divide by zero.'&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;$a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// In your test&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;testDivisionByZeroThrowsException&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="nf"&gt;expectException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;InvalidArgumentException&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expectExceptionMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Cannot divide by zero.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$calculator&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;Calculator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$calculator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&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;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;expectException()&lt;/code&gt;: Tells PHPUnit that you expect an exception of a certain type to be thrown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;expectExceptionMessage()&lt;/code&gt;: (Optional) Checks if the exception message is what you expect.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the expected exception is thrown, the test passes. If no exception is thrown, or if an exception of a different type is thrown, the test fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With this knowledge, you can now write a variety of unit tests for your code. In the next module, we will explore how to organize your tests more effectively, using &lt;code&gt;Data Providers&lt;/code&gt; to avoid code repetition and understanding the test lifecycle with the &lt;code&gt;setUp()&lt;/code&gt; and &lt;code&gt;tearDown()&lt;/code&gt; methods.&lt;/p&gt;

</description>
      <category>php</category>
      <category>productivity</category>
      <category>phpunit</category>
    </item>
    <item>
      <title>Module 1: Introduction to PHPUnit and the World of Testing</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sat, 16 Aug 2025 19:15:43 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/phpunit-course-module-1-introduction-to-phpunit-and-the-world-of-testing-n4h</link>
      <guid>https://dev.to/xxzeroxx/phpunit-course-module-1-introduction-to-phpunit-and-the-world-of-testing-n4h</guid>
      <description>&lt;p&gt;Welcome to the first module of our PHPUnit course! Here, we'll lay the foundations for your journey into the world of automated testing. By the end of this module, you'll have a clear understanding of what tests are, why they're crucial for developing quality software and how to take your first steps with PHPUnit.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What are Automated Tests?
&lt;/h2&gt;

&lt;p&gt;Imagine you're building a house. Before handing it over, you check that the windows open and close, that the taps don't leak and that the electricity works in every room. These are manual tests. In software development, we do something similar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual software testing&lt;/strong&gt; involves one person running the program and checking that everything works as expected. Although important, this process can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Slow and repetitive&lt;/strong&gt;: Running the same tests with every new change to the code is tiring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prone to human error&lt;/strong&gt;: It's easy to forget to test a specific scenario or make a mistake during verification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not scalable&lt;/strong&gt;: As the software grows, the number of tests required increases exponentially&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where &lt;strong&gt;automated testing&lt;/strong&gt; comes in. Instead of a person, we write code to test our own code. These tests are run by a program, which checks that the behavior of the software is as expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types of Automated Tests:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are several types of tests, each with a different focus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit testing:&lt;/strong&gt; They are the focus of this course. They test the smallest single unit of code (a function, a method or a class). The aim is to ensure that each “piece” of your software works correctly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration Testing:&lt;/strong&gt; Checks that different units of code work well together. For example, if your “User” class interacts correctly with the “Database” class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Functional (or End-to-End - E2E) Testing:&lt;/strong&gt; Simulates the behavior of a real user, testing complete application flows. For example, a functional test could simulate a user logging in, adding a product to the cart and finalizing the purchase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this course, our main focus will be on &lt;strong&gt;unit tests&lt;/strong&gt;, as they form the basis of a solid testing strategy and are the ideal starting point for those just starting out.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Introducing PHPUnit
&lt;/h2&gt;

&lt;p&gt;PHPUnit is the most popular and widely used testing framework in the PHP ecosystem. It provides a set of tools and a structure for writing and executing tests in an organized and efficient way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why PHPUnit?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Community Standard:&lt;/strong&gt; It is the de facto standard for PHP testing, which means that there is a vast amount of documentation, tutorials and community support available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature-rich:&lt;/strong&gt; It offers a wide range of features for writing tests, from simple assertions to the creation of “test doubles” (mocks and stubs), which we'll look at later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy integration:&lt;/strong&gt; Integrates perfectly with popular development tools, such as Composer, and with Continuous Integration (CI/CD) systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detailed Reports:&lt;/strong&gt; Generates clear reports on test execution, indicating which tests passed, which failed and why.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Setting up the environment
&lt;/h2&gt;

&lt;p&gt;To start using PHPUnit, you'll need to have it installed in your project. The recommended way to do this is via &lt;strong&gt;Composer&lt;/strong&gt;, PHP's dependency manager. If you don't have Composer installed yet, you can find the instructions on the &lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;official website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With Composer installed, open the terminal in your project folder and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require &lt;span class="nt"&gt;--dev&lt;/span&gt; phpunit/phpunit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's understand what this command does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;composer require&lt;/code&gt;: Tells Composer that you want to add a new dependency to your project.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--dev&lt;/code&gt;: This is an important flag. It indicates that PHPUnit is a development dependency, i.e. it is needed to develop and test the application, but does not need to be installed in a production environment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;phpunit/phpunit&lt;/code&gt;: This is the name of the PHPUnit package in the Packagist (Composer's package repository).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Your First Test
&lt;/h2&gt;

&lt;p&gt;Let's create a simple test to see PHPUnit in action. The most common convention is to have a &lt;code&gt;src&lt;/code&gt; (or &lt;code&gt;app&lt;/code&gt;) folder for your application code and a &lt;code&gt;tests&lt;/code&gt; folder for the tests, mirroring the &lt;code&gt;src&lt;/code&gt; structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-project/ 
├── src/ 
│ └── Example.php 
├── tests/ 
│ └── ExampleTest.php 
├── vendor/ 
└── composer.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Class to be tested&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;src/&lt;/code&gt; folder, create a file named &lt;code&gt;Example.php&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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App&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;Example&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;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$b&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;$a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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;2. Create a test file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;tests/&lt;/code&gt; folder, create a file named &lt;code&gt;ExampleTest.php&lt;/code&gt;. The convention is to name test files with the &lt;code&gt;Test.php&lt;/code&gt; suffix.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Example&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;ExampleTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&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;testSum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$calc&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;Example&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;$calc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertEquals&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="nv"&gt;$result&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;Let's analyze this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;use PHPUnit\Framework\TestCase;&lt;/code&gt;: Imports the TestCase class from PHPUnit, which all of our test classes must extend.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;class ExampleTest extends TestCase&lt;/code&gt;: Defines our test class, which extends &lt;code&gt;TestCase&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;public function testSum()&lt;/code&gt;: This is our test method. The convention is for test method names to start with the &lt;code&gt;test&lt;/code&gt; prefix.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$result = $calc-&amp;gt;add(2, 3);&lt;/code&gt;: The code we want to test.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$this-&amp;gt;assertEquals(5, $result);&lt;/code&gt;: This is an &lt;strong&gt;assertion&lt;/strong&gt;. We are telling PHPUnit: "I assert that the expected value (5) is equal to the actual value (&lt;code&gt;$result&lt;/code&gt;)". If the assertion is true, the test passes. If it's false, the test fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Configuring autoload (&lt;code&gt;composer.json&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;composer.json&lt;/code&gt; file, add the following:&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="nl"&gt;"autoload"&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="nl"&gt;"psr-4"&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="nl"&gt;"App\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/"&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="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"autoload-dev"&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="nl"&gt;"psr-4"&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="nl"&gt;"Tests\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tests/"&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;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer dump-autoload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Run the test&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, in your terminal, from the root of your project, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpunit tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;./vendor/bin/phpunit&lt;/code&gt;: Executes the PHPUnit executable that was installed by Composer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tests&lt;/code&gt;: Tells PHPUnit to look for and run the tests in the &lt;code&gt;tests/&lt;/code&gt; folder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything went well, you should see output similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PHPUnit x.x.x by Sebastian Bergmann and contributors.

Runtime:       PHP x.x.x

&lt;span class="nb"&gt;.&lt;/span&gt;                                                                   1 / 1 &lt;span class="o"&gt;(&lt;/span&gt;100%&lt;span class="o"&gt;)&lt;/span&gt;

Time: 00:00.024, Memory: 14.00 MB

OK &lt;span class="o"&gt;(&lt;/span&gt;1 &lt;span class="nb"&gt;test&lt;/span&gt;, 1 assertion&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dot (&lt;code&gt;.&lt;/code&gt;) indicates that a test passed successfully. If the test had failed (for example, if we expected the result to be 5 but it wasn't), the output would be different, showing an &lt;code&gt;F&lt;/code&gt; and a detailed error message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congratulations!&lt;/strong&gt; You have just written and executed your first test with PHPUnit. In the next module, we will dive deeper into writing tests and explore the various assertions that PHPUnit offers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Module 1 Final Challenge
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;subtract($a, $b)&lt;/code&gt; method in the &lt;code&gt;Example&lt;/code&gt; class and write a test for it in &lt;code&gt;ExampleTest&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>productivity</category>
      <category>learning</category>
      <category>phpunit</category>
    </item>
    <item>
      <title>From Form to Mascot: My AI App with Google AI Studio</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Tue, 15 Jul 2025 22:21:46 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/from-form-to-mascot-my-ai-app-with-google-ai-studio-32lk</link>
      <guid>https://dev.to/xxzeroxx/from-form-to-mascot-my-ai-app-with-google-ai-studio-32lk</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is my submission for &lt;a href="https://dev.to/deved/build-apps-with-google-ai-studio"&gt;DEV Education Track: Build Apps with Google AI Studio&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built Mascot AI Generator, an intuitive app that allows anyone to generate custom mascot illustrations using structured input fields. Instead of relying on a single prompt, the user fills out a simple form choosing the mascot type, personality, accessories, colors, style, and background and the app uses Google’s Imagen API to render the image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt I Used to Generate the App
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Make a mascot generator based on the prompt provided by the user. Use Imagen to generate the mascot.&lt;/p&gt;

&lt;p&gt;User data includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type of creature or animal (e.g. cat, dragon, octopus)&lt;/li&gt;
&lt;li&gt;Personality of the mascot (e.g. fun, wise, curious)&lt;/li&gt;
&lt;li&gt;Accessories or clothes (e.g. glasses, hat, backpack)&lt;/li&gt;
&lt;li&gt;Desired artistic style (e.g. cartoon, pixel art, realistic)&lt;/li&gt;
&lt;li&gt;Predominant colors (e.g. blue, yellow)&lt;/li&gt;
&lt;li&gt;Desired backdrop (optional)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aistudio.google.com/apps/drive/1XuqtJgTTszvlHXHriiVWhrXH9w6kCo3C?showPreview=true&amp;amp;resourceKey=" rel="noopener noreferrer"&gt;Click here to try the Mascote AI Generator&lt;/a&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fciq9nlz8r84j22ev1ucj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fciq9nlz8r84j22ev1ucj.png" alt="1" width="800" height="449"&gt;&lt;/a&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0y2uqtvnrop1ts2zj2xw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0y2uqtvnrop1ts2zj2xw.png" alt="2" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience
&lt;/h2&gt;

&lt;p&gt;Building with Google AI Studio was incredibly smooth and intuitive. The visual editor made it easy to create a useful interface without writing a lot of code, and the Imagen API delivered surprisingly good results based on structured inputs. I learned that offering users a guided prompt experience (via forms) can be just as powerful if not more than letting them type free-form text.&lt;/p&gt;

&lt;p&gt;This project taught me how to think in terms of user experience and prompt engineering at the same time. I’m excited to continue experimenting with similar tools and creative AI apps!&lt;/p&gt;

</description>
      <category>deved</category>
      <category>learngoogleaistudio</category>
      <category>ai</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Perfect Landing: Brazil's traditional Festas Juninas</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sun, 29 Jun 2025 02:13:05 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/perfect-landing-brazils-traditional-festas-juninas-2376</link>
      <guid>https://dev.to/xxzeroxx/perfect-landing-brazils-traditional-festas-juninas-2376</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2025-06-04"&gt;Frontend Challenge - June Celebrations, Perfect Landing: June Celebrations&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;For this challenge, I created a vibrant and accessible landing page to celebrate Festa Junina, one of the most colorful and joyful traditional festivals in Brazil. It’s a June celebration filled with music, typical foods, folk dances like “quadrilha,” bonfires, and cheerful decorations like paper lanterns and banners.&lt;/p&gt;

&lt;p&gt;The landing page is built with semantic HTML and custom CSS, highlighting key sections of the celebration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;origin&lt;/strong&gt; of the festival&lt;/li&gt;
&lt;li&gt;A list of &lt;strong&gt;traditional foods&lt;/strong&gt; like pamonha, canjica, and curau&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popular activities&lt;/strong&gt; like the mock wedding and typical games&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The design was inspired by real Festa Junina posters, using warm tones, bold fonts, and thematic emojis to reflect the festive spirit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/AntonioCarioca/embed/KwpQzXo?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;As a Brazilian developer, Festa Junina holds a special place in my heart. I wanted to create something that could reflect its energy, joy, and cultural richness.&lt;/p&gt;

&lt;p&gt;I started by sketching the layout based on traditional event flyers, then translated that into HTML/CSS while ensuring accessibility and responsive behavior. Some parts I’m particularly proud of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The bright color palette that evokes the festive vibe&lt;/li&gt;
&lt;li&gt;The layout with flexible sections and mobile responsiveness&lt;/li&gt;
&lt;li&gt;The use of accessible semantic elements and emoji decorations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Through this project, I refined my CSS design skills and practiced planning a layout based on cultural references. If I had more time, I would like to add animations (like waving flags) and a form to share favorite Festa Junina memories.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>frontendchallenge</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>CSS Art: Brazil's traditional Festas Juninas</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sun, 29 Jun 2025 00:34:41 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/css-art-june-celebrations-31bg</link>
      <guid>https://dev.to/xxzeroxx/css-art-june-celebrations-31bg</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2025-06-04"&gt;Frontend Challenge - June Celebrations, CSS Art: June Celebrations&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;My inspiration came from Brazil's traditional Festas Juninas, a joyful and colorful celebration that takes place throughout the month of June. It's a time marked by flags, gangs, bonfires, typical food and lots of balloons in the sky. I wanted to capture this energy using only HTML and CSS, creating a small animated universe that harks back to childhood, community and dance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/AntonioCarioca/embed/jEPZrQg?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;I started with the simple idea of animated balloons floating around, but quickly wanted to bring the scene to life. I added variations in color, depth and movement using &lt;code&gt;transform&lt;/code&gt;, &lt;code&gt;z-index&lt;/code&gt;and &lt;code&gt;opacity&lt;/code&gt;, which brought a touch of realism and visual depth.&lt;/p&gt;

&lt;p&gt;Then I felt that something was missing, so I included a &lt;strong&gt;dancing silhouette&lt;/strong&gt;, representing the traditional quadrilha dances of the Festas Juninas. This part was a bit of a creative challenge with &lt;code&gt;divs&lt;/code&gt;, &lt;code&gt;clip-path&lt;/code&gt;, pseudo-elements and CSS animations to simulate the body in motion.&lt;/p&gt;

&lt;p&gt;It was a fun exercise in &lt;strong&gt;pure CSS&lt;/strong&gt;, without SVGs or JavaScript, which forced me to explore the limits of shapes and animations with native code. I was especially happy with the festive mood of the artwork and the visual atmosphere I managed to create.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Team Submission&lt;/strong&gt;: This is an individual creation. No team participated in this submission.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the next steps, I'm thinking of making the artwork responsive, adding June music and perhaps integrating an interactive version with click and drag balloon events. I also want to experiment with dynamic shadows and bonfire lights!&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
    </item>
    <item>
      <title>PHP Design Patterns: Remote Facade</title>
      <dc:creator>Antonio Silva</dc:creator>
      <pubDate>Sat, 29 Mar 2025 20:36:04 +0000</pubDate>
      <link>https://dev.to/xxzeroxx/php-design-patterns-remote-facade-4gk9</link>
      <guid>https://dev.to/xxzeroxx/php-design-patterns-remote-facade-4gk9</guid>
      <description>&lt;h3&gt;
  
  
  Remote Facade Design Pattern
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Remote Facade&lt;/strong&gt; design pattern is used to reduce the number of remote calls between the client and the server. It acts as a single entry point to the underlying subsystem, offering coarse-grained methods that aggregate and manage the details of more complex operations. This pattern helps minimize latency issues caused by multiple network requests by wrapping complex processes inside a unified interface.&lt;/p&gt;

&lt;p&gt;In PHP, the &lt;strong&gt;Remote Facade&lt;/strong&gt; pattern is particularly useful in cases where the server provides a RESTful API or web services to a client.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivm7tgnkczgmv1bvswsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivm7tgnkczgmv1bvswsg.png" alt="facade" width="452" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Facade&lt;/strong&gt; class simplifies the interaction with various subsystems or services.&lt;/li&gt;
&lt;li&gt;The client makes a single call to the Facade instead of multiple fine-grained calls.&lt;/li&gt;
&lt;li&gt;The Facade coordinates with underlying services, performs any necessary data processing, and returns a simpler response to the client.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;Let's create a &lt;strong&gt;detailed&lt;/strong&gt; example of the &lt;strong&gt;Remote Facade&lt;/strong&gt; pattern using PHP, simulating a real-world e-commerce system with a REST API. This example will cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Subsystem Services&lt;/strong&gt;: Separate services for users, orders, and inventory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote Facade&lt;/strong&gt;: A class that acts as a single entry point for the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Request&lt;/strong&gt;: Simulating how a client (like a frontend or mobile app) interacts with the API.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Folder Structure&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ecommerce-app/
│── public/                  # Public-facing directory
│   ├── index.php            # Main entry point
│
│── src/                     # Core application logic
│   ├── Services/            # Subsystems (fine-grained remote services)
│   │   ├── UserService.php
│   │   ├── OrderService.php
│   │   ├── InventoryService.php
│   │
│   ├── Facade/              # Remote Facade
│   │   ├── ECommerceFacade.php
│   │
│   ├── Config/              # Configuration files (optional)
│   │   ├── config.php
│
│── api/                     # API layer (if exposing via REST)
│   ├── dashboard.php        # API endpoint using the facade
│
│── tests/                   # Unit tests for services and facade
│
│── vendor/                  # Composer dependencies (if used)
│
│── composer.json            # PHP dependency manager file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Setting Up Autoloading&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To make namespaces work, &lt;strong&gt;configure Composer&lt;/strong&gt;.&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;"autoload"&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="nl"&gt;"psr-4"&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="nl"&gt;"Services\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/Services/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Facade\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/Facade/"&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;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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer dump-autoload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;1️⃣ &lt;strong&gt;Implementing the Folder Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1.1 - &lt;code&gt;src/Services/&lt;/code&gt; (Subsystem Services)&lt;/p&gt;

&lt;p&gt;Each service simulates a remote API or database call.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/Services/UserService.php&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Services&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;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Get user information by user ID.
     *
     * @param int $userId
     * @return array
     */&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;getUserInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$userId&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;// Simulate data fetched from a database or external API&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;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Alice Johnson'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'alice@example.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'loyaltyPoints'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;120&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;&lt;code&gt;src/Services/OrderService.php&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Services&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;OrderService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Get the user's most recent orders.
     *
     * @param int $userId
     * @return array
     */&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;getRecentOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$userId&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;// Simulate order data (e.g., from a database or API)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'orderId'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Delivered'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'totalAmount'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;250.50&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'orderId'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Pending'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'totalAmount'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;89.99&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;&lt;code&gt;src/Services/InventoryService.php&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Services&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;InventoryService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Check the stock level of a given product.
     *
     * @param int $productId
     * @return array
     */&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;checkStock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$productId&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;// Simulate stock information&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;'productId'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$productId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'stockLevel'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'reorderThreshold'&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;1.2 - &lt;code&gt;src/Facade/&lt;/code&gt;&lt;strong&gt;(Remote Facade)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This &lt;strong&gt;ECommerceFacade.php&lt;/strong&gt; aggregates responses from multiple services.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/Facade/ECommerceFacade.php&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Facade&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;Services\UserService&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;Services\OrderService&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;Services\InventoryService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * ECommerceFacade simplifies interactions with multiple services.
 * This is the Remote Facade entry point for client applications.
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ECommerceFacade&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;UserService&lt;/span&gt; &lt;span class="nv"&gt;$userService&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;OrderService&lt;/span&gt; &lt;span class="nv"&gt;$orderService&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;InventoryService&lt;/span&gt; &lt;span class="nv"&gt;$inventoryService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Constructor initializes the service objects.
     */&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;userService&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;UserService&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;orderService&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;OrderService&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;inventoryService&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;InventoryService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Get dashboard data for a user, including user info,
     * recent orders, and stock info for a selected product.
     *
     * @param int $userId
     * @param int $productId
     * @return array
     */&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;getDashboardData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$productId&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;// Retrieve user information&lt;/span&gt;
        &lt;span class="nv"&gt;$userInfo&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;userService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUserInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Retrieve user's recent orders&lt;/span&gt;
        &lt;span class="nv"&gt;$recentOrders&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;orderService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRecentOrders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Retrieve stock information for a specific product&lt;/span&gt;
        &lt;span class="nv"&gt;$productStock&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;inventoryService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;checkStock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$productId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Aggregate and return the data to the client&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;'user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$userInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'recentOrders'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$recentOrders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'productStock'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$productStock&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;2️⃣ &lt;strong&gt;Exposing as an API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to use this in an API, create an &lt;code&gt;api/dashboard.php&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;api/dashboard.php&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require_once&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;'/../vendor/autoload.php'&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;Facade\ECommerceFacade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Set response type to JSON&lt;/span&gt;
&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve query parameters (with defaults)&lt;/span&gt;
&lt;span class="nv"&gt;$userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'userId'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$productId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'productId'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create the facade instance&lt;/span&gt;
&lt;span class="nv"&gt;$facade&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;ECommerceFacade&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Get the dashboard data using the facade&lt;/span&gt;
&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$facade&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getDashboardData&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$productId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Output the data as JSON&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;JSON_PRETTY_PRINT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📌 To test the API, start a local PHP server and visit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;http://localhost:8000/api/dashboard.php?userId&lt;span class="o"&gt;=&lt;/span&gt;1&amp;amp;productId&lt;span class="o"&gt;=&lt;/span&gt;2001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"user"&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="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&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;"Alice Johnson"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alice@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"loyaltyPoints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&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="nl"&gt;"recentOrders"&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;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Delivered"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"totalAmount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;250.5&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;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pending"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"totalAmount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;89.99&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;span class="nl"&gt;"productStock"&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="nl"&gt;"productId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stockLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reorderThreshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&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;3️⃣ &lt;strong&gt;Running the Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you don’t want an API and just want to test the facade, use &lt;code&gt;public/index.php&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;public/index.php&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require_once&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;'/../vendor/autoload.php'&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;Facade\ECommerceFacade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create the facade instance&lt;/span&gt;
&lt;span class="nv"&gt;$facade&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;ECommerceFacade&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Fetch dashboard data&lt;/span&gt;
&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$facade&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getDashboardData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Print results to browser (for testing purposes)&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;pre&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&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;"&amp;lt;/pre&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;Start a local server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php &lt;span class="nt"&gt;-S&lt;/span&gt; localhost:8000 &lt;span class="nt"&gt;-t&lt;/span&gt; public
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;Array&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Array&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&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="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Alice&lt;/span&gt; &lt;span class="nc"&gt;Johnson&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&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="n"&gt;alice&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;loyaltyPoints&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;recentOrders&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Array&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Array&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Delivered&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;totalAmount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;250.5&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Array&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Pending&lt;/span&gt;
                    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;totalAmount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;89.99&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="n"&gt;productStock&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Array&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2001&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stockLevel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;reorderThreshold&lt;/span&gt;&lt;span class="p"&gt;]&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why Use Remote Facade?
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Reduces multiple API calls&lt;/strong&gt; → Instead of calling three services separately, the client makes a single request.&lt;br&gt;
✅ &lt;strong&gt;Encapsulates complex logic&lt;/strong&gt; → The client does not need to worry about how the data is fetched or aggregated.&lt;br&gt;
✅ &lt;strong&gt;Improves performance&lt;/strong&gt; → Reduces network latency by combining responses.&lt;br&gt;
✅ &lt;strong&gt;Enhances maintainability&lt;/strong&gt; → Changes to services do not affect the client, as long as the facade interface remains stable.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Should You Use This Pattern?
&lt;/h2&gt;

&lt;p&gt;🔹 When you have a &lt;strong&gt;distributed system&lt;/strong&gt; with multiple microservices.&lt;br&gt;
🔹 When your client &lt;strong&gt;should not directly&lt;/strong&gt; interact with complex subsystems.&lt;br&gt;
🔹 When you want to &lt;strong&gt;minimize network requests&lt;/strong&gt; and improve performance.&lt;/p&gt;

</description>
      <category>php</category>
      <category>designpatterns</category>
    </item>
  </channel>
</rss>
