<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ PHP - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ PHP - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 14 May 2026 09:13:50 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/php/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build an Automatic Knowledge Graph for Your Blog with PHP and JSON-LD ]]>
                </title>
                <description>
                    <![CDATA[ When someone searches for information today, they increasingly turn to AI models like ChatGPT, Perplexity, or Gemini instead of Google. But these models don't return a list of links. They synthesize a ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-automatic-knowledge-graph-php-json-ld/</link>
                <guid isPermaLink="false">69e80305e436727814adb8df</guid>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JSON-LD ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SEO ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Shinobis ]]>
                </dc:creator>
                <pubDate>Tue, 21 Apr 2026 23:06:45 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/397b339f-25e0-48f6-b3fc-07f0548be746.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When someone searches for information today, they increasingly turn to AI models like ChatGPT, Perplexity, or Gemini instead of Google. But these models don't return a list of links. They synthesize an answer and cite the sources they trust most.</p>
<p>The question for anyone who runs a blog or content site is: how do you become one of those trusted sources? The answer lies in structured data, specifically JSON-LD Knowledge Graphs that help AI models understand not just what your content says, but how it connects to everything else you've published.</p>
<p>In this tutorial, you'll build a PHP function that auto-generates a JSON-LD Knowledge Graph for every blog post on your site. There are no plugins, no external APIs, and just one function. It will detect entities in your content, map relationships between posts, and output a unified schema that both Google and AI models like ChatGPT can parse as a connected system.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-why-this-matters-now">Why This Matters Now</a></p>
</li>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-the-pipeline">The Pipeline</a></p>
</li>
<li><p><a href="#heading-what-static-json-ld-looks-like-and-why-it-falls-short">What Static JSON-LD Looks Like (And Why It Falls Short)</a></p>
</li>
<li><p><a href="#heading-step-1-define-your-entity-helpers">Step 1: Define Your Entity Helpers</a></p>
</li>
<li><p><a href="#heading-step-2-build-the-blogposting-schema">Step 2: Build the BlogPosting Schema</a></p>
</li>
<li><p><a href="#heading-step-3-detect-topics-automatically">Step 3: Detect Topics Automatically</a></p>
</li>
<li><p><a href="#heading-step-4-map-relationships-between-posts">Step 4: Map Relationships Between Posts</a></p>
</li>
<li><p><a href="#heading-step-5-add-multilingual-connections">Step 5: Add Multilingual Connections</a></p>
</li>
<li><p><a href="#heading-step-6-assemble-the-graph">Step 6: Assemble the Graph</a></p>
</li>
<li><p><a href="#heading-what-the-output-looks-like-in-production">What the Output Looks Like in Production</a></p>
</li>
<li><p><a href="#heading-testing-your-implementation">Testing Your Implementation</a></p>
</li>
<li><p><a href="#heading-what-i-learned-after-3-months-in-production">What I Learned After 3 Months in Production</a></p>
</li>
</ul>
<h3 id="heading-why-this-matters-now">Why This Matters Now</h3>
<p>AI search engines are replacing blue links with synthesized answers. When someone asks ChatGPT a question, it doesn't return a list of URLs. It builds a response by citing the sources it trusts.</p>
<p><a href="https://www.accuracast.com/articles/optimisation/schema-markup-impact-ai-search/">According to AccuraCast's research on AI search citations</a>, 81% of pages cited by AI engines use schema markup with JSON-LD as the dominant format. Pages with structured schema are 3 to 4 times more likely to be cited by ChatGPT or Perplexity than pages without it.</p>
<p>Most JSON-LD tutorials teach you to paste a static <code>&lt;script&gt;</code> tag with your title and author name. That gets you into Google's index. But it doesn't get you cited by AI.</p>
<p>For that, you need a Knowledge Graph: a system where your entities (author, site, topics, tools, related articles) are connected through persistent identifiers that machines can follow across every page on your site.</p>
<p>I built this system for my own blog. After three months in production with 52 posts in three languages, I asked ChatGPT, Gemini, and Perplexity to audit the resulting schema. ChatGPT scored it 9.1 out of 10 and called it "production-grade graph design." This article walks you through how to build the same thing.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow this tutorial, you'll need:</p>
<ul>
<li><p>PHP 7.4 or higher running on your server</p>
</li>
<li><p>A MySQL or MariaDB database with a posts table that stores your blog content (title, slug, content, excerpt, created_at, updated_at)</p>
</li>
<li><p>Basic PHP knowledge: variables, arrays, functions, and database queries with PDO</p>
</li>
<li><p>A working blog where you can edit PHP files and add schema markup to your HTML output</p>
</li>
</ul>
<p>The tools we'll use are all built into PHP. No external packages or Composer dependencies are required. The entity detection uses simple string matching with strpos(), the database queries use PDO prepared statements, and the JSON-LD output uses PHP's native json_encode(). If you've built a blog with PHP before, you have everything you need.</p>
<h2 id="heading-the-pipeline">The Pipeline</h2>
<p>The system works in four stages:</p>
<img src="https://cdn.hashnode.com/uploads/covers/69b380d893256dfc53256f05/58404ce5-4603-4095-930f-761cb72c8e95.png" alt="Diagram showing the four-stage pipeline: Post from Database to Entity Detection to Relationship Mapping to @graph Output" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><strong>Stage 1</strong>: PHP queries MariaDB for the post content, metadata, and related post IDs.</p>
<p><strong>Stage 2</strong>: The system scans the content for known topics and tools using keyword matching. No NLP libraries needed. A simple associative array maps keywords to schema entities.</p>
<p><strong>Stage 3</strong>: Related posts are fetched and mapped as both navigation links (<code>relatedLink</code>) and knowledge relationships (<code>citation</code>).</p>
<p><strong>Stage 4</strong>: Everything gets combined into a single <code>@graph</code> array with five connected entities: WebSite, Organization, Person, WebPage, and BlogPosting. Each entity has a stable <code>@id</code> that machines can reference across pages.</p>
<h2 id="heading-what-static-json-ld-looks-like-and-why-it-falls-short">What Static JSON-LD Looks Like (And Why It Falls Short)</h2>
<p>Here is what a typical tutorial tells you to add:</p>
<pre><code class="language-json">{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "My Blog Post",
  "author": {
    "@type": "Person",
    "name": "Jane"
  },
  "datePublished": "2026-01-15"
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/69b380d893256dfc53256f05/d2e717e6-ad9c-4267-955f-d9c27b6b43a7.png" alt="Comparison between a minimal static JSON-LD schema and a full Knowledge Graph with five connected entities" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>This tells Google "there is an article by Jane." It doesn't say what topics the article covers, what tools it mentions, how it connects to other articles on your site, who publishes the site, or what makes Jane an authority on the subject.</p>
<p>For a blog with dozens of posts about interconnected topics, every post exists in isolation. Search engines and AI models can't see that your articles form a system of knowledge. They can't tell that your post about Midjourney prompts connects to your post about AI design workflows, which connects to your post about fintech UX.</p>
<p>By the end of this tutorial, that same post will generate a <code>@graph</code> with five linked entities, automatic topic detection, relationship mapping, multilingual connections, and an abstract that LLMs read before deciding whether to cite you.</p>
<h2 id="heading-step-1-define-your-entity-helpers">Step 1: Define Your Entity Helpers</h2>
<p>Three PHP functions define your core entities. They return arrays that get reused on every page of your site.</p>
<pre><code class="language-php">function getSchemaAuthor($baseUrl) {
    return [
        '@type' =&gt; 'Person',
        '@id' =&gt; $baseUrl . '/#author',
        'name' =&gt; 'Your Name',
        'description' =&gt; 'Your professional description.',
        'url' =&gt; $baseUrl . '/about',
        'image' =&gt; $baseUrl . '/photo.png',
        'jobTitle' =&gt; 'Your Title',
        'sameAs' =&gt; [
            'https://linkedin.com/in/yourprofile',
            'https://x.com/yourhandle',
            'https://dev.to/yourprofile'
        ]
    ];
}

function getSchemaOrganization($baseUrl) {
    return [
        '@type' =&gt; 'Organization',
        '@id' =&gt; $baseUrl . '/#organization',
        'name' =&gt; 'Your Site Name',
        'url' =&gt; $baseUrl,
        'logo' =&gt; [
            '@type' =&gt; 'ImageObject',
            'url' =&gt; $baseUrl . '/logo.png'
        ]
    ];
}

function getSchemaWebSite(\(baseUrl, \)siteName, \(siteDesc, \)langCode) {
    return [
        '@type' =&gt; 'WebSite',
        '@id' =&gt; $baseUrl . '/#website',
        'name' =&gt; $siteName,
        'description' =&gt; $siteDesc,
        'url' =&gt; $baseUrl,
        'inLanguage' =&gt; $langCode,
        'publisher' =&gt; ['@id' =&gt; $baseUrl . '/#organization']
    ];
}
</code></pre>
<p>The <code>@id</code> values are the most important detail. <code>/#author</code>, <code>/#organization</code>, and <code>/#website</code> are persistent identifiers that stay the same across every page.</p>
<p>When a machine reads your homepage and then reads a blog post, it recognizes that <code>https://yoursite.com/#author</code> is the same entity in both places. Without <code>@id</code>, each page creates a new floating entity that machines can't connect.</p>
<p>One decision that matters: the <code>publisher</code> should be an Organization, not a Person. AI systems assign more trust to content published by organizations than by individuals. Even if you're a solo creator, define your site as an Organization for publishing purposes and keep yourself as the Person author.</p>
<h2 id="heading-step-2-build-the-blogposting-schema">Step 2: Build the BlogPosting Schema</h2>
<p>This function takes a post from your database and the current language code, then builds the core BlogPosting entity.</p>
<pre><code class="language-php">function generateBlogPostingSchema(\(post, \)langCode) {
    $baseUrl = rtrim(SITE_URL, '/');
    \(siteName = getLocalizedSetting('site_name', \)langCode);
    \(siteDesc = getLocalizedSetting('site_description', \)langCode);
    $defaultLang = getDefaultLanguage();
    \(postSlug = \)post['slug'];

    \(postUrl = \)langCode === $defaultLang
        ? \(baseUrl . '/' . \)postSlug
        : \(baseUrl . '/' . \)langCode . '/' . $postSlug;

    \(excerpt = \)post['excerpt']
        ?: mb_substr(strip_tags($post['content']), 0, 160);

    $blogPosting = [
        '@type' =&gt; 'BlogPosting',
        '@id' =&gt; $postUrl . '#article',
        'headline' =&gt; $post['title'],
        'description' =&gt; $excerpt,
        'abstract' =&gt; $excerpt,
        'url' =&gt; $postUrl,
        'datePublished' =&gt; date('c', strtotime($post['created_at'])),
        'dateModified' =&gt; date('c', strtotime($post['updated_at'])),
        'author' =&gt; [
            '@type' =&gt; 'Person',
            '@id' =&gt; $baseUrl . '/#author',
            'name' =&gt; 'Your Name',
            'url' =&gt; $baseUrl . '/about'
        ],
        'publisher' =&gt; [
            '@type' =&gt; 'Organization',
            '@id' =&gt; $baseUrl . '/#organization',
            'name' =&gt; 'Your Site Name',
            'logo' =&gt; [
                '@type' =&gt; 'ImageObject',
                'url' =&gt; $baseUrl . '/logo.png'
            ]
        ],
        'isPartOf' =&gt; ['@id' =&gt; $baseUrl . '/#website'],
        'mainEntityOfPage' =&gt; [
            '@type' =&gt; 'WebPage',
            '@id' =&gt; $postUrl
        ],
        'inLanguage' =&gt; $langCode,
        'wordCount' =&gt; str_word_count(strip_tags($post['content']))
    ];
</code></pre>
<p>Two properties deserve attention.</p>
<p><code>abstract</code> maps the post excerpt. LLMs read the abstract first to decide whether the rest of the page is worth processing. If your excerpt says "In this post I explore some ideas about..." models may skip you entirely. Make it a direct statement: "To implement a Knowledge Graph you need five connected entities with persistent @id references." That's something an LLM can evaluate immediately.</p>
<p><code>isPartOf</code> connects the article to the WebSite entity. This tells machines "this article belongs to a larger knowledge source." Without it, each post looks like an independent document.</p>
<p>Notice that <code>author</code> and <code>publisher</code> include both <code>@id</code> and inline properties. The <code>@id</code> connects to the full entity in the <code>@graph</code>. The inline properties are a fallback because some parsers (including Google's Rich Results Test) don't always resolve <code>@id</code> references. Including both ensures zero validation warnings.</p>
<h2 id="heading-step-3-add-automatic-entity-detection">Step 3: Add Automatic Entity Detection</h2>
<p>This is where static JSON-LD tutorials stop and your Knowledge Graph begins. Instead of manually tagging each post with its topics, the system scans the content automatically.</p>
<pre><code class="language-php">    \(contentLower = strtolower(\)post['content'] . ' ' . $post['title']);

    $topicMap = [
        'midjourney'      =&gt; ['name' =&gt; 'Midjourney', 'url' =&gt; 'https://midjourney.com'],
        'prompt'          =&gt; ['name' =&gt; 'Prompt Engineering'],
        'fintech'         =&gt; ['name' =&gt; 'Fintech UX Design'],
        'ux design'       =&gt; ['name' =&gt; 'UX Design'],
        'llms.txt'        =&gt; ['name' =&gt; 'llms.txt', 'url' =&gt; 'https://llmstxt.org'],
        'knowledge graph' =&gt; ['name' =&gt; 'Knowledge Graph'],
    ];

    $aboutItems = [];
    $keywordsList = [];
    foreach (\(topicMap as \)keyword =&gt; $meta) {
        if (strpos(\(contentLower, \)keyword) !== false) {
            \(item = ['@type' =&gt; 'Thing', 'name' =&gt; \)meta['name']];
            if (isset(\(meta['url'])) \)item['url'] = $meta['url'];
            \(aboutItems[] = \)item;
            \(keywordsList[] = \)meta['name'];
        }
    }
    if (!empty($aboutItems)) {
        \(blogPosting['about'] = \)aboutItems;
    }
</code></pre>
<p>The same pattern detects tools mentioned in the content:</p>
<pre><code class="language-php">    $toolMap = [
        'midjourney' =&gt; ['name' =&gt; 'Midjourney', 'url' =&gt; 'https://midjourney.com'],
        'claude'     =&gt; ['name' =&gt; 'Claude', 'url' =&gt; 'https://claude.ai'],
        'chatgpt'    =&gt; ['name' =&gt; 'ChatGPT', 'url' =&gt; 'https://chat.openai.com'],
        'figma'      =&gt; ['name' =&gt; 'Figma', 'url' =&gt; 'https://figma.com'],
    ];

    $mentionItems = [];
    foreach (\(toolMap as \)keyword =&gt; $meta) {
        if (strpos(\(contentLower, \)keyword) !== false) {
            $mentionItems[] = [
                '@type' =&gt; 'Thing',
                'name' =&gt; $meta['name'],
                'url' =&gt; $meta['url']
            ];
            \(keywordsList[] = \)meta['name'];
        }
    }
    if (!empty($mentionItems)) {
        \(blogPosting['mentions'] = \)mentionItems;
    }

    if (!empty($keywordsList)) {
        \(blogPosting['keywords'] = array_values(array_unique(\)keywordsList));
    }
</code></pre>
<p>The difference between <code>about</code> and <code>mentions</code> matters for AI citation. <code>about</code> declares the main topics. <code>mentions</code> declares tools and references that appear in the content. If a post is a Midjourney tutorial that also mentions Claude, <code>about</code> gets Midjourney and <code>mentions</code> gets Claude.</p>
<p>This distinction helps AI models decide whether to cite your page when someone asks about Midjourney versus when they ask about Claude.</p>
<p>A question that comes up often: do you need NLP for entity detection? No. A keyword map with <code>strpos</code> handles the vast majority of cases for a personal blog. NLP adds complexity, latency, and a dependency you don't need. If your topic map has 20 to 30 entries, keyword matching is fast, predictable, and easy to debug.</p>
<h2 id="heading-step-4-map-relationships-between-posts">Step 4: Map Relationships Between Posts</h2>
<p>Each post connects to related posts through two properties: <code>relatedLink</code> for navigation and <code>citation</code> for knowledge relationships.</p>
<pre><code class="language-php">    \(relatedUrls = getRelatedPostUrls(\)post['id'], $langCode);
    if (!empty($relatedUrls)) {
        \(blogPosting['relatedLink'] = \)relatedUrls;
        \(blogPosting['citation'] = \)relatedUrls;
    }
</code></pre>
<p>The helper function queries a <code>post_connections</code> table:</p>
<pre><code class="language-php">function getRelatedPostUrls(\(postId, \)langCode) {
    $pdo = getDB();
    $baseUrl = rtrim(SITE_URL, '/');
    $defaultLang = getDefaultLanguage();

    \(stmt = \)pdo-&gt;prepare(
        "SELECT connected_post_id FROM post_connections WHERE post_id = ?"
    );
    \(stmt-&gt;execute([\)postId]);
    \(connections = \)stmt-&gt;fetchAll(PDO::FETCH_COLUMN);

    $urls = [];
    foreach (\(connections as \)connId) {
        \(slug = getPostSlugForLanguage(\)connId, $langCode);
        if ($slug) {
            \(urls[] = \)langCode === $defaultLang
                ? \(baseUrl . '/' . \)slug
                : \(baseUrl . '/' . \)langCode . '/' . $slug;
        }
    }
    return $urls;
}
</code></pre>
<p>Why use both <code>relatedLink</code> and <code>citation</code> on the same URLs? They signal different things to machines. <code>relatedLink</code> says "the reader might want to visit these pages next." <code>citation</code> says "this article builds on the knowledge in these other articles."</p>
<p>AI models weigh <code>citation</code> more heavily when deciding whether your content is part of a larger knowledge system. Using both tells machines that your related posts aren't just navigation. They're sources this article builds upon.</p>
<h2 id="heading-step-5-add-multilingual-support">Step 5: Add Multilingual Support</h2>
<p>If your blog publishes in multiple languages, <code>workTranslation</code> connects different language versions of the same article.</p>
<pre><code class="language-php">    $languages = getActiveLanguages();
    $translations = [];
    foreach (\(languages as \)lang) {
        \(lc = \)lang['code'];
        if (\(lc === \)langCode) continue;

        \(translatedSlug = getPostSlugForLanguage(\)post['id'], $lc);
        if ($translatedSlug) {
            \(translatedUrl = \)lc === $defaultLang
                ? \(baseUrl . '/' . \)translatedSlug
                : \(baseUrl . '/' . \)lc . '/' . $translatedSlug;

            \(stmtT = \)pdo-&gt;prepare(
                "SELECT title FROM post_translations
                 WHERE post_id = ? AND language_code = ? LIMIT 1"
            );
            \(stmtT-&gt;execute([\)post['id'], $lc]);
            \(translatedTitle = \)stmtT-&gt;fetchColumn() ?: $post['title'];

            $translations[] = [
                '@type' =&gt; 'CreativeWork',
                '@id' =&gt; $translatedUrl . '#article',
                'headline' =&gt; $translatedTitle,
                'url' =&gt; $translatedUrl,
                'inLanguage' =&gt; $lc
            ];
        }
    }
    if (!empty($translations)) {
        \(blogPosting['workTranslation'] = \)translations;
    }
</code></pre>
<p>Without <code>workTranslation</code>, a blog with 50 posts in three languages looks like 150 independent articles to AI models. With it, the same blog looks like 50 pieces of knowledge with multilingual reach. The authority consolidates instead of fragmenting.</p>
<p>The translations use <code>@type: CreativeWork</code> instead of <code>BlogPosting</code>. This avoids warnings in Google's Rich Results Test where each translation would be flagged as a separate article with missing required fields.</p>
<h2 id="heading-step-6-assemble-the-graph">Step 6: Assemble the Graph</h2>
<p>Bring everything together:</p>
<pre><code class="language-php">    $webPage = [
        '@type' =&gt; 'WebPage',
        '@id' =&gt; $postUrl,
        'url' =&gt; $postUrl,
        'name' =&gt; $post['title'],
        'isPartOf' =&gt; ['@id' =&gt; $baseUrl . '/#website']
    ];

    $graph = [
        '@context' =&gt; 'https://schema.org',
        '@graph' =&gt; [
            getSchemaWebSite(\(baseUrl, \)siteName, \(siteDesc, \)langCode),
            getSchemaOrganization($baseUrl),
            getSchemaAuthor($baseUrl),
            $webPage,
            $blogPosting
        ]
    ];

    return '&lt;script type="application/ld+json"&gt;'
        . json_encode($graph,
            JSON_UNESCAPED_SLASHES
            | JSON_UNESCAPED_UNICODE
            | JSON_PRETTY_PRINT)
        . '&lt;/script&gt;';
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/69b380d893256dfc53256f05/04e9ab4f-ab33-432f-baf8-b318bbef949f.png" alt="Visual representation of the @graph architecture showing WebSite, Organization, Person, WebPage, and BlogPosting connected via @id references" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>The <code>json_encode</code> flags matter. <code>JSON_UNESCAPED_SLASHES</code> prevents URLs from getting escaped. <code>JSON_UNESCAPED_UNICODE</code> keeps non-ASCII characters readable for multilingual content. Without these, a single special character in a blog post title fetched from the database can break the entire JSON-LD block silently.</p>
<h2 id="heading-what-the-output-looks-like-in-production">What the Output Looks Like in Production</h2>
<p>Here is the actual JSON-LD generated by a real post on <a href="https://shinobis.com">shinobis.com</a>, a blog about AI tools and UX design:</p>
<pre><code class="language-json">{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "WebSite",
      "@id": "https://shinobis.com/#website",
      "name": "Designer in the Age of AI",
      "description": "AI tools and real workflows from a designer who builds with AI.",
      "url": "https://shinobis.com",
      "inLanguage": "en",
      "publisher": { "@id": "https://shinobis.com/#organization" }
    },
    {
      "@type": "Organization",
      "@id": "https://shinobis.com/#organization",
      "name": "Shinobis",
      "url": "https://shinobis.com",
      "logo": { "@type": "ImageObject", "url": "https://shinobis.com/3117045.png" }
    },
    {
      "@type": "Person",
      "@id": "https://shinobis.com/#author",
      "name": "Shinobis",
      "description": "UX/UI Designer with 10+ years in banking and fintech.",
      "url": "https://shinobis.com/en/about",
      "jobTitle": "UX/UI Designer",
      "sameAs": [
        "https://www.linkedin.com/company/shinobis-ai",
        "https://dev.to/shinobis_ia"
      ]
    },
    {
      "@type": "WebPage",
      "@id": "https://shinobis.com/en/one-year-with-ai-open-letter-to-designers",
      "url": "https://shinobis.com/en/one-year-with-ai-open-letter-to-designers",
      "name": "One Year with AI: Open Letter to Designers",
      "isPartOf": { "@id": "https://shinobis.com/#website" }
    },
    {
      "@type": "BlogPosting",
      "@id": "https://shinobis.com/en/one-year-with-ai-open-letter-to-designers#article",
      "headline": "One Year with AI: Open Letter to Designers",
      "description": "One year ago I started this journey. Today I write to all designers who are still doubting, fearing, or ignoring AI.",
      "abstract": "One year ago I started this journey. Today I write to all designers who are still doubting, fearing, or ignoring AI.",
      "url": "https://shinobis.com/en/one-year-with-ai-open-letter-to-designers",
      "datePublished": "2026-02-15T09:00:00-05:00",
      "dateModified": "2026-03-20T14:30:00-05:00",
      "inLanguage": "en",
      "wordCount": 1842,
      "author": {
        "@type": "Person",
        "@id": "https://shinobis.com/#author",
        "name": "Shinobis",
        "url": "https://shinobis.com/en/about"
      },
      "publisher": {
        "@type": "Organization",
        "@id": "https://shinobis.com/#organization",
        "name": "Shinobis",
        "logo": { "@type": "ImageObject", "url": "https://shinobis.com/3117045.png" }
      },
      "isPartOf": { "@id": "https://shinobis.com/#website" },
      "mainEntityOfPage": {
        "@type": "WebPage",
        "@id": "https://shinobis.com/en/one-year-with-ai-open-letter-to-designers"
      },
      "about": [
        { "@type": "Thing", "name": "Midjourney", "url": "https://midjourney.com" },
        { "@type": "Thing", "name": "Prompt Engineering" }
      ],
      "mentions": [
        { "@type": "Thing", "name": "Claude", "url": "https://claude.ai" }
      ],
      "relatedLink": [
        "https://shinobis.com/en/ai-is-not-going-to-take-your-job-your-comfort-zone-will",
        "https://shinobis.com/en/the-designer-as-creative-director-of-machines"
      ],
      "citation": [
        "https://shinobis.com/en/ai-is-not-going-to-take-your-job-your-comfort-zone-will",
        "https://shinobis.com/en/the-designer-as-creative-director-of-machines"
      ],
      "keywords": ["Midjourney", "Prompt Engineering", "Claude"],
      "workTranslation": [
        {
          "@type": "CreativeWork",
          "@id": "https://shinobis.com/un-ano-con-ia-carta-abierta-disenadores#article",
          "headline": "Un año con IA: carta abierta a los diseñadores",
          "url": "https://shinobis.com/un-ano-con-ia-carta-abierta-disenadores",
          "inLanguage": "es"
        },
        {
          "@type": "CreativeWork",
          "@id": "https://shinobis.com/ja/one-year-with-ai-open-letter-to-designers#article",
          "headline": "AIと一年：デザイナーへの公開書簡",
          "url": "https://shinobis.com/ja/one-year-with-ai-open-letter-to-designers",
          "inLanguage": "ja"
        }
      ]
    }
  ]
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/69b380d893256dfc53256f05/943d4463-c7a7-4210-8e88-a3c72dd82d70.png" alt="Annotated JSON-LD output showing key properties: persistent @id, abstract for LLMs, auto-detected entities, citation relationships, and workTranslation for multilingual authority" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>Compare that to the static version: one <code>BlogPosting</code> with a headline and an author name. The difference isn't cosmetic. It's the difference between "there is an article" and "there is a knowledge node connected to an author with verified profiles, published by an organization, linked to related articles through citation relationships, covering specific topics, and available in three languages."</p>
<h2 id="heading-testing-your-implementation">Testing Your Implementation</h2>
<p>After deploying, validate at <a href="https://search.google.com/test/rich-results">Google's Rich Results Test</a>. Paste any post URL and look for your BlogPosting with all properties.</p>
<p>For a deeper audit, copy the <code>&lt;script type="application/ld+json"&gt;</code> block from your page source and paste it into ChatGPT with this prompt: "Audit this JSON-LD schema for AI citation visibility. Score it 1-10 and tell me what is missing." The feedback is surprisingly specific.</p>
<p>When I did this, ChatGPT identified five improvements that raised the score from 8.7 to 9.1.</p>
<h2 id="heading-what-i-learned-after-3-months-in-production">What I Learned After 3 Months in Production</h2>
<p>I have been running this system on a blog with 52 posts in three languages since early 2026. Google indexed pages went from 26 to 48 in three months. The keyword "llms txt" reached position 4 on Google. AI models started citing my content in responses about JSON-LD implementation.</p>
<p>Three things I would do differently if starting today.</p>
<p>First, add the <code>abstract</code> property from day one. I added it three months in and the impact was immediate. LLMs use abstract as a first filter. Perplexity confirmed that the first 200 characters of a page are critical for whether AI extracts the content.</p>
<p>Second, use <code>citation</code> alongside <code>relatedLink</code> from the beginning. <code>relatedLink</code> is a navigation hint. <code>citation</code> signals a knowledge relationship. AI models interpret the connections between your posts differently depending on which property you use.</p>
<p>Third, define the publisher as an Organization immediately. I started with <code>@type: Person</code> and changed it later. AI systems assign more trust to organizational publishers.</p>
<p>The system generates JSON-LD on every page load. At this scale (under 100 posts) the performance impact is negligible. For thousands of posts, generate on publish and cache the output.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>This system is one layer of what is now called Generative Engine Optimization: structuring content so AI models cite you in their responses.</p>
<p>The other layers include an <a href="https://llmstxt.org">llms.txt</a> file at your domain root (which gives AI crawlers a site-level overview) and writing content that AI can extract without needing additional context (direct statements over narrative introductions).</p>
<p>The complete source code is running in production at <a href="https://shinobis.com">shinobis.com</a>. Every post uses the exact system described here.</p>
<p>The next SEO battlefield isn't rankings. It's citations. And citations start with structure.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Build Secure Web Applications with PHP, Symfony, and MongoDB ]]>
                </title>
                <description>
                    <![CDATA[ Data breaches are a constant threat, and traditional encryption practices often aren't enough to protect sensitive information throughout its entire lifecycle. We just posted a course on the freeCodeCamp.org YouTube channel that will teach you how to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-secure-web-applications-with-php-symfony-and-mongodb/</link>
                <guid isPermaLink="false">68c2cf0fe8903924be3e8c8c</guid>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Symfony ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 11 Sep 2025 13:30:55 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1757573041841/0bbcb80c-76b9-4792-be3b-fba79ea344b1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Data breaches are a constant threat, and traditional encryption practices often aren't enough to protect sensitive information throughout its entire lifecycle.</p>
<p>We just posted a course on the freeCodeCamp.org YouTube channel that will teach you how to build applications that are truly secure from the ground up using PHP, Symfony, and MongoDB.</p>
<p>I developed this course. I will teach you how to build a system where data is protected not just at rest and in transit, but also while it's in use.</p>
<p>Throughout this comprehensive, step-by-step tutorial, you will build a fully functional personal finance application. The application will allow users to create accounts, log transactions, and view their financial information.</p>
<p>The core of this course focuses on solving a major challenge in application security which is how to perform queries on encrypted data. You'll learn how to find a user by their social security number or search for transactions within a specific amount range, all without ever decrypting the information on the database server.</p>
<p>I use MongoDB's Queryable Encryption to encrypt sensitive data on the client-side. This data is then stored as fully randomized encrypted fields in the database, yet you can still run equality and range-check queries on it. The server never has access to the unencrypted data or the encryption keys, keeping the data secure throughout its entire life cycle.</p>
<p>This tutorial is designed for developers who have some experience with PHP and a framework like Symfony or Laravel, but even if you're new to these technologies, you should be able to follow along.</p>
<p>Watch the full course now <a target="_blank" href="https://youtu.be/UuknxVdqzb4">on the freeCodeCamp.org YouTube channel</a> (1-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/UuknxVdqzb4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Build a Google Calendar Clone with PHP, MySql & JavaScript ]]>
                </title>
                <description>
                    <![CDATA[ Building something from scratch using just PHP, MySQL, JavaScript, HTML, and CSS is one of the best ways to level up your skills and gain a real understanding of full-stack development. We just published a course on the freeCodeCamp.org YouTube chann... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-google-calendar-clone-with-php-mysql-and-javascript/</link>
                <guid isPermaLink="false">6867c64cd0d1e1e4f2cbe4f8</guid>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Fri, 04 Jul 2025 12:17:16 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751631421687/ecb8f621-7ba8-4100-8e54-d51dc3866578.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building something from scratch using just PHP, MySQL, JavaScript, HTML, and CSS is one of the best ways to level up your skills and gain a real understanding of full-stack development.</p>
<p>We just published a course on the freeCodeCamp.org YouTube channel that will teach you how to build a full stack Google Calendar-style app. If you want to learn how web apps actually work behind the scenes, without depending on frameworks or third-party libraries, this is the course for you. It’s a great project to add to your portfolio or use as a starting point for your own scheduling or booking tools.</p>
<p>The project covers everything from laying out the calendar UI to wiring up a MySQL database, writing all the backend logic in PHP, and making the app dynamic with vanilla JavaScript. You won’t be using any frameworks, packages, or helpers; only just clean, readable code. That makes it a solid learning tool whether you're a beginner trying to understand the fundamentals or someone more experienced who wants to see how to build a real app without relying on a tech stack.</p>
<h3 id="heading-heres-what-youll-build-and-learn">Here's what you'll build and learn:</h3>
<ul>
<li><p>A fully responsive calendar layout using plain HTML and CSS</p>
</li>
<li><p>A real-time clock and modern UI with dropdowns and modals for better user interaction</p>
</li>
<li><p>Multi-day appointment support, including start/end time slots</p>
</li>
<li><p>Full CRUD functionality using PHP and MySQL (add, edit, delete bookings)</p>
</li>
<li><p>Booking conflict logic to prevent overlapping appointments</p>
</li>
<li><p>Clean JavaScript that dynamically renders the calendar and controls the modals</p>
</li>
<li><p>A final polished app that could easily be adapted into tools like school systems, event planners, or personal schedulers</p>
</li>
</ul>
<p>The calendar interface is smooth and intuitive. Users can jump between months, view multiple bookings per day, and interact with modals to manage events. Everything updates in real time without page reloads. It’s a complete full-stack experience with front-end design, back-end logic, and database integration all in one.</p>
<p>The course is around 3 hours long and broken into clearly structured sections, so you can follow along even if you're new to some of the technologies. The instructor explains each step clearly, and by the end, you'll not only have a working app, you’ll understand how and why everything works.</p>
<p>You can watch the full tutorial now for free on the <a target="_blank" href="https://youtu.be/pHMtbdGoP_g">freeCodeCamp.org YouTube channel</a> (3-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/pHMtbdGoP_g" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write a PHP Script to Calculate the Area of a Triangle ]]>
                </title>
                <description>
                    <![CDATA[ In programming, being able to find the area of a triangle is useful for many reasons. It can help you understand logic-building and syntax, and it’s a common programming problem used in school assignments. There are also many real-world applications,... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-php-to-calculate-the-area-of-a-triangle/</link>
                <guid isPermaLink="false">68542db2cefef90e768ba1fe</guid>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mathematics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ triangle ]]>
                    </category>
                
                    <category>
                        <![CDATA[ DSA ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Programming Blogs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MathJax ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ AYUSH MISHRA ]]>
                </dc:creator>
                <pubDate>Thu, 19 Jun 2025 15:33:06 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750346934679/2e46bebb-9614-4f1a-afb5-9bbe27906b4e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In programming, being able to find the area of a triangle is useful for many reasons. It can help you understand logic-building and syntax, and it’s a common programming problem used in school assignments. There are also many real-world applications, such as computer graphics, geometry-based simulations, or construction-related calculations.</p>
<p>In this article, we’ll look at a common problem: we are given the dimensions of a triangle, and our task is to calculate its area. You can calculate the area of a triangle using different formulas, depending on the information you have about the triangle. Here, you’re going to learn how to do it using PHP.</p>
<h3 id="heading-after-reading-this-tutorial">After reading this tutorial:</h3>
<ul>
<li><p>You will understand the basic logic behind calculating the area of a triangle.</p>
</li>
<li><p>You will know how to write PHP code that calculates the triangle’s area using pre-defined and user-entered values.</p>
</li>
<li><p>You will know how to apply this logic in small projects and assignments.</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-find-the-area-of-a-triangle-using-direct-formulas">Find the Area of a Triangle Using Direct Formulas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-find-the-area-of-a-triangle-using-the-base-and-height-approach">Find the Area of a Triangle Using the Base and Height Approach</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-find-the-area-of-a-triangle-using-herons-formula">Find the Area of a Triangle Using Heron's Formula</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-find-the-area-of-a-triangle-using-two-sides-and-included-angle-trigonometric-formula">Find the Area of a Triangle Using Two Sides and Included Angle (Trigonometric Formula)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You’ll understand this guide more easily if you have some knowledge about a few things:</p>
<h3 id="heading-basic-php">Basic PHP</h3>
<p>You’ll need to know basic PHP syntax to fully understand the problem. If you know how to write a simple echo statement or create a variable in PHP, then you should be good to go.</p>
<h3 id="heading-local-php-environment">Local PHP Environment</h3>
<p>To run the PHP code successfully, you should have local PHP development, such as XAMPP or WAMP, on your machine. You can also use online PHP editors like PHP Fiddle or OnlineGDB to run a PHP script without any installation.</p>
<p>In this tutorial we are going to explore three approaches to determine the area of the triangle in PHP based on the amount of information available about the triangle.</p>
<ul>
<li><p><strong>Base and Height Formula Approach:</strong> This approach is applicable when you have the perpendicular height from the base and length of the base in the problem.</p>
</li>
<li><p><strong>Heron’s Formula:</strong> This approach is used to calculate the area of triangle when you have the lengths of all three sides of the triangle.</p>
</li>
<li><p><strong>Trigonometric Formula Approach:</strong> This approach is applied on the problem when you have the length of two sides and the included angle between them.</p>
</li>
</ul>
<p>First, let’s go back to math class and use some direct formulas to find the area.</p>
<h2 id="heading-find-the-area-of-a-triangle-using-direct-formulas">Find the Area of a Triangle Using Direct Formulas</h2>
<h3 id="heading-example-1">Example 1:</h3>
<p>In this first example, you’re given the input base and height of a triangle. You have to return the area of the triangle. For this example, you’ll use a direct formula to calculate the area of the triangle.</p>
<p><strong>Input:</strong></p>
<p>Base = 5,</p>
<p>Height = 10</p>
<p>You can calculate the area of the triangle using the formula:</p>
<p>$$Area = (Base * Height) / 2$$</p><p>So, if you plug in the values you have, you get: (5* 10) / 2 = 25.</p>
<p><strong>Output:</strong></p>
<p>Area = 25</p>
<h3 id="heading-example-2">Example 2:</h3>
<p>In this second example, you’re given the length of two sides of a triangle and one angle between them. You have to return the area of the triangle. In this example, you’ll use another direct formula to calculate the area of the triangle.</p>
<p><strong>Input:</strong></p>
<p>Side A = 7, Side B = 9, Angle between them = 60°</p>
<p>In this case, you’ll use the formula:</p>
<p>$$Area = (1/2) A B * sin(Angle).$$</p><p>Then just substitute in the values you’ve been given to find the area.</p>
<p><strong>Output:</strong></p>
<p>Area = 27.33 (approximately)</p>
<p>Now let’s look at some different approaches to finding the area of a triangle using PHP.</p>
<h2 id="heading-find-the-area-of-a-triangle-using-the-base-and-height-approach">Find the Area of a Triangle Using the Base and Height Approach</h2>
<p>This is the simplest and most direct approach for calculating the area of a triangle when you know the base and height. In this approach, you’ll directly put values in the formula and find the area of the triangle – but you’ll do it with PHP code.</p>
<p>First, define the base and height of the triangle. Then apply the formula for the area of the triangle. As we saw above, the formula for the area of a triangle is:</p>
<p>$$Area = (Base * Height) / 2$$</p><p>After calculating the area of the triangle, output the answer.</p>
<p>Alright, so here’s how we can implement that in PHP:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-comment">// Define the base and height</span>
$base = <span class="hljs-number">5</span>;
$height = <span class="hljs-number">10</span>;

<span class="hljs-comment">// Calculate the area</span>
$area = ($base * $height) / <span class="hljs-number">2</span>;

<span class="hljs-comment">// Output the result</span>
<span class="hljs-keyword">echo</span> <span class="hljs-string">"The area of the triangle is: "</span> . $area . <span class="hljs-string">" square units."</span>;
<span class="hljs-meta">?&gt;</span>
</code></pre>
<p>Output:</p>
<p>The area of the triangle is 25 square units.</p>
<p>In the above code, first we initialize the base and height of triangle in two variables. Then we plug those values into the area formula. PHP calculates the area of the triangle and displays the answer.</p>
<p><strong>Time Complexity</strong>: In the above approach, we are using the direct formula to calculate and return the area of the triangle, so the time complexity will be constant at O(1). The constant time complexity is efficient as it will remain constant, regardless of the size or values of the base and height.</p>
<p><strong>Space Complexity</strong>: The Space Complexity will be O(1). The space used by the above program is constant, which ensures minimal use of memory. This space complexity is ideal in environments where memory efficiency is a priority.</p>
<p>We use the above approach when we have the length of the base and height of the triangle (whether directly given or easily measurable in a right angle triangle). This method works best for right-angled triangles.</p>
<h2 id="heading-find-the-area-of-a-triangle-using-herons-formula">Find the Area of a Triangle Using Heron's Formula</h2>
<p>Heron’s formula is named after a Greek mathematician named Heron of Alexandria. Heron’s formula is useful when you know the lengths of all three sides of the triangle and you want to calculate the area without needing the height. This formula works for any type of triangle, including scalene triangles (triangles with sides of all different lengths).</p>
<p>Here’s Heron’s formula to calculate the area of a triangle:</p>
<p>$$√s(s−a)(s−b)(s−c) ​$$</p><p>Where:</p>
<ul>
<li><p>s = semi-perimeter = (a+b+c)/2 is the semi-perimeter of the triangle.</p>
</li>
<li><p>a, b, and c are the lengths of the sides.</p>
</li>
</ul>
<p>First, we define the three sides of the triangle. Then, we check all three conditions of the <a target="_blank" href="https://en.wikipedia.org/wiki/Triangle_inequality">Triangle Inequality Theorem</a> which states that if the sum of two sides is greater than the third side, then it is a valid triangle, and the given sides can form a triangle.</p>
<p>We can calculate the semi-perimeter of the triangle using the formula s = a+b+c/2. Then we can apply Heron's formula to calculate the area. After calculating the area, then output the answer.</p>
<p>Here’s how you can implement this in PHP:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-comment">// Define the sides of the triangle</span>
$a = <span class="hljs-number">7</span>;
$b = <span class="hljs-number">9</span>;
$c = <span class="hljs-number">10</span>;

<span class="hljs-comment">// Check if the sides form a valid triangle using the Triangle Inequality Theorem</span>
<span class="hljs-keyword">if</span> (($a + $b &gt; $c) &amp;&amp; ($a + $c &gt; $b) &amp;&amp; ($b + $c &gt; $a)) {

    <span class="hljs-comment">// Calculate the semi-perimeter</span>
    $s = ($a + $b + $c) / <span class="hljs-number">2</span>;

    <span class="hljs-comment">// Calculate the area using Heron's formula</span>
    $area = sqrt($s * ($s - $a) * ($s - $b) * ($s - $c));

    <span class="hljs-comment">// Output the result</span>
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"The area of the triangle is: "</span> . $area . <span class="hljs-string">" square units."</span>;

} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// If the sides can't form a valid triangle</span>
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"The given sides do not form a valid triangle."</span>;
}
<span class="hljs-meta">?&gt;</span>
</code></pre>
<p>Output:</p>
<p>The area of the triangle is: 27.321 square units.</p>
<p>In the above code, we first create three variables to store the lengths of the triangle’s sides, and check if the given sides form a valid triangle or not using the Triangle Inequality Theorem. Then we calculate the semi-perimeter using the formula: s = a + b + c / 2. We put the value of the semi-perimeter and lengths of all sides in Heron’s formula to calculate the area. The area of triangle is returned after calculating using the formula.</p>
<p><strong>Time Complexity</strong>: There is a total fixed number of operations such as addition, subtraction, multiplication, and square root. These operations don’t depend on input size as they are performed only a fixed number of times. This means that the time complexity is constant O(1).</p>
<p><strong>Space Complexity</strong>: We have used a fixed number of variables to calculate the area of the triangle. We have not used any additional data structures such as arrays or objects. The memory usage in the program is constant, which is better for low-memory environments. The space complexity is constant O(1).</p>
<p>This approach works best when the lengths of all sides are given. This approach is used mainly for scalene or isosceles triangles where height is directly not given. This approach can work for any type of triangle, however – scalene, isosceles, or equilateral.</p>
<h2 id="heading-find-the-area-of-a-triangle-using-two-sides-and-included-angle-trigonometric-formula">Find the Area of a Triangle Using Two Sides and Included Angle (Trigonometric Formula)</h2>
<p>In this approach, we will see a different variation of the problem. When you know two sides of a triangle and the included angle between them, you can calculate the area using this formula:</p>
<p>$$Area = 1/2 × a × b × sin(θ)$$</p><p>Where:</p>
<ul>
<li><p>a and b are the lengths of the two sides.</p>
</li>
<li><p>θ is the included angle between the two sides, measured in degrees or radians.</p>
</li>
</ul>
<p>Using the above formula, you can calculate the area of a triangle without needing its height. First, you define the two sides of the triangle and the angle between them. Then you convert the angle from degrees to radians if needed (in PHP, you can use deg2rad() to convert degrees to radians). Then you apply the formula.</p>
<p>After calculating the area of the triangle, output the result.</p>
<p>Here’s how to implement this in PHP:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-comment">// Define the two sides and the included angle</span>
$a = <span class="hljs-number">7</span>;
$b = <span class="hljs-number">9</span>;
$angle = <span class="hljs-number">60</span>; <span class="hljs-comment">// Angle in degrees</span>

<span class="hljs-comment">// Convert the angle from degrees to radians</span>
$angle_in_radians = deg2rad($angle);

<span class="hljs-comment">// Calculate the area using the formula</span>
$area = <span class="hljs-number">0.5</span> * $a * $b * sin($angle_in_radians);

<span class="hljs-comment">// Output the result</span>
<span class="hljs-keyword">echo</span> <span class="hljs-string">"The area of the triangle is: "</span> . $area . <span class="hljs-string">" square units."</span>;
<span class="hljs-meta">?&gt;</span>
</code></pre>
<p>Output:</p>
<p>The area of the triangle is: 27.321 square units.</p>
<p>Explanation:</p>
<p>In the above case, we’re using the formula:</p>
<p>Area of Triangle = 1/2 × a × b × sin(θ)</p>
<p>And we’re substituting the following values into the formula:</p>
<p>Area= 1/2 × 7 × 9 × sin(60 ∘) ≈ 27.321</p>
<p>In the code, we declared two variables to store the length of the two sides of the triangle, and the variable <code>$angle</code> hold the included angle in degrees. We used <code>deg2rad()</code>, a PHP built-in function which converts an angle from degrees to radians. Then, we applied the actual formula: Area = 1/2 × 7 × 9 × sin(60 ∘). PHP stores the final answer in the <code>$area</code> variable.</p>
<p><strong>Time Complexity</strong>: We are using the direct formula to calculate the area of a triangle when the length of two sides and the angle between them are given. The constant time complexity is O(1).</p>
<p><strong>Space Complexity</strong>: Similarly, it does not take any extra space or use any data structures. It uses a single variable to store the result, which is why the space complexity is constant O(1).</p>
<p>This approach is perfect for the problem in which two sides and the included angle (angle between those sides) are known. You can use it when you cannot easily calculate the height of the triangle. This problem has real-life applications in geometry problems, CAD applications, or physics simulations. This method is very accurate and doesn’t require the length of all sides.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you’ve learned how you can calculate the area of a triangle, both manually and using PHP. You have seen different approaches and learned about which one is best given the information you have. First, we discussed the base and height approach, then looked at Heron’s formula, and finally examined how to handle things when two sides and the included angle are given.</p>
<p>Understanding the logic behind each of these approaches helps you choose the right one based on the given data.</p>
<p>And if you'd like to support me and my work directly so I can keep creating these tutorials, <a target="_blank" href="https://paypal.me/ayushM010">you can do so here</a>. Thank you!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Loops Work in PHP: A Complete Guide for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ PHP loops help you repeat a block of code based on a condition. You can use them to work through arrays or repeat actions. You can also use them to skip steps based on logic. In this article, you will learn how PHP loops work and when to use each ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-loops-work-in-php-beginners-guide/</link>
                <guid isPermaLink="false">685338f9c57f030c11bb6ddb</guid>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP7 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ php8 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHPUnit ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PhpStorm ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Montasser Mossallem ]]>
                </dc:creator>
                <pubDate>Wed, 18 Jun 2025 22:08:57 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750178963918/bf8c63b9-9624-4cb0-bd31-10ffbdbe67f6.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>PHP loops help you repeat a block of code based on a condition. You can use them to work through arrays or repeat actions. You can also use them to skip steps based on logic.</p>
<p>In this article, you will learn how PHP loops work and when to use each type.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-understand-how-loops-work-in-php">Understand How Loops Work in PHP</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-while-loop-in-php">The <code>while</code> Loop in PHP</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-do-while-loop-in-php">The <code>do...while</code> Loop in PHP</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-for-loop-in-php">The <code>for</code> Loop in PHP</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-foreach-loop-in-php">The <code>foreach</code> Loop in PHP</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-break-statement">Use <code>break</code> Statement</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-continue-statement">Use <code>continue</code> Statement</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-replace-loops-with-array_map-in-php">Replace Loops with <code>array_map()</code> in PHP</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understand-nested-loops">Understand Nested Loops</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<p>Let’s get started.</p>
<h2 id="heading-understand-how-loops-work-in-php">Understand How Loops Work in PHP</h2>
<p>A loop lets PHP run the same set of instructions more than once. It checks a certain condition before each run. Then the code runs again if the condition is true and it stops if the condition is false.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749910672507/5a4f946c-bbe8-407d-bfd0-c524d7fef9e0.png" alt="Diagram showing how loops work in PHP" class="image--center mx-auto" width="1536" height="1024" loading="lazy"></p>
<p>Loops help reduce repeated code. You can process items in a list or check values. Loops let you write a block of code once and run it multiple times.</p>
<p>PHP provides four main types of loops:</p>
<ul>
<li><p>while</p>
</li>
<li><p>do...while</p>
</li>
<li><p>for</p>
</li>
<li><p>foreach</p>
</li>
</ul>
<p>Let’s take a look at each one in detail</p>
<h2 id="heading-the-while-loop-in-php">The <code>while</code> Loop in PHP</h2>
<p>The while loop checks if the condition is true before it runs the code block. If the condition is true, it runs the block. Then it checks again. The loop repeats until the condition becomes false.</p>
<p>Here is the syntax:</p>
<pre><code class="lang-plaintext">while (condition) {
  // code block
}
</code></pre>
<p>Here is an example:</p>
<pre><code class="lang-php">$count = <span class="hljs-number">1</span>;
<span class="hljs-keyword">while</span> ($count &lt;= <span class="hljs-number">3</span>) {
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"Count: <span class="hljs-subst">$count</span>\n"</span>;
  $count++;
}
</code></pre>
<p>This loop starts with <code>$count = 1</code>. It prints the value and adds 1 each time. It stops when <code>$count</code> becomes 4.</p>
<p>It gives you this output:</p>
<pre><code class="lang-plaintext">Count: 1
Count: 2
Count: 3
</code></pre>
<p>Here’s another example:</p>
<pre><code class="lang-php">$index = <span class="hljs-number">0</span>;
$names = [<span class="hljs-string">'Tom'</span>, <span class="hljs-string">'Anna'</span>, <span class="hljs-string">'Joe'</span>];
<span class="hljs-keyword">while</span> ($index &lt; count($names)) {
  <span class="hljs-keyword">echo</span> $names[$index] . <span class="hljs-string">"\n"</span>;
  $index++;
}
</code></pre>
<p>This loop prints each name from the array. It uses the index to move through the list.</p>
<p>Output:</p>
<pre><code class="lang-plaintext">Tom
Anna
Joe
</code></pre>
<p>So, <strong>when should you use a</strong> <code>while</code> <strong>loop?</strong></p>
<p>Use a <code>while</code> loop when you want to check the condition first before running the code. This type fits best when the loop should not run at all if the condition is false from the start.</p>
<p>Here is an example:</p>
<p>You ask a user to enter a number. You only want to run your loop if the number is positive.</p>
<pre><code class="lang-php">$number = getUserInput();

<span class="hljs-keyword">while</span> ($number &gt; <span class="hljs-number">0</span>) {
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"You entered: <span class="hljs-subst">$number</span>\n"</span>;
  $number = getUserInput();
}
</code></pre>
<p>If the first number is zero or negative, the loop will skip. That makes sense here – you only want the loop to run for valid numbers.</p>
<p>You’ll learn how the PHP <code>do while</code> loop works in the next part.</p>
<h2 id="heading-the-dowhile-loop-in-php">The <code>do...while</code> Loop in PHP</h2>
<p>The <code>do...while</code> loop runs the code block once, then checks the condition. It always runs at least one time.</p>
<pre><code class="lang-plaintext">do {
  // code block
} while (condition);
</code></pre>
<p>Example:</p>
<pre><code class="lang-php">$start = <span class="hljs-number">5</span>;
<span class="hljs-keyword">do</span> {
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"Start: <span class="hljs-subst">$start</span>\n"</span>;
  $start++;
} <span class="hljs-keyword">while</span> ($start &lt; <span class="hljs-number">8</span>);
</code></pre>
<p>This loop prints numbers from 5 to 7. It checks the condition after the block runs.</p>
<p>Output:</p>
<pre><code class="lang-plaintext">Start: 5
Start: 6
Start: 7
</code></pre>
<p>Here’s another example:</p>
<pre><code class="lang-php">$retry = <span class="hljs-number">0</span>;
<span class="hljs-keyword">do</span> {
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"Attempt <span class="hljs-subst">$retry</span>\n"</span>;
  $retry++;
} <span class="hljs-keyword">while</span> ($retry &lt; <span class="hljs-number">1</span>);
</code></pre>
<p>The code runs once, even if the condition is false at the start. Output:</p>
<pre><code class="lang-plaintext">Attempt 0
</code></pre>
<p>Use a <code>do...while</code> loop when you want the code to run at least once. This makes sense when the first step must happen before checking the condition.</p>
<p>Here is an example:</p>
<p>You want to show a menu to the user at least once. Then you keep showing it until they choose to exit.</p>
<pre><code class="lang-php"><span class="hljs-keyword">do</span> {
  $option = showMenuAndGetChoice();
} <span class="hljs-keyword">while</span> ($option != <span class="hljs-string">"exit"</span>);
</code></pre>
<p>The menu appears once no matter what. If the user types "exit" right away, the loop stops after one run.</p>
<p>Let’s move on to the following section to take a look at the most common loop in PHP which is the for loop.</p>
<h2 id="heading-the-for-loop-in-php">The <code>for</code> Loop in PHP</h2>
<p>The <code>for</code> loop works when you know how many times you want the loop to run. It gives you a clean way to set a counter, check a condition, and update the counter – all in one line. This makes the loop easy to read and control.</p>
<p>The loop has three parts inside the parentheses:</p>
<ol>
<li><p><strong>Start</strong> – This sets up the loop. You usually define a counter here, like <code>$i = 0</code>.</p>
</li>
<li><p><strong>Condition</strong> – The loop runs while this part is true. As soon as it becomes false, the loop stops.</p>
</li>
<li><p><strong>Step</strong> – This updates the counter after each loop run. You can increase or decrease the value here.</p>
</li>
</ol>
<p>Here is the structure:</p>
<pre><code class="lang-plaintext">for (start; condition; step) {
  // code block
}
</code></pre>
<p>Here is an example:</p>
<pre><code class="lang-php"><span class="hljs-keyword">for</span> ($i = <span class="hljs-number">1</span>; $i &lt;= <span class="hljs-number">3</span>; $i++) {
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"Number: <span class="hljs-subst">$i</span>\n"</span>;
}
</code></pre>
<p>This is what happens:</p>
<ul>
<li><p><code>$i = 1</code> sets the starting value.</p>
</li>
<li><p>The condition <code>$i &lt;= 3</code> checks if the loop should run.</p>
</li>
<li><p>If the condition is true, the code inside runs.</p>
</li>
<li><p>Then <code>$i++</code> increases the counter by 1.</p>
</li>
<li><p>The loop repeats until <code>$i</code> becomes greater than 3.</p>
</li>
</ul>
<p>Here is the output:</p>
<pre><code class="lang-plaintext">Number: 1
Number: 2
Number: 3
</code></pre>
<p>Here’s another example:</p>
<pre><code class="lang-php"><span class="hljs-keyword">for</span> ($i = <span class="hljs-number">2</span>; $i &lt;= <span class="hljs-number">6</span>; $i += <span class="hljs-number">2</span>) {
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$i</span> is even\n"</span>;
}
</code></pre>
<p>The step here is <code>$i += 2</code>, not just <code>$i++</code>. This adds 2 to <code>$i</code> after each run instead of 1. So the values go from 2 to 4 to 6. That is how you control the pace of the loop.</p>
<p>Here is the output:</p>
<pre><code class="lang-plaintext">2 is even
4 is even
6 is even
</code></pre>
<p>You use a <code>for</code> loop when:</p>
<ul>
<li><p>You know exactly how many times you need to run the code</p>
</li>
<li><p>You’re working with a counter that increases or decreases</p>
</li>
<li><p>You’re looping through a range, like numbers 1 to 10</p>
</li>
<li><p>You want to keep all the loop setup in one place</p>
</li>
</ul>
<p>In the following section, you will learn about another loop called <code>foreach</code>. Let’s move on.</p>
<h2 id="heading-the-foreach-loop-in-php">The <code>foreach</code> Loop in PHP</h2>
<p><a target="_blank" href="https://flatcoding.com/tutorials/php/foreach-loop-in-php/">PHP’s foreach</a> loop is built to work with arrays. It lets you move through each item in the array, one at a time. You don’t need a counter, and you don’t need to check the size – PHP handles that part for you.</p>
<p>There are two ways to use <code>foreach</code>, and both work only with arrays or objects that act like arrays:</p>
<ul>
<li><p>Loop through values only</p>
</li>
<li><p>Loop through keys and values</p>
</li>
</ul>
<p>Let’s look at each one.</p>
<p><strong>Loop through values only:</strong> this version gives you one value from the array on each run:</p>
<pre><code class="lang-php">$colors = [<span class="hljs-string">'red'</span>, <span class="hljs-string">'green'</span>, <span class="hljs-string">'blue'</span>];

<span class="hljs-keyword">foreach</span> ($colors <span class="hljs-keyword">as</span> $color) {
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$color</span>\n"</span>;
}
</code></pre>
<p>Here, the array has three values. The loop gives you one at a time. You don’t get the position or index – just the value.</p>
<p>Here is output:</p>
<pre><code class="lang-plaintext">red  
green  
blue
</code></pre>
<p><strong>Loop through keys and values</strong>: This version gives you both the key and the value for each array item.</p>
<p>Here is an example:</p>
<pre><code class="lang-php">$person = [<span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'Alice'</span>, <span class="hljs-string">'age'</span> =&gt; <span class="hljs-number">30</span>, <span class="hljs-string">'city'</span> =&gt; <span class="hljs-string">'Cape Town'</span>];

<span class="hljs-keyword">foreach</span> ($person <span class="hljs-keyword">as</span> $key =&gt; $value) {
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$key</span>: <span class="hljs-subst">$value</span>\n"</span>;
}
</code></pre>
<p>Here, <code>$key</code> holds each index or name, and <code>$value</code> holds what is stored at that key.</p>
<p>Here is the output:</p>
<pre><code class="lang-php">name: Alice  
age: <span class="hljs-number">30</span>  
city: Cape Town
</code></pre>
<p>This format helps when you want to label data, work with both the name and value, or build something like a form or report.</p>
<p>Remember that <code>foreach</code> works only with arrays or objects that act like arrays (such as objects that implement <code>Traversable</code>). You cannot use it with a plain string or number.</p>
<p>If you try this:</p>
<pre><code class="lang-php"><span class="hljs-keyword">foreach</span> (<span class="hljs-number">123</span> <span class="hljs-keyword">as</span> $item) {
  <span class="hljs-keyword">echo</span> $item;
}
</code></pre>
<p>You get an error. PHP expects something that holds multiple items, like an array or an iterable object.</p>
<p>You can exit the loop with <code>break</code> a statement based on a condition or expression. Let’s move on to the next part to see how we can do that.</p>
<h2 id="heading-how-to-use-the-break-statement-in-php">How to Use the <code>break</code> Statement in PHP</h2>
<p>The <a target="_blank" href="https://flatcoding.com/tutorials/php/php-break-exit-php-loop/">break statement</a> in PHP ends the loop immediately, even if its condition remains true. Here is its syntax:</p>
<pre><code class="lang-plaintext">break;
</code></pre>
<p>Here is an example:</p>
<pre><code class="lang-php"><span class="hljs-keyword">for</span> ($i = <span class="hljs-number">1</span>; $i &lt;= <span class="hljs-number">5</span>; $i++) {
  <span class="hljs-keyword">if</span> ($i === <span class="hljs-number">3</span>) {
    <span class="hljs-keyword">break</span>;
  }
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$i</span>\n"</span>;
}
</code></pre>
<p>This loop stops when <code>$i</code> becomes 3. Output:</p>
<pre><code class="lang-plaintext">1
2
</code></pre>
<p>This PHP code uses a <code>for</code> loop to count from 1 to 5. It includes a condition that stops the loop early with <code>break</code>. If <code>$i</code> equals 3, the loop ends.</p>
<p>Otherwise, it prints the value of <code>$i</code>. The output is 1 and 2, and the loop exits before it gets to 3.</p>
<p>Here are some common reasons to use the <code>break</code> statement:</p>
<ul>
<li><p>When you find what you need</p>
</li>
<li><p>If you want to exit on a certain condition</p>
</li>
<li><p>Inside a menu or user input loop</p>
</li>
<li><p>In <code>switch</code> statements</p>
</li>
</ul>
<p>PHP will run all the code after the first match if you don’t use <code>break</code>. That can cause bugs.</p>
<p>In the next section, you will see how to skip parts of a loop when certain conditions are true.</p>
<h2 id="heading-how-to-use-the-continue-statement">How to Use the <code>continue</code> Statement</h2>
<p><a target="_blank" href="https://flatcoding.com/tutorials/php/php-continue-statement/">PHP’s continue statement</a> skips the rest of the loop for the current step. Here’s its syntax:</p>
<pre><code class="lang-php"><span class="hljs-keyword">continue</span>;
</code></pre>
<p>Here is an example:</p>
<pre><code class="lang-php"><span class="hljs-keyword">for</span> ($i = <span class="hljs-number">1</span>; $i &lt;= <span class="hljs-number">4</span>; $i++) {
  <span class="hljs-keyword">if</span> ($i === <span class="hljs-number">2</span>) {
    <span class="hljs-keyword">continue</span>;
  }
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$i</span>\n"</span>;
}
</code></pre>
<p>This loop doesn’t print 2 and moves to the next value. Output:</p>
<pre><code class="lang-plaintext">1
3
4
</code></pre>
<p>So, <strong>why would you skip part of a loop with</strong> <code>continue</code><strong>?</strong></p>
<p>You use the <code>continue</code> statement in PHP when you want to skip the rest of the current loop block and move to the next item. This helps when you need to avoid some steps in a loop based on a condition.</p>
<p>You might use <code>continue</code> in a <code>foreach</code>, <code>for</code>, or <code>while</code> loop. If a value does not match what you need, you skip it and go on. You don’t stop the loop – you only skip the current run.</p>
<p><strong>So why would you want to avoid loops in some cases?</strong></p>
<p>Loops give you full control, but they can lead to clutter. You repeat the same logic over and over. That makes the code harder to read. You also risk bugs if you forget to update a counter or break at the right time.</p>
<p>If all you want is to apply one action to every item in an array, a loop might feel like too much. You don’t need full control – just a clean way to map values. That is where a built-in function like <code>array_map</code> makes more sense.</p>
<p>In the following part, you will see how <code>array_map</code> replaces a loop when you want a way to change every item in an array.</p>
<h2 id="heading-how-to-replace-loops-with-arraymap-in-php">How to Replace Loops with <code>array_map()</code> in PHP</h2>
<p><a target="_blank" href="https://flatcoding.com/tutorials/php/array_map/">PHP’s array_map</a> function helps you avoid repetitive loops. It applies a <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-arrow-functions-in-php/">callback function</a> to every item in one or more arrays and returns a new array with the results.</p>
<pre><code class="lang-php">$numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>];
$doubled = array_map(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$n</span>) =&gt; $<span class="hljs-title">n</span> * 2, $<span class="hljs-title">numbers</span>)</span>;
print_r($doubled);
</code></pre>
<p>The output:</p>
<pre><code class="lang-plaintext">[2, 4, 6, 8]
</code></pre>
<p>This does the same thing as a <code>foreach</code> loop where you multiply each number by 2 and store the result. But with <code>array_map</code>, the logic stays in one place.</p>
<p>You pass the function and the array as arguments. That’s what people mean by a “functional style” – you use built-in tools that focus on input and output, not steps or counters.</p>
<p>You get the same result, but the code is shorter to read. You also avoid side effects since <code>array_map</code> returns a new array without changing the original one.</p>
<p>In the following section, you will understand how nested loops work.</p>
<h2 id="heading-how-nested-loops-work-in-php">How Nested Loops Work in PHP</h2>
<p>A nested loop means one loop sits inside another. The outer loop controls the bigger cycle while the inner loop runs completely every time the outer loop runs once.</p>
<p>So if the outer loop runs two times and the inner loop runs three times each cycle, the inner loop runs six times in total.</p>
<p>For example:</p>
<pre><code class="lang-php"><span class="hljs-keyword">for</span> ($i = <span class="hljs-number">1</span>; $i &lt;= <span class="hljs-number">2</span>; $i++) {
  <span class="hljs-keyword">for</span> ($j = <span class="hljs-number">1</span>; $j &lt;= <span class="hljs-number">3</span>; $j++) {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"i=<span class="hljs-subst">$i</span>, j=<span class="hljs-subst">$j</span>\n"</span>;
  }
}
</code></pre>
<p>Here is how it works:</p>
<ul>
<li><p>The outer loop uses <code>$i</code>. It starts at 1 and runs while <code>$i &lt;= 2</code>.</p>
</li>
<li><p>That means the outer loop runs two times: once for <code>$i = 1</code> and once for <code>$i = 2</code>.</p>
</li>
<li><p>Inside that, the inner loop uses <code>$j</code>. It starts at 1 and runs while <code>$j &lt;= 3</code>.</p>
</li>
<li><p>So for each time the outer loop runs, the inner loop runs three times: for <code>$j = 1</code>, <code>$j = 2</code>, and <code>$j = 3</code>.</p>
</li>
</ul>
<p>Output:</p>
<pre><code class="lang-plaintext">i=1, j=1
i=1, j=2
i=1, j=3
i=2, j=1
i=2, j=2
i=2, j=3
</code></pre>
<p>So, <strong>how do you use nested loops with arrays?</strong></p>
<p>You can also use nested loops to read a two-dimensional array. Here is an example using a matrix:</p>
<pre><code class="lang-php">$matrix = [
  [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>],
  [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
];

<span class="hljs-keyword">foreach</span> ($matrix <span class="hljs-keyword">as</span> $row) {
  <span class="hljs-keyword">foreach</span> ($row <span class="hljs-keyword">as</span> $cell) {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"<span class="hljs-subst">$cell</span> "</span>;
  }
  <span class="hljs-keyword">echo</span> <span class="hljs-string">"\n"</span>;
}
</code></pre>
<p>In this case:</p>
<ul>
<li><p>The outer <code>foreach</code> gets each row from the matrix.</p>
</li>
<li><p>Each <code>$row</code> is an array: first <code>[1, 2]</code>, then <code>[3, 4]</code>.</p>
</li>
<li><p>The inner <code>foreach</code> goes through each value inside the row.</p>
</li>
</ul>
<p>So the output is:</p>
<pre><code class="lang-plaintext">1 2
3 4
</code></pre>
<p>You can use nested loops when you need to handle a grid or matrix. It also works when you want to group values.</p>
<p><strong>When should you use nested loops, and when should you not?</strong></p>
<p>You might have:</p>
<ul>
<li><p>Rows and columns in a matrix</p>
</li>
<li><p>A list of orders, each with items</p>
</li>
<li><p>Categories, each with subcategories</p>
</li>
</ul>
<p>Any time you have to work through a group that sits inside another group, nested loops help. They let you go step by step through both levels.</p>
<p>For example, if you have products grouped by type, you can use an outer loop for the types and an inner loop for each product inside.</p>
<p>But nested loops also have limits. If both loops run many times, your code slows down fast. A loop inside a loop means the total steps grow quickly.</p>
<p>If the outer loop runs 100 times and the inner loop runs 100 times, that makes 10,000 steps. That can cause long load times or even freeze the server with large data sets.</p>
<p>Nested loops solve real problems, but just make sure you use them only when they fit. Not every task needs one. If you can solve the same problem with one loop and clear data, that is often better.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Loops help you repeat tasks in PHP. You can use while, for, or even foreach based on what you need. Use break to stop early. Use continue to skip steps. Use nested loops if you work with grids or grouped data.</p>
<p>Now hopefully you understand how each <a target="_blank" href="https://flatcoding.com/tutorials/php/php-loop-with-loops-examples/">PHP loop</a> works based on these examples and clear use cases.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Arrow Functions in PHP 7.4+ ]]>
                </title>
                <description>
                    <![CDATA[ Arrow functions were introduced in PHP 7.4 to allow devs to write short, anonymous functions. They offer a compact alternative to traditional closures, especially when the function body is small and focused. In this article, you will learn how to use... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-arrow-functions-in-php/</link>
                <guid isPermaLink="false">681cf9062cbe43bee0f4138f</guid>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web developers ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Montasser Mossallem ]]>
                </dc:creator>
                <pubDate>Thu, 08 May 2025 18:33:42 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746354775446/092005ae-12bb-4be9-a72c-aacc5f044962.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Arrow functions were introduced in PHP 7.4 to allow devs to write short, anonymous functions. They offer a compact alternative to traditional closures, especially when the function body is small and focused.</p>
<p>In this article, you will learn how to use the arrow function in PHP with examples. You’ll also learn about the difference between arrow functions and anonymous functions.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#understand-the-arrow-functions-in-php">Understand the Arrow Functions in PHP</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-difference-between-arrow-functions-and-anonymous-functions-in-php">The Difference Between Arrow Functions and Anonymous Functions in PHP</a></p>
<ul>
<li><p><a class="post-section-overview" href="#1-syntax">1. Syntax</a></p>
</li>
<li><p><a class="post-section-overview" href="#2-variable-scope-lexical-scope">2. Variable Scope (Lexical Scope)</a></p>
</li>
<li><p><a class="post-section-overview" href="#3-readability-and-brevity">3. Readability and Brevity</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#how-to-return-arrow-functions-from-other-functions">How to Return Arrow Functions from Other Functions</a></p>
</li>
<li><p><a class="post-section-overview" href="#how-to-use-arrow-functions-in-your-code">How to Use Arrow Functions in Your Code?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#use-the-arrow-function-within-array_map">Use the Arrow Function within <code>array_map()</code></a></p>
</li>
<li><p><a class="post-section-overview" href="#use-the-arrow-function-with-array_filter">Use the Arrow Function with <code>array_filter()</code></a></p>
</li>
<li><p><a class="post-section-overview" href="#use-the-arrow-function-with-array_reduce">Use the arrow function with <code>array_reduce()</code></a></p>
</li>
<li><p><a class="post-section-overview" href="#nest-arrow-functions-in-php">Nest arrow functions in PHP</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You should know how to write basic PHP code, such as functions, and be able to work with arrays. Make sure you’re using PHP 7.4 or newer because arrow functions only work in that version and above.</p>
<h2 id="heading-understanding-arrow-functions-in-php">Understanding Arrow Functions in PHP</h2>
<p>The <a target="_blank" href="https://flatcoding.com/tutorials/php/arrow-functions/">PHP arrow function</a> is a shorthand syntax. It defines an anonymous function and is designed for simple operations and expressions.</p>
<p>Arrow functions in PHP are best used when:</p>
<ul>
<li><p>You need a quick callback or inline function.</p>
</li>
<li><p>The function returns a single expression.</p>
</li>
<li><p>You want to avoid repetitive <code>use</code> statements.</p>
</li>
</ul>
<p>The basic syntax of an arrow function is:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">parameter_list</span>) =&gt; <span class="hljs-title">expression</span></span>;
</code></pre>
<ul>
<li><p><code>fn</code> is the keyword that defines the arrow function.</p>
</li>
<li><p><code>parameter_list</code> is the list of parameters (similar to a normal function).</p>
</li>
<li><p><code>=&gt;</code> separates the parameter list from the expression.</p>
</li>
<li><p><code>expression</code> is the value the function returns. You cannot use a block of statements here – only a single expression is allowed.</p>
</li>
</ul>
<p>Arrow functions automatically capture variables from the scope. They don’t need the <code>use</code> keyword as shown below:</p>
<pre><code class="lang-php">$var_name = <span class="hljs-number">10</span>; 
$func = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$n</span>) <span class="hljs-title">use</span> (<span class="hljs-params"> $var_name </span>) </span>{
   <span class="hljs-keyword">return</span> $n * $var_name;
}
</code></pre>
<p>You can use the variables in the scope directly:</p>
<pre><code class="lang-php">$var_name = <span class="hljs-number">10</span>; 
$func = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$n</span>) =&gt; $<span class="hljs-title">n</span> * $<span class="hljs-title">var_name</span></span>;
</code></pre>
<p>Here’s a lexical scoping example:</p>
<pre><code class="lang-php">$multiplier = <span class="hljs-number">3</span>;
$multiply = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$x</span>) =&gt; $<span class="hljs-title">x</span> * $<span class="hljs-title">multiplier</span></span>;
<span class="hljs-keyword">echo</span> $multiply(<span class="hljs-number">4</span>); <span class="hljs-comment">// Outputs: 12</span>
</code></pre>
<p>The variable <code>$multiplier</code> is automatically captured from the outer scope. You don’t need to use <code>use($multiplier)</code> as you would in a traditional anonymous function.</p>
<p>Key rules of arrow function syntax:</p>
<ul>
<li><p>Always use <code>fn</code>, not <code>function</code>.</p>
</li>
<li><p>No curly braces or <code>return</code> keyword – just a single expression.</p>
</li>
<li><p>Automatic variable capture from the outer scope.</p>
</li>
<li><p>It cannot contain multiple statements or control structures (like <code>if</code>, <code>foreach</code>, and so on).</p>
</li>
</ul>
<p>Let’s move on to the following section to take a look at the difference between arrow functions and <a target="_blank" href="https://flatcoding.com/tutorials/php-programming/php-anonymous-functions/">anonymous functions in PHP</a>.</p>
<h2 id="heading-the-difference-between-arrow-functions-and-anonymous-functions-in-php">The Difference Between Arrow Functions and Anonymous Functions in PHP</h2>
<p>PHP supports two types of anonymous functions (that is, functions without a name):</p>
<ul>
<li><p><strong>Traditional anonymous functions</strong> are defined by the <code>function</code> keyword</p>
</li>
<li><p><strong>Arrow functions</strong> are introduced in PHP 7.4 within the <code>fn</code> keyword</p>
</li>
</ul>
<p>Both types can be assigned to variables and used for callbacks or as function arguments. They serve similar purposes, but differ in syntax and how they handle external variables.</p>
<p>Let’s look at their key differences.</p>
<h3 id="heading-1-syntax">1. Syntax</h3>
<h4 id="heading-arrow-function">Arrow Function:</h4>
<p>Arrow functions use a single-line expression without braces or a <code>return</code> statement.</p>
<pre><code class="lang-php">$square = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$n</span>) =&gt; $<span class="hljs-title">n</span> * $<span class="hljs-title">n</span></span>;
</code></pre>
<p>The arrow function assigns it to the variable <code>$square</code>. The function takes one parameter, <code>$n</code>, and returns <code>$n * $n</code> (the square of <code>$n</code>).</p>
<h4 id="heading-anonymous-function">Anonymous Function:</h4>
<pre><code class="lang-php">$square = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$n</span>) </span>{
    <span class="hljs-keyword">return</span> $n * $n;
};
</code></pre>
<p>Anonymous functions use a full function block and require an explicit <code>return</code>. They’re used for multi-line logic or complex behavior.</p>
<h3 id="heading-2-variable-scope-lexical-scope">2. Variable Scope (Lexical Scope)</h3>
<p>Arrow functions automatically capture variables from the outer scope:</p>
<pre><code class="lang-php">$factor = <span class="hljs-number">2</span>;
$multiply = <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$x</span>) =&gt; $<span class="hljs-title">x</span> * $<span class="hljs-title">factor</span></span>;
</code></pre>
<p>Anonymous functions require you to manually import external variables using <code>use</code>:</p>
<pre><code class="lang-php">$factor = <span class="hljs-number">2</span>;
$multiply = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$x</span>) <span class="hljs-title">use</span> (<span class="hljs-params">$factor</span>) </span>{
    <span class="hljs-keyword">return</span> $x * $factor;
};
</code></pre>
<p>You cannot use the variable in the scope within the anonymous function unless you use the <code>use</code> keyword.</p>
<h3 id="heading-3-readability-and-brevity">3. Readability and Brevity</h3>
<p>Arrow functions are shorter. They help you write small and single-expression callbacks:</p>
<pre><code class="lang-php">$numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
$squares = array_map(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$n</span>) =&gt; $<span class="hljs-title">n</span> * $<span class="hljs-title">n</span>, $<span class="hljs-title">numbers</span>)</span>;
</code></pre>
<p>But anonymous functions are better when:</p>
<ul>
<li><p>The function body has multiple lines.</p>
</li>
<li><p>You need complex logic or control structures.</p>
</li>
</ul>
<p><strong>Here is a table that shows you the key differences:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>Arrow Function</td><td>Anonymous Function</td></tr>
</thead>
<tbody>
<tr>
<td>Introduced in</td><td>PHP 7.4</td><td>PHP 5.3</td></tr>
<tr>
<td>Syntax</td><td>Short, single-expression</td><td>Verbose, full-function body</td></tr>
<tr>
<td>Scope handling</td><td>Automatic (lexical)</td><td>Manual (<code>use</code>) keyword</td></tr>
<tr>
<td>Multiline body</td><td>Not allowed</td><td>Allowed</td></tr>
<tr>
<td>Return keyword</td><td>Not used</td><td>Required</td></tr>
</tbody>
</table>
</div><p>Let’s move on to the section below to understand how to return an arrow function from another function.</p>
<h2 id="heading-how-to-return-arrow-functions-from-other-functions">How to Return Arrow Functions from Other Functions</h2>
<p>Functions are first-class citizens. This means you can return a function from another function. That includes arrow functions.</p>
<p>You can define and return an arrow function from within a regular function like this:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMultiplier</span>(<span class="hljs-params">$factor</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$x</span>) =&gt; $<span class="hljs-title">x</span> * $<span class="hljs-title">factor</span></span>;
}

$double = getMultiplier(<span class="hljs-number">2</span>);
<span class="hljs-keyword">echo</span> $double(<span class="hljs-number">5</span>); <span class="hljs-comment">// Outputs: 10</span>
</code></pre>
<p>In this example:</p>
<ul>
<li><p><code>getMultiplier()</code> returns an arrow function.</p>
</li>
<li><p>The arrow function captures <code>$factor</code> from the outer scope automatically (lexical scoping).</p>
</li>
<li><p>The returned function can be stored in a variable and used like any other callable.</p>
</li>
</ul>
<p>It lets you generate small functions based on parameters and reduces code repetition.</p>
<p>Use this syntax when you need to build dynamic behavior – like custom filters or function factories.</p>
<p>Let’s move on to the section below to see how you can use arrow functions in your code.</p>
<h2 id="heading-how-to-use-arrow-functions-in-your-code">How to Use Arrow Functions in Your Code</h2>
<h3 id="heading-use-the-arrow-function-within-arraymap">Use the Arrow Function within <code>array_map()</code>:</h3>
<p><code>array_map()</code> lets you set a callback to each element of an array. It allows you to define the callback directly within the function call.</p>
<p>Example:</p>
<pre><code class="lang-php">$numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];

$squares = array_map(<span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$n</span>) =&gt; $<span class="hljs-title">n</span> * $<span class="hljs-title">n</span>, $<span class="hljs-title">numbers</span>)</span>;

print_r($squares);
<span class="hljs-comment">// Outputs: [1, 4, 9, 16, 25]</span>
</code></pre>
<p>The arrow function <code>fn($n) =&gt; $n * $n</code> is executed for each element of the <code>$numbers</code> array. The result is a new array of squared values.</p>
<h3 id="heading-use-the-arrow-function-with-arrayfilter">Use the Arrow Function with <code>array_filter()</code></h3>
<p><code>array_filter()</code> filters elements of an array within a callback. Arrow functions define a short filter condition inline.</p>
<p>Example:</p>
<pre><code class="lang-php">$numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>];

$evenNumbers = array_filter($numbers, <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$n</span>) =&gt; $<span class="hljs-title">n</span> % 2 === 0)</span>;

print_r($evenNumbers);
<span class="hljs-comment">// Outputs: [2, 4, 6]</span>
</code></pre>
<p>Here, the arrow function checks if each number is even. The result is an array that contains only the even numbers.</p>
<h3 id="heading-use-the-arrow-function-with-arrayreduce">Use the arrow function with <code>array_reduce()</code></h3>
<p><code>array_reduce()</code> reduces an array to a single value based on a callback function. Arrow functions help make the code compact.</p>
<p>Example:</p>
<pre><code class="lang-php">$numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];

$sum = array_reduce($numbers, <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$carry, $n</span>) =&gt; $<span class="hljs-title">carry</span> + $<span class="hljs-title">n</span>, 0)</span>;

<span class="hljs-keyword">echo</span> $sum; <span class="hljs-comment">// Outputs: 15</span>
</code></pre>
<p>The arrow function adds each number in the array. <code>$carry</code> holds the running total and <code>$n</code> is the current number.</p>
<h3 id="heading-nest-arrow-functions-in-php">Nest arrow functions in PHP</h3>
<p>Here the inner function performs one operation and the outer function processes the results of the inner function.</p>
<pre><code class="lang-php">$numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>];

$doubleAndSquare = array_map(
    <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$n</span>) =&gt; <span class="hljs-title">fn</span>(<span class="hljs-params">$x</span>) =&gt; (<span class="hljs-params">$x * <span class="hljs-number">2</span></span>) ** 2,  
    $<span class="hljs-title">numbers</span>
)</span>;

$results = array_map(
    <span class="hljs-function"><span class="hljs-keyword">fn</span>(<span class="hljs-params">$fn</span>) =&gt; $<span class="hljs-title">fn</span>(<span class="hljs-params"><span class="hljs-number">3</span></span>),  
    $<span class="hljs-title">doubleAndSquare</span>
)</span>;

print_r($results);
<span class="hljs-comment">// Outputs: [36, 36, 36, 36, 36]</span>
</code></pre>
<p>In the above code, the first <code>array_map()</code> creates a list of arrow functions that double and then square the number. Each element in the <code>$numbers</code> array gets mapped to a nested arrow function.</p>
<p>The second <code>array_map()</code> applies the inner arrow function (which doubles and squares the value) to the number <code>3</code>. It results in an array of the same result.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this article, you’ve learned the basic features and syntax of arrow functions. It shows you their advantages over anonymous functions.</p>
<p>Here are some key takeaways:</p>
<ol>
<li><p>Arrow functions were introduced in PHP 7.4. They provide you with a new syntax to define anonymous functions with simpler code.</p>
</li>
<li><p>Arrow functions are a shorter way to write anonymous functions. They use one line of code and don’t need curly braces or the <code>return</code> keyword.</p>
</li>
<li><p>Arrow functions automatically get variables from scope. This allows you to use an arrow function as a callback in functions like <code>array_map()</code> or <code>array_filter()</code>.</p>
</li>
</ol>
<p>Resources:</p>
<ul>
<li><p><a target="_blank" href="https://www.php.net/manual/en/functions.arrow.php">PHP docs on arrow functions</a></p>
</li>
<li><p><a target="_blank" href="https://flatcoding.com/">Flatcoding blog</a> where I publish many other tutorials</p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write a Good Conference Talk Proposal – CFP Guide ]]>
                </title>
                <description>
                    <![CDATA[ When conferences organize events, they seek knowledgeable speakers to share insights that educate, inspire, and engage attendees. They discover and select speakers through a Call for Proposals (CFP), an open invitation for experts to submit talk idea... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-write-a-good-conference-talk-proposal/</link>
                <guid isPermaLink="false">68079cde283b1638560a2135</guid>
                
                    <category>
                        <![CDATA[ conference ]]>
                    </category>
                
                    <category>
                        <![CDATA[ speaking  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sule-Balogun Olanrewaju ]]>
                </dc:creator>
                <pubDate>Tue, 22 Apr 2025 13:42:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745329255973/f4fbb77f-8cab-4c29-bdd0-2791037bc6fd.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When conferences organize events, they seek knowledgeable speakers to share insights that educate, inspire, and engage attendees. They discover and select speakers through a Call for Proposals (CFP), an open invitation for experts to submit talk ideas. A well-crafted CFP submission can be the difference between being selected to speak or getting lost in a sea of applications.</p>
<p>Conferences offer different session formats, such as lightning talks, workshops, panels, and full-length sessions. Organizers look for clear, relevant, and valuable topics for their audience. A strong proposal aligns with the event's topic and clearly demonstrates its significance to reviewers.</p>
<p>I have been selected to speak at conferences such as API World, API Specification Conference, PyCon Italia, and PHP Day Italy, and I co-organize API Conf Lagos. From both sides of the table, when submitting and reviewing CFPs, I have seen what works and what does not.</p>
<p>In this guide, I’d like to share what makes a good CFP and offer tips on creating a standout proposal. Whether you are submitting for the first time or looking to refine your approach, these insights will help you craft a compelling proposal that gets noticed.</p>
<p>In this article, you’ll learn the following:</p>
<ul>
<li><p><a class="post-section-overview" href="#understanding-the-cfp-criteria">Understanding the CFP Criteria</a></p>
</li>
<li><p><a class="post-section-overview" href="#key-components-of-a-cfp-submission">Key Components of a CFP Submission</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-choose-the-right-topic-theme">How to Choose the Right Topic</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-craft-a-strong-title-and-abstract">How to Craft a Strong Title and Abstract</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-structure-the-proposal">How to Structure the Proposal</a></p>
</li>
<li><p><a class="post-section-overview" href="#submission-best-practices">Submission Best Practices</a></p>
</li>
<li><p><a class="post-section-overview" href="#where-to-find-cfp-opportunities">Where to Find CFP Opportunities</a></p>
</li>
</ul>
<h2 id="heading-understanding-the-cfp-criteria">Understanding the CFP Criteria</h2>
<p>CFP requirements vary from conference to conference, so understanding the specific criteria before submitting your application is crucial to increasing your chances of selection. Most conferences provide a criteria page outlining key details. When you’re writing a CFP submission, some criteria are more crucial than others in shaping a strong proposal.</p>
<p>The most relevant criteria include:</p>
<ul>
<li><p><strong>Topic</strong> – Areas of interest that the conference aims to cover.</p>
</li>
<li><p><strong>Session format and duration</strong> – This indicates the available sessions for the conference. It could be a session, workshop, or lightning talk, along with the time allocated.</p>
</li>
<li><p><strong>Audience expectations</strong> – This is used to gauge the audience's level of expertise (beginner, intermediate, advanced) and what attendees hope to gain from the event.</p>
</li>
</ul>
<p>Keeping an eye on the core criteria, topic, audience, and format will help ensure your CFP submission aligns well with the conference expectations. And this can help increase your chances of acceptance.</p>
<p>While necessary for planning, other logistical aspects play a less direct role in crafting the proposal. These include:</p>
<ul>
<li><p><strong>Speaker logistics and support</strong> – Information on travel, accommodation, and benefits for speakers, such as honorariums or reimbursements.</p>
</li>
<li><p><strong>Event fees and scholarships</strong> – Whether speakers receive free entry or if financial aid options are available.</p>
</li>
<li><p><strong>Code of conduct</strong> – The conference sets the ethical and behavioral guidelines for speakers and attendees.</p>
</li>
<li><p><strong>Conference duration</strong> – Whether the event lasts for one day, two days, or multiple days, which may affect scheduling and availability.</p>
</li>
</ul>
<h2 id="heading-elements-of-a-cfp">Elements of a CFP</h2>
<h3 id="heading-talk-title">Talk Title</h3>
<p>First, you’ll need to decide on a clear, compelling title that makes it obvious what the talk is about in an easy-to-understand way. Clarity and simplicity always win.</p>
<p>You should avoid overly verbose or clickbait-style titles like: <em>“Harnessing the Ultimate</em> <em>Power of Next-Gen APIs to Revolutionize Your Tech Stack”</em>. Instead, you could say something friendlier and clearer: <em>“How to Design Scalable APIs That Align With Your Product.”</em></p>
<h3 id="heading-abstract">Abstract</h3>
<p>The abstract is a brief description of your talk. In this section, you should provide a summary that generally explains what your talk is about, how the audience would benefit from it, and why the conference organizers should value and select your talk.</p>
<p>It’s acceptable to discuss example scenarios you plan to cover and the tools or libraries you’ll be using, as this will help promote your idea more effectively than a simple sentence or two with no technical info.</p>
<h3 id="heading-detailed-descriptionproposal">Detailed Description/Proposal</h3>
<p>I would like to note that not all conferences offer this section, but for those that do, it is a more in-depth and detailed explanation of your abstract, which sometimes can exceed 1000 words. This will enable you to explain the value, structure, areas of focus, and key takeaways of your talk.</p>
<p>In both the abstract and proposal, you should discuss the problems you’re addressing in your talk and what the audience stands to learn, which are both very important.</p>
<h3 id="heading-speaker-bio">Speaker Bio</h3>
<p>This is just as important as the talk title itself, as it informs the organizers about who you are, where you work, your relevant experience, and how the conference can benefit from having you at the event. Include a recent picture of yourself and, if possible, provide your social media profiles like LinkedIn, so they can connect with you.</p>
<p>Alright, now that you know the various parts involved in creating a CFP, let's look at each component in more detail – and how you can actually craft each part.</p>
<h2 id="heading-how-to-choose-the-right-topic">How to Choose the Right Topic</h2>
<p>Most CFP pages showcase topics that interest conference organizers. As a prospective speaker, your goal is to select a topic that aligns with these subjects. You’ll also want to make sure that you have a deep enough knowledge on the topic you choose to speak and answer questions about it confidently.</p>
<p>For example, if a conference emphasizes specific topics such as PHP, Continuous Delivery, DevOps, Security, Testing, or APIs, proposals that align with those subjects are more likely to be accepted. Submitting a topic outside the listed themes the conference plans to cover may reduce your chances unless it provides exceptional value to the audience.</p>
<p>Here are some practical examples:</p>
<ul>
<li><p>If a conference is focused on <strong>DevOps</strong>, your proposal is more likely to be accepted if it covers continuous delivery pipelines, performance and monitoring, infrastructure automation, or incident response practices. Submitting a topic outside the listed subject, such as frontend design, may reduce your chances unless it offers exceptional value to the audience.</p>
</li>
<li><p>If a conference is focused on <strong>APIs</strong>, your proposal is more likely to be accepted if it covers how to design versioned APIs, securing API endpoints with Authentication and Authorization, scaling API-first applications, compliance and governance, Api performance and observability, Api documentation, or managing third-party integrations.</p>
</li>
<li><p>For a PHP conference, you should submit a proposal that cover performance improvements in PHP 8+, real-world security use cases in Laravel applications such as OWASP, PHP architecture patterns, scaling large PHP applications, writing extensions in PHP, highlighting important libraries you use daily, or guiding attendees on how to contribute to such PHP libraries.</p>
</li>
</ul>
<p>When selecting your topics, ask yourself:</p>
<ul>
<li><p>What’s the value I’m bringing to attendees?</p>
</li>
<li><p>Is the topic something I’m passionate about and knowledgeable about?</p>
</li>
<li><p>Does it align with the needs and interests of the target audience?</p>
</li>
</ul>
<p>To improve your chances, tailor your proposal to fit the conference’s focus. Pay close attention to the wording of your topic and ensure it directly connects with the event’s goals.</p>
<h2 id="heading-how-to-craft-a-strong-title-and-abstract">How to Craft a Strong Title and Abstract</h2>
<p>Once you've chosen a relevant topic, you’ll need to create your talk title and abstract. For instance, you might focus on addressing security concerns using a particular programming language or tackle modern security challenges within a niche area.</p>
<p>It’s important to remember that while tools like AI models (for example, ChatGPT) can be helpful, relying too heavily on them to craft your title and abstract can work against you. The key is to use clear, simple language that speaks directly to your audience. Avoid overly technical jargon or convoluted phrasing, as this may hinder understanding.</p>
<p>Here are some key things to keep in mind when choosing a title and writing your abstract:</p>
<h3 id="heading-select-a-friendly-title"><strong>Select a Friendly Title</strong></h3>
<p>Your title is the first thing conference organizers see, and keeping it simple, engaging, and clear should be the goal.</p>
<p>Examples of strong titles might include:</p>
<ul>
<li><p>Moving Beyond CRUD: Designing More Scalable APIs with TDD</p>
</li>
<li><p>How to Keep Your Application Secure with the Zero Trust Principle</p>
</li>
<li><p>Why You Should Care About the Risk and Rewards of Feature Flags</p>
</li>
<li><p>How to Orchestrate Effective Releases with CI/CD with Practical Tips for Teams</p>
</li>
</ul>
<p>You may be wondering why these are examples of strong titles. Well, it’s because:</p>
<ul>
<li><p>They are clear and accessible, and at a glance, you already know what the topic is about. The topics are also approachable even if you’re not an expert.</p>
</li>
<li><p>The topics also highlight values or possible outcomes: either the audience will learn about risk and rewards with feature flags, or they will equip themselves with knowledge of securing their applications using the Zero Trust principle, or learn how to design scalable APIs in a test-driven manner.</p>
</li>
<li><p>The topic targets those directly involved in the software delivery lifecycle, including developers, DevOps engineers, engineering teams, and managers.</p>
</li>
</ul>
<h3 id="heading-writing-a-compelling-abstract"><strong>Writing a Compelling Abstract</strong></h3>
<p>When writing your abstract, it’s essential to provide a thorough overview of what your talk will cover. A one or two-sentence summary likely won’t be enough to give conference organizers the deeper insight they need into what your session offers.</p>
<p>Your abstract expands on the talk title, providing a more detailed description of the topic. This includes what your talk will cover (if it’s a workshop, mention the language or tools used, along with any expected outcomes or builds), the attendees who would benefit most from the talk, and possible learning outcomes.</p>
<p>Spending most of your time crafting your abstract is crucial to your talk getting accepted. From experience, here’s what a good abstract should include:</p>
<ul>
<li><p>Start with a sentence or two introducing the subject. So if you’re talking about the Zero-trust principle, explain what it means and discuss why it matters. Then talk about the problem it helps stakeholders involved in software delivery solve.</p>
</li>
<li><p>Describe what the talk will cover. Mention tools, frameworks, or case studies you’ll use here to deliver the talk if selected. For example, “We’ll cover core concepts like 'Never trust, always verify,' least privilege, and continuous monitoring, along with practical steps such as using OAuth2, MFA, RBAC, JWTs, and encryption”.</p>
</li>
<li><p>Explain who the target audience is. Are they beginners, intermediates, or experts? This will help organizers place your talk on the right track for the identified audience.</p>
</li>
<li><p>End your abstract with 2-3 clear learning outcomes. What will attendees be able to do, understand, or think differently about after your session? For example, attendees will learn about Zero Trust architecture, enforcing strong authentication and authorization, as well as tools for continuous monitoring and auditing to detect threats.</p>
</li>
</ul>
<p>Don’t rush through the process of writing your abstract. Allow yourself time to develop it gradually as ideas come to mind. It’s perfectly fine to keep your proposal open and pinned, updating and refining it over time. This approach will give you the bandwidth to ensure your abstract is clear, comprehensive, and engaging, ultimately leading to a stronger proposal.</p>
<p>Remember, your abstract should be written in simple, clear language and be free from grammatical errors. Keep in mind that some conferences have word limits for abstracts, so ensure your description fits these constraints.</p>
<h2 id="heading-how-to-structure-the-proposal">How to Structure the Proposal</h2>
<p>Once you’ve identified a topic and written the abstract, it’s crucial to structure your proposal in a way that is easy to read and provides clarity regarding your target audience and the learning outcomes. A well-structured proposal makes it easier for conference organizers to understand the value of your session and decide whether it’s a good fit.</p>
<p>To illustrate this, we’ll look at two proposal examples: one that can be improved and one with a strong structure that’s likely to be accepted.</p>
<h4 id="heading-weaker-proposal">❌ Weaker Proposal</h4>
<p><strong>Topic</strong>: Security in Software Development</p>
<p><strong>Abstract</strong>:<br>Security in software development is important. This session will cover security practices and techniques in code.</p>
<p><em>Why this proposal is weak</em>:</p>
<ul>
<li><p>The title is too vague and doesn’t specify the talk's focus.</p>
</li>
<li><p>The abstract lacks depth and does not clearly describe what the attendees will learn.</p>
</li>
<li><p>The audience is unclear, and no specific learning outcomes are mentioned.</p>
</li>
</ul>
<h4 id="heading-strong-proposal">✅ <strong>Strong Proposal</strong></h4>
<p><strong>Topic</strong>: Building Secure Web Applications with Modern [Programming Language 1] Frameworks</p>
<p><strong>Abstract</strong>:</p>
<p>It’s important to think security first when trying to build applications for the web, regardless of what programming language or framework you’re using. In today’s world, securing your application will protect you from data breaches, prevent fraudulent transactions, and help you avoid common vulnerabilities, ultimately improving the performance of your system.</p>
<p>In this talk, we will discuss the key security practices that developers should follow when building web applications with modern JavaScript frameworks, such as [Framework 1] and [Framework 2]. We’ll cover concepts such as input validation, securing APIs, handling authentication, and best practices to prevent common security vulnerabilities, including cross-site scripting (XSS) and SQL injection.</p>
<p>At the end of this session, developers will gain actionable insights on implementing security measures, explore common vulnerabilities, and build a demo app using [Framework 1] or [Framework 2] to address the security concept listed above, along with secure coding practices and tools to safeguard their apps.</p>
<p>This talk is designed for intermediate and advanced JavaScript developers who want to enhance the security of their web applications.</p>
<p><em>Why this proposal is strong</em>:</p>
<ul>
<li><p>The title is clear and specific, highlighting the session's main focus.</p>
</li>
<li><p>The abstract provides an introduction, a detailed description of the content that will be covered, ensuring organizers know exactly what to expect.</p>
</li>
<li><p>The target audience is defined as "intermediate and advanced JavaScript developers."</p>
</li>
<li><p>Learning outcomes are clearly outlined, including actionable takeaways and specific skills attendees will gain.</p>
</li>
</ul>
<p>Here are two samples of my proposals that have been accepted in the past.</p>
<ul>
<li><p>PHPDAY ITALY ‘25: <a target="_blank" href="https://www.phpday.it/talks_speakers/#Securing-PHP-Applications-with-Zero-Trust-Principles">Securing PHP Applications with Zero Trust Principles</a></p>
</li>
<li><p>API SPECIFICATION CONFERENCE ‘21: <a target="_blank" href="https://apispecs21.sched.com/event/lMMS/abc-of-graphql-alabi-deborah-sule-balogun-olanrewaju-g">ABC of GRAPHQL</a></p>
</li>
</ul>
<h2 id="heading-submission-best-practices">Submission Best Practices</h2>
<p>Once you've completed your proposal, it's essential to take a step back and reflect on your topic and abstract. Review your submission carefully for any areas that need refining, check for typos, and ensure the message is clear and well-structured.</p>
<p>Sometimes, sharing your proposal with colleagues or peers for feedback can be invaluable. They might catch things you overlooked or offer suggestions to improve clarity or focus.</p>
<p>This reflection and review process acts as a safety net, ensuring you haven’t missed anything important before submitting. Keep in mind that conference organizers receive hundreds of CFPs, so taking the extra time to polish your submission can significantly improve your chances of standing out in a competitive pool.</p>
<p>The submission process typically looks like this:</p>
<h3 id="heading-1-call-for-paper-cfp-announcement">1. Call for Paper (CFP) Announcement</h3>
<p>The conference announces its call for papers (CFP) information, including details such as the deadline, topics, venue, session types, and submission guidelines.</p>
<h3 id="heading-2-submission-platform">2. Submission Platform</h3>
<p>Conferences use tools like Typeform, Sessionize, Papercall, and even Google Docs, based on preference, and you’ll be asked to provide information about your talk proposal. This information includes:</p>
<ul>
<li><p>Talk title</p>
</li>
<li><p>Abstract</p>
</li>
<li><p>Talk format (Workshop, Session, Keynote)</p>
</li>
<li><p>Target audience</p>
</li>
<li><p>Speaker bio</p>
</li>
<li><p>[Optional] Past speaking experience, like YouTube links to previous talks, and so on</p>
</li>
</ul>
<h3 id="heading-review-phase">Review Phase</h3>
<p>After the CFP closes, panels begin reviewing submissions and deciding who will speak at the conference. They select speakers based on their own checklist and determine the lineup of speakers.</p>
<h3 id="heading-notification-and-follow-up">Notification and Follow-up</h3>
<p>Successful speakers will receive congratulatory emails notifying them to confirm their participation in the conference and may need to submit additional information, such as a slide deck or session outline.</p>
<p>Speakers who don’t make the cut will typically get a rejection email, and often some organizers extend free or discounted event tickets to those speakers who have invested their time in submitting a proposal.</p>
<h3 id="heading-conference-schedule">Conference schedule</h3>
<p>Once selected, speakers will have their bio, talk title, and abstract published on the conference website. The schedule will also include the date, time, and room where each session will take place, helping attendees plan which talks to attend.</p>
<h2 id="heading-where-to-find-cfp-opportunities">Where to Find CFP Opportunities</h2>
<p>If you're looking for conferences to submit your proposal to, several platforms and resources regularly list open calls for papers (CFPs). Instead of waiting to stumble upon a CFP announcement, you can actively search for speaking opportunities that align with your expertise.</p>
<h3 id="heading-popular-cfp-platforms">Popular CFP Platforms:</h3>
<ul>
<li><p><a target="_blank" href="https://sessionize.com/"><strong>Sessionize</strong></a> – A widely used platform where conferences post CFPs, allowing speakers to submit proposals easily.</p>
</li>
<li><p><a target="_blank" href="https://www.papercall.io/"><strong>PaperCall.io</strong></a> – A hub for discovering CFPs across different industries, including tech and open-source events.</p>
</li>
</ul>
<h3 id="heading-other-ways-to-discover-cfps">Other Ways to Discover CFPs:</h3>
<ul>
<li><p><strong>Conference websites</strong>: Many conferences post their CFPs directly under a "Call for Papers" or "Call for Speakers" section.</p>
</li>
<li><p><strong>Tech communities and newsletters:</strong> Platforms like Dev.to, Hashnode, and newsletters often share open CFPs.</p>
</li>
<li><p><strong>Social media</strong>: Following conference organizers and speakers on LinkedIn and Twitter can help you stay updated about new CFP openings.</p>
</li>
<li><p><strong>Local and virtual meetups</strong>: Many meetup groups are seeking speakers, and these smaller events can be a great way to gain experience before applying to larger conferences.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this article, you learned what makes a good conference talk proposal, how to structure your proposal with examples, and submission best practices.</p>
<p>Keep improving your proposal, and good luck with your submissions!</p>
<p>You can find me on <a target="_blank" href="https://www.linkedin.com/in/suleolanrewaju/">LinkedIn</a> and <a target="_blank" href="https://twitter.com/bigdevlarry">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Develop with CodeIgniter on Ubuntu – Step-by-Step Environment Setup ]]>
                </title>
                <description>
                    <![CDATA[ CodeIgniter is a popular open-source PHP framework you can use to build dynamic and robust web applications. It’s simple to use, fast, and flexible. This makes it a good option for any developer who wants to have a light yet powerful framework that w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-develop-with-codeigniter-on-ubuntu-environment-setup/</link>
                <guid isPermaLink="false">6793a7b71b1cdac77474f13a</guid>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webdev ]]>
                    </category>
                
                    <category>
                        <![CDATA[ code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ codeigniter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ valentine Gatwiri ]]>
                </dc:creator>
                <pubDate>Fri, 24 Jan 2025 14:46:15 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737640002689/7c78cd9c-40ef-45b3-82f6-97bc33f713d7.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>CodeIgniter is a popular open-source PHP framework you can use to build dynamic and robust web applications. It’s simple to use, fast, and flexible. This makes it a good option for any developer who wants to have a light yet powerful framework that will let them prototype or develop scalable applications fast.</p>
<p>Also, CodeIgnitor’s MVC (Model-View-Controller) architecture makes the process of organizing code and separating business logic from the user interface a piece of cake, yielding cleaner and maintainable projects.</p>
<p>Whether you’re building a small website or a complex application, CodeIgniter has a bunch of tools, libraries, and helpers that make the development process easier. They help you handle common tasks like database queries, session management, and form validation. Many devs love this tool because of its ease of use, making it an ideal framework for both beginners and experienced coders.</p>
<p>In this guide, I’ll walk you through the process of configuring CodeIgniter step by step, ensuring that you have a fully functional setup for your project on your local development environment.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before getting started, make sure you meet the following requirements:</p>
<ul>
<li><p>Basic Knowledge of PHP: Understanding PHP syntax and basic programming concepts will help you follow along more easily.</p>
</li>
<li><p>Web Server (for example, Apache or NGINX): CodeIgniter needs a server to run. Make sure you have a working server set up on your local machine or hosting environment.</p>
</li>
<li><p>PHP Installed: You’ll need PHP 7.3 or higher (depending on the version of CodeIgniter you’re using).</p>
</li>
<li><p>Database System: CodeIgniter supports several databases, but MySQL is the most commonly used. Make sure you have access to a database system and know its credentials.</p>
</li>
<li><p>CodeIgniter Download: Download the latest version of CodeIgniter from the official website, GitHub repository, or use <code>composer</code> to install it.</p>
</li>
</ul>
<h2 id="heading-how-to-use-composer-to-install-codeigniter">How to Use Composer to Install CodeIgniter</h2>
<p>Now that you understand the prerequisites and have everything set up, let’s move on to installing CodeIgniter. One of the easiest and most efficient ways to install CodeIgniter is by using Composer, a popular dependency management tool for PHP. In this section, I’ll guide you through the steps to install CodeIgniter using Composer.</p>
<p>First, create a new directory using <code>mkdir my_project</code> then navigate to the directory using <code>cd my_project</code>. Run the following Composer command to install CodeIgniter. You can specify the version you want (e.g., <code>^4.0</code> for the latest version of CodeIgniter 4).</p>
<pre><code class="lang-bash">composer create-project codeigniter4/appstarter .
</code></pre>
<p>This command will download and install the latest version of CodeIgniter 4 and set up the project for you:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737222358773/c0be04da-c507-41cf-b98e-8c9126146b31.png" alt="CodeIgnitor download via composer output." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>After the installation is complete, you should see the CodeIgniter project structure in your directory. To check if everything is working, you can start the built-in PHP server by running:</p>
<pre><code class="lang-bash">php spark serve
</code></pre>
<p>Output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737224950979/8e7ccdac-ce8b-4b71-b41b-5ee02dfd9970.png" alt="Php spark serve output." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Then, open your browser and go to <a target="_blank" href="http://localhost:8080"><code>http://localhost:8080</code></a>. You should see the CodeIgniter welcome page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737225118799/c7a38536-62fa-4788-814d-cd246a973691.png" alt="CodeIgnitor welcome page." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-install-codeigniter-manually">How to Install CodeIgniter Manually</h2>
<p>If you prefer not to use Composer, or if you’re working in an environment where Composer isn’t available, you can manually install CodeIgniter. This method involves downloading the framework files directly and setting up your project manually. While it requires a few more steps than using Composer, it’s still straightforward and gives you full control over the installation process.</p>
<p>In this section, I’ll walk you through the steps to manually install CodeIgniter and configure it for your project.</p>
<p><strong>Download via Git:</strong></p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /var/www/html
sudo git <span class="hljs-built_in">clone</span> https://github.com/bcit-ci/CodeIgniter.git codeigniter
</code></pre>
<p>Or <strong>download as ZIP (from CodeIgniter official website):</strong> <a target="_blank" href="https://www.codeigniter.com/download">Download here</a>. Extract it in <code>/var/www/html</code>. Whereby you can do so using the terminal or UI.</p>
<h3 id="heading-extracting-the-zip-file-via-the-ui">Extracting the ZIP File via the UI:</h3>
<p>If you’re not comfortable using command-line tools, you can easily extract the ZIP file using your computer’s graphical interface. Here's how:</p>
<p>Click on <code>files/Other Locations/computer</code> to access <code>/var/www/html</code>. Copy the <code>.Zip</code> file you downloaded earlier in the created folder and <code>right click</code>. Then click on <code>extract here</code> to unzip it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737210782723/25317e2b-151b-491e-8e83-89c32d9cf5ee.png" alt="ZIP Extraction image." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-extracting-the-zip-file-via-the-terminal">Extracting the ZIP File via the Terminal:</h3>
<p>If you’re comfortable using the command line, you can extract the CodeIgniter ZIP file directly via the terminal. This method is especially useful for Linux and macOS users or if you're working on a remote server without a graphical user interface.</p>
<p>First, ensure you have <code>unzip</code> installed on your Ubuntu system:</p>
<pre><code class="lang-bash">sudo apt update
sudo apt install unzip
</code></pre>
<p><strong>Check your permissions</strong> to ensure that you have the necessary access to the <code>/var/www/html</code> directory. If needed, use <code>sudo</code> for administrative privileges.</p>
<h3 id="heading-steps-to-extract-the-file">Steps to Extract the File</h3>
<p>Assuming your uploaded file is currently located in <code>downloads/data…</code>, move it to <code>/var/www/html</code>:</p>
<pre><code class="lang-bash">sudo mv /mnt/data/CodeIgniter.zip /var/www/html
</code></pre>
<p>Navigate to the <code>/var/www/html</code>directory:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /var/www/html
</code></pre>
<p>Extract the ZIP file by using the <code>unzip</code> command to extract the contents:</p>
<pre><code class="lang-bash">sudo unzip CodeIgniter.zip
</code></pre>
<p>After extracting, set the correct ownership and permissions for web server access:</p>
<pre><code class="lang-bash">sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html
</code></pre>
<blockquote>
<ul>
<li><p><code>www-data</code> (first part) → The <strong>user</strong>.</p>
</li>
<li><p><code>www-data</code> (second part) → The <strong>group</strong>.</p>
</li>
</ul>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737212632072/6240acc1-27bd-49fe-acd4-5b3f80a92163.png" alt="Extracted folder(Codeigniter-develop) image." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<blockquote>
<p>change <code>Codeigniter-develop /bcit-ci-CodeIgniter-bcb17eb/….</code>folder name to just codeigniter</p>
</blockquote>
<h3 id="heading-verify-extraction">Verify Extraction</h3>
<p>Visit your web server's URL (for example, <a target="_blank" href="http://localhost"><code>http://localhost</code></a>) to check if the contents are correctly deployed.</p>
<h3 id="heading-set-folder-permissions"><strong>Set Folder Permissions</strong></h3>
<p>After installing CodeIgniter, make sure you have the correct permissions for your directories, particularly <code>writable</code> and <code>cache</code> directories. This ensures that CodeIgniter can write logs, cache files, and session data.</p>
<p>Run the following commands to set the correct permissions:</p>
<pre><code class="lang-bash">sudo chmod -R 755 /var/www/html/codeigniter
</code></pre>
<h3 id="heading-configure-the-base-url"><strong>Configure the Base URL</strong></h3>
<p>The base URL for your project needs to be set up in <code>application/config/config.php</code>.</p>
<p>Open the <code>config.php</code> file:</p>
<pre><code class="lang-bash">sudo nano /var/www/html/codeigniter/application/config/config.php
</code></pre>
<p>Output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737213372442/259f712f-2df4-4517-a382-88966b021950.png" alt="Config.php terminal image." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Set the <code>base_url</code> as follows:</p>
<pre><code class="lang-php">$config[<span class="hljs-string">'base_url'</span>] = <span class="hljs-string">'http://your-domain-or-ip/'</span>;
</code></pre>
<p>Replace <a target="_blank" href="http://your-domain-or-ip/"><code>http://your-domain-or-ip/</code></a> with your actual domain or IP address where the project will be accessible.</p>
<p>After making changes:</p>
<ul>
<li><p><strong>Save the file:</strong> Press <code>Ctrl + O</code> (Write Out).</p>
</li>
<li><p><strong>Confirm the filename:</strong> Press <code>Enter</code>.</p>
</li>
<li><p><strong>Exit the editor:</strong> Press <code>Ctrl + X</code>.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">You can also edit the files using UI by accessing them from <code>Other Locations//var/www/html/codeigniter</code></div>
</div>

<h3 id="heading-configure-the-database-if-applicable"><strong>Configure the Database (if Applicable)</strong></h3>
<p>If your project uses a database, you'll need to set up the database configuration in <code>application/config/database.php</code>.</p>
<p>To do this, open the database configuration file:</p>
<pre><code class="lang-bash">sudo nano /var/www/html/codeigniter/application/config/database.php
</code></pre>
<p>Configure the database connection by setting the following options:</p>
<pre><code class="lang-php">$db[<span class="hljs-string">'default'</span>] = <span class="hljs-keyword">array</span>(
    <span class="hljs-string">'dsn'</span>   =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'hostname'</span> =&gt; <span class="hljs-string">'localhost'</span>,
    <span class="hljs-string">'username'</span> =&gt; <span class="hljs-string">'your-db-username'</span>,
    <span class="hljs-string">'password'</span> =&gt; <span class="hljs-string">'your-db-password'</span>,
    <span class="hljs-string">'database'</span> =&gt; <span class="hljs-string">'your-database-name'</span>,
    <span class="hljs-string">'dbdriver'</span> =&gt; <span class="hljs-string">'mysqli'</span>,
    <span class="hljs-string">'dbprefix'</span> =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'pconnect'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'db_debug'</span> =&gt; (ENVIRONMENT !== <span class="hljs-string">'production'</span>),
    <span class="hljs-string">'cache_on'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'cachedir'</span> =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'char_set'</span> =&gt; <span class="hljs-string">'utf8'</span>,
    <span class="hljs-string">'dbcollat'</span> =&gt; <span class="hljs-string">'utf8_general_ci'</span>,
    <span class="hljs-string">'swap_pre'</span> =&gt; <span class="hljs-string">''</span>,
    <span class="hljs-string">'encrypt'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'compress'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'stricton'</span> =&gt; <span class="hljs-literal">FALSE</span>,
    <span class="hljs-string">'failover'</span> =&gt; <span class="hljs-keyword">array</span>(),
    <span class="hljs-string">'save_queries'</span> =&gt; <span class="hljs-literal">TRUE</span>
);
</code></pre>
<p>Replace <code>your-db-username</code>, <code>your-db-password</code>, and <code>your-database-name</code> with your actual database credentials.</p>
<h3 id="heading-set-the-environment"><strong>Set the Environment</strong></h3>
<p>CodeIgniter uses the environment setting to load different configuration files depending on the environment (for example, development, production).</p>
<p>To set the environment, open the <code>index.php</code> file in the root directory of your project:</p>
<pre><code class="lang-bash">sudo nano /var/www/html/codeigniter/index.php
</code></pre>
<p>Locate the following line:</p>
<pre><code class="lang-php">define(<span class="hljs-string">'ENVIRONMENT'</span>, <span class="hljs-string">'development'</span>);
</code></pre>
<p>You can set it to <code>production</code>, <code>testing</code>, or <code>development</code> depending on your setup. For development, it should be set to <code>development</code></p>
<h3 id="heading-autoload-libraries-helpers-or-config-files"><strong>Autoload Libraries, Helpers, or Config Files</strong></h3>
<p>You can specify which libraries, helpers, or config files to autoload in <code>application/config/autoload.php</code>. Open the autoload configuration file:</p>
<pre><code class="lang-bash">sudo nano /var/www/html/codeigniter/application/config/autoload.php
</code></pre>
<p>Modify the autoload array to load commonly used libraries and helpers:</p>
<pre><code class="lang-php">$autoload[<span class="hljs-string">'libraries'</span>] = <span class="hljs-keyword">array</span>(<span class="hljs-string">'database'</span>, <span class="hljs-string">'session'</span>, <span class="hljs-string">'form_validation'</span>);
$autoload[<span class="hljs-string">'helper'</span>] = <span class="hljs-keyword">array</span>(<span class="hljs-string">'url'</span>, <span class="hljs-string">'file'</span>);
</code></pre>
<h3 id="heading-enable-mod-rewrite-for-clean-urls"><strong>Enable Mod Rewrite (For Clean URLs)</strong></h3>
<p>If you want clean URLs, you need to enable <code>mod_rewrite</code> on Apache. Edit the Apache configuration file as follows:</p>
<pre><code class="lang-bash">sudo nano /etc/apache2/sites-available/000-default.conf
</code></pre>
<p>Ensure that the <code>AllowOverride</code> directive is set to <code>All</code> in the <code>&lt;Directory&gt;</code> section:</p>
<pre><code class="lang-bash">&lt;Directory /var/www/html&gt;
    AllowOverride All
&lt;/Directory&gt;
</code></pre>
<p>Enable mod_rewrite and restart Apache:</p>
<pre><code class="lang-bash">sudo a2enmod rewrite
sudo systemctl restart apache2
</code></pre>
<h3 id="heading-verify-codeigniter-directory-placement">Verify CodeIgniter Directory Placement</h3>
<p>If CodeIgniter is not in <code>/opt/lampp/htdocs</code>, move it there:</p>
<pre><code class="lang-bash">sudo mv /var/www/html/codeigniter /opt/lampp/htdocs/
</code></pre>
<h3 id="heading-test-codeigniter"><strong>Test CodeIgniter</strong></h3>
<p>Open your web browser and navigate to the base URL (<a target="_blank" href="http://your-domain-or-ip"><code>http://your-domain-or-ip</code></a>). You should see the default CodeIgniter welcome page if everything is set up correctly:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737218343140/7a41485a-152e-496e-9ba7-811e5c4b774b.png" alt="CodeIgniter welcome page." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Run <code>curl</code> <a target="_blank" href="http://ifconfig.me"><code>ifconfig.me</code></a> to find your public IP. If you're hosting CodeIgniter on a local machine (for example, in your home network), use the following command to check your local IP: <code>hostname -I</code>.</p>
<h2 id="heading-troubleshooting">Troubleshooting</h2>
<p>If you encounter any issues while setting up CodeIgniter, here are some common problems and how to resolve them:</p>
<h3 id="heading-set-codeigniter-as-the-default-app"><strong>Set CodeIgniter as the Default App</strong></h3>
<p>If you want CodeIgniter to load as the default app (instead of the XAMPP landing page if you have XAMPP installed), remove or rename the default <code>index.php</code> in the <code>htdocs</code> directory:</p>
<pre><code class="lang-bash">sudo mv /opt/lampp/htdocs/index.php /opt/lampp/htdocs/index.php.bak
</code></pre>
<p>Move the CodeIgniter files to the root of the <code>htdocs</code> folder:</p>
<pre><code class="lang-bash">sudo mv /opt/lampp/htdocs/codeigniter/* /opt/lampp/htdocs/
</code></pre>
<h3 id="heading-restart-apache"><strong>Restart Apache</strong></h3>
<p>After making changes, restart Apache to apply the configuration:</p>
<pre><code class="lang-bash">sudo /opt/lampp/lampp restart
</code></pre>
<h3 id="heading-creating-a-controller"><strong>Creating a Controller</strong></h3>
<p>To start developing your application, you can create a controller to handle requests.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737219751160/af7240e8-2793-45b9-9cff-1f9a74add34f.png" alt="Application folders." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Create a new controller in <code>application/controllers/</code> like this:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Welcome</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">CI_Controller</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">$this</span>-&gt;load-&gt;view(<span class="hljs-string">'welcome_message'</span>);
    }
}
</code></pre>
<p>Then create Views and Models. Views go into <code>application/views/</code> and models into <code>application/models/</code>. You can start adding your views and models accordingly.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Setting up a development environment for CodeIgniter on Ubuntu is an essential step to unlock the full potential of this lightweight yet powerful PHP framework.</p>
<p>By carefully following the outlined steps—from installing prerequisites, configuring file permissions, and customizing settings to creating controllers, views, and models—you are now equipped to start building dynamic web applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ PHP Arrays in Practice: How to Rebuild the Football Team Cards Project with PHP and MongoDB ]]>
                </title>
                <description>
                    <![CDATA[ This is the second part of my PHP array handbook. You can find the first part here, where I cover array basics. In the first part, you learned about arrays, how to create arrays, array functions, and how to loop through arrays. This second part will ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/php-arrays-how-to-rebuild-the-football-team-cards-with-php-and-mongodb/</link>
                <guid isPermaLink="false">66adf1bf007ea266ef6d923b</guid>
                
                    <category>
                        <![CDATA[ arrays ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kolade Chris ]]>
                </dc:creator>
                <pubDate>Tue, 18 Jun 2024 20:58:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/PHP-Arrays-in-Practice-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This is the second part of my PHP array handbook. You can <a target="_blank" href="https://www.freecodecamp.org/news/php-array-handbook/">find the first part here</a>, where I cover array basics.</p>
<p>In the first part, you learned about arrays, how to create arrays, array functions, and how to loop through arrays.</p>
<p>This second part will teach you how to use PHP and MongoDB to rebuild the football team cards project of freeCodeCamp's updated JavaScript curriculum.</p>
<p>The football team data will live in a MongDB Atlas database. We will fetch it as an array, and display it based on the players selected (goalkeepers, defenders, midfielders, and forwards).</p>
<p>This will help you build on top of what you learned about looping through arrays. After all, on many occassions, you'll be looping through what you get from a database or an API, not necessarily some hard-coded arrays.</p>
<p>In order not to shock you by jumping straight into databases from arrays, we'll start with what data and databases are, and then go on to learn about:</p>
<ul>
<li><p>Relational vs non-relational databases</p>
</li>
<li><p>How to use MongoDB Atlas</p>
</li>
<li><p>How to Install MongoDB for PHP on a Mac</p>
</li>
<li><p>How to set up MongoDB Atlas</p>
</li>
<li><p>How to build a CRUD app with PHP and MongoDB Atlas</p>
</li>
<li><p>And finally, how to rebuild the football team cards project with PHP and MongoDB Atlas</p>
</li>
</ul>
<h2 id="heading-pre-requisites">Pre-requisites</h2>
<p>To get the best put of this guide, I suggest you have a basic knowledge of the following:</p>
<ul>
<li><p>PHP fundamentals (variables, arrays, functions, loops)</p>
</li>
<li><p>HTML and CSS</p>
</li>
<li><p>JavaScript events</p>
</li>
<li><p>Command line</p>
</li>
<li><p>Composer</p>
</li>
<li><p>How to set up a PHP development environment with VS Code</p>
</li>
<li><p>Databases</p>
</li>
<li><p>MongoDB Atlas</p>
</li>
<li><p>Git and GitHub</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-are-data-and-databases">What are Data and Databases?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-relational-vs-non-relational-databases">Relational vs Non-relational Databases</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-mongodb-atlas-an-example-of-a-non-relational-database">MongoDB Atlas – An Example of a Non-relational Database</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-mongodb-for-php">How to Install MongoDB for PHP</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-install-the-mongodb-extension-with-pecl-php-extension-community-library">Step 1: Install the MongoDB Extension with PECL (PHP Extension Community Library)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-modify-the-phpini-file-to-include-the-mongodb-extension">Step 2: Modify the <code>php.ini</code> File to Include the MongoDB Extension</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-verify-the-installation-of-the-mongodb-extension">Step 3: Verify the Installation of the MongoDB Extension</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-set-up-a-mongodb-atlas-cluster">Step 4: Set Up a MongoDB Atlas Cluster</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-install-the-mongodb-php-library">Step 5: Install the MongoDB PHP Library</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-crud-operations-using-php-and-mongodb">CRUD Operations Using PHP and MongoDB</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-install-mongodb-library-and-dotenv-package">Step 1: Install MongoDB Library and Dotenv Package</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-create-a-env-file-for-your-mongodb-atlas-uri-credential">Step 2: Create a <code>.env</code> File for your MongoDB Atlas URI Credential</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-create-a-database-connection-file">Step 3: Create a Database Connection File</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-the-read-part-of-the-crud">Step 4: The <code>READ</code> Part of the CRUD</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-the-create-part-of-the-crud">Step 5: The <code>CREATE</code> Part of the CRUD</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-the-update-part-of-the-crud">Step 6: The <code>UPDATE</code> Part of the CRUD</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-7-the-delete-part-of-the-crud">Step 7: The <code>DELETE</code> Part of the CRUD</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-project-how-to-use-php-to-rebuild-the-football-team-cards-project-of-the-updated-javascript-curriculum">Project: How to Use PHP to Rebuild the Football Team Cards Project of the Updated JavaScript Curriculum</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-set-up-mongodb-atlas">Step 1: Set up MongoDB Atlas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-install-the-project-dependencies-with-composer">Step 2: Install the Project Dependencies with Composer</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-create-project-files">Step 3: Create Project Files</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-wrap-the-select-tag-in-a-form-element">Step 4: Wrap the <code>select</code> tag in a <code>form</code> Element</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-create-the-logic-for-fetching-the-footballers-from-the-footballers-collection">Step 5: Create the Logic for Fetching the Footballers from the <code>footballers</code> Collection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-create-the-logic-for-filtering-the-footballers-based-on-position">Step 6: Create the Logic for Filtering the Footballers Based on Position</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-7-display-the-players-on-the-page-based-on-the-selected-position">Step 7: Display the Players on the Page Based on the Selected Position</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-what-are-data-and-databases">What are Data and Databases?</h2>
<p>Data is central to pretty much everything in the modern world. The people you see on social media and other websites, the content they post, the comments they add to posts, and many other online activities all produce a lot of data. Even patient files in a hospital or a company's payroll hosted on a local server are data. Data does not have to be on the Internet.</p>
<p>To effectively manage and utilize data for growth, you need a <strong>database</strong>. A <strong>Database</strong> is a structured collection of data that helps you efficiently store, retrieve, and manipulate that data.</p>
<p>Databases come in two primary types – relational and non-relational databases. We'll discuss the differences between them next.</p>
<p>Both relational and non-relational databases are managed with what is called database management systems (DBMS). A DBMS is an interface between the user and the database that allows you to create, read, update, and delete data in the database.</p>
<h2 id="heading-relational-vs-non-relational-databases">Relational vs Non-relational Databases</h2>
<h3 id="heading-what-are-relational-databases">What are Relational Databases?</h3>
<p><strong>Relational databases</strong> organize data into tables consisting of rows and columns. Each table represents a specific entity, such as customers or products. The columns define the attributes of these entities, like the customer name or product name.</p>
<p>The relational model uses structured query language (SQL) for querying and managing data. Relationships between tables are established through primary and foreign keys to ensure data integrity and reduce redundancy.</p>
<p>Relational databases are known for their robustness, consistency, and support for complex queries. They are well-suited for applications that require multi-row transactions, such as financial systems, enterprise resource planning (ERP) software, and customer relationship management (CRM) systems.</p>
<p>Examples of relational databases are MySQL, PostgreSQL, and Microsoft SQL Server.</p>
<h3 id="heading-what-are-non-relational-databases">What are Non-Relational Databases?</h3>
<p><strong>Non-relational</strong> databases store and manage data in flexible, schema-less formats like key-value pairs, documents, wide-columns, or graphs. They are also known as NoSQL databases because they don't use SQL like relational databases.</p>
<p>Non-relational databases are designed to scale horizontally, making them ideal for large-scale data processing and real-time web applications.</p>
<p>Non-relational databases are easy to use, scalable, and high-performing at the same time. Due to that, they often sacrifice some degree of consistency in favor of availability and partition tolerance.</p>
<p>Common use cases include real-time analytics, real-time web apps, and applications requiring high-speed data ingestion.</p>
<h3 id="heading-mongodb-atlas-an-example-of-a-non-relational-database">MongoDB Atlas – An Example of a Non-relational Database</h3>
<p>MongoDB Atlas is a non-relational database that stores data in a document-oriented JSON-like format called BSON (Binary JSON). BSON extends the JSON model to provide additional data types and to be efficient for encoding and decoding within various programming languages.</p>
<p>MongoDB Atlas offers the flexibility and scalability of MongoDB, with the benefits of automated deployment, backups, and monitoring. It allows developers to focus on building applications without bothering about database management</p>
<p>MongoDB Atlas also supports advanced features such as data partitioning, replication, and global distribution. This makes it a powerful choice for modern applications requiring flexibility and performance.</p>
<h2 id="heading-how-to-install-mongodb-for-php">How to Install MongoDB for PHP</h2>
<p>Before you can install MongoDB for PHP, make sure you have PHP itself installed correctly.</p>
<p>On a Mac, you can install PHP with homebrew by running <code>brew install PHP</code>. In addition to that, make sure you have Apache installed by running <code>brew install httpd</code> and starting it by running <code>brew services start httpd</code>.</p>
<p>You can follow the steps below to install MongoDB for PHP on a Mac.</p>
<h3 id="heading-step-1-install-the-mongodb-extension-with-pecl-php-extension-community-library">Step 1: Install the MongoDB Extension with PECL (PHP Extension Community Library)</h3>
<p>Install the MongoDB extension for PHP by running <code>pecl install mongodb</code>.</p>
<h3 id="heading-step-2-modify-the-phpini-file-to-include-the-mongodb-extension">Step 2: Modify the <code>php.ini</code> File to Include the MongoDB Extension</h3>
<p>Installing the MongoDB extension should automatically add the necessary configurations to the <code>php.ini</code> file. But of it doesnt do that, locate the <code>php.ini</code> file by running the command below:</p>
<pre><code class="lang-bash">$ php --ini
Configuration File (php.ini) Path: /usr/<span class="hljs-built_in">local</span>/etc/php/8.3
</code></pre>
<p>After that, paste the following at the end of the <code>php.ini</code> file and save it:</p>
<pre><code class="lang-bash">extension=mongodb.so
</code></pre>
<p>After doing that, restart Apache by running <code>brew services restart httpd</code>.</p>
<h3 id="heading-step-3-verify-the-installation-of-the-mongodb-extension">Step 3: Verify the Installation of the MongoDB Extension</h3>
<p>Run the command below to see whether the PHP extension has been successflly installed:</p>
<pre><code class="lang-bash">php -i | grep mongo
</code></pre>
<p>You should see something like this in the terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-09.21.50.png" alt="Screenshot-2024-05-24-at-09.21.50" width="600" height="400" loading="lazy"></p>
<p>Check out <a target="_blank" href="https://www.mongodb.com/docs/languages/php/">the MongoDB PHP docs</a> for more information on how to use MongoDB with PHP and frameworks like Laravel and Symfony.</p>
<h3 id="heading-step-4-set-up-a-mongodb-atlas-cluster">Step 4: Set Up a MongoDB Atlas Cluster</h3>
<p>To test out the PHP extension you just installed, you need a MongoDB database. Atlas makes this easy for you because the heavy lifting is handled on the cloud.</p>
<h4 id="heading-1-login-to-your-mongodb-account">1. Login to your MongoDB Account</h4>
<p>Head over to https://cloud.mongodb.com/ and log in to your account. If you don't have an account, <strong>you can create one for free</strong>.</p>
<h4 id="heading-2-create-a-project">2. Create a Project</h4>
<p>If you have existing projects, create a new project by clicking on the arrow right beside the currently opened project and selecting "New Project".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-09.34.05.png" alt="Screenshot-2024-05-24-at-09.34.05" width="600" height="400" loading="lazy"></p>
<p>Give your project a name and click the "Next" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-09.37.13.png" alt="Screenshot-2024-05-24-at-09.37.13" width="600" height="400" loading="lazy"></p>
<p>Click "Create Project" to finally create the project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-09.38.29.png" alt="Screenshot-2024-05-24-at-09.38.29" width="600" height="400" loading="lazy"></p>
<h4 id="heading-3-create-a-cluster">3. Create a Cluster</h4>
<p>After creating a project, you should be prompted to create a cluster. If you're not, make sure you're in the Overview tab. From there, click the big "Create" button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/create-giant-1.png" alt="create-giant-1" width="600" height="400" loading="lazy"></p>
<p>Select the "MO" free tier, give your cluster a name, and click the "Create Deployment" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-09.44.11.png" alt="Screenshot-2024-05-24-at-09.44.11" width="600" height="400" loading="lazy"></p>
<p>I have given the cluster the name <code>movie-list</code>.</p>
<p>Just keep in mind that as your database grows, you might need to upgrade to one of the paid tiers.</p>
<h4 id="heading-4-create-a-database-user">4. Create a Database User</h4>
<p>Immediately after you create your cluster, you'll be prompted to create a database user. Fill in your database user username and password and click the "Create Database User" button. Then click "Choose a connection method".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-09.50.54.png" alt="Screenshot-2024-05-24-at-09.50.54" width="600" height="400" loading="lazy"></p>
<p>Make sure you enter a password you can remember or save it in a password manager.</p>
<h4 id="heading-5-choose-a-connection-method">5. Choose a Connection Method</h4>
<p>You'll see several methods you can use to connect to the cluster once you click the "Choose a connection method" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-09.56.37.png" alt="Screenshot-2024-05-24-at-09.56.37" width="600" height="400" loading="lazy"></p>
<p>Select Drivers from the list.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-09.58.02.png" alt="Screenshot-2024-05-24-at-09.58.02" width="600" height="400" loading="lazy"></p>
<p>Choose PHP from the list and select PHP Lib 1.9 + MongoDB 1.10 or later as the version to use. Then copy the connection string and click the "Done" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-10.02.55.png" alt="Screenshot-2024-05-24-at-10.02.55" width="600" height="400" loading="lazy"></p>
<h4 id="heading-6-choose-network-access">6. Choose Network Access</h4>
<p>Head over to the "Network Access" tab and select "Add IP ADDRESS", click "ALLOW ACCESS FROM ANYWHERE", and then click the "Confirm" button. You can change this later depending on where your app is deployed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-10.05.03.png" alt="Screenshot-2024-05-24-at-10.05.03" width="600" height="400" loading="lazy"></p>
<p>Go back to the "Database" tab and click the "Browse Collections" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-10.07.48.png" alt="Screenshot-2024-05-24-at-10.07.48" width="600" height="400" loading="lazy"></p>
<p>Select "Load a Sample Dataset" so you don't have to add your own data – at least for now.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-10.24.54.png" alt="Screenshot-2024-05-24-at-10.24.54" width="600" height="400" loading="lazy"></p>
<p>Now you should see the following databases:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-10.28.04.png" alt="Screenshot-2024-05-24-at-10.28.04" width="600" height="400" loading="lazy"></p>
<p>To test that your MongoDB extension for PHP is running, you can query any of the data in those databases. But first, you need to install the MongoDB PHP library with <code>composer</code>. <code>composer</code> lets you manage dependencies for your PHP project.</p>
<h3 id="heading-step-5-install-the-mongodb-php-library">Step 5: Install the MongoDB PHP Library</h3>
<p>If you don't have <code>composer</code> installed, install it with homebrew by running <code>brew install composer</code>.</p>
<p>After that, create a folder and open it with your Text Editor. If your Text Editor has an integrated terminal, open it and run the command below:</p>
<pre><code class="lang-bash">composer require mongodb/mongodb
</code></pre>
<p>If the installation is successful, you'll see a <code>vendor</code> folder, along with <code>composer.json</code> and <code>composer.lock</code> files in the root of your project. You'll also see the following in the terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-10.36.29.png" alt="Screenshot-2024-05-24-at-10.36.29" width="600" height="400" loading="lazy"></p>
<p>Now you need to query any data in your atlas database and display them.</p>
<p>Create an <code>index.php</code> file and paste the following inside it:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/vendor/autoload.php'</span>;

<span class="hljs-comment">// Your connection string</span>
$client = <span class="hljs-keyword">new</span> MongoDB\Client(
 <span class="hljs-string">'mongodb+srv://username:&lt;password&gt;@movie-list.s6r7qkr.mongodb.net/?retryWrites=true&amp;w=majority&amp;appName=movie-list'</span>
);

$movies = $client-&gt;selectCollection(<span class="hljs-string">'sample_mflix'</span>, <span class="hljs-string">'movies'</span>);
$document = $movies-&gt;findOne([<span class="hljs-string">'title'</span> =&gt; <span class="hljs-string">'Wild and Woolly'</span>]);

<span class="hljs-keyword">echo</span> <span class="hljs-string">'&lt;pre&gt;'</span>;
print_r($document);
</code></pre>
<p>The code above lets you connect to the <code>movies</code> database in the <code>sample_mflix</code> collection with the <code>selectCollection()</code> function and query a movie titled "Wild and Bolly" in it.</p>
<p><strong>Note</strong>: Make sure you replace the existing connection string with your own. You copied this in item 5 of step 4. Also, make sure you replace <code>&lt;password&gt;</code> with your database user password.</p>
<p>After that, run your PHP app (with <code>php -S localhost:8000</code> on Mac in the terminal). If you have everything set up correctly, you should see the following in the browser:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-05-24-at-10.54.05.png" alt="Screenshot-2024-05-24-at-10.54.05" width="600" height="400" loading="lazy"></p>
<p><strong>Note</strong>: I have the data formatted nicely because I installed the PHP View Chrome extension. It prints everything you have inside the <code>print_r()</code> function like that.</p>
<h2 id="heading-crud-operations-using-php-and-mongodb">CRUD Operations Using PHP and MongoDB</h2>
<p>With MongoDB Atlas for database management and UI persistence, and PHP for server-side logic, you can build an application that implements full CRUD operations – create, read, update, and delete.</p>
<p>The particular CRUD app we are building is a movie list. So make sure you set up an Atlas database for it, as we already covered in this guide.</p>
<p>Now let's look at how you can build a movie list CRUD app.</p>
<h3 id="heading-step-1-install-mongodb-library-and-dotenv-package">Step 1: Install MongoDB Library and Dotenv Package</h3>
<p>Make sure you have a MongoDB extension and a Dotenv package to help manage your <code>.env</code> variables by running the following commands:</p>
<pre><code class="lang-bash">composer require mongodb/mongodb
composer require vlucas/phpdotenv
</code></pre>
<h3 id="heading-step-2-create-a-env-file-for-your-mongodb-atlas-uri-credential">Step 2: Create a <code>.env</code> File for your MongoDB Atlas URI Credential</h3>
<p>Create a <code>.env</code> file and add the following in it:</p>
<pre><code class="lang-md">MDB<span class="hljs-emphasis">_URI="Your MongoDB Atlas connection string"</span>
</code></pre>
<h3 id="heading-step-3-create-a-database-connection-file">Step 3: Create a Database Connection File</h3>
<p>Create a <code>mongo_atlas_setup.php</code> file for the database connection in the root and paste the following in it:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/vendor/autoload.php'</span>;

$dotenv = Dotenv\Dotenv::createImmutable(<span class="hljs-keyword">__DIR__</span>);
$dotenv-&gt;load();

$client = <span class="hljs-keyword">new</span> MongoDB\Client($_ENV[<span class="hljs-string">'MDB_URI'</span>]);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMongoClient</span>(<span class="hljs-params"></span>)
</span>{
 <span class="hljs-keyword">global</span> $client;
 <span class="hljs-keyword">return</span> $client;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMongoCollection</span>(<span class="hljs-params">$database, $collection</span>)
</span>{
 $client = getMongoClient();
 <span class="hljs-keyword">return</span> $client-&gt;selectCollection($database, $collection);
}
</code></pre>
<p>With the code above, we are:</p>
<ul>
<li><p>loading the dependencies required for the project</p>
</li>
<li><p>loading the environment variable</p>
</li>
<li><p>using a function to get the database and the collection we want within it</p>
</li>
</ul>
<p>Importing the file and calling the <code>getMongoCollection</code> in it with the database and the collection in it will let you connect to the database and the collection.</p>
<h3 id="heading-step-4-the-read-part-of-the-crud">Step 4: The <code>READ</code> Part of the CRUD</h3>
<p>In the root again, create an <code>index.php</code> file that will take care of the READ part of the CRUD. Paste the following in the file:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/vendor/autoload.php'</span>;
<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/mongo_atlas_setup.php'</span>;

$movies_list = getMongoCollection(<span class="hljs-string">'movie_list'</span>, <span class="hljs-string">'movies'</span>);
$movies = $movies_list-&gt;find([], [<span class="hljs-string">'sort'</span> =&gt; [<span class="hljs-string">'_id'</span> =&gt; <span class="hljs-number">-1</span>]]);
<span class="hljs-meta">?&gt;</span>

&lt;!DOCTYPE html&gt;
&lt;html lang=<span class="hljs-string">"en"</span>&gt;

&lt;head&gt;
 &lt;meta charset=<span class="hljs-string">"UTF-8"</span>&gt;
 &lt;meta name=<span class="hljs-string">"viewport"</span> content=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;
 &lt;title&gt;Movie <span class="hljs-keyword">List</span> CRUD App&lt;/title&gt;
 &lt;script src=<span class="hljs-string">"https://cdn.tailwindcss.com"</span>&gt;&lt;/script&gt;
&lt;/head&gt;

&lt;body <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">bg</span>-<span class="hljs-title">gray</span>-100 <span class="hljs-title">p</span>-10"&gt;

 &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">max</span>-<span class="hljs-title">w</span>-4<span class="hljs-title">xl</span> <span class="hljs-title">mx</span>-<span class="hljs-title">auto</span> <span class="hljs-title">bg</span>-<span class="hljs-title">white</span> <span class="hljs-title">p</span>-6 <span class="hljs-title">rounded</span> <span class="hljs-title">shadow</span>"&gt;
   &lt;<span class="hljs-title">h1</span> <span class="hljs-title">class</span>="<span class="hljs-title">text</span>-3<span class="hljs-title">xl</span> <span class="hljs-title">font</span>-<span class="hljs-title">bold</span> <span class="hljs-title">mb</span>-4 <span class="hljs-title">text</span>-<span class="hljs-title">center</span>"&gt;<span class="hljs-title">Movie</span> <span class="hljs-title">List</span> <span class="hljs-title">CRUD</span> <span class="hljs-title">App</span>&lt;/<span class="hljs-title">h1</span>&gt;

   &lt;?<span class="hljs-title">php</span> <span class="hljs-title">include</span> '<span class="hljs-title">create</span>.<span class="hljs-title">php</span>' ?&gt;

   &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">space</span>-<span class="hljs-title">y</span>-4"&gt;
     &lt;?<span class="hljs-title">php</span> <span class="hljs-title">foreach</span> ($<span class="hljs-title">movies</span> <span class="hljs-title">as</span> $<span class="hljs-title">movie</span>) : ?&gt;
       &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">p</span>-4 <span class="hljs-title">border</span> <span class="hljs-title">rounded</span> <span class="hljs-title">shadow</span>-<span class="hljs-title">sm</span> <span class="hljs-title">bg</span>-<span class="hljs-title">gray</span>-50"&gt;
         &lt;<span class="hljs-title">h2</span> <span class="hljs-title">class</span>="<span class="hljs-title">text</span>-2<span class="hljs-title">xl</span> <span class="hljs-title">font</span>-<span class="hljs-title">semibold</span>"&gt;&lt;?= $<span class="hljs-title">movie</span>['<span class="hljs-title">movie_title</span>'] ?&gt;&lt;/<span class="hljs-title">h2</span>&gt;
         &lt;<span class="hljs-title">p</span> <span class="hljs-title">class</span>="<span class="hljs-title">text</span>-<span class="hljs-title">gray</span>-700"&gt;<span class="hljs-title">Year</span>: &lt;?= $<span class="hljs-title">movie</span>['<span class="hljs-title">movie_year</span>'] ?&gt;&lt;/<span class="hljs-title">p</span>&gt;
         &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">mt</span>-2"&gt;
           &lt;<span class="hljs-title">a</span> <span class="hljs-title">href</span>="<span class="hljs-title">update</span>.<span class="hljs-title">php</span>?<span class="hljs-title">id</span>=&lt;?= $<span class="hljs-title">movie</span>['<span class="hljs-title">_id</span>'] ?&gt;" <span class="hljs-title">class</span>="<span class="hljs-title">bg</span>-<span class="hljs-title">yellow</span>-500 <span class="hljs-title">text</span>-<span class="hljs-title">white</span> <span class="hljs-title">py</span>-1 <span class="hljs-title">px</span>-3 <span class="hljs-title">rounded</span>"&gt;<span class="hljs-title">Update</span>&lt;/<span class="hljs-title">a</span>&gt;
           &lt;<span class="hljs-title">a</span> <span class="hljs-title">href</span>="<span class="hljs-title">delete</span>.<span class="hljs-title">php</span>?<span class="hljs-title">id</span>=&lt;?= $<span class="hljs-title">movie</span>['<span class="hljs-title">_id</span>'] ?&gt;" <span class="hljs-title">onclick</span>="<span class="hljs-title">return</span> <span class="hljs-title">confirm</span>('<span class="hljs-title">Are</span> <span class="hljs-title">you</span> <span class="hljs-title">sure</span> <span class="hljs-title">you</span> <span class="hljs-title">want</span> <span class="hljs-title">to</span> <span class="hljs-title">delete</span> <span class="hljs-title">this</span> <span class="hljs-title">movie</span>?')" <span class="hljs-title">class</span>="<span class="hljs-title">bg</span>-<span class="hljs-title">red</span>-500 <span class="hljs-title">text</span>-<span class="hljs-title">white</span> <span class="hljs-title">py</span>-1 <span class="hljs-title">px</span>-3 <span class="hljs-title">rounded</span>"&gt;<span class="hljs-title">Delete</span>&lt;/<span class="hljs-title">a</span>&gt;
         &lt;/<span class="hljs-title">div</span>&gt;
       &lt;/<span class="hljs-title">div</span>&gt;
     &lt;?<span class="hljs-title">php</span> <span class="hljs-title">endforeach</span> ?&gt;
   &lt;/<span class="hljs-title">div</span>&gt;
 &lt;/<span class="hljs-title">div</span>&gt;

&lt;/<span class="hljs-title">body</span>&gt;

&lt;/<span class="hljs-title">html</span>&gt;</span>
</code></pre>
<p>Notice that there are the Update and Delete linking to an <code>update.php</code> and a <code>delete.php</code> files with the id of the movie clicked. That way, we will know which movie is clicked in order to update or delete it. There's also an include statement for a <code>create.php</code> file.</p>
<p>For now, you can go ahead and create the <code>create.php</code>, <code>update.php</code>, and <code>delete.php</code> files in the root.</p>
<p>At this point, you won't see anything in the UI yet because you need to handle the creation functionality.</p>
<h3 id="heading-step-5-the-create-part-of-the-crud">Step 5: The <code>CREATE</code> Part of the CRUD</h3>
<p>Create a <code>create.php</code> file in the root (if you haven't already) and paste in the following:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/mongo_atlas_setup.php'</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>] === <span class="hljs-string">'POST'</span>) {
 $movies = getMongoCollection(<span class="hljs-string">'movie_list'</span>, <span class="hljs-string">'movies'</span>);
 $newMovie = [
   <span class="hljs-string">'movie_title'</span> =&gt; $_POST[<span class="hljs-string">'movie-title'</span>],
   <span class="hljs-string">'movie_year'</span> =&gt; (<span class="hljs-keyword">int</span>)$_POST[<span class="hljs-string">'movie-year'</span>],
 ];
 $result = $movies-&gt;insertOne($newMovie);
 <span class="hljs-keyword">if</span> ($result-&gt;getInsertedCount() === <span class="hljs-number">1</span>) {
   <span class="hljs-comment">// echo "Movie created successfully!";</span>
   header(<span class="hljs-string">'Location: '</span> . <span class="hljs-string">'/'</span>);
 } <span class="hljs-keyword">else</span> {
   <span class="hljs-keyword">echo</span> <span class="hljs-string">"Failed to create movie"</span>;
 }
}
<span class="hljs-meta">?&gt;</span>

&lt;form method=<span class="hljs-string">"POST"</span> action=<span class="hljs-string">"create.php"</span> <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">space</span>-<span class="hljs-title">y</span>-4 <span class="hljs-title">mb</span>-6"&gt;
 &lt;<span class="hljs-title">div</span>&gt;
   &lt;<span class="hljs-title">label</span> <span class="hljs-title">class</span>="<span class="hljs-title">block</span> <span class="hljs-title">text</span>-<span class="hljs-title">gray</span>-700"&gt;<span class="hljs-title">Movie</span> <span class="hljs-title">Title</span>&lt;/<span class="hljs-title">label</span>&gt;
   &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">text</span>" <span class="hljs-title">name</span>="<span class="hljs-title">movie</span>-<span class="hljs-title">title</span>" <span class="hljs-title">required</span> <span class="hljs-title">class</span>="<span class="hljs-title">w</span>-<span class="hljs-title">full</span> <span class="hljs-title">p</span>-2 <span class="hljs-title">border</span> <span class="hljs-title">rounded</span> <span class="hljs-title">max</span>-<span class="hljs-title">w</span>-<span class="hljs-title">md</span>"&gt;
 &lt;/<span class="hljs-title">div</span>&gt;
 &lt;<span class="hljs-title">div</span>&gt;
   &lt;<span class="hljs-title">label</span> <span class="hljs-title">class</span>="<span class="hljs-title">block</span> <span class="hljs-title">text</span>-<span class="hljs-title">gray</span>-700"&gt;<span class="hljs-title">Movie</span> <span class="hljs-title">Year</span>&lt;/<span class="hljs-title">label</span>&gt;
   &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">text</span>" <span class="hljs-title">name</span>="<span class="hljs-title">movie</span>-<span class="hljs-title">year</span>" <span class="hljs-title">required</span> <span class="hljs-title">class</span>="<span class="hljs-title">w</span>-<span class="hljs-title">full</span> <span class="hljs-title">p</span>-2 <span class="hljs-title">border</span> <span class="hljs-title">rounded</span> <span class="hljs-title">max</span>-<span class="hljs-title">w</span>-<span class="hljs-title">md</span>"&gt;
 &lt;/<span class="hljs-title">div</span>&gt;
 &lt;<span class="hljs-title">button</span> <span class="hljs-title">type</span>="<span class="hljs-title">submit</span>" <span class="hljs-title">class</span>="<span class="hljs-title">bg</span>-<span class="hljs-title">green</span>-500 <span class="hljs-title">text</span>-<span class="hljs-title">white</span> <span class="hljs-title">py</span>-2 <span class="hljs-title">px</span>-4 <span class="hljs-title">rounded</span>"&gt;<span class="hljs-title">Create</span>&lt;/<span class="hljs-title">button</span>&gt;
&lt;/<span class="hljs-title">form</span>&gt;</span>
</code></pre>
<p>The code above contains the form and input elements for creating a movie. We are then using the name attributes in those input elements to create the <code>POST</code> request that will let us create a movie and save it in the <code>movies</code> collection of a <code>movie_list</code> database.</p>
<h3 id="heading-step-6-the-update-part-of-the-crud">Step 6: The <code>UPDATE</code> Part of the CRUD</h3>
<p>To handle the updating, we need to create a separate file and do something similar to how the movie creation worked. The exeception is that we are going to use the id (<code>_id</code>) field to determine whether the movie exists and then update it instead of creating a fresh one.</p>
<p>To do that, create an <code>update.php</code> file (if you haven't already) in the root and paste in the following:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/vendor/autoload.php'</span>;
<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/mongo_atlas_setup.php'</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">MongoDB</span>\<span class="hljs-title">BSON</span>\<span class="hljs-title">ObjectId</span>;

$movies_list = getMongoCollection(<span class="hljs-string">'movie_list'</span>, <span class="hljs-string">'movies'</span>);
$title = <span class="hljs-string">''</span>;
$year = <span class="hljs-string">''</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>] === <span class="hljs-string">'POST'</span>) {
 $filter = [<span class="hljs-string">'_id'</span> =&gt; <span class="hljs-keyword">new</span> ObjectId($_POST[<span class="hljs-string">'id'</span>])];

 $update = [<span class="hljs-string">'$set'</span> =&gt; [
   <span class="hljs-string">'movie_title'</span> =&gt; $_POST[<span class="hljs-string">'movie-title'</span>],
   <span class="hljs-string">'movie_year'</span> =&gt; (<span class="hljs-keyword">int</span>)$_POST[<span class="hljs-string">'movie-year'</span>],
 ]];

 $result = $movies_list-&gt;updateOne($filter, $update);

 <span class="hljs-keyword">if</span> ($result-&gt;getModifiedCount() === <span class="hljs-number">1</span>) {
   <span class="hljs-comment">// echo "Movie updated successfully!";</span>
   header(<span class="hljs-string">'Location: '</span> . <span class="hljs-string">'/'</span>);
 } <span class="hljs-keyword">else</span> {
   <span class="hljs-keyword">echo</span> <span class="hljs-string">"Failed to update movie."</span>;
 }
} <span class="hljs-keyword">else</span> {
 <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>($_GET[<span class="hljs-string">'id'</span>])) {
   $id = $_GET[<span class="hljs-string">'id'</span>];
   $movie = $movies_list-&gt;findOne([<span class="hljs-string">'_id'</span> =&gt; <span class="hljs-keyword">new</span> ObjectId($id)]);
   <span class="hljs-keyword">if</span> ($movie) {
     $title = $movie[<span class="hljs-string">'movie_title'</span>];
     $year = $movie[<span class="hljs-string">'movie_year'</span>];
   } <span class="hljs-keyword">else</span> {
     <span class="hljs-keyword">echo</span> <span class="hljs-string">"Movie not found."</span>;
     <span class="hljs-keyword">exit</span>;
   }
 } <span class="hljs-keyword">else</span> {
   <span class="hljs-keyword">echo</span> <span class="hljs-string">"No movie ID provided."</span>;
   <span class="hljs-keyword">exit</span>;
 }
}
<span class="hljs-meta">?&gt;</span>

&lt;!DOCTYPE html&gt;
&lt;html lang=<span class="hljs-string">"en"</span>&gt;

&lt;head&gt;
 &lt;meta charset=<span class="hljs-string">"UTF-8"</span>&gt;
 &lt;meta name=<span class="hljs-string">"viewport"</span> content=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;
 &lt;script src=<span class="hljs-string">"https://cdn.tailwindcss.com"</span>&gt;&lt;/script&gt;
 &lt;title&gt;Update Movie &lt;/title&gt;
&lt;/head&gt;

&lt;body <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">bg</span>-<span class="hljs-title">gray</span>-100 <span class="hljs-title">p</span>-10"&gt;

 &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">max</span>-<span class="hljs-title">w</span>-4<span class="hljs-title">xl</span> <span class="hljs-title">mx</span>-<span class="hljs-title">auto</span> <span class="hljs-title">bg</span>-<span class="hljs-title">white</span> <span class="hljs-title">p</span>-6 <span class="hljs-title">rounded</span> <span class="hljs-title">shadow</span>"&gt;
   &lt;<span class="hljs-title">h1</span> <span class="hljs-title">class</span>="<span class="hljs-title">text</span>-3<span class="hljs-title">xl</span> <span class="hljs-title">font</span>-<span class="hljs-title">bold</span> <span class="hljs-title">mb</span>-4"&gt;<span class="hljs-title">Update</span> &lt;?= $<span class="hljs-title">title</span> ?&gt; &lt;/<span class="hljs-title">h1</span>&gt;

   &lt;<span class="hljs-title">form</span> <span class="hljs-title">method</span>="<span class="hljs-title">POST</span>" <span class="hljs-title">action</span>="<span class="hljs-title">update</span>.<span class="hljs-title">php</span>" <span class="hljs-title">class</span>="<span class="hljs-title">space</span>-<span class="hljs-title">y</span>-4"&gt;
     &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">hidden</span>" <span class="hljs-title">name</span>="<span class="hljs-title">id</span>" <span class="hljs-title">value</span>="&lt;?<span class="hljs-title">php</span> <span class="hljs-title">echo</span> $<span class="hljs-title">id</span>; ?&gt;"&gt;

     &lt;<span class="hljs-title">div</span>&gt;
       &lt;<span class="hljs-title">label</span> <span class="hljs-title">class</span>="<span class="hljs-title">block</span> <span class="hljs-title">text</span>-<span class="hljs-title">gray</span>-700"&gt;<span class="hljs-title">Title</span>&lt;/<span class="hljs-title">label</span>&gt;
       &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">text</span>" <span class="hljs-title">name</span>="<span class="hljs-title">movie</span>-<span class="hljs-title">title</span>" <span class="hljs-title">value</span>="&lt;?= <span class="hljs-title">htmlspecialchars</span>($<span class="hljs-title">title</span>); ?&gt;" <span class="hljs-title">required</span> <span class="hljs-title">class</span>="<span class="hljs-title">w</span>-<span class="hljs-title">full</span> <span class="hljs-title">p</span>-2 <span class="hljs-title">border</span> <span class="hljs-title">rounded</span>" /&gt;
     &lt;/<span class="hljs-title">div</span>&gt;

     &lt;<span class="hljs-title">div</span>&gt;
       &lt;<span class="hljs-title">label</span> <span class="hljs-title">class</span>="<span class="hljs-title">block</span> <span class="hljs-title">text</span>-<span class="hljs-title">gray</span>-700"&gt;<span class="hljs-title">Release</span> <span class="hljs-title">Year</span>&lt;/<span class="hljs-title">label</span>&gt;
       &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">number</span>" <span class="hljs-title">name</span>="<span class="hljs-title">movie</span>-<span class="hljs-title">year</span>" <span class="hljs-title">value</span>="&lt;?= <span class="hljs-title">htmlspecialchars</span>($<span class="hljs-title">year</span>); ?&gt;" <span class="hljs-title">required</span> <span class="hljs-title">class</span>="<span class="hljs-title">w</span>-<span class="hljs-title">full</span> <span class="hljs-title">p</span>-2 <span class="hljs-title">border</span> <span class="hljs-title">rounded</span>" /&gt;
     &lt;/<span class="hljs-title">div</span>&gt;

     &lt;<span class="hljs-title">button</span> <span class="hljs-title">class</span>=" <span class="hljs-title">bg</span>-<span class="hljs-title">green</span>-500 <span class="hljs-title">text</span>-<span class="hljs-title">white</span> <span class="hljs-title">py</span>-2 <span class="hljs-title">px</span>-4 <span class="hljs-title">rounded</span>" <span class="hljs-title">type</span>="<span class="hljs-title">submit</span>"&gt;<span class="hljs-title">Update</span>&lt;/<span class="hljs-title">button</span>&gt;
   &lt;/<span class="hljs-title">form</span>&gt;

   &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">mt</span>-4"&gt;
     &lt;<span class="hljs-title">a</span> <span class="hljs-title">href</span>="<span class="hljs-title">index</span>.<span class="hljs-title">php</span>" <span class="hljs-title">class</span>="<span class="hljs-title">bg</span>-<span class="hljs-title">gray</span>-500 <span class="hljs-title">text</span>-<span class="hljs-title">white</span> <span class="hljs-title">py</span>-2 <span class="hljs-title">px</span>-4 <span class="hljs-title">rounded</span>"&gt;<span class="hljs-title">Back</span> <span class="hljs-title">to</span> <span class="hljs-title">List</span>&lt;/<span class="hljs-title">a</span>&gt;
   &lt;/<span class="hljs-title">div</span>&gt;
 &lt;/<span class="hljs-title">div</span>&gt;

&lt;/<span class="hljs-title">body</span>&gt;

&lt;/<span class="hljs-title">html</span>&gt;</span>
</code></pre>
<h3 id="heading-step-7-the-delete-part-of-the-crud">Step 7: The <code>DELETE</code> Part of the CRUD</h3>
<p>To handle the delete functionality, we can get the movie and use the <code>deleteOne</code> function provided by MongoDB to delete it. Once the deleting is done, we will then use the <code>header()</code> function again to redirect to the home page.</p>
<p>Paste the following code in your <code>delete.php</code> file:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/mongo_atlas_setup.php'</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">MongoDB</span>\<span class="hljs-title">BSON</span>\<span class="hljs-title">ObjectId</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>] === <span class="hljs-string">'GET'</span> &amp;&amp; <span class="hljs-keyword">isset</span>($_GET[<span class="hljs-string">'id'</span>])) {
 $movies = getMongoCollection(<span class="hljs-string">'movie_list'</span>, <span class="hljs-string">'movies'</span>);
 $filter = [<span class="hljs-string">'_id'</span> =&gt; <span class="hljs-keyword">new</span> ObjectId($_GET[<span class="hljs-string">'id'</span>])];
 $result = $movies-&gt;deleteOne($filter);
 <span class="hljs-keyword">if</span> ($result-&gt;getDeletedCount() === <span class="hljs-number">1</span>) {
   <span class="hljs-comment">// echo "Movie deleted successfully!";</span>
   header(<span class="hljs-string">'Location: '</span> . <span class="hljs-string">'/'</span>);
 } <span class="hljs-keyword">else</span> {
   <span class="hljs-keyword">echo</span> <span class="hljs-string">"Failed to delete movie."</span>;
 }
} <span class="hljs-keyword">else</span> {
 <span class="hljs-keyword">echo</span> <span class="hljs-string">"No movie provided."</span>;
}
<span class="hljs-meta">?&gt;</span>
</code></pre>
<p>This is what the CRUD app should look like now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/CRUD-gif.gif" alt="CRUD-gif" width="600" height="400" loading="lazy"></p>
<p>All the code is in this <a target="_blank" href="https://github.com/Ksound22/crud-app-for-php-fcc-article">GitHub repo</a></p>
<h2 id="heading-project-how-to-use-php-to-rebuild-the-football-team-cards-project-of-the-updated-javascript-curriculum">Project: How to Use PHP to Rebuild the Football Team Cards Project of the Updated JavaScript Curriculum</h2>
<p>Before you start going through the steps to build the project, grab the starter code for the project in <a target="_blank" href="https://github.com/Ksound22/football-team-cards-php-rebuild">the starter branch of this GitHub repo</a>.</p>
<p>You can also take a look at <a target="_blank" href="https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures-v8/learn-modern-javascript-methods-by-building-football-team-cards/step-1">the football team cards project</a> to know what we are trying to achieve.</p>
<h3 id="heading-step-1-set-up-mongodb-atlas">Step 1: Set up MongoDB Atlas</h3>
<p>Log in to your MongoDB Atlas account and create a <code>football-team-cards</code> database. Feel free to create it in an existing project or a new one if you want. In the <code>football-team-cards</code> database, create a <code>footballers</code> collection.</p>
<p>In the <code>footballers</code> collection, click the "INSERT DOCUMENT" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-06-09-at-14.33.15.png" alt="Screenshot-2024-06-09-at-14.33.15" width="600" height="400" loading="lazy"></p>
<p>Then paste in the content of the <code>footballers.json</code> file in the starter branch of the project GitHub repo and click "Done".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-06-09-at-14.42.47.png" alt="Screenshot-2024-06-09-at-14.42.47" width="600" height="400" loading="lazy"></p>
<p>After that, your <code>footballers</code> collection should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-06-09-at-14.44.59.png" alt="Screenshot-2024-06-09-at-14.44.59" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-2-install-the-project-dependencies-with-composer">Step 2: Install the Project Dependencies with Composer</h3>
<p>Create a <code>football-team-cards-php</code> folder on your computer and open it with your favorite text editor. Open the same folder in your terminal and run the following commands:</p>
<pre><code class="lang-bash">composer require vlucas/phpdotenv 
composer require mongodb/mongodb
</code></pre>
<h3 id="heading-step-3-create-project-files">Step 3: Create Project Files</h3>
<p>Inside the <code>football-team-cards-php</code> folder, create the following files:</p>
<ul>
<li><p><code>.env</code></p>
</li>
<li><p><code>mongo_atlas_php_setup.php</code></p>
</li>
<li><p><code>index.php</code></p>
</li>
<li><p><code>styles.css</code></p>
</li>
</ul>
<p>In the <code>.env</code> file, you should have the MongoDB Atlas URI:</p>
<pre><code class="lang-bash">MDB_URI=<span class="hljs-string">"Your MongoDB Atlas connection string"</span>
</code></pre>
<p>In the <code>mongo_atlas_php_setup.php</code> file, you should connect to the database with this code:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/vendor/autoload.php'</span>;
$dotenv = Dotenv\Dotenv::createImmutable(<span class="hljs-keyword">__DIR__</span>);
$dotenv-&gt;load();


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMongoClient</span>(<span class="hljs-params"></span>)
</span>{
 <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> MongoDB\Client($_ENV[<span class="hljs-string">'MDB_URI'</span>]);
}


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMongoCollection</span>(<span class="hljs-params">$database, $collection</span>)
</span>{
 $client = getMongoClient();
 <span class="hljs-keyword">return</span> $client-&gt;selectCollection($database, $collection);
}
</code></pre>
<p>In the code above, we are loading the environment variables and using a <code>getMongCollection</code> function to connect the database. Make sure you replace the connection string with your own.</p>
<p>Now, anytime you want to connect to a database, require the file, then pass the database and the collection names to the <code>getMongoCollection</code> function.</p>
<p>Copy the content of the <code>index.html</code> and <code>styles.css</code> files in the starter branch of the project GitHub repo and paste them into your <code>index.php</code> and <code>styles.css</code> files.</p>
<h3 id="heading-step-4-wrap-the-select-tag-in-a-form-element">Step 4: Wrap the <code>select</code> tag in a <code>form</code> Element</h3>
<p>Replace the existing <code>select</code> tag with the following:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">""</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"options-label"</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"players"</span>&gt;</span>Filter Teammates:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"position"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"players"</span> <span class="hljs-attr">onchange</span>=<span class="hljs-string">"this.form.submit()"</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"all"</span>&gt;</span>All Players<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"nickname"</span>&gt;</span>Nicknames<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"forward"</span>&gt;</span>Position Forward<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"midfielder"</span>&gt;</span>Position Midfielder<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"defender"</span>&gt;</span>Position Defender<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"goalkeeper"</span>&gt;</span>Position Goalkeeper<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>This will let you make a <code>POST</code> request with the <code>name</code> attribute set to <code>position</code>. And with the <code>onchange</code> attribute of <code>this.form.submit()</code>, you'll be able to fetch footballers based on any of the options selected. More on this later.</p>
<h3 id="heading-step-5-create-the-logic-for-fetching-the-footballers-from-the-footballers-collection">Step 5: Create the Logic for Fetching the Footballers from the <code>footballers</code> Collection</h3>
<pre><code class="lang-php"><span class="hljs-keyword">require_once</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/mongo_atlas_php_setup.php'</span>;

$position = <span class="hljs-keyword">isset</span>($_POST[<span class="hljs-string">'position'</span>]) ? $_POST[<span class="hljs-string">'position'</span>] : <span class="hljs-string">'all'</span>;

$collection = getMongoCollection(<span class="hljs-string">'football-team-cards'</span>, <span class="hljs-string">'footballers'</span>);
$team = $collection-&gt;findOne([<span class="hljs-string">'team'</span> =&gt; <span class="hljs-string">'Argentina'</span>]);
$players = $team[<span class="hljs-string">'players'</span>]-&gt;getArrayCopy();
</code></pre>
<p>With the code above, we are:</p>
<ul>
<li><p>importing the database connection file</p>
</li>
<li><p>checking for <code>POST</code> data with the name on the <code>select</code> tag and setting a default value of <code>all</code> (the first option in the select element)</p>
</li>
<li><p>getting the database and collection in it</p>
</li>
<li><p>using the <code>findOne</code> method from MongoDB to get the team</p>
</li>
<li><p>and fetching the data as an array with <code>getArraCopy()</code> so we can loop through it</p>
</li>
</ul>
<p>At this point, you can print the <code>$players</code> variable with <code>print_r()</code> or <code>var_dump()</code> to see what it looks like. On my end, it looks like this when I ran the app with <code>php -S localhost:4000</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Screenshot-2024-06-09-at-16.24.47.png" alt="Screenshot-2024-06-09-at-16.24.47" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-6-create-the-logic-for-filtering-the-footballers-based-on-position">Step 6: Create the Logic for Filtering the Footballers Based on Position</h3>
<p>Remember we have to display the players based on whether they are goakeepers, defenders, midfielders, or forwards. To do that, we can utilize the code below:</p>
<pre><code class="lang-php">$filteredPlayers = $players;


<span class="hljs-keyword">if</span> ($position !== <span class="hljs-string">'all'</span>) {
 <span class="hljs-keyword">if</span> ($position === <span class="hljs-string">'nickname'</span>) {
   $filteredPlayers = array_filter($players, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$player</span>) </span>{
     <span class="hljs-keyword">return</span> !<span class="hljs-keyword">empty</span>($player[<span class="hljs-string">'nickname'</span>]);
   });
 } <span class="hljs-keyword">else</span> {
   $filteredPlayers = array_filter($players, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$player</span>) <span class="hljs-title">use</span> (<span class="hljs-params">$position</span>) </span>{
     <span class="hljs-keyword">return</span> $player[<span class="hljs-string">'position'</span>] === $position;
   });
 }
}
</code></pre>
<p>At first, we are initializing <code>$filteredPlayers</code> to all the players. If the selected position is not <code>all</code>, we filter the players based on <code>nickname</code>. And if the selected position is not <code>nickname</code>, we filter the players to include only those whose position matches the selected <code>position</code>.</p>
<h3 id="heading-step-7-display-the-players-on-the-page-based-on-the-selected-position">Step 7: Display the Players on the Page Based on the Selected Position</h3>
<p>Now, all we need to do is set each option's value (all players, goalkeepers, defenders, midfielders, forwards) to <code>selected</code> if that option is matched. After that, we need to use <code>foreach</code> loop to do the proper display.</p>
<p>Here's one way you can set the value of each <code>option</code> to <code>selected</code>:</p>
<pre><code class="lang-php">&lt;option value=<span class="hljs-string">"all"</span> <span class="hljs-meta">&lt;?=</span> $position === <span class="hljs-string">'all'</span> ? <span class="hljs-string">'selected'</span> : <span class="hljs-string">''</span> <span class="hljs-meta">?&gt;</span>&gt;All Players&lt;/option&gt;
       &lt;option value=<span class="hljs-string">"nickname"</span> <span class="hljs-meta">&lt;?=</span> $position === <span class="hljs-string">'nickname'</span> ? <span class="hljs-string">'selected'</span> : <span class="hljs-string">''</span> <span class="hljs-meta">?&gt;</span>&gt;Nicknames&lt;/option&gt;
       &lt;option value=<span class="hljs-string">"forward"</span> <span class="hljs-meta">&lt;?=</span> $position === <span class="hljs-string">'forward'</span> ? <span class="hljs-string">'selected'</span> : <span class="hljs-string">''</span> <span class="hljs-meta">?&gt;</span>&gt;Forwards&lt;/option&gt;
       &lt;option value=<span class="hljs-string">"midfielder"</span> <span class="hljs-meta">&lt;?=</span> $position === <span class="hljs-string">'midfielder'</span> ? <span class="hljs-string">'selected'</span> : <span class="hljs-string">''</span> <span class="hljs-meta">?&gt;</span>&gt;Midfielders&lt;/option&gt;
       &lt;option value=<span class="hljs-string">"defender"</span> <span class="hljs-meta">&lt;?=</span> $position === <span class="hljs-string">'defender'</span> ? <span class="hljs-string">'selected'</span> : <span class="hljs-string">''</span> <span class="hljs-meta">?&gt;</span>&gt;Defenders&lt;/option&gt;
       &lt;option value=<span class="hljs-string">"goalkeeper"</span> <span class="hljs-meta">&lt;?=</span> $position === <span class="hljs-string">'goalkeeper'</span> ? <span class="hljs-string">'selected'</span> : <span class="hljs-string">''</span> <span class="hljs-meta">?&gt;</span>&gt;Goalkeepers&lt;/option&gt;
</code></pre>
<p>And here's how you can use the <code>foreach</code> loop to finally display the players selected:</p>
<pre><code class="lang-php">&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">cards</span>" <span class="hljs-title">id</span>="<span class="hljs-title">player</span>-<span class="hljs-title">cards</span>"&gt;
     &lt;?<span class="hljs-title">php</span> <span class="hljs-title">if</span> (<span class="hljs-title">empty</span>($<span class="hljs-title">filteredPlayers</span>)) : ?&gt;
       &lt;<span class="hljs-title">p</span>&gt;<span class="hljs-title">No</span> <span class="hljs-title">players</span> <span class="hljs-title">found</span> <span class="hljs-title">for</span> <span class="hljs-title">the</span> <span class="hljs-title">selected</span> <span class="hljs-title">position</span>.&lt;/<span class="hljs-title">p</span>&gt;
     &lt;?<span class="hljs-title">php</span> <span class="hljs-title">else</span> : ?&gt;
       &lt;?<span class="hljs-title">php</span> <span class="hljs-title">foreach</span> ($<span class="hljs-title">filteredPlayers</span> <span class="hljs-title">as</span> $<span class="hljs-title">players</span>) : ?&gt;
         &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">player</span>-<span class="hljs-title">card</span>"&gt;
           &lt;<span class="hljs-title">h2</span>&gt;&lt;?= $<span class="hljs-title">players</span>['<span class="hljs-title">name</span>'] . ($<span class="hljs-title">players</span>['<span class="hljs-title">isCaptain</span>'] ? ' (<span class="hljs-title">Captain</span>)' : '') ?&gt;&lt;/<span class="hljs-title">h2</span>&gt;
           &lt;<span class="hljs-title">p</span>&gt;<span class="hljs-title">Position</span>: &lt;?= $<span class="hljs-title">players</span>['<span class="hljs-title">position</span>'] ?&gt;&lt;/<span class="hljs-title">p</span>&gt;
           &lt;<span class="hljs-title">p</span>&gt;<span class="hljs-title">Number</span>: &lt;?= $<span class="hljs-title">players</span>['<span class="hljs-title">number</span>'] ?&gt;&lt;/<span class="hljs-title">p</span>&gt;
           &lt;<span class="hljs-title">p</span>&gt;<span class="hljs-title">Nickname</span>: &lt;?= !<span class="hljs-title">empty</span>($<span class="hljs-title">players</span>['<span class="hljs-title">nickname</span>']) ? $<span class="hljs-title">players</span>['<span class="hljs-title">nickname</span>'] : '<span class="hljs-title">N</span>/<span class="hljs-title">A</span>' ?&gt;&lt;/<span class="hljs-title">p</span>&gt;
         &lt;/<span class="hljs-title">div</span>&gt;
       &lt;?<span class="hljs-title">php</span> <span class="hljs-title">endforeach</span> ?&gt;
     &lt;?<span class="hljs-title">php</span> <span class="hljs-title">endif</span> ?&gt;
   &lt;/<span class="hljs-title">div</span>&gt;</span>
</code></pre>
<p>Now, everything works as expected:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/football-team-cards.gif" alt="football-team-cards" width="600" height="400" loading="lazy"></p>
<p>You can grab the final code of the project in the main branch of this <a target="_blank" href="https://github.com/Ksound22/football-team-cards-php-rebuild">GitHub repo</a>.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Rebuilding the football team cards project with PHP and MongoDB Atlas shows just how powerful and flexible it can be to combine server-side scripting with a cloud-based NoSQL database.</p>
<p>The project not only highlights how smoothly PHP and MongoDB Atlas work together, but it also shows the advantages of using a cloud-based database like Atlas. Atlas offers scalability, high availability, and easy management, making it a great choice for modern web applications.</p>
<p>Whichever data-driven application you're making, these techniques that we used here to build the project and the initial CRUD app can help you out.</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ JavaScript Frameworks vs Laravel – Which Should You Choose for Web Development? ]]>
                </title>
                <description>
                    <![CDATA[ For a long time, developers in the JavaScript ecosystem have tried to launch Laravel-like frameworks for JavaScript. We've seen Blitz for NextJS, Adonis for NodeJS, RedwoodJS, and more. All these frameworks tried to build a Laravel for JavaScript. Bu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/javascript-frameworks-vs-laravel/</link>
                <guid isPermaLink="false">66d45d5a33b83c4378a517b0</guid>
                
                    <category>
                        <![CDATA[ framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Afan Khan ]]>
                </dc:creator>
                <pubDate>Mon, 17 Jun 2024 14:28:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/Group-3148.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>For a long time, developers in the JavaScript ecosystem have tried to launch Laravel-like frameworks for JavaScript.</p>
<p>We've seen Blitz for NextJS, Adonis for NodeJS, RedwoodJS, and more. All these frameworks tried to build a Laravel for JavaScript.</p>
<p>But none of them were really successful. Why? We'll figure it out in this article. It's worth going over because beginners learning JavaScript struggle to find an all-in-one solution.</p>
<p>This means it can be tough to choose a framework (or library) in JavaScript when you have so many choices – like React, Vue, Angular, Svelte, NextJS, Meteor, and more.</p>
<p>Meanwhile, PHP offers one simple solution: Laravel. It's a one-stop shop with many frameworks and libraries combined into one. But is it the right option for you?</p>
<p>In this article, I'll dive deeper into why the JavaScript ecosystem doesn't have a Laravel-like framework and whether you should switch to PHP for a one-stop solution like Laravel.</p>
<p>I will discuss the advantages and disadvantages of using JavaScript frameworks compared to a one-stop solution like Laravel and end it with a comparison table to help you decide.</p>
<h2 id="heading-what-well-cover-in-this-article">What we'll cover in this article:</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-why-javascript-vs-laravel">Why JavaScript vs Laravel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-javascript-lacks-an-all-in-one-solution">Why JavaScript lacks an all-in-one solution</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-javascript-frameworks-and-libraries">Benefits of JavaScript frameworks and libraries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-laravel">Benefits of Laravel</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-differences-between-laravel-and-js-tools">Differences between Laravel and JS tools</a></p>
</li>
</ol>
<h2 id="heading-why-javascript-vs-laravel">Why JavaScript vs Laravel</h2>
<p>When beginners decide to learn Web Development, they often choose between JavaScript/TypeScript and PHP. Other solutions require more expertise, so most beginners gravitate towards these two languages.</p>
<p>Many JavaScript beginners eventually find its vast ecosystem overwhelming, whereas PHP learners often feel constrained by the limited frameworks and lack of advanced capabilities.</p>
<p>To deal with that confusion, I am comparing the tools available for JavaScript and PHP, not the languages directly. Since PHP has an all-in-one solution most developers use, I'll use Laravel for the comparison.</p>
<p>JavaScript lacks a single all-in-one solution or a specific representative framework. Therefore, I'll refer to tools like React, Vue, Angular, and so on as "JavaScript Frameworks."</p>
<p>Let's begin by understanding why the JavaScript ecosystem lacks a Laravel-like framework.</p>
<h2 id="heading-why-javascript-lacks-an-all-in-one-solution">Why JavaScript Lacks an All-in-One Solution</h2>
<p>I'll begin by acknowledging that JavaScript developers have tried in the past to make a Laravel for JavaScript.</p>
<p>Start with RedwoodJS. It's an open-source full-stack JavaScript framework started by Tom Preston-Werner, the co-founder and former CEO of GitHub. It helps developers build their applications and ship faster.</p>
<p>Redwood has many innovative solutions packed into one framework. Sounds familiar? That's precisely like Laravel. Do you see anyone shipping using Redwood? Most likely not.</p>
<p>The next option is Blitz. It makes the same promise as Redwood: a replacement for NextJS. Blitz is an all-in-one solution with custom built-in solutions for authentication, database, and so on.</p>
<p>But Blitz doesn't allow developers to choose what they want to use, like Laravel. It has custom solutions crafted by the core team. Developers cannot replace any solution piece with some other recommended solution.</p>
<p>Customization is a point worth noting in the JavaScript ecosystem, and I'll explain why as we uncover more frameworks. But Blitz didn't succeed either.</p>
<p>Then, there's AdonisJS. But, I think you get the point. Each all-in-one solution in JavaScript has tried to implement their version of Laravel – and none of them really took hold.</p>
<p>Blitz, Adonis, and Redwood followed a theme: a full-stack framework of ready-made non-customizable solutions for JavaScript developers to build applications.</p>
<p>These frameworks didn't gain popularity because they didn't meet the needs of the developers they aimed to serve.</p>
<p>The JavaScript ecosystem is unique, offering many solutions for the same problem. There's a reason for this diversity, and why those frameworks didn't succeed.</p>
<p>Let's discuss the reasons and benefits of the current popular JavaScript tools, as they directly impact the choice between JavaScript frameworks and Laravel. As I outline each benefit, consider whether it aligns with your needs.</p>
<h2 id="heading-benefits-of-javascript-frameworks-and-libraries">Benefits of JavaScript Frameworks and Libraries</h2>
<p>JavaScript frameworks and libraries are collections of pre-written resources, techniques, and functions created by developers to save time and effort.</p>
<p>These frameworks began emerging in the 2000s, with notable ones like React, Svelte, Angular, NextJS, and Vue standing out over time.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-80.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Source:</em> <a target="_blank" href="https://raygun.com/blog/popular-javascript-frameworks/"><em>Raygun</em></a></p>
<p>However, having more options doesn't necessarily mean greater effectiveness. Below, we’ll explore the benefits of using JavaScript frameworks and why all-in-one solutions haven't succeeded in the JavaScript ecosystem.</p>
<h3 id="heading-versatility">Versatility</h3>
<p>It's easier to switch or choose one solution over the other in the JavaScript ecosystem. For example, to implement authentication, we have Clerk, Auth0, AuthJS, NextAuth, Supabase, and more.</p>
<p>The JavaScript ecosystem always had multiple options for a specific solution and startups dedicated to providing bespoke solutions. If you didn't like Clerk, you could use NextAuth for more customization.</p>
<p>JavaScript frameworks are highly versatile. When there are ten solutions for one problem, developers can easily switch and see what works for them.</p>
<p>Blitz and other frameworks couldn't succeed for this reason. If a developer disliked Blitz's approach to authentication, they would just switch to another solution.</p>
<h3 id="heading-npm">NPM</h3>
<p>Unlike JavaScript, other languages don't have an ecosystem around building tools for others, like libraries or packages. It's not as easy in those languages.</p>
<p>The JavaScript ecosystem has an entire registry filled with packages and libraries for the smallest solutions, like emails. JavaScript has many packages, frameworks, and libraries for each solution.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-81.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Source:</em> <a target="_blank" href="https://kinsta.com/knowledgebase/what-is-npm/"><em>Kinsta</em></a></p>
<p>Ironically, even the NPM registry has competitors. There are multiple other registries with unique packages and features. JavaScript follows the versatility rule everywhere, but does that indicate reliability? Maybe not.</p>
<h3 id="heading-startups">Startups</h3>
<p>Each solution for a specific problem is likely a startup funded by VC firms and Angel Investors.</p>
<p>JavaScript-based startups have the capital and the resources to conduct in-depth research and hire the best talent to build bespoke solutions for a targeted problem.</p>
<p>With unlimited resources allocated to a specific topic or problem, the solutions are specific and cater to different needs to their developers.</p>
<p>In return, JavaScript developers pay these startups for those solutions and startups are incentivised to create better solutions for the ecosystem.</p>
<h3 id="heading-the-common-dev">The Common Dev</h3>
<p>Any developer in the JavaScript ecosystem can identify a problem during their experience using a specific technology, build a solution, and offer it as a product.</p>
<p>JavaScript developers have the liberty to build and sell their solutions because startups push the idea of paying for bespoke solutions and developers have no problem doing that.</p>
<p>Take <a target="_blank" href="https://x.com/marc_louvion">Marc Lou</a> as an example. He built <a target="_blank" href="https://shipfa.st/">ShipFast</a> and other products that churn over $100,000 per month. He is an example of the possibilities in the field.</p>
<p>But perhaps these benefits and reasons seem intangible to you. Don’t worry—the web development domain offers more than one alternative. Let’s explore Laravel.</p>
<h2 id="heading-laravel">Laravel</h2>
<p>Laravel is a framework for the PHP programming language. Taylor Otwell introduced Laravel in 2011.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-45.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Source: Cloudways</em></p>
<p>Laravel offers many solutions packed into one tool, and can be a one-stop solution for everything. It offers authentication, debugging, serverless deployment, user-friendly form systems, starter kits, and so on.</p>
<p>The solutions provided by Laravel are many, but without the core language, they don't mean anything. Laravel is all about PHP.</p>
<p>PHP is a general-purpose scripting language. Rasmus Lardof introduced it to developers in the 1990s. Since then, the language has evolved with significant updates in 2004, 2015, and 2020.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/image-46.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Source: Gecko Dynamics</em></p>
<p>Before JavaScript frameworks had taken off, developers used PHP with JavaScript.</p>
<p>Laravel is a back-end framework and PHP focuses on the server-side. JavaScript without a framework is a client-side language at its core.</p>
<p>Developers traditionally used JavaScript on the client-side and PHP on the server-side to create full-fledged applications.</p>
<p>However, the tech stack landscape shifted when Laravel gained popularity and frameworks like React began to dominate the JavaScript ecosystem.</p>
<p>Many developers worldwide, especially from countries like India, are doubling down on PHP because of its robust and reliable nature.</p>
<p>Government websites and large infrastructures use Laravel (PHP) because it supports a variety of solutions in one place. Many developers don't want to combine and switch technologies.</p>
<p>Companies and individuals using PHP or Laravel want to ship quickly, make changes, and avoid learning a new library or technology at every step of the way like JavaScript.</p>
<p>PHP only has JavaScript as its direct rival that challenges its existence. However, JavaScript isn't the best for many situations. Let's see how Laravel performs better.</p>
<h2 id="heading-benefits-of-laravel">Benefits of Laravel</h2>
<h3 id="heading-one-stop-solution">One-Stop Solution</h3>
<p>Laravel is an all-in-one framework. It contains everything a developer would reasonably require to build compact, reliable, and robust solutions.</p>
<p>You don't need to spend time searching for various libraries and frameworks that may or may not integrate well with your foundational technology—it's all built-in for you.</p>
<p>If speed of deployment is your priority, Laravel is the ideal choice.</p>
<p>Moreover, for PHP developers using Laravel, there's less need to learn new libraries, syntax, and more because everything is integrated seamlessly.</p>
<h3 id="heading-less-wasted-time">Less Wasted Time</h3>
<p>The PHP ecosystem has fewer solutions for specific problems. It's difficult to identify a specific solution for a specific problem.</p>
<p>Developers rather choose an all-in-one solution than invest time in finding bespoke solutions for specific problems.</p>
<p>That's where the PHP ecosystem shines because developers don't spend a lot of time trying out different options. They already have everything in one place.</p>
<p>If there's a new project, their go-to choice is Laravel. In the JavaScript land, if a developer isn't using an existing solution or tech stack, they are likely finding a new one or creating one.</p>
<h3 id="heading-stable-and-robust">Stable and Robust</h3>
<p>Web Applications created using PHP are robust because the framework is battle-tested. You can create anything using it.</p>
<p>You could sabotage the entire application if you mess up with one choice of library or framework in a JavaScript project. But it's not the same with Laravel.</p>
<p>Since Laravel has fewer solutions, the chances of sabotaging are reduced to the bare minimum.</p>
<h3 id="heading-no-catching-up">No Catching Up</h3>
<p>With Laravel, you don't need to catch up with new technologies and frameworks frequently. You can learn one framework, library, or skill and consider it useful for a long time.</p>
<p>It's the opposite in JavaScript. Unlike JS, Laravel has more stable and less frequent updates.</p>
<p>The PHP ecosystem receives fewer updates so developers can reliably use the existing features without worrying about another framework or library providing a better solution or another version.</p>
<p>A new framework or library doesn't pop up each week. You don't need to follow up on versions frequently.</p>
<h3 id="heading-a-massive-community">A Massive Community</h3>
<p>Laravel was first launched a decade ago. It has gained popularity over time and invited many developers to create communities and share ideas.</p>
<p>Every PHP developer uses Laravel. If you ever need any help, you always have developers helping you.</p>
<h3 id="heading-free-solutions">Free Solutions</h3>
<p>Most PHP frameworks and libraries are open-source and free to access. Startups are rare in the PHP ecosystem.</p>
<p>If a developer is offering any bespoke solutions, most are public, especially free.</p>
<p>Any PHP developer can refer to those open-source free solutions, contribute to them, and extend those solutions further.</p>
<h2 id="heading-differences-between-laravel-and-js-tools">Differences Between Laravel and JS Tools</h2>
<p>You can create any type of application using both of these technologies. But the experience won't be exactly the same, of course. Here are some of the differences:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Features</td><td>JavaScript Frameworks</td><td>Laravel</td></tr>
</thead>
<tbody>
<tr>
<td>Beginner Friendly</td><td>They often use TypeScript, which is beginner-friendly and beneficial for developers switching from C, C#, Java, and C++</td><td>Laravel is easier to adopt if you have a grasp of PHP or other JavaScript frameworks.</td></tr>
<tr>
<td>Flexibility</td><td>High flexibility with the ability to choose different tools and libraries.</td><td>Less flexibility but provides a cohesive, opinionated structure.</td></tr>
<tr>
<td>Salary</td><td>Developers using JavaScript frameworks have higher salaries.</td><td>Laravel developers get a generally lower salary than JavaScript/TypeScript developers.</td></tr>
<tr>
<td>Availability of tools</td><td>JavaScript frameworks are widely available and ready-to-use. You can download them from the NPM registry and start immediately.</td><td>Laravel offers solutions for a wide range of problems, but if you encounter issues with their built-in solutions, you have fewer alternatives.</td></tr>
<tr>
<td>Security</td><td>Depends on the back-end setup of the respective framework, but there are options to choose from if the security measures lack.</td><td>It has built-in security features like CSRF and encryption.</td></tr>
<tr>
<td>Documentation</td><td>Depends on the framework. React, NextJS, and a few other frameworks have the most detailed documentations with code snippets and explanations.</td><td>Laravel has a structured and organised documentation with code snippets and explanations.</td></tr>
<tr>
<td>Testing &amp; Debugging</td><td>JavaScript frameworks have multiple testing libraries, like Jest.</td><td>Laravel has built-in tools, like PHPUnit intergration for testing.</td></tr>
<tr>
<td>Learning Curve</td><td>JavaScript frameworks have a higher learning curve due to frequent and significant updates, as well as the regular release of new frameworks.</td><td>Laravel has a gentle learning curve because its built-in solutions are easy to adopt, even for those familiar with JavaScript frameworks.</td></tr>
<tr>
<td>Scalability</td><td>JavaScript frameworks are highly scalable, allowing you to swap libraries as needed to maximize performance.</td><td>Laravel has limited options to modify and swap solutions. Hence, it is less scalable, but reliable.</td></tr>
<tr>
<td>Deployment &amp; Hosting</td><td>JavaScript frameworks can be deployed with any VPS, or using Vercel with a few clicks. However, it requires NodeJS on the server.</td><td>Laravel projects can be hosted on any server supporting PHP.</td></tr>
<tr>
<td>Customization</td><td>JavaScript frameworks allow for easy swapping and customization, enabling you to tailor libraries or frameworks to suit your needs.</td><td>Laravel solutions are limited and cannot be modified.</td></tr>
<tr>
<td>Performance</td><td>JavaScript frameworks have high-performance for dynamic, interactive Uls.</td><td>Laravel has high-performance for back-end processes and server-side rendering.</td></tr>
<tr>
<td>Future</td><td>JavaScript frameworks continue to grow, with more startups being founded and developers launching their own solutions.</td><td>Laravel continuously evolves, releasing new sub-frameworks and solutions to address problems in the most effective way possible.</td></tr>
</tbody>
</table>
</div><p>And that's it! I hope you enjoyed the article and learned something new. If you want, you can also follow me on <a target="_blank" href="https://x.com/whyafan">Twitter</a> (X) or <a target="_blank" href="https://www.linkedin.com/in/khanafan/">LinkedIn</a>. Also, I've built a <a target="_blank" href="https://store.afankhan.com/l/codenexus">Notion Dashboard</a> for Software Engineers to ace their coding interviews.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ PHP Array Handbook – How to Create, Work with, and Loop Through Arrays ]]>
                </title>
                <description>
                    <![CDATA[ In every programming language, arrays provide a flexible option to store more than one data type in a single variable. They are one of the most versatile data structures in the programming world, which is one reason a lot of external data and many AP... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/php-array-handbook/</link>
                <guid isPermaLink="false">66adf1bb6992d2a84c5d7936</guid>
                
                    <category>
                        <![CDATA[ arrays ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kolade Chris ]]>
                </dc:creator>
                <pubDate>Wed, 08 May 2024 22:25:55 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/PHP-Array-Handbook-Cover-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In every programming language, arrays provide a flexible option to store more than one data type in a single variable. They are one of the most versatile data structures in the programming world, which is one reason a lot of external data and many APIs come as arrays.</p>
<p>When you create an array in PHP, you'll want to be able to use it. To do so, you have to manipulate or loop through it. PHP provides several built-in functions for manipulating arrays and several ways to loop through arrays.</p>
<p>Understanding and utilizing those built-in functions and loops is essential for efficient array manipulation. With them, you'll save time, write cleaner code, and become a more efficient PHP developer.</p>
<p>Note that this is the first part of a two-article series. The second part will focus on how to use MongoDB in PHP by rebuilding the Football Team Cards project. The footballers will come from a MongoDB Atlas database. We will then fetch them as arrays and display them on the page.</p>
<h2 id="heading-what-well-cover">What We'll Cover</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-create-arrays-in-php">How to Create Arrays in PHP</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-create-arrays-with-the-array-function">How to Create Arrays with the Array Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-arrays-with-the-square-bracket-syntax">How to Create Arrays with the Square Bracket Syntax</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-print-arrays-in-php">How to Print Arrays in PHP</a></p>
<ul>
<li><p><a class="post-section-overview" href="#howtoprintanarraywiththeprintrfunction">How to Print an Array with the <code>print_r()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#howtoprintanarraywiththevardumpfunction">How to Print an Array with the var_dump() Function</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-php-array-functions">PHP Array Functions</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-the-count-array-function">The <code>count()</code> Array Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#thearraypush_arrayfunction">The <code>array_push()</code> Array Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arraypop-function">The <code>array_pop()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arrayshift-function">The <code>array_shift()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arrayunshift-function">The <code>array_unshift()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arraysplice-function">The <code>array_splice()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arraykeys-function">The <code>array_keys()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arrayvalues-function">The <code>array_values()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arrayreduce-function">The <code>array_reduce()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-sort-function">The <code>sort()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-rsort-function">The <code>rsort()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arrayreplace-function">The <code>array_replace()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arrayreverse-function">The <code>array_reverse()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arrayslice-function">The <code>array_slice()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arraysum-function">The <code>array_sum()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arraymerge-function">The <code>array_merge()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arrayfilter-function">The <code>array_filter()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#thearraymap_function">The <code>array_map()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-arraysearch-function">The <code>array_search()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#thearraycolumnfunction">The <code>array_column()</code> Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-inarray-function">The <code>in_array()</code> Function</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-loop-through-arrays-in-php">How to Loop Through Arrays in PHP</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-loop-through-an-indexed-array">How to Loop through an Indexed Array</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-loop-through-an-associative-array">How to Loop through an Associative Array</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-loop-through-an-array-inside-the-html-template">How to Loop through an Array Inside the HTML Template</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-how-to-create-arrays-in-php">How to Create Arrays in PHP</h2>
<p>In PHP, arrays exist in 3 forms:</p>
<ul>
<li><p><strong>indexed</strong> – a regular array with predefined indexes</p>
</li>
<li><p><strong>multidimensional</strong> – an array with arrays within it</p>
</li>
<li><p><strong>associative</strong> – an array with string indexes</p>
</li>
</ul>
<p>There are two ways you can create any of those 3 forms of arrays in PHP. You can either use the <code>Array()</code> function or the square brackets syntax (<code>[ ]</code>).</p>
<h3 id="heading-how-to-create-arrays-with-the-array-function">How to Create Arrays with the Array Function</h3>
<p>To create a PHP array with the <code>array()</code> function, just pass the elements into the function.</p>
<p>Here's the catch:</p>
<ul>
<li><p>a <strong>regular array</strong> is created with the <code>array()</code> function by passing the elements directly into the function</p>
</li>
<li><p>a <strong>multidimensional array</strong> is created with the <code>array()</code> function by nesting one or more <code>array()</code> functions inside one <code>array()</code> function</p>
</li>
<li><p>an <strong>associative array</strong> is created with the <code>array()</code> function by separating the key and values with a fat arrow (<code>=&gt;</code>) and separating each entry with a comma</p>
</li>
</ul>
<p>Here's examples of all of them in code:</p>
<pre><code class="lang-php"><span class="hljs-comment">// regular array with the array function</span>
$myFruitsArr1 = <span class="hljs-keyword">array</span>(<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>);


<span class="hljs-comment">// multidimensional array with the array function</span>
$myFruitsArr2 = <span class="hljs-keyword">array</span>(
 <span class="hljs-keyword">array</span>(<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Avocado"</span>, <span class="hljs-string">"Apricot"</span>),
 <span class="hljs-keyword">array</span>(<span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Blackeberry"</span>, <span class="hljs-string">"Babaco"</span>),
 <span class="hljs-keyword">array</span>(<span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Cherry"</span>, <span class="hljs-string">"Canary melon"</span>),
 <span class="hljs-keyword">array</span>(<span class="hljs-string">"Mango"</span>, <span class="hljs-string">"Melon"</span>, <span class="hljs-string">"Miracle fruit"</span>),
);


<span class="hljs-comment">// associative array with the array function</span>
$myFruitsArr3 = <span class="hljs-keyword">array</span>(
 <span class="hljs-string">"fruit 1"</span> =&gt; <span class="hljs-string">"Apple"</span>,
 <span class="hljs-string">"fruit 2"</span> =&gt; <span class="hljs-string">"Banana"</span>,
 <span class="hljs-string">"fruit 3"</span> =&gt; <span class="hljs-string">"Cashew"</span>,
 <span class="hljs-string">"fruit 4"</span> =&gt; <span class="hljs-string">"Mango"</span>,
);
</code></pre>
<h3 id="heading-how-to-create-arrays-with-the-square-bracket-syntax">How to Create Arrays with the Square Bracket Syntax</h3>
<p>The square bracket syntax is the most common way to create an array in PHP (and JavaScript as well).</p>
<p>To create an array with the square bracket syntax, replace every occurrence of <code>array()</code> with opening and closing square brackets:</p>
<pre><code class="lang-php"><span class="hljs-comment">// regular array with the square bracket syntax</span>
$myFruitsArr1 = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];


<span class="hljs-comment">// multidimensional array with the square bracket syntax</span>
$myFruitsArr2 = [
 [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Avocado"</span>, <span class="hljs-string">"Apricot"</span>],
 [<span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Blackeberry"</span>, <span class="hljs-string">"Babaco"</span>],
 [<span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Cherry"</span>, <span class="hljs-string">"Canary melon"</span>],
 [<span class="hljs-string">"Mango"</span>, <span class="hljs-string">"Melon"</span>, <span class="hljs-string">"Miracle fruit"</span>],
];


<span class="hljs-comment">// associative array with the square bracket syntax</span>
$myFruitsArr3 = [
 <span class="hljs-string">"fruit 1"</span> =&gt; <span class="hljs-string">"Apple"</span>,
 <span class="hljs-string">"fruit 2"</span> =&gt; <span class="hljs-string">"Banana"</span>,
 <span class="hljs-string">"fruit 3"</span> =&gt; <span class="hljs-string">"Cashew"</span>,
 <span class="hljs-string">"fruit 4"</span> =&gt; <span class="hljs-string">"Mango"</span>,
];
</code></pre>
<h2 id="heading-how-to-print-arrays-in-php">How to Print Arrays in PHP</h2>
<p>Most times, you might need to print an array for debugging or visual purposes. PHP provides the <code>echo</code> statement, <code>print_r()</code>, and <code>var_dump()</code> functions for printing data.</p>
<p><code>echo</code> does not print an array as it should because it is meant for printing strings, integers, and floats. You should use <code>print_r()</code> and <code>var_dump()</code> to print arrays instead.</p>
<h3 id="heading-how-to-print-an-array-with-the-printr-function">How to Print an Array with the <code>print_r()</code> Function</h3>
<p>The <code>print_r()</code> function displays structured information about a variable in a human-readable format.</p>
<p><code>print_r()</code> is particularly useful for displaying and inspecting the contents of complex data structures like arrays and objects. You use it by passing the array identifier into it:</p>
<pre><code class="lang-php">print_r($myFruitsArr1);
print_r($myFruitsArr2);
print_r($myFruitsArr3);
</code></pre>
<p>Even if the array or object has nested elements, <code>print_r()</code> will traverse the entire array or object and display the content without missing any elements.</p>
<p>Here's what each of the 3 types of arrays looks like when you print them with the <code>print_r()</code> function:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image6-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Regular, multidimensional, and associative array examples.</em></p>
<h3 id="heading-how-to-print-an-array-with-the-vardump-function">How to Print an Array with the <code>var_dump()</code> Function</h3>
<p>The <code>var_dump()</code> function lets you print an array or variable like the <code>print_r()</code> function. What it does differently is that it displays the data type of what you're printing, including each element of the array.</p>
<p>Here's how to use the <code>var_dump()</code> function:</p>
<pre><code class="lang-php">var_dump($myFruitsArr1);
var_dump($myFruitsArr2);
var_dump($myFruitsArr3);
</code></pre>
<p>And here's what each of the 3 types of array looks like when you print them with the <code>var_dump()</code> function:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Regular, multidimensional, and associative arrays printed with var_dump()</em></p>
<h2 id="heading-php-array-functions">PHP Array Functions</h2>
<p>PHP provides a rich variety of array functions. They allow you to perform a wide range of operations on arrays, from basic manipulation to advanced data processing.</p>
<p>There are more than 70 array functions you can use in PHP, so we won't be able to cover all of them in this handbook.</p>
<p>Here are the ones we’ll cover:</p>
<ul>
<li><p><code>count()</code></p>
</li>
<li><p><code>array_push()</code></p>
</li>
<li><p><code>array_pop()</code></p>
</li>
<li><p><code>array_shift()</code></p>
</li>
<li><p><code>array_unshift()</code></p>
</li>
<li><p><code>array_splice()</code></p>
</li>
<li><p><code>array_keys()</code></p>
</li>
<li><p><code>array_values()</code></p>
</li>
<li><p><code>array_reduce()</code></p>
</li>
<li><p><code>sort()</code></p>
</li>
<li><p><code>rsort()</code></p>
</li>
<li><p><code>array_replace()</code></p>
</li>
<li><p><code>array_reverse()</code></p>
</li>
<li><p><code>array_slice()</code></p>
</li>
<li><p><code>array_sum()</code></p>
</li>
<li><p><code>array_merge()</code></p>
</li>
<li><p><code>array_filter()</code></p>
</li>
<li><p><code>array_map()</code></p>
</li>
<li><p><code>array_search()</code></p>
</li>
<li><p><code>array_column()</code></p>
</li>
<li><p><code>in_array()</code></p>
</li>
</ul>
<h3 id="heading-the-count-array-function">The <code>count()</code> Array Function</h3>
<p>The <code>count()</code> function does what its name implies — it goes through an array, counts the items, and returns an integer representing the array's length.</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
<span class="hljs-keyword">echo</span> count($myFruitsArr); <span class="hljs-comment">// 4</span>
</code></pre>
<p><code>count()</code> can be helpful if you want to do something based on the length of a particular array:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];


<span class="hljs-keyword">if</span> (count($myFruitsArr) === <span class="hljs-number">4</span>) {
 <span class="hljs-keyword">echo</span> <span class="hljs-string">"The fruits are enough"</span>;
} <span class="hljs-keyword">else</span> {
 <span class="hljs-keyword">echo</span> <span class="hljs-string">"The fruits are not enough"</span>;
}


<span class="hljs-comment">// The fruits are enough</span>
</code></pre>
<p>Because <code>count()</code> gets the length of an array, its commonly used in loops:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];


<span class="hljs-keyword">for</span> ($i = <span class="hljs-number">0</span>; $i &lt; count($myFruitsArr); $i++) {
 <span class="hljs-keyword">echo</span> $myFruitsArr[$i] . <span class="hljs-string">"&lt;br&gt;"</span>;
}


<span class="hljs-comment">/*
Output:


Apple
Banana
Cashew
Mango
*/</span>
</code></pre>
<h3 id="heading-the-arraypush-array-function">The <code>array_push()</code> Array Function</h3>
<p><code>array_push()</code> “pushes” an element to the end of the array. That is, it adds a specified item after the last item in the array. This means it modifies the original array.</p>
<p><code>array_push</code> takes a compulsory <code>array</code> argument and the element you want to push into the existing array:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];


array_push($myFruitsArr, <span class="hljs-string">"Avocado"</span>);
print_r($myFruitsArr); <span class="hljs-comment">// Array ( [0] =&gt; Apple [1] =&gt; Banana [2] =&gt; Cashew [3] =&gt; Mango [4] =&gt; Avocado )</span>
</code></pre>
<p>You can echo out the <code>&lt;pre&gt;</code> tag to format the resulting array better:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];


array_push($myFruitsArr, <span class="hljs-string">"Avocado"</span>);
<span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;pre&gt;"</span>;
var_dump($myFruitsArr);
<span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;pre&gt;"</span>;


<span class="hljs-comment">/*
Output:


array(5) {
 [0]=&gt;
 string(5) "Apple"
 [1]=&gt;
 string(6) "Banana"
 [2]=&gt;
 string(6) "Cashew"
 [3]=&gt;
 string(5) "Mango"
 [4]=&gt;
 string(7) "Avocado"
}
*/</span>
</code></pre>
<p>You can also push two or more items:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];


array_push($myFruitsArr, <span class="hljs-string">"Avocado"</span>, <span class="hljs-string">"Pineapple"</span>);
<span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;pre&gt;"</span>;
var_dump($myFruitsArr);
<span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;pre&gt;"</span>;


<span class="hljs-comment">/*
Output:


array(6) {
 [0]=&gt;
 string(5) "Apple"
 [1]=&gt;
 string(6) "Banana"
 [2]=&gt;
 string(6) "Cashew"
 [3]=&gt;
 string(5) "Mango"
 [4]=&gt;
 string(7) "Avocado"
 [5]=&gt;
 string(9) "Pineapple"
}
*/</span>
</code></pre>
<h3 id="heading-the-arraypop-function">The <code>array_pop()</code> Function</h3>
<p><code>array_pop()</code> does the opposite of what <code>array_push()</code> does – <strong>it removes an element from the end of the array</strong>. That means it can be useful in stack-based data structures.</p>
<p>To use the <code>array_pop()</code> function, you only need to pass in the array you want to remove from:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
array_pop($myFruitsArr);


<span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;pre&gt;"</span>;
var_dump($myFruitsArr);
<span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;pre&gt;"</span>;


<span class="hljs-comment">/*
Mango is gone:


array(3) {
 [0]=&gt;
 string(5) "Apple"
 [1]=&gt;
 string(6) "Banana"
 [2]=&gt;
 string(6) "Cashew"
}
*/</span>
</code></pre>
<p>You can echo out the popped element because <code>array_pop()</code> modifies the original array:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
$poppedElem = array_pop($myFruitsArr);


<span class="hljs-keyword">echo</span> $poppedElem; <span class="hljs-comment">// Mango</span>
</code></pre>
<h3 id="heading-the-arrayshift-function">The <code>array_shift()</code> Function</h3>
<p><code>array_shift()</code> is like <code>array_pop</code>, but it removes the first element of an array and not the last. So, it's helpful in queue-based data structures.</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
array_shift($myFruitsArr);
var_dump($myFruitsArr);


<span class="hljs-comment">/*
Apple is gone:


array(3) {
 [0]=&gt;
 string(6) "Banana"
 [1]=&gt;
 string(6) "Cashew"
 [2]=&gt;
 string(5) "Mango"
}
*/</span>
</code></pre>
<p>Because the <code>array_shift()</code> function modifies the original array, it reorders the indices:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];


<span class="hljs-keyword">echo</span> <span class="hljs-string">"before shift: "</span>;
var_dump($myFruitsArr);


<span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;br&gt;"</span>;


<span class="hljs-keyword">echo</span> <span class="hljs-string">"after shift: "</span>;
array_shift($myFruitsArr);
var_dump($myFruitsArr);
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Before and after using the shift() function</em></p>
<p><code>array_shift()</code> also returns the removed array because it modifies the original array:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
$shiftedElem = array_shift($myFruitsArr);

<span class="hljs-keyword">echo</span> $shiftedElem; <span class="hljs-comment">// Apple</span>
</code></pre>
<h3 id="heading-the-arrayunshift-function">The <code>array_unshift()</code> Function</h3>
<p>The <code>array_unshift()</code> function adds one or more elements to the beginning of an array. It modifies the original array by inserting the new elements at the start and re-indexing the existing elements.</p>
<p>It takes the array you want to add to and the element you want to add as the arguments. You can use it without providing the element to add to the beginning of the array, but it is advised not to do so.</p>
<p>Here’s an example:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
array_unshift($myFruitsArr, <span class="hljs-string">"Avocado"</span>);

var_dump($myFruitsArr);

<span class="hljs-comment">/*
array(5) {
 [0]=&gt;
 string(7) "Avocado"
 [1]=&gt;
 string(5) "Apple"
 [2]=&gt;
 string(6) "Banana"
 [3]=&gt;
 string(6) "Cashew"
 [4]=&gt;
 string(5) "Mango"
}
*/</span>
</code></pre>
<h3 id="heading-the-arraysplice-function">The <code>array_splice()</code> Function</h3>
<p>The <code>array_splice()</code> method removes an item from an array and replaces it with the specified replacement. <code>array_splice()</code> modifies the original array, so it returns that removed item.</p>
<p><code>array_splice()</code> takes up to 4 arguments, as you can see in its basic syntax below:</p>
<pre><code class="lang-php">array_splice(<span class="hljs-keyword">array</span>, startingIndex, length, replacement)
</code></pre>
<ul>
<li><p><code>array</code> is the array you’re using the <code>array_splice()</code> function on</p>
</li>
<li><p><code>startingIndex</code> is the position where you want to start removing the item(s) in the array. That means if you specify <code>0</code>, it will remove the first element in the array.</p>
</li>
<li><p><code>length</code> is how far you want the splicing to go. For instance, if you specify <code>2</code>, two items will be removed starting from the specified <code>startingIndex</code></p>
</li>
<li><p><code>replacement</code> is the item that will replace the item to be removed. This could be a single item or another array.</p>
</li>
</ul>
<p>Here’s an example with an array and a string replacement:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
$splicedItem = array_splice($myFruitsArr, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-string">"Avocado"</span>);

var_dump($myFruitsArr);

<span class="hljs-comment">/*
Output:

array(4) {
 [0]=&gt;
 string(5) "Apple"
 [1]=&gt;
 string(7) "Avocado"
 [2]=&gt;
 string(6) "Cashew"
 [3]=&gt;
 string(5) "Mango"
}
*/</span>
<span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;br&gt;"</span>;

var_dump($splicedItem);

<span class="hljs-comment">/*
Output:
array(1) {
 [0]=&gt;
 string(6) "Banana"
}
*/</span>
</code></pre>
<p>Here’s another example with an array as the replacement:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
$splicedItem = array_splice($myFruitsArr, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-keyword">array</span>(<span class="hljs-string">"Avocado"</span>, <span class="hljs-string">"Apricot"</span>, <span class="hljs-string">"Abiu"</span>));

var_dump($myFruitsArr);
<span class="hljs-comment">/*
Output:

array(6) {
 [0]=&gt;
 string(5) "Apple"
 [1]=&gt;
 string(7) "Avocado"
 [2]=&gt;
 string(7) "Apricot"
 [3]=&gt;
 string(4) "Abiu"
 [4]=&gt;
 string(6) "Cashew"
 [5]=&gt;
 string(5) "Mango"
}
*/</span>

var_dump($splicedItem);
<span class="hljs-comment">/*
Output:

array(1) {
 [0]=&gt;
 string(6) "Banana"
}
*/</span>
</code></pre>
<h3 id="heading-the-arraykeys-function">The <code>array_keys()</code> Function</h3>
<p>There are two components in every array – the keys and the values. For a regular array, the keys are the indexes. For an associative array, the keys are the indices specified for each array item.</p>
<p>The <code>array_keys</code> function extracts the keys of the items in an array.</p>
<p>If the array is a regular array, it lists the indices of the array as the keys:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
$myFruitsArrKeys = array_keys($myFruitsArr);

print_r($myFruitsArrKeys);
<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; 0
   [1] =&gt; 1
   [2] =&gt; 2
   [3] =&gt; 3
)
*/</span>
</code></pre>
<p>If the array is an associative array, it lists out the keys you specified for each item in the array:</p>
<pre><code class="lang-php">$myFruitsWithColors = [
 <span class="hljs-string">"apple"</span> =&gt; <span class="hljs-string">"red"</span>,
 <span class="hljs-string">"banana"</span> =&gt; <span class="hljs-string">"yellow"</span>,
 <span class="hljs-string">"orange"</span> =&gt; <span class="hljs-string">"orange"</span>,
 <span class="hljs-string">"grape"</span> =&gt; <span class="hljs-string">"purple"</span>,
 <span class="hljs-string">"watermelon"</span> =&gt; <span class="hljs-string">"green"</span>,
];

$myFruitsWithColorsKeys = array_keys($myFruitsWithColors);

print_r($myFruitsWithColorsKeys);
<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; apple
   [1] =&gt; banana
   [2] =&gt; orange
   [3] =&gt; grape
   [4] =&gt; watermelon
)
*/</span>
</code></pre>
<p><code>array_keys()</code> can accept a second argument. This is usually an item in the array.</p>
<p>If you specify an item as that second argument, <code>array_keys()</code> will return the key for that item only:</p>
<pre><code class="lang-php">$myFruitsWithColors = [
 <span class="hljs-string">"apple"</span> =&gt; <span class="hljs-string">"red"</span>,
 <span class="hljs-string">"banana"</span> =&gt; <span class="hljs-string">"yellow"</span>,
 <span class="hljs-string">"orange"</span> =&gt; <span class="hljs-string">"orange"</span>,
 <span class="hljs-string">"grape"</span> =&gt; <span class="hljs-string">"purple"</span>,
 <span class="hljs-string">"watermelon"</span> =&gt; <span class="hljs-string">"green"</span>,
];

$myFruitsWithColorsKeys = array_keys($myFruitsWithColors, <span class="hljs-string">"orange"</span>);

print_r($myFruitsWithColorsKeys);
<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; orange
)
*/</span>
</code></pre>
<h3 id="heading-the-arrayvalues-function">The <code>array_values()</code> Function</h3>
<p>The <code>array_values()</code> function extracts the other part of an array – the values.</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
$myFruitsArrValues = array_values($myFruitsArr);

print_r($myFruitsArrValues);

<span class="hljs-comment">/*
Output:
Array
(
   [0] =&gt; Apple
   [1] =&gt; Banana
   [2] =&gt; Cashew
   [3] =&gt; Mango
)
*/</span>
</code></pre>
<p>The output of <code>array_values()</code> looks like what happens when you print a regular array with the <code>print_r()</code> function, but it’s not. What happens is it also assigns indices to those printed values.</p>
<p>An example with an associative array would make that clearer:</p>
<pre><code class="lang-php">$myFruitsWithColors = [
 <span class="hljs-string">"apple"</span> =&gt; <span class="hljs-string">"red"</span>,
 <span class="hljs-string">"banana"</span> =&gt; <span class="hljs-string">"yellow"</span>,
 <span class="hljs-string">"orange"</span> =&gt; <span class="hljs-string">"orange"</span>,
 <span class="hljs-string">"grape"</span> =&gt; <span class="hljs-string">"purple"</span>,
 <span class="hljs-string">"watermelon"</span> =&gt; <span class="hljs-string">"green"</span>,
];

$myFruitsWithColorsValues = array_values($myFruitsWithColors);
print_r($myFruitsWithColorsValues);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; red
   [1] =&gt; yellow
   [2] =&gt; orange
   [3] =&gt; purple
   [4] =&gt; green
)
*/</span>
</code></pre>
<h3 id="heading-the-arrayreduce-function">The <code>array_reduce()</code> Function</h3>
<p>The <code>array_reduce()</code> function is used to "reduce" an array to a single value by applying a callback function to each element of the array. It works like the <code>reduce()</code> array method of JavaScript.</p>
<p><code>array_reduce()</code> iterates through the array and performs the callback function on each element, accumulating a single result.</p>
<p>That means you can use it for data aggregation and computation, like calculating the total value of items in a shopping cart.</p>
<p><code>array_reduce()</code> takes 2 required arguments and 1 optional argument. Here’s the syntax:</p>
<pre><code class="lang-php">array_reduce(arraytoReduce, callbackFunction, initialValue)
</code></pre>
<ul>
<li><p><code>arrayToReduce</code> is the array you’re using <code>reduce</code> on</p>
</li>
<li><p><code>callbackFunction</code> is the function that will “reduce” the items of the array into a single value</p>
</li>
<li><p><code>initialValue</code> is optional. It specifies the initial value of the accumulator. If provided, it will be used as the initial value for the first call to the callback function. If not provided, the first element of the array will be used as the initial accumulator value.</p>
</li>
</ul>
<p><code>array_reduce()</code> is usually used with numbers:</p>
<pre><code class="lang-php">$myNumbers = [<span class="hljs-number">5</span>, <span class="hljs-number">89</span>, <span class="hljs-number">19</span>, <span class="hljs-number">10</span>, <span class="hljs-number">49</span>];

$total = array_reduce($myNumbers, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$carry, $item</span>) </span>{
 <span class="hljs-keyword">return</span> $carry + $item;
}, <span class="hljs-number">0</span>);

<span class="hljs-keyword">echo</span> $total; <span class="hljs-comment">// 172</span>
</code></pre>
<p>You can extract that callback function into a separate function and pass it in as one of the arguments of the <code>array_reduce()</code> function:</p>
<pre><code class="lang-php">$myNumbers = [<span class="hljs-number">5</span>, <span class="hljs-number">89</span>, <span class="hljs-number">19</span>, <span class="hljs-number">10</span>, <span class="hljs-number">49</span>];


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addNums</span>(<span class="hljs-params">$carry, $item</span>)
</span>{
 <span class="hljs-keyword">return</span> $carry + $item;
}

$total = array_reduce($myNumbers, <span class="hljs-string">'addNums'</span>, <span class="hljs-number">0</span>);

<span class="hljs-keyword">echo</span> $total; <span class="hljs-comment">// 172</span>
</code></pre>
<p><code>array_reduce()</code> also works with strings:</p>
<pre><code class="lang-php">$words = [<span class="hljs-string">"Hello"</span>, <span class="hljs-string">"camper!"</span>, <span class="hljs-string">"How"</span>, <span class="hljs-string">"are"</span>, <span class="hljs-string">"you"</span>, <span class="hljs-string">"today?"</span>];

<span class="hljs-comment">// Use array_reduce to concatenate all the strings</span>
$result = array_reduce($words, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$carry, $item</span>) </span>{
 <span class="hljs-keyword">return</span> $carry . <span class="hljs-string">" "</span> . $item;
}, <span class="hljs-string">""</span>);

<span class="hljs-keyword">echo</span> $result; <span class="hljs-comment">//  Hello camper! How are you today?</span>
</code></pre>
<h3 id="heading-the-sort-function">The <code>sort()</code> Function</h3>
<p>The <code>sort()</code> function takes an array and sorts it in ascending order based on the values of its items. It modifies the original array by rearranging its elements in ascending order.</p>
<p>If you have some data in an array that you want to organize in ascending order, the <code>sort()</code> function is perfect for that.</p>
<pre><code class="lang-php">$myNums = [<span class="hljs-number">4</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>];
sort($myNums);

print_r($myNums);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; 1
   [1] =&gt; 2
   [2] =&gt; 3
   [3] =&gt; 4
   [4] =&gt; 5
)
*/</span>
</code></pre>
<h3 id="heading-the-rsort-function">The <code>rsort()</code> Function</h3>
<p>The <code>rsort()</code> function is similar to <code>sort()</code>, but it sorts the array in descending order instead of ascending order.</p>
<pre><code class="lang-php">$myNums = <span class="hljs-keyword">array</span>(<span class="hljs-number">4</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>);
rsort($myNums);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; 5
   [1] =&gt; 4
   [2] =&gt; 3
   [3] =&gt; 2
   [4] =&gt; 1
)
*/</span>

print_r($myNums);
</code></pre>
<h3 id="heading-the-arrayreplace-function">The <code>array_replace()</code> Function</h3>
<p>The <code>array_replace()</code> function is used to replace the values of the first array with the values of a provided array. It's perfect for updating data.</p>
<p><code>array_replace()</code> takes two arguments – the array you want to replace, and the new array.</p>
<pre><code class="lang-php">$myNamesArr1 = [<span class="hljs-string">"Zen"</span>, <span class="hljs-string">"Kay"</span>, <span class="hljs-string">"Luger"</span>];
$myNamesArr2 = [<span class="hljs-string">"Yuan"</span>, <span class="hljs-string">"Jay"</span>, <span class="hljs-string">"John"</span>];

$replaceRes = array_replace($myNamesArr1, $myNamesArr2);

print_r($replaceRes);

<span class="hljs-comment">/*
Output:
Array
(
   [0] =&gt; Yuan
   [1] =&gt; Jay
   [2] =&gt; John
)
*/</span>
</code></pre>
<p>If you don’t provide a second value, it returns the only argument you provide:</p>
<pre><code class="lang-php">$myNamesArr1 = [<span class="hljs-string">"Zen"</span>, <span class="hljs-string">"Kay"</span>, <span class="hljs-string">"Luger"</span>];
$myNamesArr2 = [<span class="hljs-string">"Yuan"</span>, <span class="hljs-string">"Jay"</span>, <span class="hljs-string">"John"</span>];

$replaceRes = array_replace($myNamesArr1);

print_r($replaceRes);

<span class="hljs-comment">/*
Output:
Array
(
   [0] =&gt; Zen
   [1] =&gt; Kay
   [2] =&gt; Luger
)
*/</span>
</code></pre>
<p>If you pass in three or more arrays as the arguments, the last argument will be the replacement for the first one, not the second:</p>
<pre><code class="lang-php">$myNamesArr1 = [<span class="hljs-string">"Zen"</span>, <span class="hljs-string">"Kay"</span>, <span class="hljs-string">"Luger"</span>];
$myNamesArr2 = [<span class="hljs-string">"Yuan"</span>, <span class="hljs-string">"Jay"</span>, <span class="hljs-string">"John"</span>];
$myNamesArr3 = [<span class="hljs-string">"Eddy"</span>, <span class="hljs-string">"White"</span>, <span class="hljs-string">"Jane"</span>];


$replaceRes = array_replace($myNamesArr1, $myNamesArr2, $myNamesArr3);

print_r($replaceRes);

<span class="hljs-comment">/*
Output:
Array
(
   [0] =&gt; Eddy
   [1] =&gt; White
   [2] =&gt; Jane
)
*/</span>
</code></pre>
<p>You can selectively replace an item in a particular index too:</p>
<pre><code class="lang-php">$myFruitsArr1 = [<span class="hljs-string">"a"</span> =&gt; <span class="hljs-string">"apple"</span>, <span class="hljs-string">"b"</span> =&gt; <span class="hljs-string">"banana"</span>, <span class="hljs-string">"c"</span> =&gt; <span class="hljs-string">"cherry"</span>];
$myFruitsArr2 = <span class="hljs-keyword">array</span>(<span class="hljs-string">"b"</span> =&gt; <span class="hljs-string">"blueberry"</span>, <span class="hljs-string">"c"</span> =&gt; <span class="hljs-string">"cranberry"</span>);
$replaceRes = array_replace($myFruitsArr1, $myFruitsArr2);

print_r($replaceRes);

<span class="hljs-comment">/*
Output:
Array
(
   [a] =&gt; apple
   [b] =&gt; blueberry
   [c] =&gt; cranberry
)
*/</span>
</code></pre>
<h3 id="heading-the-arrayreverse-function">The <code>array_reverse()</code> Function</h3>
<p>The <code>array_reverse()</code> function is used to reverse the order of elements in an array. It creates a new array with the elements in reverse order.</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
$reversedArr = array_reverse($myFruitsArr);

print_r($reversedArr);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; Mango
   [1] =&gt; Cashew
   [2] =&gt; Banana
   [3] =&gt; Apple
)
*/</span>
</code></pre>
<p>If you remember how the <code>rsort()</code> function works, it’s very similar to how <code>array_reverse()</code> works. The only difference is that <code>rsort()</code> modifies the original array, but <code>array_reverse()</code> does not.</p>
<h3 id="heading-the-arrayslice-function">The <code>array_slice()</code> Function</h3>
<p>If you want to extract a particular part of an array and return it as a separate array, <code>array_slice()</code> is the ideal function for you to use.</p>
<p><code>array_slice()</code> allows you to specify the start index, the length of the slice, and whether to preserve the keys of the original array. Here’s the basic syntax:</p>
<pre><code class="lang-php">array_slice(arrayToSlice, startIndex, length, preserve)
</code></pre>
<ul>
<li><p><code>arrayToSlice</code> is the array you want to use <code>array_slice()</code> on</p>
</li>
<li><p><code>startIndex</code> is the index you want to start the slicing from</p>
</li>
<li><p><code>length</code> is how far you want the slicing to go in the <code>arrayToSlice</code>. It is optional.</p>
</li>
<li><p><code>preserve</code> specifies whether you want the index(es) of the array to change or not. It’s a boolean.</p>
</li>
</ul>
<p>The example below starts the slicing from the second element in the array, which means it’ll leave the first element out and return the others:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>, <span class="hljs-string">"Avocado"</span>, <span class="hljs-string">"Pineapple"</span>];
$slicedArr = array_slice($myFruitsArr, <span class="hljs-number">1</span>);

print_r($slicedArr);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; Banana
   [1] =&gt; Cashew
   [2] =&gt; Mango
   [3] =&gt; Avocado
   [4] =&gt; Pineapple
)
*/</span>
</code></pre>
<p>Don’t forget you can specify the number of items you want from the slicing by specifying a third optional argument:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>, <span class="hljs-string">"Avocado"</span>, <span class="hljs-string">"Pineapple"</span>];
$slicedArr = array_slice($myFruitsArr, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>);

print_r($slicedArr);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; Banana
   [1] =&gt; Cashew
   [2] =&gt; Mango
)
*/</span>
</code></pre>
<p>If you want to preserve the indexes, you can specify a fourth optional boolean argument of <code>true</code>:</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>, <span class="hljs-string">"Avocado"</span>, <span class="hljs-string">"Pineapple"</span>];
$slicedArr = array_slice($myFruitsArr, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-literal">true</span>);

print_r($slicedArr);

<span class="hljs-comment">/*
Output:

Array
(
   [1] =&gt; Banana
   [2] =&gt; Cashew
   [3] =&gt; Mango
)
*/</span>
</code></pre>
<h3 id="heading-the-arraysum-function">The <code>array_sum()</code> Function</h3>
<p><code>array_sum()</code> adds all the numeric values in an array together and returns the result. The only parameter it takes is the array containing the numeric values.</p>
<pre><code class="lang-php">$myNums = [<span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">9</span>, <span class="hljs-number">20</span>, <span class="hljs-number">1</span>];

$total = array_sum($myNums);
<span class="hljs-keyword">echo</span> $total; <span class="hljs-comment">// 41</span>
</code></pre>
<p>If used on an array containing strings, <code>array_sum()</code> throws the error <code>Warning: array_sum(): Addition is not supported on type string in /location/index.php on line #</code> :</p>
<pre><code class="lang-php">$myFruitsArr = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>, <span class="hljs-string">"Avocado"</span>, <span class="hljs-string">"Pineapple"</span>];
$total = array_sum($myFruitsArr);
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>sum() function error</em></p>
<h3 id="heading-the-arraymerge-function">The <code>array_merge()</code> Function</h3>
<p><code>array_merge()</code> merges two or more arrays. That means it's ideal for combining multiple arrays into one giant array.</p>
<pre><code class="lang-php">$array1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
$array2 = [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>];

$result = array_merge($array1, $array2);

print_r($result);
<span class="hljs-comment">/*
Output:


Array
(
   [0] =&gt; 1
   [1] =&gt; 2
   [2] =&gt; 3
   [3] =&gt; 4
   [4] =&gt; 5
   [5] =&gt; 6
   [6] =&gt; 7
   [7] =&gt; 8
)
*/</span>
</code></pre>
<p>You can also use <code>array_merge()</code> on associative arrays:</p>
<pre><code class="lang-php">$array1 = [
 <span class="hljs-string">'fname'</span> =&gt; <span class="hljs-string">'John'</span>,
 <span class="hljs-string">'sex'</span> =&gt; <span class="hljs-string">'male'</span>,
];


$array2 = [
 <span class="hljs-string">'lname'</span> =&gt; <span class="hljs-string">'Doe'</span>,
 <span class="hljs-string">'favColor'</span> =&gt; <span class="hljs-string">'red'</span>,
];

$result = array_merge($array1, $array2);
print_r($result);

<span class="hljs-comment">/*
Output:

Array
(
   [fname] =&gt; John
   [sex] =&gt; male
   [lname] =&gt; Doe
   [favColor] =&gt; red
)
*/</span>
</code></pre>
<p>If the arrays contain similar keys, the last one overrides the previous one(s) in the result:</p>
<pre><code class="lang-php">$array1 = [
 <span class="hljs-string">'fname'</span> =&gt; <span class="hljs-string">'John'</span>,
 <span class="hljs-string">'sex'</span> =&gt; <span class="hljs-string">'male'</span>,
];


$array2 = [
 <span class="hljs-string">'fname'</span> =&gt; <span class="hljs-string">'Jane'</span>,
 <span class="hljs-string">'favColor'</span> =&gt; <span class="hljs-string">'red'</span>,
];

$result = array_merge($array1, $array2);
print_r($result);

<span class="hljs-comment">/*
Output:

Array
(
   [fname] =&gt; Jane
   [sex] =&gt; male
   [favColor] =&gt; red
)
*/</span>
</code></pre>
<p>If a single array is passed into <code>array_merge()</code> and the keys are not sequential integers starting from 0, but rather a sequence like <code>3</code>, <code>7</code>, <code>8</code>, the resulting array will have its keys reindexed starting from <code>0</code>:</p>
<pre><code class="lang-php">$myArray = [<span class="hljs-number">3</span> =&gt; <span class="hljs-string">'Barn'</span>, <span class="hljs-number">7</span> =&gt; <span class="hljs-string">'Silo'</span>, <span class="hljs-number">8</span> =&gt; <span class="hljs-string">'Tank'</span>];
$res = array_merge($myArray);

print_r($res);

<span class="hljs-comment">/*
Array
(
   [0] =&gt; Barn
   [1] =&gt; Silo
   [2] =&gt; Tank
)
*/</span>
</code></pre>
<h3 id="heading-the-arrayfilter-function">The <code>array_filter()</code> Function</h3>
<p>The <code>array_filter()</code> function “filters” the items of an array based on a callback function you pass into it. You can use it to remove unnecessary items from an array.</p>
<p>If the callback function returns <code>true</code> for an element in the array, that element is included in the resulting array, otherwise, it is excluded.</p>
<p><code>array_filter()</code> takes up to 3 arguments. The basic syntax looks like this:</p>
<pre><code class="lang-php">array_filter(arrayToFilter, callbackFunction, flag)
</code></pre>
<ul>
<li><p><code>arrayToFilter</code> is the array you want to filter. It’s a compulsory argument.</p>
</li>
<li><p><code>callbackFunction</code> is the callback function you want to apply to each element of the array. If not provided, all elements evaluated to <code>true</code> will be included in the result.</p>
</li>
<li><p><code>flag</code> specifies whether the array keys will be preserved or reindexed. Possible values are <code>ARRAY_FILTER_USE_KEY</code>, <code>ARRAY_FILTER_USE_BOTH</code>, and <code>ARRAY_FILTER_USE_BOTH</code>.</p>
</li>
</ul>
<p>Here’s an example that gets the even numbers from an array of numbers:</p>
<pre><code class="lang-php">$array = [<span class="hljs-number">76</span>, <span class="hljs-number">11</span>, <span class="hljs-number">12</span>, <span class="hljs-number">22</span>, <span class="hljs-number">13</span>, <span class="hljs-number">43</span>, <span class="hljs-number">54</span>];
$getEvenNums = array_filter($array, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$value</span>) </span>{
 <span class="hljs-keyword">return</span> $value % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>;
});


print_r($getEvenNums);


<span class="hljs-comment">/*
Array
(
   [0] =&gt; 76
   [2] =&gt; 12
   [3] =&gt; 22
   [6] =&gt; 54
)
*/</span>
</code></pre>
<p>Here’s a more complex example of getting everyone with the first name “John” in a multidimensional associative array:</p>
<pre><code class="lang-php">$persons = [
 [<span class="hljs-string">'first'</span> =&gt; <span class="hljs-string">'John'</span>, <span class="hljs-string">'last'</span> =&gt; <span class="hljs-string">'Doe'</span>],
 [<span class="hljs-string">'first'</span> =&gt; <span class="hljs-string">'Janet'</span>, <span class="hljs-string">'last'</span> =&gt; <span class="hljs-string">'Jackson'</span>],
 [<span class="hljs-string">'first'</span> =&gt; <span class="hljs-string">'John'</span>, <span class="hljs-string">'last'</span> =&gt; <span class="hljs-string">'Smith'</span>],
 [<span class="hljs-string">'first'</span> =&gt; <span class="hljs-string">'Jane'</span>, <span class="hljs-string">'last'</span> =&gt; <span class="hljs-string">'Doe'</span>],
 [<span class="hljs-string">'first'</span> =&gt; <span class="hljs-string">'David'</span>, <span class="hljs-string">'last'</span> =&gt; <span class="hljs-string">'Lee'</span>],
 [<span class="hljs-string">'first'</span> =&gt; <span class="hljs-string">'John'</span>, <span class="hljs-string">'last'</span> =&gt; <span class="hljs-string">'Olga'</span>]
];


$personsWithJohnFirstnames = array_filter($persons, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$person</span>) </span>{
 <span class="hljs-keyword">return</span> $person[<span class="hljs-string">'first'</span>] === <span class="hljs-string">"John"</span>;
});

print_r($personsWithJohnFirstnames);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; Array
       (
           [first] =&gt; John
           [last] =&gt; Doe
       )

   [2] =&gt; Array
       (
           [first] =&gt; John
           [last] =&gt; Smith
       )

   [5] =&gt; Array
       (
           [first] =&gt; John
           [last] =&gt; Olga
       )

)
*/</span>
</code></pre>
<p>Remember that if you pass in the array as the only argument, the resulting array will contain every item that evaluates to <code>true</code>:</p>
<pre><code class="lang-php">$array = [<span class="hljs-number">9</span>, <span class="hljs-number">4</span>, <span class="hljs-number">10</span>, <span class="hljs-number">0</span>, <span class="hljs-number">3</span>];
$result = array_filter($array);


print_r($result);


<span class="hljs-comment">/*
Output:


Array
(
   [0] =&gt; 9
   [1] =&gt; 4
   [2] =&gt; 10
   [4] =&gt; 3
)
*/</span>
</code></pre>
<h3 id="heading-the-arraymap-function">The <code>array_map()</code> Function</h3>
<p>The <code>array_map()</code> function transforms all the elements of an array based on a callback function passed into it. It then returns a new array containing the transformed elements.</p>
<p>You can think about <code>array_map()</code> as a more convenient way to "loop" through an array, even though it's technically not a loop.</p>
<p><code>array_map()</code> takes two compulsory parameters – the callback function and the array you want to transform.</p>
<p>Here's an example in which all the numbers of an array are squared:</p>
<pre><code class="lang-php">$numbers = [<span class="hljs-number">5</span>, <span class="hljs-number">8</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>];

$squaredNumbers = array_map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$num</span>) </span>{
 <span class="hljs-keyword">return</span> $num * $num;
}, $numbers);

print_r($squaredNumbers);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; 25
   [1] =&gt; 64
   [2] =&gt; 9
   [3] =&gt; 16
)
*/</span>
</code></pre>
<p>You can also extract the callback function into a separate function and pass it in:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">squareNums</span>(<span class="hljs-params">$num</span>)
</span>{
 <span class="hljs-keyword">return</span> $num * $num;
}

$numbers = [<span class="hljs-number">5</span>, <span class="hljs-number">8</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>];
$squaredNumbers = array_map(<span class="hljs-string">'squareNums'</span>, $numbers);

print_r($squaredNumbers);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; 25
   [1] =&gt; 64
   [2] =&gt; 9
   [3] =&gt; 16
)
*/</span>
</code></pre>
<p>You can also use the <code>array_map()</code> function on an array of strings. The example below converts all the fruits in the <code>$fruitsArr</code> array to uppercase:</p>
<pre><code class="lang-php">$fruitsArr = [<span class="hljs-string">'mango'</span>, <span class="hljs-string">'apple'</span>, <span class="hljs-string">'orange'</span>, <span class="hljs-string">'strawberry'</span>];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toUpperCase</span>(<span class="hljs-params">$str</span>)
</span>{
 <span class="hljs-keyword">return</span> strtoupper($str);
}

$uppercasedFruits = array_map(<span class="hljs-string">'toUpperCase'</span>, $fruitsArr);

print_r($uppercasedFruits);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; MANGO
   [1] =&gt; APPLE
   [2] =&gt; ORANGE
   [3] =&gt; STRAWBERRY
)
*/</span>
</code></pre>
<p>Here's an example using an associative array where all the values are prefixed with <code>prefix_</code>:</p>
<pre><code class="lang-php">$fruitsArr = [
 <span class="hljs-string">'fruit1'</span> =&gt; <span class="hljs-string">'mango'</span>,
 <span class="hljs-string">'fruit2'</span> =&gt; <span class="hljs-string">'banana'</span>,
 <span class="hljs-string">'fruit3'</span> =&gt; <span class="hljs-string">'orange'</span>,
];


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addPrefixToFruits</span>(<span class="hljs-params">$fruit</span>)
</span>{
 <span class="hljs-keyword">return</span> <span class="hljs-string">'prefix_'</span> . $fruit;
}

$prefixedFruits = array_map(<span class="hljs-string">'addPrefixToFruits'</span>, $fruitsArr);

print_r($prefixedFruits);

<span class="hljs-comment">/*
Output:

Array
(
   [fruit1] =&gt; prefix_mango
   [fruit2] =&gt; prefix_banana
   [fruit3] =&gt; prefix_orange
)
*/</span>
</code></pre>
<blockquote>
<p><strong>Note</strong>: If you're wondering what the difference between <code>array_map()</code> and <code>array_filter()</code> is, the catch is that <code>array_map()</code> transforms all the elements of the array based on a callback function. In contrast, <code>array_filter()</code> returns any element of the array that matches the callback function passed into it.</p>
</blockquote>
<h3 id="heading-the-arraysearch-function">The <code>array_search()</code> Function</h3>
<p>The <code>array_search()</code> function is used to search for a given value within an array. If the value is found, it returns the key of the value, otherwise, it returns nothing.</p>
<p><code>array_search()</code> takes up to 3 arguments. Here's the syntax:</p>
<pre><code class="lang-php">array_search(valueToSearch, arrayToSearch, strict)
</code></pre>
<ul>
<li><p><code>valueToSearch</code> is the value you're looking for</p>
</li>
<li><p><code>arrayToSearch</code> is the array in which you want to search for the value</p>
</li>
<li><p><code>strict</code> is an optional boolean argument that determines whether a strict comparison operator should be used in the search. It's <code>false</code> by default. But if set to <code>true</code>, it will search for identical elements in the array and return them. For example, <code>"1"</code> and <code>1</code>.</p>
</li>
</ul>
<p>Here's an example checking for the item <code>Cashew</code> in an array of fruits:</p>
<pre><code class="lang-php">$myFruitsArr = [
 <span class="hljs-string">"fruit1"</span> =&gt; <span class="hljs-string">"Apple"</span>,
 <span class="hljs-string">"fruit2"</span> =&gt; <span class="hljs-string">"Banana"</span>,
 <span class="hljs-string">"fruit3"</span> =&gt; <span class="hljs-string">"Cashew"</span>,
 <span class="hljs-string">"fruit4"</span> =&gt; <span class="hljs-string">"Mango"</span>,
 <span class="hljs-string">"fruit5"</span> =&gt; <span class="hljs-string">"Avocado"</span>,
 <span class="hljs-string">"fruit6"</span> =&gt; <span class="hljs-string">"Pineapple"</span>
];

$checkForCashew = array_search(<span class="hljs-string">'Cashew'</span>, $myFruitsArr);

<span class="hljs-keyword">echo</span> $checkForCashew; <span class="hljs-comment">// fruit3</span>
</code></pre>
<p>And if you use it on a regular array, it will still return the index of the array, which is the key under the hood:</p>
<pre><code class="lang-php">$myFruitsArr = [
 <span class="hljs-string">"Apple"</span>,
 <span class="hljs-string">"Banana"</span>,
 <span class="hljs-string">"Cashew"</span>,
 <span class="hljs-string">"Mango"</span>,
 <span class="hljs-string">"Avocado"</span>,
 <span class="hljs-string">"Pineapple"</span>
];


$CheckForCashew = array_search(<span class="hljs-string">'Cashew'</span>, $myFruitsArr);


<span class="hljs-keyword">echo</span> $CheckForCashew; <span class="hljs-comment">// 2</span>
</code></pre>
<h3 id="heading-the-arraycolumn-function">The <code>array_column()</code> Function</h3>
<p>The <code>array_column()</code> extracts a single column of values from a multi-dimensional array. It returns an array containing the values of a specified column from the input array.</p>
<p>That means <code>array_column</code> is useful when you want to make an array out of the column of an existing array.</p>
<p><code>array_column()</code> takes up to 3 arguments. Here's the syntax:</p>
<pre><code class="lang-php">array_column(parentArray, columKey, indexKey)
</code></pre>
<ul>
<li><p><code>parentArray</code>: usually a multidimensional array, it's the array to extract the column of values from</p>
</li>
<li><p><code>columnKey</code>: the key or index of the column to extract values from. This can be an integer index or a string key representing the column name.</p>
</li>
<li><p><code>indexKey</code> (optional): the column to use as the index for the returned array. If omitted or set to null, numerical indexes are used.</p>
</li>
</ul>
<p>The example below uses the name key of the array to create a new array:</p>
<pre><code class="lang-php">$pupils = [
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">1</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"John"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">90</span>],
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">2</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Jane"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">79</span>],
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">3</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Will"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">83</span>],
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">4</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Jill"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">92</span>],
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">5</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"steven"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">100</span>],
];

$arrayFromNameColumn = array_column($pupils, <span class="hljs-string">'name'</span>);

print_r($arrayFromNameColumn);

<span class="hljs-comment">/*
Output:

Array
(
   [0] =&gt; John
   [1] =&gt; Jane
   [2] =&gt; Will
   [3] =&gt; Jill
   [4] =&gt; steven
)
*/</span>
</code></pre>
<p>Remember you can pass in another key in the array to make its values the indexes of the resulting array. I'll use the <code>"id"</code> for that:</p>
<pre><code class="lang-php">$pupils = [
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">1</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"John"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">90</span>],
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">2</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Jane"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">79</span>],
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">3</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Will"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">83</span>],
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">4</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Jill"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">92</span>],
 [<span class="hljs-string">"id"</span> =&gt; <span class="hljs-number">5</span>, <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"steven"</span>, <span class="hljs-string">"score"</span> =&gt; <span class="hljs-number">100</span>],
];

$arrayFromNameColumn = array_column($pupils, <span class="hljs-string">"name"</span>, <span class="hljs-string">"id"</span>);

print_r($arrayFromNameColumn);

<span class="hljs-comment">/*
Output:



Array
(
   [1] =&gt; John
   [2] =&gt; Jane
   [3] =&gt; Will
   [4] =&gt; Jill
   [5] =&gt; steven
)
*/</span>
</code></pre>
<h3 id="heading-the-inarray-function">The <code>in_array()</code> Function</h3>
<p><code>in_array()</code> is used to check if a particular element is in an array. It takes two compulsory parameters and one optional parameter.</p>
<p>Here's the syntax:</p>
<pre><code class="lang-php">in_array(itemToSearch, arrayToSearchThrough, strict)
</code></pre>
<ul>
<li><p><code>itemToSearch</code> is the element you're looking for. It's compulsory.</p>
</li>
<li><p><code>arrayToSearchThrough</code> is the array in which you want to search for <code>itemToSearch</code>. It's also compulsory.</p>
</li>
<li><p><code>strict</code> is a boolean value that lets you specify whether you want the search to be done with loose comparison (<code>==</code>) or strict comparison (<code>===</code>). It defaults to <code>false</code>.</p>
</li>
</ul>
<p>Here's the <code>in_array()</code> function in action:</p>
<pre><code class="lang-php">$myFruitsArr1 = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];
var_dump(in_array(<span class="hljs-string">"Banana"</span>, $myFruitsArr1)); <span class="hljs-comment">// bool(true)</span>
var_dump(in_array(<span class="hljs-string">"banana"</span>, $myFruitsArr1)); <span class="hljs-comment">// bool(false)</span>
</code></pre>
<p>Because the result of <code>in_array()</code> is a boolean, it's commonly used in conditionals:</p>
<pre><code class="lang-php">$myFruitsArr1 = [<span class="hljs-string">"Apple"</span>, <span class="hljs-string">"Banana"</span>, <span class="hljs-string">"Cashew"</span>, <span class="hljs-string">"Mango"</span>];


<span class="hljs-keyword">if</span> (in_array(<span class="hljs-string">"Banana"</span>, $myFruitsArr1)) {
 <span class="hljs-keyword">echo</span> <span class="hljs-string">"Banana is in the array"</span>; <span class="hljs-comment">// Banana is in the array</span>
} <span class="hljs-keyword">else</span> {
 <span class="hljs-keyword">echo</span> <span class="hljs-string">"Banana is not in the array"</span>;
}
</code></pre>
<h2 id="heading-how-to-loop-through-arrays-in-php">How to Loop Through Arrays in PHP</h2>
<p>PHP provides the traditional <code>for</code> loop for iterating through both indexed and associative arrays. You can also use a cleaner <code>forEach()</code> function for the same purpose.</p>
<h3 id="heading-how-to-loop-through-an-indexed-array">How to Loop through an Indexed Array</h3>
<p>Here's the basic syntax for looping through an array with a <code>for</code> loop:</p>
<pre><code class="lang-php"><span class="hljs-keyword">for</span> ($i=<span class="hljs-number">0</span>; $i &lt; count($arr); $i++) {
 <span class="hljs-comment"># do something with $arr ...</span>
}
</code></pre>
<p>And here's that of <code>foreach()</code>:</p>
<pre><code class="lang-php"><span class="hljs-keyword">foreach</span> ($arrs <span class="hljs-keyword">as</span> $arr) {
 <span class="hljs-comment"># do something with $arr</span>
}
</code></pre>
<p>Here's an example using the <code>for</code> loop to loop through an array of strings:</p>
<pre><code class="lang-php">$retiredBallers = [<span class="hljs-string">"Pele"</span>, <span class="hljs-string">"Maradona"</span>, <span class="hljs-string">"Zidane"</span>, <span class="hljs-string">"Lampard"</span>, <span class="hljs-string">"Okocha"</span>];

<span class="hljs-keyword">for</span> ($i = <span class="hljs-number">0</span>; $i &lt; count($retiredBallers); $i++) {
 <span class="hljs-keyword">echo</span> $retiredBallers[$i] . <span class="hljs-string">"&lt;br&gt;"</span>;
}

<span class="hljs-comment">/*
Output:

Pele
Maradona
Zidane
Lampard
Okocha
*/</span>
</code></pre>
<p>You can loop through numbers the same way:</p>
<pre><code class="lang-php"><span class="hljs-keyword">for</span> ($i = <span class="hljs-number">0</span>; $i &lt; count($myNums); $i++) {
 <span class="hljs-keyword">echo</span> $myNums[$i] . <span class="hljs-string">"&lt;br&gt;"</span>;
}

<span class="hljs-comment">/*
Output:

45
8
90
2
5
*/</span>
</code></pre>
<p>You can also print the index for each element of the array:</p>
<pre><code class="lang-php"><span class="hljs-keyword">for</span> ($i = <span class="hljs-number">0</span>; $i &lt; count($myNums); $i++) {
 <span class="hljs-keyword">echo</span> $myNums[$i] . <span class="hljs-string">" is at index "</span> . $i . <span class="hljs-string">"&lt;br&gt;"</span>;
}

<span class="hljs-comment">/*
Output:

45 is at index 0
8 is at index 1
90 is at index 2
2 is at index 3
5 is at index 4
*/</span>
</code></pre>
<p>Don't forget you can use <code>foreach</code> to loop through any array too:</p>
<pre><code class="lang-php"><span class="hljs-keyword">foreach</span> ($retiredBallers <span class="hljs-keyword">as</span> $retiredBaller) {
 <span class="hljs-keyword">echo</span> $retiredBaller . <span class="hljs-string">"&lt;br&gt;"</span>;
}


<span class="hljs-comment">/*
Pele
Maradona
Zidane
Lampard
Okocha
*/</span>
</code></pre>
<p>You can get the index this way as well:</p>
<pre><code class="lang-php"><span class="hljs-keyword">foreach</span> ($retiredBallers <span class="hljs-keyword">as</span> $key =&gt; $retiredBaller) {
 <span class="hljs-keyword">echo</span> $retiredBaller . <span class="hljs-string">" is at index "</span> . $key . <span class="hljs-string">"&lt;br&gt;"</span>;
}


<span class="hljs-comment">/*
Pele is at index 0
Maradona is at index 1
Zidane is at index 2
Lampard is at index 3
Okocha is at index 4
*/</span>
</code></pre>
<h3 id="heading-how-to-loop-through-an-associative-array">How to Loop through an Associative Array</h3>
<p>An associative array can be complex with items nested deep into it. So, you have to get what you want from it instead of displaying everything in it.</p>
<p>Here's how I got the name and country of some retired footballers from a <code>$retiredFootballers</code> array:</p>
<pre><code class="lang-php">$retiredFootballers = [
 [
   <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Pele"</span>,
   <span class="hljs-string">"position"</span> =&gt; <span class="hljs-string">"Forward"</span>,
   <span class="hljs-string">"country"</span> =&gt; <span class="hljs-string">"Brazil"</span>,
   <span class="hljs-string">"club"</span> =&gt; <span class="hljs-string">"Santos"</span>
 ],


 [
   <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Diego Maradona"</span>,
   <span class="hljs-string">"position"</span> =&gt; <span class="hljs-string">"Attacking Midfielder"</span>,
   <span class="hljs-string">"country"</span> =&gt; <span class="hljs-string">"Argentina"</span>,
   <span class="hljs-string">"club"</span> =&gt; <span class="hljs-string">"Napoli"</span>
 ],


 [
   <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Zinedine Zidane"</span>,
   <span class="hljs-string">"position"</span> =&gt; <span class="hljs-string">"Midfielder"</span>,
   <span class="hljs-string">"country"</span> =&gt; <span class="hljs-string">"France"</span>,
   <span class="hljs-string">"club"</span> =&gt; <span class="hljs-string">"Real Madrid"</span>
 ],


 [
   <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Ronaldinho"</span>,
   <span class="hljs-string">"position"</span> =&gt; <span class="hljs-string">"Attacking Midfielder"</span>,
   <span class="hljs-string">"country"</span> =&gt; <span class="hljs-string">"Brazil"</span>,
   <span class="hljs-string">"club"</span> =&gt; <span class="hljs-string">"Barcelona"</span>
 ],


 [
   <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"David Beckham"</span>,
   <span class="hljs-string">"position"</span> =&gt; <span class="hljs-string">"Midfielder"</span>,
   <span class="hljs-string">"country"</span> =&gt; <span class="hljs-string">"England"</span>,
   <span class="hljs-string">"club"</span> =&gt; <span class="hljs-string">"Manchester United"</span>
 ],
 [
   <span class="hljs-string">"name"</span> =&gt; <span class="hljs-string">"Jay-Jay Okocha"</span>,
   <span class="hljs-string">"position"</span> =&gt; <span class="hljs-string">"Midfielder"</span>,
   <span class="hljs-string">"country"</span> =&gt; <span class="hljs-string">"Nigeria"</span>,
   <span class="hljs-string">"club"</span> =&gt; <span class="hljs-string">"Bolton Wanderers"</span>
 ]
];


<span class="hljs-keyword">for</span> ($i = <span class="hljs-number">0</span>; $i &lt; count($retiredFootballers); $i++) {
 <span class="hljs-keyword">echo</span> $retiredFootballers[$i][<span class="hljs-string">"name"</span>] . <span class="hljs-string">" is from "</span> . $retiredFootballers[$i][<span class="hljs-string">"country"</span>] . <span class="hljs-string">"&lt;br&gt;"</span>;
 <span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;hr&gt;"</span>;
}
</code></pre>
<p>Doing the same with <code>foreach()</code> is cleaner because you don't need an <code>$i</code> variable:</p>
<pre><code class="lang-php"><span class="hljs-keyword">foreach</span> ($retiredFootballers <span class="hljs-keyword">as</span> $retiredFootballer) {
 <span class="hljs-keyword">echo</span> $retiredFootballer[<span class="hljs-string">"name"</span>] . <span class="hljs-string">" is from "</span> . $retiredFootballer[<span class="hljs-string">"country"</span>] . <span class="hljs-string">"&lt;br&gt;"</span>;
 <span class="hljs-keyword">echo</span> <span class="hljs-string">"&lt;hr&gt;"</span>;
}
</code></pre>
<h3 id="heading-how-to-loop-through-an-array-inside-the-html-template">How to Loop through an Array Inside the HTML Template</h3>
<p>Any HTML in your PHP file is the template for that PHP file. This means you can do the looping inside the HTML, because you can write PHP inside that HTML.</p>
<p>Here's how you can do that:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
$retiredBallers = [<span class="hljs-string">"Pele"</span>, <span class="hljs-string">"Maradona"</span>, <span class="hljs-string">"Zidane"</span>, <span class="hljs-string">"Lampard"</span>, <span class="hljs-string">"Okocha"</span>];
<span class="hljs-meta">?&gt;</span>

&lt;h1 <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">text</span>-<span class="hljs-title">center</span> <span class="hljs-title">mt</span>-3 <span class="hljs-title">bd</span>-<span class="hljs-title">highlight</span>"&gt;<span class="hljs-title">Looping</span> <span class="hljs-title">Through</span> <span class="hljs-title">Arrays</span> <span class="hljs-title">in</span> <span class="hljs-title">PHP</span>&lt;/<span class="hljs-title">h1</span>&gt;

 &lt;<span class="hljs-title">h2</span> <span class="hljs-title">class</span>="<span class="hljs-title">mx</span>-5 <span class="hljs-title">mt</span>-5"&gt;<span class="hljs-title">Some</span> <span class="hljs-title">Retired</span> <span class="hljs-title">Footballers</span>&lt;/<span class="hljs-title">h2</span>&gt;

 &lt;<span class="hljs-title">ul</span> <span class="hljs-title">class</span>="<span class="hljs-title">list</span>-<span class="hljs-title">group</span> <span class="hljs-title">mx</span>-5" <span class="hljs-title">style</span>="<span class="hljs-title">width</span>: 25%;"&gt;
   &lt;!-- <span class="hljs-title">The</span> <span class="hljs-title">loop</span> --&gt;
   &lt;?<span class="hljs-title">php</span> <span class="hljs-title">for</span> ($<span class="hljs-title">i</span> = 0; $<span class="hljs-title">i</span> &lt; <span class="hljs-title">count</span>($<span class="hljs-title">retiredBallers</span>); $<span class="hljs-title">i</span>++) : ?&gt;
     &lt;<span class="hljs-title">li</span> <span class="hljs-title">class</span>="<span class="hljs-title">list</span>-<span class="hljs-title">group</span>-<span class="hljs-title">item</span>"&gt; &lt;?= $<span class="hljs-title">retiredBallers</span>[$<span class="hljs-title">i</span>] ?&gt; &lt;/<span class="hljs-title">li</span>&gt;
   &lt;?<span class="hljs-title">php</span> <span class="hljs-title">endfor</span>; ?&gt;
 &lt;/<span class="hljs-title">ul</span>&gt;</span>
</code></pre>
<p>You can do the same with <code>foreach()</code>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
$retiredBallers = [<span class="hljs-string">"Pele"</span>, <span class="hljs-string">"Maradona"</span>, <span class="hljs-string">"Zidane"</span>, <span class="hljs-string">"Lampard"</span>, <span class="hljs-string">"Okocha"</span>];
<span class="hljs-meta">?&gt;</span>

&lt;h1 <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">text</span>-<span class="hljs-title">center</span> <span class="hljs-title">mt</span>-3 <span class="hljs-title">bd</span>-<span class="hljs-title">highlight</span>"&gt;<span class="hljs-title">Looping</span> <span class="hljs-title">Through</span> <span class="hljs-title">Arrays</span> <span class="hljs-title">in</span> <span class="hljs-title">PHP</span>&lt;/<span class="hljs-title">h1</span>&gt;

 &lt;<span class="hljs-title">h2</span> <span class="hljs-title">class</span>="<span class="hljs-title">mx</span>-5 <span class="hljs-title">mt</span>-5"&gt;<span class="hljs-title">Some</span> <span class="hljs-title">Retired</span> <span class="hljs-title">Footballers</span>&lt;/<span class="hljs-title">h2</span>&gt;


 &lt;<span class="hljs-title">ul</span> <span class="hljs-title">class</span>="<span class="hljs-title">list</span>-<span class="hljs-title">group</span> <span class="hljs-title">mx</span>-5" <span class="hljs-title">style</span>="<span class="hljs-title">width</span>: 25%;"&gt;
   &lt;!-- <span class="hljs-title">The</span> <span class="hljs-title">loop</span> --&gt;
   &lt;?<span class="hljs-title">php</span> <span class="hljs-title">foreach</span> ($<span class="hljs-title">retiredBallers</span> <span class="hljs-title">as</span> $<span class="hljs-title">retiredBaller</span>) : ?&gt;
     &lt;<span class="hljs-title">li</span> <span class="hljs-title">class</span>="<span class="hljs-title">list</span>-<span class="hljs-title">group</span>-<span class="hljs-title">item</span>"&gt; &lt;?= $<span class="hljs-title">retiredBaller</span> ?&gt; &lt;/<span class="hljs-title">li</span>&gt;
   &lt;?<span class="hljs-title">php</span> <span class="hljs-title">endforeach</span>; ?&gt;
 &lt;/<span class="hljs-title">ul</span>&gt;</span>
</code></pre>
<p>Here's what that looks like in the browser:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Looping through arrays using PHP for loop inside HTML</em></p>
<p>Let's use <code>foreach()</code> to display the <code>$retiredFootballers</code> associative array too:</p>
<pre><code class="lang-php">&lt;h1 <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">text</span>-<span class="hljs-title">center</span> <span class="hljs-title">mt</span>-3 <span class="hljs-title">bd</span>-<span class="hljs-title">highlight</span>"&gt;<span class="hljs-title">Looping</span> <span class="hljs-title">Through</span> <span class="hljs-title">Arrays</span> <span class="hljs-title">in</span> <span class="hljs-title">PHP</span>&lt;/<span class="hljs-title">h1</span>&gt;


 &lt;<span class="hljs-title">h2</span> <span class="hljs-title">class</span>="<span class="hljs-title">mx</span>-5 <span class="hljs-title">mt</span>-5"&gt;<span class="hljs-title">Some</span> <span class="hljs-title">Retired</span> <span class="hljs-title">Footballers</span>&lt;/<span class="hljs-title">h2</span>&gt;


 &lt;<span class="hljs-title">ul</span> <span class="hljs-title">class</span>="<span class="hljs-title">list</span>-<span class="hljs-title">group</span> <span class="hljs-title">mx</span>-5" <span class="hljs-title">style</span>="<span class="hljs-title">width</span>: 25%;"&gt;
   &lt;!-- <span class="hljs-title">The</span> <span class="hljs-title">loop</span> --&gt;
   &lt;?<span class="hljs-title">php</span> <span class="hljs-title">foreach</span> ($<span class="hljs-title">retiredFootballers</span> <span class="hljs-title">as</span> $<span class="hljs-title">retiredFootballer</span>) : ?&gt;
     &lt;<span class="hljs-title">li</span> <span class="hljs-title">class</span>="<span class="hljs-title">list</span>-<span class="hljs-title">group</span>-<span class="hljs-title">item</span>"&gt; &lt;?= $<span class="hljs-title">retiredFootballer</span>["<span class="hljs-title">name</span>"] . " <span class="hljs-title">is</span> <span class="hljs-title">from</span> " . $<span class="hljs-title">retiredFootballer</span>["<span class="hljs-title">country</span>"] ?&gt; &lt;/<span class="hljs-title">li</span>&gt;
   &lt;?<span class="hljs-title">php</span> <span class="hljs-title">endforeach</span>; ?&gt;
 &lt;/<span class="hljs-title">ul</span>&gt;</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Looping through arrays using PHP foreach function inside HTML</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Learning how to work with arrays is a foundational step toward proficiency in PHP and web development. That's why this handbook walked you through the various capabilities of PHP arrays, from creation to manipulation and looping.</p>
<p>You should now be confident using arrays to effectively manage data in PHP, whether for simple lists with indexed arrays, or complex structures with associative and multidimensional arrays.</p>
<p>Moving forward, I encourage you to experiment with various array functions to improve your code and tackle different programming challenges. Also, consider exploring multidimensional and associative arrays for more complex data scenarios.</p>
<p>As you grow more proficient with PHP arrays, integrating them with database operations can further enhance your web applications. A good example is MongoDB, a NoSQL database that integrates seamlessly with PHP. Check out the <a target="_blank" href="https://www.mongodb.com/docs/languages/php/">MongoDB PHP docs</a> for more info.  </p>
<p>Also, look out for the second article of this series.</p>
<p>Keep coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement JSON Web Tokens (JWTs) in PHP – PHP Authentication Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ In this guide, we'll explore the process of creating JSON Web Tokens (JWTs) from scratch in PHP, which is a superior and more secure authentication scheme.  By implementing this advanced approach, you'll have a robust and highly secure authentication... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/php-jwt-authentication-implementation/</link>
                <guid isPermaLink="false">66bae6f4e2f22beb3be3a538</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oghenekparobo Stephen ]]>
                </dc:creator>
                <pubDate>Wed, 24 Apr 2024 18:41:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/How-to-Implement-JSON-Web-Tokens-in-PHP-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this guide, we'll explore the process of creating JSON Web Tokens (JWTs) from scratch in PHP, which is a superior and more secure authentication scheme. </p>
<p>By implementing this advanced approach, you'll have a robust and highly secure authentication mechanism that significantly enhances data protection and user authentication.</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-are-json-web-tokens-jwts">What Are JSON Web Tokens (JWTs)?</a></li>
<li><a class="post-section-overview" href="#heading-getting-started">Getting Started</a></li>
<li><a class="post-section-overview" href="#heading-sending-our-requests">Sending Our Requests</a></li>
<li><a class="post-section-overview" href="#heading-testing-database-connection">Testing Database Connection</a></li>
<li><a class="post-section-overview" href="#heading-registering-users">Registering Users</a></li>
<li><a class="post-section-overview" href="#heading-setting-up-the-jwt-class">Setting up the JWT Class</a></li>
<li><a class="post-section-overview" href="#heading-the-encode-method">The Encode Method</a></li>
<li><a class="post-section-overview" href="#heading-the-login-endpoint">The Login Endpoint</a></li>
<li><a class="post-section-overview" href="#heading-protected-resources-and-decoding-json-web-tokens">Protected Resources And Decoding JSON Web Tokens</a></li>
<li><a class="post-section-overview" href="#heading-what-happens-now">What Happens Now?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-the-decode-method-in-our-jwt-class">How to Set Up The Decode Method In Our JWT Class</a></li>
<li><a class="post-section-overview" href="#heading-protected-resources">Protected Resources</a></li>
<li><a class="post-section-overview" href="#heading-checking-the-headers-for-the-correct-authorization-scheme">Checking The Headers For The Correct Authorization Scheme</a></li>
<li><a class="post-section-overview" href="#heading-creating-instances-in-the-api-entry-point">Creating Instances In The API Entry Point</a></li>
<li><a class="post-section-overview" href="#heading-suggestions">Suggestions</a></li>
<li><a class="post-section-overview" href="#heading-how-to-implement-token-expiration">How to Implement Token Expiration</a></li>
<li><a class="post-section-overview" href="#heading-updated-folder-structure">Updated Folder Structure</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-what-are-json-web-tokens-jwts">What Are JSON Web Tokens (JWTs)?</h2>
<p>A JSON Web Token is a string composed of three parts, each joined by a period (.), and then base64url encoded.</p>
<p>Here are the three parts of a JWT:</p>
<p><strong>Header</strong>: A header consists of metadata about the token, such as the token type and the algorithm used.</p>
<pre><code class="lang-php"> $header = json_encode([
            <span class="hljs-string">"alg"</span> =&gt; <span class="hljs-string">"HS256"</span>,
            <span class="hljs-string">"typ"</span> =&gt; <span class="hljs-string">"JWT"</span>
        ]);

        $header = <span class="hljs-keyword">$this</span>-&gt;base64urlEncode($header);
</code></pre>
<p><strong>Payload:</strong> Within the JWT structure, the payload encapsulates specific indices referred to as claims, housing user data that is encoded using base64url.</p>
<pre><code class="lang-php">$payload = [
    <span class="hljs-string">"id"</span> =&gt; $user[<span class="hljs-string">'id'</span>],
    <span class="hljs-string">"name"</span> =&gt; $user[<span class="hljs-string">"name"</span>]
];

  $payload = <span class="hljs-keyword">$this</span>-&gt;base64urlEncode($payload);
</code></pre>
<p><strong>Signature:</strong> This is generated by creating a hash of the header and payload, combined with a secret key typically generated as either 256 bits or 32 bytes. By convention, the secret key matches the size of the hash output.</p>
<p>We will use the link below to generate a secret key we need for this project:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://generate-random.org/encryption-key-generator?source=post_page-----ebf5693b931a--------------------------------">https://generate-random.org/encryption-key-generator?source=post_page-----ebf5693b931a--------------------------------</a></div>
<pre><code class="lang-php"> $signature = hash_hmac(<span class="hljs-string">"sha256"</span>, $header . <span class="hljs-string">"."</span> . $payload, $secret_key, <span class="hljs-literal">true</span>);
 $signature = <span class="hljs-keyword">$this</span>-&gt;base64urlEncode($signature);
</code></pre>
<p>A JSON Web Token is simply a combination of the header, payload, and signature, where each component is concatenated together with periods (“.”) in between:</p>
<pre><code class="lang-bash"><span class="hljs-variable">$header</span> . <span class="hljs-string">"."</span> . <span class="hljs-variable">$payload</span> . <span class="hljs-string">"."</span> . <span class="hljs-variable">$signature</span>;
</code></pre>
<h2 id="heading-getting-started">Getting Started</h2>
<p>To kickstart this project, please download the project starter from the following link: <a target="_blank" href="https://github.com/Oghenekparobo/php_auth_jwt_tut">PHP Authentication with JWT Tutorial</a>. </p>
<p>Once downloaded, carefully review the <strong>README.md</strong> file included in the repository for comprehensive information regarding pre-installed packages. The file contains essential details such as notes on security and best practices. Taking the time to thoroughly read through the <strong>README</strong> will ensure a smooth setup and understanding of the project.</p>
<p>To initiate the setup of the project, utilize Git by executing the following command:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/Oghenekparobo/php_auth_jwt_tut.git
</code></pre>
<p>This command will clone the project repository to your local system, allowing you to proceed with the installation and configuration process.</p>
<p>After cloning the project from GitHub, your project structure should align with the following layout:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_ZQ1u8lazV-ID3fJ9bFKUMA.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>project structure on VS Code</em></p>
<p>project_root/
│
├── api/
│   ├── .htaccess
│   ├── index.php
│   └── (other PHP files)
│
├── vendor/
│   ├── (Composer dependencies)
│   └── ...
│
├── .env
├── README.md
└── (other project files)</p>
<p><strong>In this structure:</strong></p>
<ul>
<li>The <code>api/</code> directory contains PHP files responsible for handling API requests and responses. It includes an <code>.htaccess</code> file for URL rewriting and an <code>index.php</code> file, along with other PHP files for specific functionalities.</li>
<li>The <code>vendor/</code> directory contains Composer dependencies installed for the project. These dependencies are managed by Composer and should not be modified directly.</li>
<li>The <code>.env</code> file contains environment variables necessary for configuring the application environment, such as database credentials and API keys.</li>
<li>The <code>README.md</code> file provides essential information about the project, including setup instructions, usage guidelines, and any other relevant details.</li>
</ul>
<p>Ensure that you maintain this structure and follow any instructions provided in the <strong>README</strong> file to set up and run the project successfully.</p>
<h2 id="heading-sending-our-requests">Sending Our Requests</h2>
<p>When referring to our project, the URL would typically be structured as follows: <code>http://localhost/php_auth_jwt_tut/api</code>. However, depending on the project's name, this URL might vary accordingly. Nonetheless, the base URL remains consistent: <code>[http://localhost/php_auth_jwt_tut/api](http://localhost/php_auth_jwt_tut/api.)</code><a target="_blank" href="http://localhost/php_auth_jwt_tut/api.">.</a></p>
<p>Thanks to our implementation of URL rewriting in the <code>.htaccess</code> file, additional prefixes such as <code>index.php</code> or <code>.php</code> are unnecessary when accessing our URLs. We've meticulously configured our server settings to ensure seamless navigation without these prefixes.</p>
<p>In simpler terms, accessing our project’s API endpoints can be done directly from the base URL: <code>http://localhost/php_auth_jwt_tut/api</code>. This streamlined approach enhances user experience and eliminates unnecessary complexity for this project.</p>
<p>To make testing our project’s API endpoints easier, we can use the <strong>index.php</strong> file located in the <strong>api</strong> folder. This file acts as the starting point for our application and contains all the necessary setups.</p>
<p>Firstly, we’ll simply print out any desired output within the <strong>index.php</strong> file. This helps us confirm that our endpoint is working correctly. Then, we'll test the endpoint by accessing the URL: <code>[http://localhost/php_auth_jwt_tut/api](http://localhost/php_auth_jwt_tut/api.)</code><a target="_blank" href="http://localhost/php_auth_jwt_tut/api.">.</a></p>
<p>Additionally, we’ll set up our database connection to ensure smooth communication between our API endpoints and the database. All the required configurations are included within the <a target="_blank" href="https://github.com/Oghenekparobo/php_auth_jwt_tut/blob/main/api/bootstrap.php"><strong>bootstrap.php</strong></a> file for convenience. By importing this file into our <a target="_blank" href="https://github.com/Oghenekparobo/php_auth_jwt_tut/blob/main/api/index.php"><strong>index.php</strong></a>, managing configurations and imports becomes simpler.</p>
<p>Furthermore, it’s important to note that we’ll be enforcing strict typing throughout our codebase. This means that we’ll specify the types of data our variables and functions can hold or return. This helps maintain consistency and reduces the chances of errors in our code.</p>
<h2 id="heading-testing-database-connection">Testing Database Connection</h2>
<p>Before proceeding with the steps outlined in this section, it is imperative to thoroughly review the <strong>README</strong> file of this project. This will provide you with comprehensive instructions on how to set up your database properly. In the root of the project, you will find a file named <a target="_blank" href="https://github.com/Oghenekparobo/php_auth_jwt_tut/blob/main/college.sql"><strong>college.sql</strong></a>, which contains the necessary tables for your database. Simply follow the instructions provided in the <strong>README</strong> file to import and configure the database accordingly.</p>
<p>In the <strong>src</strong> folder of our project, we find essential classes and gateways, including the necessary database connections for our project. The file responsible for this is <strong>database.php</strong>, already configured to establish a PDO database connection.</p>
<p>Note: Before use, ensure to adjust or configure the variables in the <strong>.env</strong> environment file to match your database credentials.</p>
<p><strong>.env file</strong>:</p>
<pre><code class="lang-env">DB_HOST= 'db_host'
DB_NAME = 'db_name'
DB_USER = 'db_user'
DB_PASS = 'db_password'
SECRET_KEY = "secret_key"
</code></pre>
<p><strong>bootstrap.php</strong>:</p>
<pre><code class="lang-php"><span class="hljs-keyword">require</span> dirname(<span class="hljs-keyword">__DIR__</span>)  . <span class="hljs-string">'/vendor/autoload.php'</span>;

set_error_handler(<span class="hljs-string">'ErrorHandler::handleError'</span>);
set_exception_handler(<span class="hljs-string">'ErrorHandler::handleException'</span>);

$dotenv = Dotenv\Dotenv::createImmutable(dirname(<span class="hljs-keyword">__DIR__</span>));
$dotenv-&gt;load();

header(<span class="hljs-string">"Content-type: application/json; charset=UTF-8"</span>);


$database = <span class="hljs-keyword">new</span> Database(
    $_ENV[<span class="hljs-string">"DB_HOST"</span>],
    $_ENV[<span class="hljs-string">"DB_NAME"</span>],
    $_ENV[<span class="hljs-string">"DB_USER"</span>],
    $_ENV[<span class="hljs-string">"DB_PASS"</span>]
);
</code></pre>
<p>The code prepares our application by doing a few key things. First, it loads the necessary files to handle errors and exceptions smoothly. Then, it grabs environment variables from a special file (<strong>.env</strong>) where we store important settings like database information. After that, it tells the application to send back data in a specific format (JSON). Finally, it sets up a connection to the database using the information from the <strong>.env</strong> file. This setup ensures our application runs smoothly and securely.</p>
<p><strong>database.php</strong>:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Database</span>
</span>{
    <span class="hljs-keyword">private</span> ?PDO $conn = <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $host,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $name,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $user,
        <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $password
    </span>) </span>{
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getConnection</span>(<span class="hljs-params"></span>): ?<span class="hljs-title">PDO</span>
    </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;conn === <span class="hljs-literal">null</span>) {
                <span class="hljs-keyword">$this</span>-&gt;conn = <span class="hljs-keyword">new</span> PDO(<span class="hljs-string">"mysql:host=<span class="hljs-subst">$this</span>-&gt;host;dbname=<span class="hljs-subst">{$this-&gt;name}</span>"</span>, <span class="hljs-keyword">$this</span>-&gt;user, <span class="hljs-keyword">$this</span>-&gt;password);
                <span class="hljs-keyword">$this</span>-&gt;conn-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                <span class="hljs-keyword">$this</span>-&gt;conn-&gt;setAttribute(PDO::ATTR_EMULATE_PREPARES, <span class="hljs-literal">false</span>);
                <span class="hljs-keyword">$this</span>-&gt;conn-&gt;setAttribute(PDO::ATTR_STRINGIFY_FETCHES, <span class="hljs-literal">false</span>);
            }

            <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;conn;
        } <span class="hljs-keyword">catch</span> (PDOException $e) {
            <span class="hljs-keyword">echo</span> <span class="hljs-string">"Connection failed: "</span> . $e-&gt;getMessage();
            <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
        }
    }
}
</code></pre>
<p>Include an echo statement to indicate a successful database connection before returning the <code>$this-&gt;conn</code> object. This helps to verify the connection status and ensure smooth operation of the application. For instance:</p>
<pre><code class="lang-php"><span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">$this</span>-&gt;conn === <span class="hljs-literal">null</span>) {
        <span class="hljs-keyword">$this</span>-&gt;conn = <span class="hljs-keyword">new</span> PDO(<span class="hljs-string">"mysql:host=<span class="hljs-subst">$this</span>-&gt;host;dbname=<span class="hljs-subst">{$this-&gt;name}</span>"</span>, <span class="hljs-keyword">$this</span>-&gt;user, <span class="hljs-keyword">$this</span>-&gt;password);
        <span class="hljs-keyword">$this</span>-&gt;conn-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        <span class="hljs-keyword">$this</span>-&gt;conn-&gt;setAttribute(PDO::ATTR_EMULATE_PREPARES, <span class="hljs-literal">false</span>);
        <span class="hljs-keyword">$this</span>-&gt;conn-&gt;setAttribute(PDO::ATTR_STRINGIFY_FETCHES, <span class="hljs-literal">false</span>);

        <span class="hljs-comment">// Echo message indicating successful database connection</span>
        <span class="hljs-keyword">echo</span> <span class="hljs-string">"Database connected successfully."</span>;
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;conn;
} <span class="hljs-keyword">catch</span> (PDOException $e) {
    <span class="hljs-keyword">echo</span> <span class="hljs-string">"Connection failed: "</span> . $e-&gt;getMessage();
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
<p>Proceed to the <strong>index.php</strong> file to invoke the <code>getConnection</code> function and verify the application's functionality. It's important to note that we've initialized our <code>Database</code> class in our bootstrap PHP file, ensuring seamless integration and operation.</p>
<p>Invoking the <code>getConnection</code> function in the <strong>index.php</strong> file should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_YrpE0hGl-qf8QB8pChAFdA.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>index.php file</em></p>
<p>Upon successfully implementing the database connection and firing our request, you can expect the following response:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_hnCfjp2hp1Gzf2gkuey_nA.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>database connected successfully</em></p>
<p><strong>Note</strong>: Make sure you clear the echo after we are done.</p>
<h2 id="heading-registering-users">Registering Users</h2>
<p>To efficiently manage user data, we will implement a minimal frontend solution by creating a new file named <a target="_blank" href="https://github.com/Oghenekparobo/php_auth_jwt_tut/blob/main/register.php"><strong>register.php</strong></a> in the root directory of our project. Additionally, we will introduce a stylesheet named <a target="_blank" href="https://github.com/Oghenekparobo/php_auth_jwt_tut/blob/main/style.css"><strong>style.css</strong></a> to enhance the visual presentation of the registration page. </p>
<p>We will establish a connection to our database, facilitating the seamless addition of users to the user table within our college database. Upon successful user registration, a confirmation message will be echoed to affirm the addition of the user to the database.</p>
<p><strong>register.php</strong>:</p>
<pre><code class="lang-php"><span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/vendor/autoload.php"</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">"REQUEST_METHOD"</span>] === <span class="hljs-string">"POST"</span>) {

    $dotenv = Dotenv\Dotenv::createImmutable(<span class="hljs-keyword">__DIR__</span>);
    $dotenv-&gt;load();

    $database = <span class="hljs-keyword">new</span> Database(
        $_ENV[<span class="hljs-string">"DB_HOST"</span>],
        $_ENV[<span class="hljs-string">"DB_NAME"</span>],
        $_ENV[<span class="hljs-string">"DB_USER"</span>],
        $_ENV[<span class="hljs-string">"DB_PASS"</span>]
    );

    $conn = $database-&gt;getConnection();

    $sql = <span class="hljs-string">"INSERT INTO user (name, username, password_hash)
            VALUES (:name, :username, :password_hash)"</span>;

    $stmt = $conn-&gt;prepare($sql);

    $password_hash = password_hash($_POST[<span class="hljs-string">"password"</span>], PASSWORD_DEFAULT);


    $stmt-&gt;bindValue(<span class="hljs-string">":name"</span>, $_POST[<span class="hljs-string">"name"</span>], PDO::PARAM_STR);
    $stmt-&gt;bindValue(<span class="hljs-string">":username"</span>, $_POST[<span class="hljs-string">"username"</span>], PDO::PARAM_STR);
    $stmt-&gt;bindValue(<span class="hljs-string">":password_hash"</span>, $password_hash, PDO::PARAM_STR);


    $stmt-&gt;execute();

    <span class="hljs-keyword">echo</span> <span class="hljs-string">"Thank you for registering."</span>;
    <span class="hljs-keyword">exit</span>;
}

<span class="hljs-meta">?&gt;</span>
&lt;!DOCTYPE html&gt;
&lt;html lang=<span class="hljs-string">"en"</span>&gt;

&lt;head&gt;
    &lt;meta charset=<span class="hljs-string">"UTF-8"</span>&gt;
    &lt;meta name=<span class="hljs-string">"viewport"</span> content=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;
    &lt;title&gt;User Registration&lt;/title&gt;
    &lt;link rel=<span class="hljs-string">"stylesheet"</span> href=<span class="hljs-string">"style.css"</span>&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;div <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">container</span>"&gt;
        &lt;<span class="hljs-title">h2</span>&gt;<span class="hljs-title">User</span> <span class="hljs-title">Registration</span>&lt;/<span class="hljs-title">h2</span>&gt;
        &lt;<span class="hljs-title">form</span> <span class="hljs-title">action</span>="<span class="hljs-title">register</span>.<span class="hljs-title">php</span>" <span class="hljs-title">method</span>="<span class="hljs-title">post</span>"&gt;
            &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">form</span>-<span class="hljs-title">group</span>"&gt;
                &lt;<span class="hljs-title">label</span> <span class="hljs-title">for</span>="<span class="hljs-title">name</span>"&gt;<span class="hljs-title">Name</span>:&lt;/<span class="hljs-title">label</span>&gt;
                &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">text</span>" <span class="hljs-title">id</span>="<span class="hljs-title">name</span>" <span class="hljs-title">name</span>="<span class="hljs-title">name</span>" <span class="hljs-title">required</span>&gt;
            &lt;/<span class="hljs-title">div</span>&gt;
            &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">form</span>-<span class="hljs-title">group</span>"&gt;
                &lt;<span class="hljs-title">label</span> <span class="hljs-title">for</span>="<span class="hljs-title">username</span>"&gt;<span class="hljs-title">Username</span>:&lt;/<span class="hljs-title">label</span>&gt;
                &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">text</span>" <span class="hljs-title">id</span>="<span class="hljs-title">username</span>" <span class="hljs-title">name</span>="<span class="hljs-title">username</span>" <span class="hljs-title">required</span>&gt;
            &lt;/<span class="hljs-title">div</span>&gt;
            &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">form</span>-<span class="hljs-title">group</span>"&gt;
                &lt;<span class="hljs-title">label</span> <span class="hljs-title">for</span>="<span class="hljs-title">password</span>"&gt;<span class="hljs-title">Password</span>:&lt;/<span class="hljs-title">label</span>&gt;
                &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">password</span>" <span class="hljs-title">id</span>="<span class="hljs-title">password</span>" <span class="hljs-title">name</span>="<span class="hljs-title">password</span>" <span class="hljs-title">required</span>&gt;
            &lt;/<span class="hljs-title">div</span>&gt;
            &lt;<span class="hljs-title">div</span> <span class="hljs-title">class</span>="<span class="hljs-title">form</span>-<span class="hljs-title">group</span>"&gt;
                &lt;<span class="hljs-title">input</span> <span class="hljs-title">type</span>="<span class="hljs-title">submit</span>" <span class="hljs-title">value</span>="<span class="hljs-title">Register</span>"&gt;
            &lt;/<span class="hljs-title">div</span>&gt;
        &lt;/<span class="hljs-title">form</span>&gt;
    &lt;/<span class="hljs-title">div</span>&gt;
&lt;/<span class="hljs-title">body</span>&gt;

&lt;/<span class="hljs-title">html</span>&gt;</span>
</code></pre>
<p><strong>style.css</strong>:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span>,
<span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">font-family</span>: Arial, sans-serif;
}

<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8px</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">10px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">300px</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto;
}

<span class="hljs-selector-tag">h2</span> {
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.form-group</span> {
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-tag">label</span> {
  <span class="hljs-attribute">font-weight</span>: bold;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">"text"</span>]</span>,
<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">"password"</span>]</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">8px</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ccc</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">"submit"</span>]</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#007bff</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">"submit"</span>]</span><span class="hljs-selector-pseudo">:hover</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#0056b3</span>;
}
</code></pre>
<p>Note: Ensure that these files are placed in the root directory of your project. The user interface will appear as follows:</p>
<p>Registration process:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_KOO1tlf51t0fBLoYvVm9-w.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>user registration form</em></p>
<p>Successful registration:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_elpUg7Wz7NIguur_xKYU6w.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>successful registration page</em></p>
<p>Our database structure is illustrated in the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_ZWe06DjCYU3iorRAGBGi8w.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>database structure on phpMyAdmin</em></p>
<p>Kudos! You deserve a big glass of juice for getting to this point, now let’s get to the next part, which is creating an JWT from scratch!</p>
<h3 id="heading-setting-up-the-jwt-class">Setting up the JWT Class</h3>
<p>In our project template, the <strong>Jwt.php</strong> file has already been created. Now, let’s proceed to create our <code>Jwt</code> class and implement the logic for encoding and generating a JWT token.</p>
<h3 id="heading-encoding-to-jwt">Encoding To JWT</h3>
<p>In order to create a JWT, we need to convert our header, payload, and signature to base64url encoding. However, PHP doesn’t support the Base64URL standard, Therefore, we will develop our custom Base64URL encoding method to perform the necessary encoding operation.</p>
<p>Please copy the following code snippet and paste it into the <code>Jwt</code> class located in the <strong>src</strong> folder.</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Jwt</span>
</span>{

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $key</span>)
    </span>{

    }


    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">base64URLEncode</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $text</span>): <span class="hljs-title">string</span>
    </span>{

        <span class="hljs-keyword">return</span> str_replace([<span class="hljs-string">'+'</span>, <span class="hljs-string">'/'</span>, <span class="hljs-string">'='</span>], [<span class="hljs-string">'-'</span>, <span class="hljs-string">'_'</span>, <span class="hljs-string">''</span>], base64_encode($text));
    }


}
</code></pre>
<p>This class is responsible for encoding JWT tokens using the base64url encoding scheme. It includes a constructor that accepts a key parameter, which presumably represents the secret key used for encoding the tokens. Additionally, it contains a private method named <code>base64URLEncode</code>, which performs the base64URL encoding operation.</p>
<p><strong>The base64URLEncode Method:</strong> The base64urlEncode method is a private function within the <code>Jwt</code> class. It takes a string parameter, text, and returns the base64URL encoded version of the input string. The method first applies the standard base64 encoding to the input text using the base64_encode function.</p>
<p>Then, it replaces the characters ‘+’ (plus), ‘/’ (slash), and ‘=’ (equals sign) with ‘-’ (hyphen), ‘_’ (underscore), and an empty string, respectively. This substitution is necessary to ensure compatibility with the base64URL encoding scheme, which uses URL-safe characters. Finally, the method returns the base64URL encoded string.</p>
<p>Overall, the base64URLEncode method provides a crucial functionality for encoding data in JWT tokens using the base64URL encoding scheme, which is commonly used in JWT implementations.</p>
<h3 id="heading-the-encode-method">The encode Method</h3>
<p>Paste the following code snippet in your <code>Jwt</code> class:</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">encode</span>(<span class="hljs-params"><span class="hljs-keyword">array</span> $payload</span>): <span class="hljs-title">string</span>
    </span>{

        $header = json_encode([
            <span class="hljs-string">"alg"</span> =&gt; <span class="hljs-string">"HS256"</span>,
            <span class="hljs-string">"typ"</span> =&gt; <span class="hljs-string">"JWT"</span>
        ]);

        $header = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($header);
        $payload = json_encode($payload);
        $payload = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($payload);

        $signature = hash_hmac(<span class="hljs-string">"sha256"</span>, $header . <span class="hljs-string">"."</span> . $payload, <span class="hljs-keyword">$this</span>-&gt;key, <span class="hljs-literal">true</span>);
        $signature = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($signature);
        <span class="hljs-keyword">return</span> $header . <span class="hljs-string">"."</span> . $payload . <span class="hljs-string">"."</span> . $signature;
    }
</code></pre>
<p>First, we have a class called <code>Jwt</code>. This class helps us create JWT tokens, In the constructor of the <code>Jwt</code> class, we specified a secret key. This secret key is important for creating and verifying the tokens on the signature component.</p>
<p>The <code>encode</code> method is where the magic happens. It takes some data (which we call the payload) and turns it into a JWT token. Here’s how it works:</p>
<ol>
<li>We create a header for the token. This header contains information about how the token is encrypted and what type of token it is. We then turn this header into a base64URL format.</li>
<li>Next, we take the payload data (the information we want to include in the token) and turn that into a base64URL format too.</li>
<li>After that, we combine the encoded header and payload with our secret key to create a signature. This signature helps ensure that the token hasn’t been tampered with.</li>
<li>Finally, we put everything together; the encoded header, payload, and signature to create the final JWT token. This token is what we can use in our applications to authenticate users and authorize access to certain resources.</li>
</ol>
<p>The base64URLEncode method ensures that data is encoded in a format suitable for URLs, making it safe for transmission over the web. Within our <code>Jwt</code> class, this method is employed internally by the encode function to encode both the header and payload sections of the token.</p>
<p>With that being said, let’s proceed to test and see our first JWT token, hurray!</p>
<h3 id="heading-the-login-endpoint">The Login Endpoint</h3>
<p>In our project, the <strong>api</strong> folder serves as the entry point for requests. Now that we’ve implemented the algorithm to encode and create a JWT token, let’s proceed to test it. To do this, we’ll create a <strong>login.php</strong> file within our <strong>api</strong> folder. In this file, we’ll send a request containing the username and password of the user profiled or created in our frontend <strong>register.php</strong> UI. We’ll pass the required user details in JSON format:</p>
<pre><code class="lang-php">{
    <span class="hljs-string">"username"</span>: <span class="hljs-string">"test"</span>,
    <span class="hljs-string">"password"</span>: <span class="hljs-string">"12345"</span>
}
</code></pre>
<p>Please integrate the following code snippet into the <strong>login.php</strong> file located within our <strong>api</strong> directory:</p>
<pre><code class="lang-php">
<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/bootstrap.php'</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>] !== <span class="hljs-string">'POST'</span>) {
    http_response_code(<span class="hljs-number">405</span>);
    header(<span class="hljs-string">'ALLOW: POST'</span>);
    <span class="hljs-keyword">exit</span>();
}

$contentType = <span class="hljs-keyword">isset</span>($_SERVER[<span class="hljs-string">"CONTENT_TYPE"</span>]) ? trim($_SERVER[<span class="hljs-string">"CONTENT_TYPE"</span>]) : <span class="hljs-string">''</span>;


<span class="hljs-keyword">if</span> ($contentType !== <span class="hljs-string">'application/json'</span>) {
    http_response_code(<span class="hljs-number">415</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Only JSON content is supported"</span>]);
    <span class="hljs-keyword">exit</span>();
}

$data = json_decode(file_get_contents(<span class="hljs-string">'php://input'</span>), <span class="hljs-literal">true</span>);

<span class="hljs-keyword">if</span> ($data === <span class="hljs-literal">null</span>) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Invalid JSON data"</span>]);
    <span class="hljs-keyword">exit</span>();
}


<span class="hljs-keyword">if</span> (!array_key_exists(<span class="hljs-string">'username'</span>, $data) || !array_key_exists(<span class="hljs-string">'password'</span>, $data)) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Missing login credentials"</span>]);
    <span class="hljs-keyword">exit</span>();
}
</code></pre>
<p>This code snippet serves as the backend logic for handling user login requests. It begins by including the <strong>bootstrap.php</strong> file to initialize essential components. Then, it checks if the incoming request method is POST, returning a “Method Not Allowed” error if not. </p>
<p>Next, it verifies that the content type of the request is JSON, responding with an “Unsupported Media Type” error if not. The code proceeds to decode the JSON data from the request body and checks its validity. If the JSON data is invalid or lacks the “username” and “password” keys, it returns a “Bad Request” error.</p>
<p>Before proceeding with our login endpoint, we need to configure our <code>UserGateway</code> class, which is already available in our project template within the <strong>src</strong> folder. This class facilitates interaction with the user data in the database. The provided snippet initializes the class and defines a method <code>getByUsername()</code> to fetch user data based on the provided username.</p>
<pre><code class="lang-php">
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserGateway</span>
</span>{

    <span class="hljs-keyword">private</span> PDO $conn;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">Database $database</span>)
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;conn = $database-&gt;getConnection();
    }


    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getByUsername</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $username</span>): <span class="hljs-title">array</span> | <span class="hljs-title">false</span>
    </span>{
        $sql = <span class="hljs-string">'SELECT * FROM user WHERE username = :username'</span>;
        $stmt = <span class="hljs-keyword">$this</span>-&gt;conn-&gt;prepare($sql);
        $stmt-&gt;bindValue(<span class="hljs-string">':username'</span>, $username, PDO::PARAM_STR);

        $stmt-&gt;execute();

        <span class="hljs-keyword">return</span> $stmt-&gt;fetch(PDO::FETCH_ASSOC);
    }
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_Tc_Mdl0618eD5ZPmfv-mEA.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You will see the need for this as we go on.</p>
<p>Proceed to <strong>login.php</strong>.</p>
<p>Okay after that quick commercial break, we can create a class instance called <code>$user_gateway</code> and pass our <code>$database</code> connection to it. Next, we retrieve user data based on the provided username from the <code>$user_gateway</code> instance using the <code>getByUsername()</code> method. If no user is found (indicating invalid authentication), we return a 401 HTTP response status along with a corresponding error message in JSON format. </p>
<p>We validate the provided password against the hashed password stored in the user data. If the password verification fails, we return a similar 401 status and error message. If authentication is successful, we construct a payload containing the user's ID and name. Subsequently, we create a JWT token by encoding the payload using the <code>Jwt</code> class instantiated with the secret key from the environment variables. Finally, we respond with the generated token in JSON format, allowing access to protected resources, which will be implemented in a later section.</p>
<p>The code to implement this logic would be the following:</p>
<pre><code class="lang-php">$user_gateway = <span class="hljs-keyword">new</span> UserGateway($database);

$user = $user_gateway-&gt;getByUsername($data[<span class="hljs-string">'username'</span>]);

<span class="hljs-keyword">if</span> ($user === <span class="hljs-literal">false</span>) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}

<span class="hljs-keyword">if</span> (!password_verify($data[<span class="hljs-string">'password'</span>], $user[<span class="hljs-string">'password_hash'</span>])) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}


$payload = [
    <span class="hljs-string">"id"</span> =&gt; $user[<span class="hljs-string">'id'</span>],
    <span class="hljs-string">"name"</span> =&gt; $user[<span class="hljs-string">"name"</span>]
];


$JwtController = <span class="hljs-keyword">new</span> Jwt($_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);

$token =$$JwtController-&gt;encode($payload);

<span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"token"</span> =&gt; $token]);
</code></pre>
<p>Full <strong>login.php</strong> code:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/bootstrap.php'</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>] !== <span class="hljs-string">'POST'</span>) {
    http_response_code(<span class="hljs-number">405</span>);
    header(<span class="hljs-string">'ALLOW: POST'</span>);
    <span class="hljs-keyword">exit</span>();
}

$contentType = <span class="hljs-keyword">isset</span>($_SERVER[<span class="hljs-string">"CONTENT_TYPE"</span>]) ? trim($_SERVER[<span class="hljs-string">"CONTENT_TYPE"</span>]) : <span class="hljs-string">''</span>;


<span class="hljs-keyword">if</span> ($contentType !== <span class="hljs-string">'application/json'</span>) {
    http_response_code(<span class="hljs-number">415</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Only JSON content is supported"</span>]);
    <span class="hljs-keyword">exit</span>();
}

$data = json_decode(file_get_contents(<span class="hljs-string">'php://input'</span>), <span class="hljs-literal">true</span>);

<span class="hljs-keyword">if</span> ($data === <span class="hljs-literal">null</span>) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Invalid JSON data"</span>]);
    <span class="hljs-keyword">exit</span>();
}


<span class="hljs-keyword">if</span> (!array_key_exists(<span class="hljs-string">'username'</span>, $data) || !array_key_exists(<span class="hljs-string">'password'</span>, $data)) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Missing login credentials"</span>]);
    <span class="hljs-keyword">exit</span>();
}

$user_gateway = <span class="hljs-keyword">new</span> UserGateway($database);

$user = $user_gateway-&gt;getByUsername($data[<span class="hljs-string">'username'</span>]);

<span class="hljs-keyword">if</span> ($user === <span class="hljs-literal">false</span>) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}

<span class="hljs-keyword">if</span> (!password_verify($data[<span class="hljs-string">'password'</span>], $user[<span class="hljs-string">'password_hash'</span>])) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}


<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/tokens.php"</span>;

$refresh_token_gateway = <span class="hljs-keyword">new</span> RefreshTokenGateway($database, $_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);

$refresh_token_gateway-&gt;create($refresh_token, $refresh_token_expiry);
</code></pre>
<p>Now that we have set up our login endpoint, established database connections, and implemented the JWT encoding algorithm, nothing stands in our way of obtaining our first JWT token. Let us proceed to test our application with the following steps:</p>
<ol>
<li>Please navigate to our user interface for registering users. The URL should be <a target="_blank" href="http://localhost/php_auth_jwt_tut/register.php">http://localhost/php_auth_jwt_tut/register.php</a> if you followed the project structure.</li>
<li>Send the username and password of the created user to the login endpoint (<a target="_blank" href="http://localhost/php_auth_jwt_tut/register.php">http://localhost/php_auth_jwt_tut/api/login.php</a>) in JSON format, like this, and fire the request:</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_Yrpa_En9sjEKsK9ruO_jhg.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>endpoint testing</em></p>
<p>Voila! Just like that, we obtain our JWT token!</p>
<h2 id="heading-protected-resources-and-decoding-json-web-tokens">Protected Resources And Decoding JSON Web Tokens</h2>
<p>Having successfully generated a JWT token, let us now explore how we can safeguard our resources and verify the token’s contents by decoding it.</p>
<p>You’ll find that our controller classes, <code>StudentController.php</code>, and the gateway class <code>StudentGateway.php</code>, situated in the <strong>src</strong> folder, has already been configured with essential methods. Now, all that's left is to instantiate these classes in our <strong>index.php</strong>, serving as the entry point for our requests in the <strong>api</strong> folder.</p>
<p>To do this add the following code snippet in the <strong>index.php</strong> file located at the <strong>api</strong> folder of our project:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/bootstrap.php'</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>] !== <span class="hljs-string">'POST'</span>) {
    http_response_code(<span class="hljs-number">405</span>);
    header(<span class="hljs-string">'ALLOW: POST'</span>);
    <span class="hljs-keyword">exit</span>();
}

$contentType = <span class="hljs-keyword">isset</span>($_SERVER[<span class="hljs-string">"CONTENT_TYPE"</span>]) ? trim($_SERVER[<span class="hljs-string">"CONTENT_TYPE"</span>]) : <span class="hljs-string">''</span>;


<span class="hljs-keyword">if</span> ($contentType !== <span class="hljs-string">'application/json'</span>) {
    http_response_code(<span class="hljs-number">415</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Only JSON content is supported"</span>]);
    <span class="hljs-keyword">exit</span>();
}

$data = json_decode(file_get_contents(<span class="hljs-string">'php://input'</span>), <span class="hljs-literal">true</span>);

<span class="hljs-keyword">if</span> ($data === <span class="hljs-literal">null</span>) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Invalid JSON data"</span>]);
    <span class="hljs-keyword">exit</span>();
}


<span class="hljs-keyword">if</span> (!array_key_exists(<span class="hljs-string">'username'</span>, $data) || !array_key_exists(<span class="hljs-string">'password'</span>, $data)) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Missing login credentials"</span>]);
    <span class="hljs-keyword">exit</span>();
}

$user_gateway = <span class="hljs-keyword">new</span> UserGateway($database);

$user = $user_gateway-&gt;getByUsername($data[<span class="hljs-string">'username'</span>]);

<span class="hljs-keyword">if</span> ($user === <span class="hljs-literal">false</span>) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}

<span class="hljs-keyword">if</span> (!password_verify($data[<span class="hljs-string">'password'</span>], $user[<span class="hljs-string">'password_hash'</span>])) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}


$payload = [
    <span class="hljs-string">"id"</span> =&gt; $user[<span class="hljs-string">'id'</span>],
    <span class="hljs-string">"name"</span> =&gt; $user[<span class="hljs-string">"name"</span>]
];


$JwtController = <span class="hljs-keyword">new</span> Jwt($_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);

$token =$JwtController-&gt;encode($payload);

<span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"token"</span> =&gt; $token]);

$user = <span class="hljs-keyword">new</span> UserGateway($database);


$gateway = <span class="hljs-keyword">new</span> StudentGateway($database);

$controller = <span class="hljs-keyword">new</span> StudentController($gateway);


$controller-&gt;processRequest($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>]);
</code></pre>
<p>How the files are structured at this current stage:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1_MAuYnkgxspnOmgDINUvkSQ.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>file structure on VS Code</em></p>
<p>Please note that upon testing the endpoint (<a target="_blank" href="http://localhost/phpAuthJWT/api">http://localhost/phpAuthJWT/api</a>) at this point, you’ll receive the following result, without any restrictions applied:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1__c8i8N9Vm4MGaZK4alfnQA.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>endpoint testing</em></p>
<p>Note: After setting up the database connection and importing the provided file, <strong>college.sql</strong>, as instructed, the tables, including the “students” table, are populated with pre-added data. This enables us to view the student details that are currently visible.</p>
<h3 id="heading-what-happens-now">What Happens Now?</h3>
<p>We establish a custom URL endpoint to retrieve data via the GET HTTP method. The URL, <code>[http://localhost/phpAuthJWT/api/](http://localhost/phpAuthJWT/api/getALLStudents)getAllStudents</code>, will remain functional due to the server configuration specified in our <strong>.htaccess</strong> file located within the <strong>api</strong> folder. When making requests to this URL, we’ll include our token in the header using the standard HTTP Authorization request header, adhering to the bearer token format:</p>
<p>Authorization: Bearer </p>
<p>In our <strong>src</strong> folder, we have set up an Auth class where we will create a method to validate the JWT token. This method verifies if the token is provided in the HTTP header and decodes it.</p>
<h2 id="heading-how-to-set-up-the-decode-method-in-our-jwt-class">How to Set Up The Decode Method In Our JWT Class</h2>
<p>When setting up the decoding functionality in the <code>Jwt</code> class, as we did with the encoding method, we will ensure that our <code>Jwt</code> class, located in the <strong>src</strong> folder of our project within the <strong>jwt.php</strong> file handles this task. To achieve this, we will incorporate the following code snippets into our <code>Jwt</code> class – the new methods are the <code>decode</code> and <code>base64UrlDecode</code> methods, thus completing its structure. The final code will resemble the following:</p>
<pre><code class="lang-php">
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Jwt</span>
</span>{

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $key</span>)
    </span>{

    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">encode</span>(<span class="hljs-params"><span class="hljs-keyword">array</span> $payload</span>): <span class="hljs-title">string</span>
    </span>{

        $header = json_encode([
            <span class="hljs-string">"alg"</span> =&gt; <span class="hljs-string">"HS256"</span>,
            <span class="hljs-string">"typ"</span> =&gt; <span class="hljs-string">"JWT"</span>
        ]);

        $header = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($header);
        $payload = json_encode($payload);
        $payload = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($payload);

        $signature = hash_hmac(<span class="hljs-string">"sha256"</span>, $header . <span class="hljs-string">"."</span> . $payload, <span class="hljs-keyword">$this</span>-&gt;key, <span class="hljs-literal">true</span>);
        $signature = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($signature);
        <span class="hljs-keyword">return</span> $header . <span class="hljs-string">"."</span> . $payload . <span class="hljs-string">"."</span> . $signature;
    }



    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">decode</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $token</span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">if</span> (
            preg_match(
                <span class="hljs-string">"/^(?&lt;header&gt;.+)\.(?&lt;payload&gt;.+)\.(?&lt;signature&gt;.+)$/"</span>,
                $token,
                $matches
            ) !== <span class="hljs-number">1</span>
        ) {

            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">InvalidArgumentException</span>(<span class="hljs-string">"invalid token format"</span>);
        }

        $signature = hash_hmac(
            <span class="hljs-string">"sha256"</span>,
            $matches[<span class="hljs-string">"header"</span>] . <span class="hljs-string">"."</span> . $matches[<span class="hljs-string">"payload"</span>],
            <span class="hljs-keyword">$this</span>-&gt;key,
            <span class="hljs-literal">true</span>
        );

        $signature_from_token = <span class="hljs-keyword">$this</span>-&gt;base64URLDecode($matches[<span class="hljs-string">"signature"</span>]);

        <span class="hljs-keyword">if</span> (!hash_equals($signature, $signature_from_token)) {

            <span class="hljs-comment">// throw new Exception("signature doesn't match");</span>
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidSignatureException;
        }

        $payload = json_decode(<span class="hljs-keyword">$this</span>-&gt;base64URLDecode($matches[<span class="hljs-string">"payload"</span>]), <span class="hljs-literal">true</span>);

        <span class="hljs-keyword">return</span> $payload;
    }


    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">base64URLEncode</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $text</span>): <span class="hljs-title">string</span>
    </span>{

        <span class="hljs-keyword">return</span> str_replace([<span class="hljs-string">'+'</span>, <span class="hljs-string">'/'</span>, <span class="hljs-string">'='</span>], [<span class="hljs-string">'-'</span>, <span class="hljs-string">'_'</span>, <span class="hljs-string">''</span>], base64_encode($text));
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">base64URLDecode</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $text</span>): <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-keyword">return</span> base64_decode(
            str_replace(
                [<span class="hljs-string">"-"</span>, <span class="hljs-string">"_"</span>],
                [<span class="hljs-string">"+"</span>, <span class="hljs-string">"/"</span>],
                $text
            )
        );
    }


}
</code></pre>
<h3 id="heading-decode-method">Decode Method:</h3>
<p>The <code>decode</code> method is responsible for decoding a JWT token into its respective header and payload components. Here's a brief overview of what it does:</p>
<ol>
<li><strong>Token Validation</strong>: First, it verifies if the provided token follows the expected format of three sections separated by periods.</li>
<li><strong>Signature Verification</strong>: It recalculates the signature based on the header and payload from the token and compares it with the signature provided in the token. This step ensures the integrity of the token.</li>
<li><strong>Payload Extraction</strong>: If the signature verification passes, it decodes the payload component of the token from base64 URL encoding into a JSON format. This decoded payload contains information about the user associated with the token.</li>
<li>Finally, it returns the decoded payload as an associative array.</li>
</ol>
<h3 id="heading-base64urldecode-method">base64URLDecode Method:</h3>
<p>The <code>base64URLDecode</code> method is a helper function used specifically for decoding strings that have been encoded using base64 URL encoding. Here's a breakdown of its functionality:</p>
<ol>
<li><strong>Replace Characters</strong>: It first replaces the characters <code>-</code> and <code>_</code> in the encoded string with <code>+</code> and <code>/</code> respectively. This step is necessary because URL encoding replaces certain characters for safe transmission over the web.</li>
<li><strong>Base64 Decoding</strong>: After character replacement, it performs the standard base64 decoding operation on the modified string.</li>
<li>Finally, it returns the decoded string.</li>
</ol>
<p>In summary, the <code>decode</code> method validates and extracts the payload from a JWT token, while the <code>base64URLDecode</code> method assists in decoding strings encoded using base64 URL encoding, ensuring the integrity and accuracy of the decoded data.</p>
<h3 id="heading-protected-resources">Protected Resources</h3>
<p>Now that we have completed the setup, let’s finalize our <code>Jwt</code> class. It’s essential to restrict access to our endpoints without the required authorization header. For instance, accessing the URL <code>[http://localhost/phpAuthJWT/api/](http://localhost/phpAuthJWT/api/getALLStudents)getAllStudents</code> should be restricted if the necessary authorization header is absent, and access to resources should be denied if the URL is incorrect.</p>
<p>To achieve this, add the following code snippet to the top of your <strong>index.php</strong> file, which serves as the entry point for accessing our student data. Paste this code after importing the <strong>bootstrap.php</strong> configuration file.</p>
<pre><code class="lang-php"><span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/bootstrap.php'</span>;

$path = parse_url($_SERVER[<span class="hljs-string">"REQUEST_URI"</span>], PHP_URL_PATH);

$parts = explode(<span class="hljs-string">"/"</span>, $path);


$resource = $parts[<span class="hljs-number">3</span>];

$id = $parts[<span class="hljs-number">4</span>] ?? <span class="hljs-literal">null</span>;

<span class="hljs-keyword">if</span> ($resource != <span class="hljs-string">"getAllStudents"</span>) {

    http_response_code(<span class="hljs-number">404</span>);
    <span class="hljs-keyword">exit</span>;
}
</code></pre>
<p>This snippet shows how we extracted the path from the requested URI using the <code>parse_url()</code> function, isolating the endpoint accessed by the user. Then splitting the path into segments using the <code>explode()</code> function, allowing us to identify the requested resource. If the requested resource is not “getAllStudents”, indicating an invalid endpoint, the code responds with a 404 Not Found status code, signaling that the requested resource does not exist. This ensures that only valid endpoints can be accessed, preventing unauthorized access to our API’s resources.</p>
<p>Note: To verify that our project is functioning as intended, send a request to the “getAllStudents” endpoint at http://localhost/phpAuthJWT/api/getAllStudents</p>
<p>This request will help us ensure that our API is correctly configured and capable of retrieving all student data.</p>
<h3 id="heading-checking-the-headers-for-the-correct-authorization-scheme">Checking The Headers For The Correct Authorization Scheme</h3>
<p>We have established a custom URL, but it is crucial to verify that the JWT token provided in the header is valid. To accomplish this, we will utilize the Auth class, which is already available in our project’s <strong>src</strong> folder. This class, which was provided with our project template, will assist in ensuring the integrity of the JWT token.</p>
<p><strong>Auth.php</strong>:</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Auth</span>
</span>{



    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> UserGateway $user_gateway, <span class="hljs-keyword">private</span> Jwt $JwtCtrl</span>)
    </span>{
    }



    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">authenticateJWTToken</span>(<span class="hljs-params"></span>): <span class="hljs-title">bool</span>
    </span>{

        <span class="hljs-keyword">if</span> (!preg_match(<span class="hljs-string">"/^Bearer\s+(.*)$/"</span>, $_SERVER[<span class="hljs-string">"HTTP_AUTHORIZATION"</span>], $matches)) {
            http_response_code(<span class="hljs-number">400</span>);
            <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"incomplete authorization header"</span>]);
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }

        <span class="hljs-keyword">try</span> {
            $data = <span class="hljs-keyword">$this</span>-&gt;JwtCtrl-&gt;decode($matches[<span class="hljs-number">1</span>]);
        } <span class="hljs-keyword">catch</span> (InvalidSignatureException) {

            http_response_code(<span class="hljs-number">401</span>);
            <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid signature"</span>]);
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        } <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Exception</span> $e) {

            http_response_code(<span class="hljs-number">400</span>);
            <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; $e-&gt;getMessage()]);
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }



        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
}
</code></pre>
<p>This class is responsible for handling the authentication of JWT tokens. Within the class, we have a constructor method that initializes the <code>Auth</code> object with instances of two other classes: <code>UserGateway</code> and <code>Jwt</code>.</p>
<p>Absolutely! Let’s break down the code snippet in a more detailed and narrative manner:</p>
<p>In the provided PHP code snippet, we defined a class named <code>Auth</code>. This class is responsible for handling the authentication of JWT tokens. Within the class, we have a constructor method that initializes the <code>Auth</code> object with instances of two other classes: <code>UserGateway</code> and <code>Jwt</code>.</p>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Auth</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> UserGateway $user_gateway, <span class="hljs-keyword">private</span> Jwt $JwtCtrl</span>)
    </span>{
    }
    <span class="hljs-comment">// Other methods will go here...</span>
}
</code></pre>
<p>The constructor method allows the <code>Auth</code> class to interact with user data through the <code>UserGateway</code> class and handle JWT tokens using the <code>Jwt</code> class.</p>
<p>Next, we have a method called <code>authenticateJWTToken()</code>, which is tasked with verifying the validity of a JWT token present in the HTTP authorization header of incoming requests.</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">authenticateJWTToken</span>(<span class="hljs-params"></span>): <span class="hljs-title">bool</span>
</span>{

}
</code></pre>
<p>Within the <code>authenticateJWTToken()</code> method, the code first checks if the authorization header is properly formatted and contains a valid JWT token.</p>
<pre><code class="lang-php"><span class="hljs-keyword">if</span> (!preg_match(<span class="hljs-string">"/^Bearer\s+(.*)$/"</span>, $_SERVER[<span class="hljs-string">"HTTP_AUTHORIZATION"</span>], $matches)) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"incomplete authorization header"</span>]);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p>If the authorization header is incomplete or improperly formatted, the method returns a 400 Bad Request response along with a message indicating the issue.</p>
<p>Next, the code attempts to decode the JWT token using the <code>decode()</code> method of the <code>Jwt</code> class. If the decoding process fails due to an invalid signature or any other exception, appropriate HTTP response codes and error messages are returned.</p>
<pre><code class="lang-php"><span class="hljs-keyword">try</span> {
    $data = <span class="hljs-keyword">$this</span>-&gt;JwtCtrl-&gt;decode($matches[<span class="hljs-number">1</span>]);
} <span class="hljs-keyword">catch</span> (InvalidSignatureException) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid signature"</span>]);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
} <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Exception</span> $e) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; $e-&gt;getMessage()]);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p>If the JWT token is successfully decoded without any exceptions, the method returns <code>true</code>, indicating that the authentication process was successful.</p>
<p>The <code>authenticateJWTToken()</code> method ensures that incoming requests contain a valid JWT token in the Authorization header and handles various error scenarios gracefully to provide appropriate feedback to clients interacting with the API.</p>
<h2 id="heading-creating-instances-in-the-api-entry-point">Creating Instances In The API Entry Point</h2>
<p>Now that we have finished setting up our methods let us add our class instances to enable the protection of our resources from unauthorized users.</p>
<p><strong>index.php</strong>:</p>
<pre><code class="lang-php">
<span class="hljs-keyword">declare</span>(strict_types=<span class="hljs-number">1</span>);

<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/bootstrap.php'</span>;

$path = parse_url($_SERVER[<span class="hljs-string">"REQUEST_URI"</span>], PHP_URL_PATH);

$parts = explode(<span class="hljs-string">"/"</span>, $path);


$resource = $parts[<span class="hljs-number">3</span>];

<span class="hljs-keyword">if</span> ($resource != <span class="hljs-string">"getAllStudents"</span>) {

    http_response_code(<span class="hljs-number">404</span>);
    <span class="hljs-keyword">exit</span>;
}


$user = <span class="hljs-keyword">new</span> UserGateway($database);


$JwtCtrl = <span class="hljs-keyword">new</span> Jwt($_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);

$auth = <span class="hljs-keyword">new</span> Auth($user, $JwtCtrl);

<span class="hljs-keyword">if</span> (!$auth-&gt;authenticateJWTToken()) {
    <span class="hljs-keyword">exit</span>;
}



$gateway = <span class="hljs-keyword">new</span> StudentGateway($database);

$controller = <span class="hljs-keyword">new</span> StudentController($gateway);



$controller-&gt;processRequest($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>]);
</code></pre>
<p>Once we’ve incorporated the provided snippet into our <strong>index.php</strong>, it's crucial to observe the different scenarios that occur when we access our API endpoint at <code>http://localhost/phpAuthJWT/api/getAllStudents</code>.</p>
<p>By accessing this URL, we can witness several possible outcomes, each indicative of a different state or functionality within our application. These outcomes may include:</p>
<ol>
<li><strong>Successful Response</strong>: If the authentication process is successful and the JWT token is valid, the API should return a response containing the desired data, such as a list of all students.</li>
<li><strong>Invalid Token</strong>: In case the JWT token provided in the request’s Authorization header is invalid, expired, or improperly formatted, the API should respond with an error message indicating the issue. This ensures that only authorized users can access the protected resources.</li>
<li><strong>Unauthorized Access</strong>: If the request does not include a JWT token or lacks proper authorization, the API should respond with a 401 Unauthorized status code, indicating that access to the requested resource is restricted.</li>
<li><strong>Invalid Endpoint</strong>: If the URL provided does not match any of the defined endpoints or routes within our application, the API should respond with a 404 Not Found status code, signaling that the requested resource does not exist.</li>
</ol>
<p>By examining these outcomes, we can gain insights into the functionality and reliability of our API, ensuring that it behaves as intended and provides appropriate responses to different types of requests and scenarios.</p>
<p>Working properly with Authorization Header: <code>http://localhost/phpAuthJWT/api/getAllStudents</code></p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*KpQHCYFFD7qN7j2gjTvaBg.png" alt="Image" width="700" height="331" loading="lazy">
<em>endpoint testing</em></p>
<p>Not working properly without Authorization Header: <code>http://localhost/phpAuthJWT/api/getAllStudents</code></p>
<p><img src="https://miro.medium.com/v2/resize:fit:700/1*BCtXpT7RiFoMq2IshlTl3Q.png" alt="Image" width="700" height="305" loading="lazy">
<em>endpoint testing</em></p>
<h2 id="heading-suggestions">Suggestions</h2>
<p>After setting up our JWT, there’s a whole new world to explore. You can experiment with our API by creating custom URLs for specific tasks, such as finding students by name or letting users create and update their own student profiles by tracking the <code>user_id</code> of the user. You can use various HTTP methods like GET, POST, PATCH, and DELETE to manage data effectively. While this article covers the basics, there’s an abundance of possibilities waiting to be explored when comes to creating a robust API.</p>
<p>JWT tokens provide a convenient and efficient way to handle authentication and authorization in web applications. However, it’s crucial to recognize that they are not absolutely foolproof. It’s essential to avoid putting sensitive information in the payload component of the token, as the payload is typically base64URLEncoded and can be easily decoded. Additionally, the secret key used to sign the token should be kept hidden and never exposed to public information, as it can compromise the security of the system.</p>
<p>In JWT tokens, the header, payload, and signature are all base64URLEncoded, ensuring compatibility with URLs and safe transmission over the web. However, it’s important to note that JWT tokens should have an expiration time to mitigate the risk of token misuse. In the next part, we will explore how to implement token expiration and introduce refresh tokens to enhance the security of our authentication system. </p>
<p>We have explored the implementation of JSON Web Tokens (JWTs) and learned how to utilize them. However, a significant security concern persists: our tokens, specifically referred to as access tokens in this context, can currently access our resources indefinitely. This practice does not align with industry standards. To enhance security, we should implement token expiration for our JWTs. Additionally, adopting a two-token system comprising a refresh token alongside our access token is recommended.</p>
<h2 id="heading-how-to-implement-token-expiration">How to Implement Token Expiration</h2>
<p><img src="https://miro.medium.com/v2/resize:fit:630/1*iexXyX3pAwzlv3M-YPQJsg.jpeg" alt="Image" width="630" height="630" loading="lazy"></p>
<p>We'll focus on implementing access tokens and refresh tokens. Any necessary additions to our project or database structure will be introduced as we progress through the implementation.</p>
<p>Let's get right into it!</p>
<p>Access tokens must have an expiration mechanism. We need our JWT tokens to automatically expire after a short period, requiring users to request a new token once it expires. </p>
<p>Prompting users to log in every minute when the token expires is not user-friendly. Instead, we can issue a refresh token. The refresh token typically has a longer lifespan than the access token. When the access token expires, the client can leverage the refresh token to obtain a new access token. We will incorporate an endpoint for the client to refresh the access token seamlessly.</p>
<p>Continuing from where we left off, we will now create a refresh endpoint in our <strong>api</strong> folder. As we know this endpoint serves as our entry point for handling requests related to token refreshing and will be named <strong>refresh.php</strong>.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">declare</span>(strict_types=<span class="hljs-number">1</span>);

<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/bootstrap.php"</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">"REQUEST_METHOD"</span>] !== <span class="hljs-string">"POST"</span>) {

    http_response_code(<span class="hljs-number">405</span>);
    header(<span class="hljs-string">"Allow: POST"</span>);
    <span class="hljs-keyword">exit</span>;
}

$data = (<span class="hljs-keyword">array</span>) json_decode(file_get_contents(<span class="hljs-string">"php://input"</span>), <span class="hljs-literal">true</span>);

<span class="hljs-keyword">if</span> ( ! array_key_exists(<span class="hljs-string">"token"</span>, $data)) {

    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"missing token"</span>]);
    <span class="hljs-keyword">exit</span>;
}

$JwtController = <span class="hljs-keyword">new</span> Jwt($_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);
</code></pre>
<p>It checks if the incoming request method is POST; otherwise, it responds with a 405 HTTP status code and allows only POST requests. The script then parses JSON data from the request body, ensuring it contains a “token” key. If the token is missing, it responds with a 400 status code and a JSON message indicating the absence of the token. Finally, the script initializes a <code>Jwt</code> object with a secret key from the environment variables for further token processing.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:630/1*qPsrno17jnQB-TiKQztLVQ.png" alt="Image" width="630" height="230" loading="lazy">
<em>refresh.php file</em></p>
<p>Before proceeding with the setup of our refresh endpoint, we will create a class called <code>RefreshTokenGateway.php</code> to handle operations related to refreshing tokens. The <code>RefreshTokenGateway</code> class includes methods for creating, deleting, fetching, and managing expired refresh tokens within our database.</p>
<p>The <code>RefreshTokenGateway</code> class utilizes a PDO connection and a secret key for hashing tokens. Its constructor initializes the database connection and secret key variables. The <code>create</code> method generates a hash for the token and inserts it into the <code>refresh_token</code> table along with its expiration time. The <code>delete</code> method removes a token from the database based on its hash value. The <code>getByToken</code> method retrieves token details based on its hash. Lastly, the <code>deleteExpired</code> method deletes expired tokens from the database, ensuring efficient token management.</p>
<p>Overall, the <code>RefreshTokenGateway</code> class provides essential functionality for maintaining and handling refresh tokens securely within our web application.</p>
<p><strong>RefreshTokenGateway.php</strong>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RefreshTokenGateway</span>
</span>{
    <span class="hljs-keyword">private</span> PDO $conn;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $key;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">Database $database, <span class="hljs-keyword">string</span> $key</span>)
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;conn = $database-&gt;getConnection();
        <span class="hljs-keyword">$this</span>-&gt;key = $key;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">create</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $token, <span class="hljs-keyword">int</span> $expiry</span>): <span class="hljs-title">bool</span>
    </span>{
        $hash = hash_hmac(<span class="hljs-string">"sha256"</span>, $token, <span class="hljs-keyword">$this</span>-&gt;key);

        $sql = <span class="hljs-string">"INSERT INTO refresh_token (token_hash, expires_at)
                VALUES (:token_hash, :expires_at)"</span>;

        $stmt = <span class="hljs-keyword">$this</span>-&gt;conn-&gt;prepare($sql);

        $stmt-&gt;bindValue(<span class="hljs-string">":token_hash"</span>, $hash, PDO::PARAM_STR);
        $stmt-&gt;bindValue(<span class="hljs-string">":expires_at"</span>, $expiry, PDO::PARAM_INT);

        <span class="hljs-keyword">return</span> $stmt-&gt;execute();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">delete</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $token</span>): <span class="hljs-title">int</span>
    </span>{
        $hash = hash_hmac(<span class="hljs-string">"sha256"</span>, $token, <span class="hljs-keyword">$this</span>-&gt;key);

        $sql = <span class="hljs-string">"DELETE FROM refresh_token
                WHERE token_hash = :token_hash"</span>;

        $stmt = <span class="hljs-keyword">$this</span>-&gt;conn-&gt;prepare($sql);

        $stmt-&gt;bindValue(<span class="hljs-string">":token_hash"</span>, $hash, PDO::PARAM_STR);

        $stmt-&gt;execute();

        <span class="hljs-keyword">return</span> $stmt-&gt;rowCount();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getByToken</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $token</span>): <span class="hljs-title">array</span> | <span class="hljs-title">false</span>
    </span>{
        $hash = hash_hmac(<span class="hljs-string">"sha256"</span>, $token, <span class="hljs-keyword">$this</span>-&gt;key);

        $sql = <span class="hljs-string">"SELECT *
                FROM refresh_token
                WHERE token_hash = :token_hash"</span>;

        $stmt = <span class="hljs-keyword">$this</span>-&gt;conn-&gt;prepare($sql);

        $stmt-&gt;bindValue(<span class="hljs-string">":token_hash"</span>, $hash, PDO::PARAM_STR);

        $stmt-&gt;execute();

        <span class="hljs-keyword">return</span> $stmt-&gt;fetch(PDO::FETCH_ASSOC);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deleteExpired</span>(<span class="hljs-params"></span>): <span class="hljs-title">int</span>
    </span>{
        $sql = <span class="hljs-string">"DELETE FROM refresh_token
                WHERE expires_at &lt; UNIX_TIMESTAMP()"</span>;

        $stmt = <span class="hljs-keyword">$this</span>-&gt;conn-&gt;query($sql);

        <span class="hljs-keyword">return</span> $stmt-&gt;rowCount();
    }
}
</code></pre>
<h3 id="heading-updated-folder-structure">Updated Folder Structure</h3>
<p>From the code snippet provided for our <code>[RefreshTokenGateway](https://github.com/Oghenekparobo/php_auth_jwt_tut/blob/refresh-token/src/RefreshTokenGateway.php)</code> class, it's evident that a new table has been incorporated into our database. We have updated our <strong>college.sql</strong> file to accommodate this change. Kindly import the updated SQL file into your database, following the process outlined in the first part of this article.</p>
<p>Additionally, a new exception class named <code>TokenExpiredException</code> has been introduced. Ensure to update your project structure or files accordingly to include this new exception handling. This ensures that your project remains up-to-date and aligned with the latest changes in token management.</p>
<p>Before we finish setting up our refresh endpoint for obtaining a new access token after expiration, let’s integrate the retrieval of our refresh token and access token into our login endpoint. We have the <code>RefreshTokenGateway</code> class to manage refresh tokens, and we'll create the <strong>tokens.php</strong> file in our <strong>api</strong> folder for token creation, which will be used in both the refresh and login endpoints. This approach ensures a straightforward and unified token management process across our application.</p>
<p><strong>tokens.php</strong>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

$payload = [
    <span class="hljs-string">"sub"</span> =&gt; $user[<span class="hljs-string">"id"</span>],
    <span class="hljs-string">"name"</span> =&gt; $user[<span class="hljs-string">"name"</span>],
    <span class="hljs-string">"exp"</span> =&gt; time() + <span class="hljs-number">20</span>
];

$JwtController = <span class="hljs-keyword">new</span> Jwt($_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);

$access_token = $JwtController-&gt;encode($payload);

$refresh_token_expiry = time() + <span class="hljs-number">432000</span>;

$refresh_token = $JwtController-&gt;encode([
    <span class="hljs-string">"sub"</span> =&gt; $user[<span class="hljs-string">"id"</span>],
    <span class="hljs-string">"exp"</span> =&gt; $refresh_token_expiry
]);

<span class="hljs-keyword">echo</span> json_encode([
    <span class="hljs-string">"access_token"</span> =&gt; $access_token,
    <span class="hljs-string">"refresh_token"</span> =&gt; $refresh_token
]);
</code></pre>
<p>The main difference between the refresh token and the payload (access token claims) is that the payload contains detailed user information like ID and name, and its expiration is shorter (20 seconds) for security reasons. On the other hand, the refresh token only contains the user ID and has a longer expiration (5 days) to allow for longer-lasting authentication without needing frequent logins. This separation of tokens and their respective lifespans enhances security and user convenience in token-based authentication systems.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:630/1*0CqrZ5zsgvCHDyhiKRU53g.png" alt="Image" width="630" height="223" loading="lazy"></p>
<p><strong>login.php</strong>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/bootstrap.php'</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">'REQUEST_METHOD'</span>] !== <span class="hljs-string">'POST'</span>) {
    http_response_code(<span class="hljs-number">405</span>);
    header(<span class="hljs-string">'ALLOW: POST'</span>);
    <span class="hljs-keyword">exit</span>();
}

$contentType = <span class="hljs-keyword">isset</span>($_SERVER[<span class="hljs-string">"CONTENT_TYPE"</span>]) ? trim($_SERVER[<span class="hljs-string">"CONTENT_TYPE"</span>]) : <span class="hljs-string">''</span>;


<span class="hljs-keyword">if</span> ($contentType !== <span class="hljs-string">'application/json'</span>) {
    http_response_code(<span class="hljs-number">415</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Only JSON content is supported"</span>]);
    <span class="hljs-keyword">exit</span>();
}

$data = json_decode(file_get_contents(<span class="hljs-string">'php://input'</span>), <span class="hljs-literal">true</span>);

<span class="hljs-keyword">if</span> ($data === <span class="hljs-literal">null</span>) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Invalid JSON data"</span>]);
    <span class="hljs-keyword">exit</span>();
}


<span class="hljs-keyword">if</span> (!array_key_exists(<span class="hljs-string">'username'</span>, $data) || !array_key_exists(<span class="hljs-string">'password'</span>, $data)) {
    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"Missing login credentials"</span>]);
    <span class="hljs-keyword">exit</span>();
}

$user_gateway = <span class="hljs-keyword">new</span> UserGateway($database);

$user = $user_gateway-&gt;getByUsername($data[<span class="hljs-string">'username'</span>]);

<span class="hljs-keyword">if</span> ($user === <span class="hljs-literal">false</span>) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}

<span class="hljs-keyword">if</span> (!password_verify($data[<span class="hljs-string">'password'</span>], $user[<span class="hljs-string">'password_hash'</span>])) {
    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}


<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/tokens.php"</span>;

$refresh_token_gateway = <span class="hljs-keyword">new</span> RefreshTokenGateway($database, $_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);

$refresh_token_gateway-&gt;create($refresh_token, $refresh_token_expiry);
</code></pre>
<p>Testing our login endpoint with the right parameters should result in the following response:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:630/1*gSWQIGxsREf7xHoB0ZDpHQ.png" alt="Image" width="630" height="392" loading="lazy">
<em>endpoint testing</em></p>
<p>Note: Before we move on let us update our <code>Jwt</code> class, the <code>decode</code> function to be specific. The updated <code>decode</code> function in the <code>Jwt</code> class checks if a token has the correct format, ensuring it has a header, payload, and signature. It then verifies the token's signature to confirm it hasn't been tampered with. After that, it decodes the payload (containing user information and expiration time) from the token. Lastly, it checks if the token has expired, throwing an error if it has. Overall, these steps ensure the token is valid, unaltered, and within its expiration period for secure usage in the application.</p>
<p><code>Jwt</code> class:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Jwt</span>
</span>{

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> $key</span>)
    </span>{

    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">encode</span>(<span class="hljs-params"><span class="hljs-keyword">array</span> $payload</span>): <span class="hljs-title">string</span>
    </span>{

        $header = json_encode([
            <span class="hljs-string">"alg"</span> =&gt; <span class="hljs-string">"HS256"</span>,
            <span class="hljs-string">"typ"</span> =&gt; <span class="hljs-string">"JWT"</span>
        ]);

        $header = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($header);
        $payload = json_encode($payload);
        $payload = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($payload);

        $signature = hash_hmac(<span class="hljs-string">"sha256"</span>, $header . <span class="hljs-string">"."</span> . $payload, <span class="hljs-keyword">$this</span>-&gt;key, <span class="hljs-literal">true</span>);
        $signature = <span class="hljs-keyword">$this</span>-&gt;base64URLEncode($signature);
        <span class="hljs-keyword">return</span> $header . <span class="hljs-string">"."</span> . $payload . <span class="hljs-string">"."</span> . $signature;
    }



    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">decode</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $token</span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">if</span> (preg_match(<span class="hljs-string">"/^(?&lt;header&gt;.+)\.(?&lt;payload&gt;.+)\.(?&lt;signature&gt;.+)$/"</span>,
                   $token,
                   $matches) !== <span class="hljs-number">1</span>) {

            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">InvalidArgumentException</span>(<span class="hljs-string">"invalid token format"</span>);
        }

        $signature = hash_hmac(<span class="hljs-string">"sha256"</span>,
                               $matches[<span class="hljs-string">"header"</span>] . <span class="hljs-string">"."</span> . $matches[<span class="hljs-string">"payload"</span>],
                               <span class="hljs-keyword">$this</span>-&gt;key,
                               <span class="hljs-literal">true</span>);   

        $signature_from_token = <span class="hljs-keyword">$this</span>-&gt;base64urlDecode($matches[<span class="hljs-string">"signature"</span>]);

        <span class="hljs-keyword">if</span> ( ! hash_equals($signature, $signature_from_token)) {

            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidSignatureException;
        }

        $payload = json_decode(<span class="hljs-keyword">$this</span>-&gt;base64urlDecode($matches[<span class="hljs-string">"payload"</span>]), <span class="hljs-literal">true</span>);

        <span class="hljs-keyword">if</span> ($payload[<span class="hljs-string">"exp"</span>] &lt; time()) {

            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> TokenExpiredException;
        }

        <span class="hljs-keyword">return</span> $payload;
    }


    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">base64URLEncode</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $text</span>): <span class="hljs-title">string</span>
    </span>{

        <span class="hljs-keyword">return</span> str_replace([<span class="hljs-string">'+'</span>, <span class="hljs-string">'/'</span>, <span class="hljs-string">'='</span>], [<span class="hljs-string">'-'</span>, <span class="hljs-string">'_'</span>, <span class="hljs-string">''</span>], base64_encode($text));
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">base64URLDecode</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $text</span>): <span class="hljs-title">string</span>
    </span>{
        <span class="hljs-keyword">return</span> base64_decode(
            str_replace(
                [<span class="hljs-string">"-"</span>, <span class="hljs-string">"_"</span>],
                [<span class="hljs-string">"+"</span>, <span class="hljs-string">"/"</span>],
                $text
            )
        );
    }


}
</code></pre>
<p>Updated <strong>UserGateway.php</strong> class</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserGateway</span>
</span>{
    <span class="hljs-keyword">private</span> PDO $conn;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">Database $database</span>)
    </span>{
        <span class="hljs-keyword">$this</span>-&gt;conn = $database-&gt;getConnection();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getByAPIKey</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $key</span>): <span class="hljs-title">array</span> | <span class="hljs-title">false</span>
    </span>{
        $sql = <span class="hljs-string">"SELECT *
                FROM user
                WHERE api_key = :api_key"</span>;

        $stmt = <span class="hljs-keyword">$this</span>-&gt;conn-&gt;prepare($sql);

        $stmt-&gt;bindValue(<span class="hljs-string">":api_key"</span>, $key, PDO::PARAM_STR);

        $stmt-&gt;execute();

        <span class="hljs-keyword">return</span> $stmt-&gt;fetch(PDO::FETCH_ASSOC);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getByUsername</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> $username</span>): <span class="hljs-title">array</span> | <span class="hljs-title">false</span>
    </span>{
        $sql = <span class="hljs-string">"SELECT *
                FROM user
                WHERE username = :username"</span>;

        $stmt = <span class="hljs-keyword">$this</span>-&gt;conn-&gt;prepare($sql);

        $stmt-&gt;bindValue(<span class="hljs-string">":username"</span>, $username, PDO::PARAM_STR);

        $stmt-&gt;execute();

        <span class="hljs-keyword">return</span> $stmt-&gt;fetch(PDO::FETCH_ASSOC);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getByID</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> $id</span>): <span class="hljs-title">array</span> | <span class="hljs-title">false</span>
    </span>{
        $sql = <span class="hljs-string">"SELECT *
                FROM user
                WHERE id = :id"</span>;

        $stmt = <span class="hljs-keyword">$this</span>-&gt;conn-&gt;prepare($sql);

        $stmt-&gt;bindValue(<span class="hljs-string">":id"</span>, $id, PDO::PARAM_INT);

        $stmt-&gt;execute();

        <span class="hljs-keyword">return</span> $stmt-&gt;fetch(PDO::FETCH_ASSOC);
    }
}
</code></pre>
<p>Fnishing up with the ‘refresh’ endpoint:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">declare</span>(strict_types=<span class="hljs-number">1</span>);

<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/bootstrap.php"</span>;

<span class="hljs-keyword">if</span> ($_SERVER[<span class="hljs-string">"REQUEST_METHOD"</span>] !== <span class="hljs-string">"POST"</span>) {

    http_response_code(<span class="hljs-number">405</span>);
    header(<span class="hljs-string">"Allow: POST"</span>);
    <span class="hljs-keyword">exit</span>;
}

$data = (<span class="hljs-keyword">array</span>) json_decode(file_get_contents(<span class="hljs-string">"php://input"</span>), <span class="hljs-literal">true</span>);

<span class="hljs-keyword">if</span> ( ! array_key_exists(<span class="hljs-string">"token"</span>, $data)) {

    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"missing token"</span>]);
    <span class="hljs-keyword">exit</span>;
}

$JwtController = <span class="hljs-keyword">new</span> Jwt($_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);

<span class="hljs-keyword">try</span> {
    $payload = $JwtController-&gt;decode($data[<span class="hljs-string">"token"</span>]);

} <span class="hljs-keyword">catch</span> (<span class="hljs-built_in">Exception</span>) {

    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid token"</span>]);
    <span class="hljs-keyword">exit</span>;
}

$user_id = $payload[<span class="hljs-string">"sub"</span>];


$refresh_token_gateway = <span class="hljs-keyword">new</span> RefreshTokenGateway($database, $_ENV[<span class="hljs-string">"SECRET_KEY"</span>]);

$refresh_token = $refresh_token_gateway-&gt;getByToken($data[<span class="hljs-string">"token"</span>]);

<span class="hljs-keyword">if</span> ($refresh_token === <span class="hljs-literal">false</span>) {

    http_response_code(<span class="hljs-number">400</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid token (not on whitelist)"</span>]);
    <span class="hljs-keyword">exit</span>;
}

$user_gateway = <span class="hljs-keyword">new</span> UserGateway($database);

$user = $user_gateway-&gt;getByID($user_id);

<span class="hljs-keyword">if</span> ($user === <span class="hljs-literal">false</span>) {

    http_response_code(<span class="hljs-number">401</span>);
    <span class="hljs-keyword">echo</span> json_encode([<span class="hljs-string">"message"</span> =&gt; <span class="hljs-string">"invalid authentication"</span>]);
    <span class="hljs-keyword">exit</span>;
}

<span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">"/tokens.php"</span>;

$refresh_token_gateway-&gt;delete($data[<span class="hljs-string">"token"</span>]);

$refresh_token_gateway-&gt;create($refresh_token, $refresh_token_expiry);
</code></pre>
<p>The code then proceeds to validate the HTTP request method, ensuring that only POST requests are accepted for sensitive operations like token handling. This validation is significant as it helps prevent unauthorized access and ensures the security of authentication processes.</p>
<p>Next, the code retrieves and decodes JSON data from the request body, specifically looking for a “token” key. This token is pivotal for authentication and access control within the application. If the token is missing, the code responds with an error message, highlighting the importance of including valid tokens for secure access.</p>
<p>The decoded token is then passed to the <code>JwtController</code> instance to decode its payload and validate its authenticity. This step is crucial as it verifies the integrity of the token and ensures that it hasn't been tampered with or forged.</p>
<p>Furthermore, the code interacts with a <code>RefreshTokenGateway</code> to manage refresh tokens, which play a vital role in generating access tokens securely. Refresh tokens provide a way to obtain new access tokens without requiring the user to log in again, enhancing user experience and maintaining continuous access to resources.</p>
<p>When a user logs in via the login endpoint, two crucial tokens are provided: an access token and a refresh token. The access token grants immediate access to resources, while the refresh token serves as a long-term authorization tool. If the access token expires, the refresh token is then passed to the refresh endpoint. This action triggers the generation of a new access token, which, in turn, creates a fresh refresh token. This process forms a robust and secure mechanism ensuring continuous access to resources while maintaining high levels of security and user convenience.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:630/1*FztaD8zQDrfY-nRdYQAbzA.png" alt="Image" width="630" height="369" loading="lazy">
<em>endpoint testing</em></p>
<p><img src="https://miro.medium.com/v2/resize:fit:630/1*tN5iW6surrwPWlwFD0iRLA.png" alt="Image" width="630" height="390" loading="lazy">
<em>endpoint testing</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In the analyzed code snippets and explanations regarding token management, authentication mechanisms, and refresh token usage within a web application, several key conclusions can be drawn.</p>
<p>Firstly, token-based authentication, especially using JSON Web Tokens, offer a secure and efficient way to handle user authentication and authorization processes. JWTs encapsulate user information in a compact format and are digitally signed, ensuring their integrity and authenticity.</p>
<p>Secondly, the implementation of access tokens and refresh tokens enhances security and user experience. Access tokens provide immediate access to resources and have a short lifespan, promoting security by limiting their usability in case of unauthorized access. On the other hand, refresh tokens have a longer lifespan and enable users to obtain new access tokens without repeated authentication, thereby improving user convenience.</p>
<p>Furthermore, strict typing enforcement, proper validation of HTTP request methods, and token format checks are crucial elements in ensuring the robustness and reliability of token-based authentication systems. These practices help prevent common vulnerabilities such as unauthorized access attempts, token tampering, and invalid token usage.</p>
<p>Overall, by combining secure token management practices, effective authentication mechanisms, and adherence to coding best practices, web applications can achieve a high level of security, user-friendliness, and resilience against potential threats.</p>
<p>See the full code <a target="_blank" href="https://github.com/Oghenekparobo/php_auth_jwt_tut/tree/refresh-token">here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Real-Time Chat App with Laravel Reverb ]]>
                </title>
                <description>
                    <![CDATA[ In March of 2024, Laravel 11 was released. And with it arrived a new tool in the Laravel ecosystem: Laravel Reverb. Reverb is a separate open-source package that's a first-party WebSocket server for Laravel applications. It helps facilitate real-time... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/laravel-reverb-realtime-chat-app/</link>
                <guid isPermaLink="false">66ba2af546ffa10237d2bc86</guid>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ San B ]]>
                </dc:creator>
                <pubDate>Wed, 27 Mar 2024 18:13:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/laravel-reverb-react-chat-boolfalse.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In March of 2024, <a target="_blank" href="https://blog.laravel.com/laravel-11-now-available">Laravel 11 was released</a>. And with it arrived a new tool in the Laravel ecosystem: <a target="_blank" href="https://reverb.laravel.com/">Laravel Reverb</a>.</p>
<p>Reverb is a separate open-source package that's a first-party WebSocket server for Laravel applications. It helps facilitate real-time communication between client and server.</p>
<p>Before this new package, Laravel had event broadcasting, but basically it didn't have a built-in way to set up a self-hosted WebSocket server. Fortunately, Reverb now gives us that option.</p>
<p>Laravel Reverb has a few key features: it's written in PHP, it's fast, and and it's scalable. It was developed in particular to be horizontally scalable. </p>
<p>Reverb basically allows you to run an application on a single server – but if the application starts to outgrow that server, you can add multiple additional servers. Then those servers can all communicate with each other to distribute the messages between themselves.</p>
<p>In this article you will learn how to build a real-time chat application using Laravel Reverb. This will let you easily implement WebSocket communications between your backend and frontend. </p>
<p>For a frontend technology, you can use anything you want – but in this case we'll use React.js with the Vite.js build tool.</p>
<p>By the end of this article, you'll have a full-stack, real-time app in your local machine, which will work like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/article-video-1.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Demo of the app showing messaging between two logged in users</em></p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-general-steps">General Steps</a></li>
<li><a class="post-section-overview" href="#heading-how-to-install-laravel">How to Install Laravel</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-model-and-migration">How to Create the Model and Migration</a></li>
<li><a class="post-section-overview" href="#heading-how-to-add-authentication">How to Add Authentication</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-routes">How to Set Up Routes</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-a-laravel-event">How to Set Up a Laravel Event</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-a-laravel-queue-job">How to Set Up a Laravel Queue Job</a></li>
<li><a class="post-section-overview" href="#heading-how-to-write-the-controller-methods">How to Write the Controller Methods</a></li>
<li><a class="post-section-overview" href="#heading-how-to-install-laravel-reverb">How to Install Laravel Reverb</a></li>
<li><a class="post-section-overview" href="#heading-how-to-setup-websocket-channels">How to Setup WebSocket Channels</a></li>
<li><a class="post-section-overview" href="#heading-how-to-customize-laravel-views">How to Customize Laravel Views</a></li>
<li><a class="post-section-overview" href="#lets-work-on-the-front-end">Let's Work on the Front End</a></li>
<li><a class="post-section-overview" href="#heading-running-the-application">Running the Application</a></li>
<li><a class="post-section-overview" href="#heading-useful-reverb-resources">Useful Reverb Resources</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You'll need the following tools for the app that we'll build in this article:</p>
<ul>
<li><strong>PHP</strong>: version 8.2 or above (run <code>php -v</code> to check the version)</li>
<li><strong>Composer</strong> (run <code>composer</code> to check that it exists)</li>
<li><strong>Node.js</strong>: version 20 or above (run <code>node -v</code> to check the version)</li>
<li><strong>MySQL</strong>: version 5.7 or above (run <code>mysql --version</code> to check if it exists, or follow the <a target="_blank" href="https://dev.mysql.com/doc/refman/5.7/en/linux-installation.html">docs</a> to install it)</li>
</ul>
<h2 id="heading-general-steps">General Steps</h2>
<p>The main steps in this article will be:</p>
<ul>
<li>Installing Laravel 11.</li>
<li>Adding authentication flow to it (authentication scaffolding). Laravel provides a basic starting point for this using Bootstrap with React / Vue.</li>
<li>Installing Reverb.</li>
<li>React.js components and event listening in the frontend.</li>
</ul>
<h2 id="heading-how-to-install-laravel">How to Install Laravel</h2>
<p>To start, install Laravel 11 by using the composer command:</p>
<pre><code class="lang-shell">composer create-project laravel/laravel:^11.0 laravel-reverb-react-chat &amp;&amp; cd laravel-reverb-react-chat/
</code></pre>
<p>At this point, you can check out the app by running the <code>serve</code> command:</p>
<pre><code class="lang-shell">php artisan serve
</code></pre>
<h2 id="heading-how-to-create-the-model-and-migration">How to Create the Model and Migration</h2>
<p>You can generate a model and a migration for the messages by using this single command:</p>
<pre><code class="lang-shell">php artisan make:model -m Message
</code></pre>
<p>Then you'll need to set up the Message's model with the following code:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Factories</span>\<span class="hljs-title">HasFactory</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Eloquent</span>\<span class="hljs-title">Relations</span>\<span class="hljs-title">BelongsTo</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Message</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span>
</span>{
    <span class="hljs-keyword">use</span> <span class="hljs-title">HasFactory</span>;

    <span class="hljs-keyword">public</span> $table = <span class="hljs-string">'messages'</span>;
    <span class="hljs-keyword">protected</span> $fillable = [<span class="hljs-string">'id'</span>, <span class="hljs-string">'user_id'</span>, <span class="hljs-string">'text'</span>];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">user</span>(<span class="hljs-params"></span>): <span class="hljs-title">BelongsTo</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;belongsTo(User::class, <span class="hljs-string">'user_id'</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getTimeAttribute</span>(<span class="hljs-params"></span>): <span class="hljs-title">string</span> </span>{
        <span class="hljs-keyword">return</span> date(
            <span class="hljs-string">"d M Y, H:i:s"</span>,
            strtotime(<span class="hljs-keyword">$this</span>-&gt;attributes[<span class="hljs-string">'created_at'</span>])
        );
    }
}
</code></pre>
<p>As you can see, there's a <code>getTimeAttribute()</code> accessor that will format the message creation timestamp into a human-readable date and time format. It will show it on the top of each message in the chat box.</p>
<p>Next, set up the migration for the <code>messages</code> database table with this code:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Migrations</span>\<span class="hljs-title">Migration</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Database</span>\<span class="hljs-title">Schema</span>\<span class="hljs-title">Blueprint</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Schema</span>;

<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Migration</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        Schema::create(<span class="hljs-string">'messages'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Blueprint $table</span>) </span>{
            $table-&gt;id();
            $table-&gt;foreignId(<span class="hljs-string">'user_id'</span>)-&gt;constrained();
            $table-&gt;text(<span class="hljs-string">'text'</span>)-&gt;nullable();
            $table-&gt;timestamps();
        });
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">down</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        Schema::dropIfExists(<span class="hljs-string">'messages'</span>);
    }
};
</code></pre>
<p>This migration creates a <code>messages</code> table in the database. The table contains columns for an auto-incrementing primary key (<code>id</code>), a foreign key (<code>user_id</code>) referencing the <code>id</code> column of the <code>users</code> table, a <code>text</code> column for storing the message content, and <code>timestamps</code> to automatically track the creation and modification times of each record. </p>
<p>The migration also includes a rollback method (<code>down()</code>) to drop the <code>messages</code> table if needed.</p>
<p>In this article, we'll use the MySQL database, but you can go with SQLite as the default one if you prefer. Just make sure to set up your database credentials in <code>.env</code> file correctly:</p>
<pre><code class="lang-env">DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=username
DB_PASSWORD=password
</code></pre>
<p>After setting up the environment variables, optimize the cache:</p>
<pre><code class="lang-shell">php artisan optimize
</code></pre>
<p>Run migrations to recreate the database tables as well as to add the <code>messages</code> table:</p>
<pre><code class="lang-shell">php artisan migrate:fresh
</code></pre>
<h2 id="heading-how-to-add-authentication">How to Add Authentication</h2>
<p>Now, you can add authentication scaffolding to your app. You can use Laravel's UI package to import some asset files. First you'll need to install the appropriate package:</p>
<pre><code class="lang-shell">composer require laravel/ui
</code></pre>
<p>Then import the React-related assets into the application:</p>
<pre><code class="lang-shell">php artisan ui react --auth
</code></pre>
<p>It may ask to overwrite the <code>app/Http/Controllers/Controller.php</code>, and you can go ahead and allow it:</p>
<pre><code class="lang-shell">The [Controller.php] file already exists. Do you want to replace it? (yes/no) [no]
</code></pre>
<p>This will do all of the authentication scaffolding compiled and installed, including routes, controllers, views, vite configurations, and a simple React-specific sample.<br>At this point, you're just one step away from the app being ready to go.</p>
<p><strong>NOTE:</strong> Make sure you have <strong>Node.js</strong> (with <strong>npm</strong>) version 20 or above installed. You can check that by running the <code>node -v</code> command. Otherwise, just go ahead and install it using the <a target="_blank" href="https://nodejs.org/en/download">official page</a>.</p>
<pre><code class="lang-shell">npm install &amp;&amp; npm run build
</code></pre>
<p>The command above will install NPM packages and build frontend assets. Now you can start the Laravel application and check out your fully ready app sample:</p>
<pre><code class="lang-shell">php artisan optimize &amp;&amp; php artisan serve
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/article-image-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot of the Register page</em></p>
<p>It's also important to note that you can separately run the <code>dev</code> command instead of using <code>build</code> every time when you're making changes to frontend files:</p>
<pre><code class="lang-shell">npm run dev
</code></pre>
<p>See the details in the <code>package.json</code> file, in the <code>scripts</code> field.</p>
<h2 id="heading-how-to-set-up-routes">How to Set Up Routes</h2>
<p>In this real-time chat app, you'll need to have a few routes:</p>
<ul>
<li><code>home</code> for the home page (already should be added)</li>
<li><code>message</code> for adding a new message</li>
<li><code>messages</code> to get all the existing messages</li>
</ul>
<p>You'll have these kind of routes in the <code>web.php</code> file:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Auth</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Route</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Controllers</span>\<span class="hljs-title">HomeController</span>;

Route::get(<span class="hljs-string">'/'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> view(<span class="hljs-string">'welcome'</span>); });

Auth::routes();

Route::get(<span class="hljs-string">'/home'</span>, [HomeController::class, <span class="hljs-string">'index'</span>])
    -&gt;name(<span class="hljs-string">'home'</span>);
Route::get(<span class="hljs-string">'/messages'</span>, [HomeController::class, <span class="hljs-string">'messages'</span>])
    -&gt;name(<span class="hljs-string">'messages'</span>);
Route::post(<span class="hljs-string">'/message'</span>, [HomeController::class, <span class="hljs-string">'message'</span>])
    -&gt;name(<span class="hljs-string">'message'</span>);
</code></pre>
<p>After setting up those routes, let's use Laravel Events and Queue Jobs advantages.</p>
<h2 id="heading-how-to-set-up-a-laravel-event">How to Set Up a Laravel Event</h2>
<p>You need to create a <code>GotMessage</code> event for listening for a specific event:</p>
<pre><code class="lang-shell">php artisan make:event GotMessage
</code></pre>
<blockquote>
<p>Laravel's events provide a simple observer pattern implementation, allowing you to subscribe and listen for various events that occur within your application. Event classes are typically stored in the <code>app/Events</code> directory. (<a target="_blank" href="https://laravel.com/docs/11.x/events">Docs</a>)</p>
</blockquote>
<p>Set up a private WebSocket channel in the <code>broadcastOn</code> method for all the authenticated users to receive messages in real time. In this case, we will call it <code>"channel_for_everyone"</code>, but you can also make it dynamic, depending on the user, like <code>"App.Models.User.{$this-&gt;message['user_id']}"</code>.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Events</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Broadcasting</span>\<span class="hljs-title">InteractsWithSockets</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Broadcasting</span>\<span class="hljs-title">PrivateChannel</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Contracts</span>\<span class="hljs-title">Broadcasting</span>\<span class="hljs-title">ShouldBroadcast</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Foundation</span>\<span class="hljs-title">Events</span>\<span class="hljs-title">Dispatchable</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">SerializesModels</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GotMessage</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ShouldBroadcast</span>
</span>{
    <span class="hljs-keyword">use</span> <span class="hljs-title">Dispatchable</span>, <span class="hljs-title">InteractsWithSockets</span>, <span class="hljs-title">SerializesModels</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">public</span> <span class="hljs-keyword">array</span> $message</span>) </span>{
        <span class="hljs-comment">//</span>
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">broadcastOn</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span> </span>{
        <span class="hljs-comment">// $this-&gt;message is available here</span>
        <span class="hljs-keyword">return</span> [
            <span class="hljs-keyword">new</span> PrivateChannel(<span class="hljs-string">"channel_for_everyone"</span>),
        ];
    }
}
</code></pre>
<p>As you can see, there's a public <code>$massage</code> property as a constructor argument, so you can get message infromation in the front end.</p>
<p>We've already used the channel name in the channels file, and we'll use it in the front end as well for real-time message updates.</p>
<p>Don't forget to implement the <code>ShouldBroadcast</code> interface in the event's class.</p>
<h2 id="heading-how-to-set-up-a-laravel-queue-job">How to Set Up a Laravel Queue Job</h2>
<p>Now it's time to create the <code>SendMessage</code> job for sending messages:</p>
<pre><code class="lang-shell">php artisan make:job SendMessage
</code></pre>
<blockquote>
<p>Laravel allows you to easily create queued jobs that may be processed in the background. By moving time intensive tasks to a queue, your application can respond to web requests with blazing speed and provide a better user experience to your customers. (<a target="_blank" href="https://laravel.com/docs/11.x/queues">Docs</a>)</p>
</blockquote>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Jobs</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Events</span>\<span class="hljs-title">GotMessage</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Message</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Bus</span>\<span class="hljs-title">Queueable</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Contracts</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">ShouldQueue</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Foundation</span>\<span class="hljs-title">Bus</span>\<span class="hljs-title">Dispatchable</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">InteractsWithQueue</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Queue</span>\<span class="hljs-title">SerializesModels</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SendMessage</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ShouldQueue</span>
</span>{
    <span class="hljs-keyword">use</span> <span class="hljs-title">Dispatchable</span>, <span class="hljs-title">InteractsWithQueue</span>, <span class="hljs-title">Queueable</span>, <span class="hljs-title">SerializesModels</span>;

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"><span class="hljs-keyword">public</span> Message $message</span>) </span>{
        <span class="hljs-comment">//</span>
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handle</span>(<span class="hljs-params"></span>): <span class="hljs-title">void</span> </span>{
        GotMessage::dispatch([
            <span class="hljs-string">'id'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;message-&gt;id,
            <span class="hljs-string">'user_id'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;message-&gt;user_id,
            <span class="hljs-string">'text'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;message-&gt;text,
            <span class="hljs-string">'time'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;message-&gt;time,
        ]);
    }
}
</code></pre>
<p>The <code>SendMessage.php</code> queue job is responsible for dispatching the <code>GotMessage</code> event with information about a newly sent message. It receives a <code>Message</code> object upon construction, representing the message to be sent. </p>
<p>In its <code>handle()</code> method, it dispatches the <code>GotMessage</code> event with details such as the message ID, user ID, text, and timestamp. This job is designed to be queued for asynchronous processing, enabling efficient handling of message sending tasks in the background.</p>
<p>As you can see, there's a public <code>$massage</code> property as a constructor argument, which we'll use to attach a message information to the queue job.</p>
<h2 id="heading-how-to-write-the-controller-methods">How to Write the Controller Methods</h2>
<p>For the defined routes, here are the appropriate controller methods:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Controllers</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Jobs</span>\<span class="hljs-title">SendMessage</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Message</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">User</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">JsonResponse</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Http</span>\<span class="hljs-title">Request</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomeController</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Controller</span>
</span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">$this</span>-&gt;middleware(<span class="hljs-string">'auth'</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">index</span>(<span class="hljs-params"></span>) </span>{
        $user = User::where(<span class="hljs-string">'id'</span>, auth()-&gt;id())-&gt;select([
            <span class="hljs-string">'id'</span>, <span class="hljs-string">'name'</span>, <span class="hljs-string">'email'</span>,
        ])-&gt;first();

        <span class="hljs-keyword">return</span> view(<span class="hljs-string">'home'</span>, [
            <span class="hljs-string">'user'</span> =&gt; $user,
        ]);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">messages</span>(<span class="hljs-params"></span>): <span class="hljs-title">JsonResponse</span> </span>{
        $messages = Message::with(<span class="hljs-string">'user'</span>)-&gt;get()-&gt;append(<span class="hljs-string">'time'</span>);

        <span class="hljs-keyword">return</span> response()-&gt;json($messages);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">message</span>(<span class="hljs-params">Request $request</span>): <span class="hljs-title">JsonResponse</span> </span>{
        $message = Message::create([
            <span class="hljs-string">'user_id'</span> =&gt; auth()-&gt;id(),
            <span class="hljs-string">'text'</span> =&gt; $request-&gt;get(<span class="hljs-string">'text'</span>),
        ]);
        SendMessage::dispatch($message);

        <span class="hljs-keyword">return</span> response()-&gt;json([
            <span class="hljs-string">'success'</span> =&gt; <span class="hljs-literal">true</span>,
            <span class="hljs-string">'message'</span> =&gt; <span class="hljs-string">"Message created and job dispatched."</span>,
        ]);
    }
}
</code></pre>
<ul>
<li>In the <code>home</code> method, we'll get the logged in user's data from the database using the <code>User</code> model and send it to the blade view.</li>
<li>In the <code>messages</code> method, we'll retrieve all the messages from the database using the <code>Message</code> model, attach the <code>user</code> relationship data to it, append the <code>time</code> field (accessor) to each item, and send all that to the view.</li>
<li>In the <code>message</code> method, a new message will be created in the database table by using the <code>Message</code> model, and the <code>SendMessage</code> queue job will be dispatched.</li>
</ul>
<h2 id="heading-how-to-install-laravel-reverb">How to Install Laravel Reverb</h2>
<p>Now we've come to the most important moment: it's time to install <a target="_blank" href="https://laravel.com/docs/11.x/reverb#installation">Reverb</a> in your Laravel app.</p>
<p>It's so easy. All the necessary packaging and configuration setup can be done using this single command:</p>
<pre><code class="lang-shell">php artisan install:broadcasting
</code></pre>
<p>It will ask you to install Laravel Reverb as well as install and build the Node dependencies required for broadcasting. Just press enter to continue.</p>
<p>After the command execution, make sure you've automatically added reverb-specific environment variables to the <code>.env</code> file, like:</p>
<pre><code class="lang-env">BROADCAST_CONNECTION=reverb

###

REVERB_APP_ID=795051
REVERB_APP_KEY=s3w3thzezulgp5g0e5bs
REVERB_APP_SECRET=gncsnk3rzpvczdakl6pz
REVERB_HOST="localhost"
REVERB_PORT=8080
REVERB_SCHEME=http

VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
</code></pre>
<p>You'll also have two new configration files in the <code>config</code> directory:</p>
<ul>
<li><code>reverb.php</code></li>
<li><code>broadcasting.php</code></li>
</ul>
<h2 id="heading-how-to-setup-websocket-channels">How to Setup WebSocket Channels</h2>
<p>Lastly, you'll need to add a channel in the <code>channels.php</code> file. It should already be created after installing Reverb.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">Broadcast</span>;

Broadcast::channel(<span class="hljs-string">'channel_for_everyone'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$user</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
});
</code></pre>
<p>You'll have only one channel. You can change the channel's name and make it dynamic – it's up to you. In the closure of the channel, we'll always return true, but you can modify it later to make some restrictions regarding the channel's subscription.</p>
<p>Optimize caches one more time:</p>
<pre><code class="lang-shell">php artisan optimize
</code></pre>
<h2 id="heading-how-to-customize-laravel-views">How to Customize Laravel Views</h2>
<p>Now your back end should be ready at this point, so you can switch to the front end.</p>
<p>Before working on the React stuff, you'll want to set up Laravel <code>*.blade.php</code> views. In the <code>home</code> blade view, make sure to have the root div with an ID of <code>main</code> to render all the React components there.</p>
<pre><code class="lang-php">@<span class="hljs-keyword">extends</span>(<span class="hljs-string">'layouts.app'</span>)

@section(<span class="hljs-string">'content'</span>)
    &lt;div <span class="hljs-class"><span class="hljs-keyword">class</span>="<span class="hljs-title">container</span>"&gt;
        &lt;<span class="hljs-title">div</span> <span class="hljs-title">id</span>="<span class="hljs-title">main</span>" <span class="hljs-title">data</span>-<span class="hljs-title">user</span>="</span>{{ json_encode($user) }}<span class="hljs-string">"&gt;&lt;/div&gt;
    &lt;/div&gt;
@endsection</span>
</code></pre>
<p>The div with ID of <code>main</code> gets a data property for holding the <code>$user</code> info sent from the controller's <code>home</code> method.</p>
<p>I won't put the whole <code>resources/views/welcome.blade.php</code> content here, but you can just make the following small changes to it:</p>
<ul>
<li>Replace <code>url('/dashboard')</code> with <code>url('/home')</code>;</li>
<li>Replace <code>Dashboard</code> with <code>Home</code>;</li>
<li>Remove <code>main</code> and <code>footer</code> sections.</li>
</ul>
<h2 id="heading-lets-work-on-the-front-end">Let's Work on the Front End</h2>
<p>In Reverb, event broadcasting is done by a server-side broadcasting driver that broadcasts your Laravel events so that the front end can receive them within the browser client. </p>
<p>In the front end, <a target="_blank" href="https://github.com/laravel/echo">Laravel Echo</a> does that job under the hood. Echo a JavaScript library that makes it painless to subscribe to channels and listen for events broadcast by your server-side broadcasting driver.</p>
<p>You can find the WebSocket configurations setup with Echo in the <code>rources/js/echo.js</code> file, but you don't need to do anything there for this project.</p>
<p>Let's create a few React components so that we have a refactored and more readable project.</p>
<p>Create a <code>Main.jsx</code> component in the new <code>components</code> folder:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'../../css/app.css'</span>;
<span class="hljs-keyword">import</span> ChatBox <span class="hljs-keyword">from</span> <span class="hljs-string">"./ChatBox.jsx"</span>;

<span class="hljs-keyword">if</span> (<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'main'</span>)) {
    <span class="hljs-keyword">const</span> rootUrl = <span class="hljs-string">"http://127.0.0.1:8000"</span>;

    ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'main'</span>)).render(
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ChatBox</span> <span class="hljs-attr">rootUrl</span>=<span class="hljs-string">{rootUrl}</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
    );
}
</code></pre>
<p>Here we'll check if there's an element with the id <code>'main'</code>. If it exists, it proceeds with rendering the React application.</p>
<p>As you can see, there's a <code>ChatBox</code> component. We'll learn more about it soon.</p>
<p>Remove the <code>resources/js/components/Example.jsx</code> file, and import the <code>Main.jsx</code> component in the <code>app.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">'./bootstrap'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./components/Main.jsx'</span>;
</code></pre>
<p>Create <code>Message.jsx</code> and <code>MessageInput.jsx</code> files so you can use them in the <code>ChatBox</code> component.</p>
<p>The <code>Message</code> component will get <code>userId</code> and <code>message</code> arguments (fields) to show each message in the chat box.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> Message = <span class="hljs-function">(<span class="hljs-params">{ userId, message }</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">row</span> ${
        <span class="hljs-attr">userId</span> === <span class="hljs-string">message.user_id</span> ? "<span class="hljs-attr">justify-content-end</span>" <span class="hljs-attr">:</span> ""
        }`}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"col-md-6"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-muted"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{message.user.name} | <span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-muted float-right"</span>&gt;</span>
                    {message.time}
                <span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">alert</span> <span class="hljs-attr">alert-</span>${
                <span class="hljs-attr">userId</span> === <span class="hljs-string">message.user_id</span> ? "<span class="hljs-attr">primary</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">secondary</span>"
                }`} <span class="hljs-attr">role</span>=<span class="hljs-string">"alert"</span>&gt;</span>
                    {message.text}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Message;
</code></pre>
<p>The <code>Message.jsx</code> component renders individual messages within the chat interface. It receives the <code>userId</code> and <code>message</code> props. Based on whether the message sender matches the current user, it aligns the message to the appropriate side of the screen. </p>
<p>Each message includes the sender's name, timestamp, and the message content itself, styled differently based on whether the message is sent by the current user or another user.</p>
<p>The <code>MessageInput</code> component will care about creating a new message:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> MessageInput = <span class="hljs-function">(<span class="hljs-params">{ rootUrl }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> [message, setMessage] = useState(<span class="hljs-string">""</span>);

    <span class="hljs-keyword">const</span> messageRequest = <span class="hljs-keyword">async</span> (text) =&gt; {
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">await</span> axios.post(<span class="hljs-string">`<span class="hljs-subst">${rootUrl}</span>/message`</span>, {
                text,
            });
        } <span class="hljs-keyword">catch</span> (err) {
            <span class="hljs-built_in">console</span>.log(err.message);
        }
    };

    <span class="hljs-keyword">const</span> sendMessage = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        e.preventDefault();
        <span class="hljs-keyword">if</span> (message.trim() === <span class="hljs-string">""</span>) {
            alert(<span class="hljs-string">"Please enter a message!"</span>);
            <span class="hljs-keyword">return</span>;
        }

        messageRequest(message);
        setMessage(<span class="hljs-string">""</span>);
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"input-group"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setMessage(e.target.value)}
                   autoComplete="off"
                   type="text"
                   className="form-control"
                   placeholder="Message..."
                   value={message}
            /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"input-group-append"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{(e)</span> =&gt;</span> sendMessage(e)}
                        className="btn btn-primary"
                        type="button"&gt;Send<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MessageInput;
</code></pre>
<p>The <code>MessageInput</code> component provides a form input field for users to type messages and send them in the chat interface. By clicking the button, it triggers a function to send the message to the server via an Axios POST request to the specified <code>rootUrl</code> that it got from the parent <code>ChatBox</code> component. It also handles validation to ensure that users cannot send empty messages. You can customize it later if you want. </p>
<p>Now create a <code>ChatBox.jsx</code> component to have the front end ready:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useEffect, useRef, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> Message <span class="hljs-keyword">from</span> <span class="hljs-string">"./Message.jsx"</span>;
<span class="hljs-keyword">import</span> MessageInput <span class="hljs-keyword">from</span> <span class="hljs-string">"./MessageInput.jsx"</span>;

<span class="hljs-keyword">const</span> ChatBox = <span class="hljs-function">(<span class="hljs-params">{ rootUrl }</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> userData = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'main'</span>)
        .getAttribute(<span class="hljs-string">'data-user'</span>);

    <span class="hljs-keyword">const</span> user = <span class="hljs-built_in">JSON</span>.parse(userData);
    <span class="hljs-comment">// `App.Models.User.${user.id}`;</span>
    <span class="hljs-keyword">const</span> webSocketChannel = <span class="hljs-string">`channel_for_everyone`</span>;

    <span class="hljs-keyword">const</span> [messages, setMessages] = useState([]);
    <span class="hljs-keyword">const</span> scroll = useRef();

    <span class="hljs-keyword">const</span> scrollToBottom = <span class="hljs-function">() =&gt;</span> {
        scroll.current.scrollIntoView({ <span class="hljs-attr">behavior</span>: <span class="hljs-string">"smooth"</span> });
    };

    <span class="hljs-keyword">const</span> connectWebSocket = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-built_in">window</span>.Echo.private(webSocketChannel)
            .listen(<span class="hljs-string">'GotMessage'</span>, <span class="hljs-keyword">async</span> (e) =&gt; {
                <span class="hljs-comment">// e.message</span>
                <span class="hljs-keyword">await</span> getMessages();
            });
    }

    <span class="hljs-keyword">const</span> getMessages = <span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">const</span> m = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">`<span class="hljs-subst">${rootUrl}</span>/messages`</span>);
            setMessages(m.data);
            <span class="hljs-built_in">setTimeout</span>(scrollToBottom, <span class="hljs-number">0</span>);
        } <span class="hljs-keyword">catch</span> (err) {
            <span class="hljs-built_in">console</span>.log(err.message);
        }
    };

    useEffect(<span class="hljs-function">() =&gt;</span> {
        getMessages();
        connectWebSocket();

        <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
            <span class="hljs-built_in">window</span>.Echo.leave(webSocketChannel);
        }
    }, []);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"row justify-content-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"col-md-8"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-header"</span>&gt;</span>Chat Box<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-body"</span>
                         <span class="hljs-attr">style</span>=<span class="hljs-string">{{height:</span> "<span class="hljs-attr">500px</span>", <span class="hljs-attr">overflowY:</span> "<span class="hljs-attr">auto</span>"}}&gt;</span>
                        {
                            messages?.map((message) =&gt; (
                                <span class="hljs-tag">&lt;<span class="hljs-name">Message</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{message.id}</span>
                                         <span class="hljs-attr">userId</span>=<span class="hljs-string">{user.id}</span>
                                         <span class="hljs-attr">message</span>=<span class="hljs-string">{message}</span>
                                /&gt;</span>
                            ))
                        }
                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{scroll}</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card-footer"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">MessageInput</span> <span class="hljs-attr">rootUrl</span>=<span class="hljs-string">{rootUrl}</span> /&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ChatBox;
</code></pre>
<p>The <code>ChatBox</code> component manages a chat interface within the application. It fetches and displays messages from a server using WebSocket and HTTP requests.</p>
<p>The component renders a list of messages, a message input field, and automatically scrolls to the bottom when new messages arrive.</p>
<p>It defines a WebSocket channel for real-time message updates. You need to set up that channel by using the same name as it was written in the <code>routes/hannels.php</code> and in the <code>app/Events/GotMessage.php</code> queue job.</p>
<p>Also, the <code>leave()</code> function is called within the <code>useEffect</code> cleanup function to unsubscribe from the WebSocket channel when the component unmounts. This prevents memory leaks and unnecessary network connections by stopping the component from listening to updates on the WebSocket channel after it's no longer needed.</p>
<h2 id="heading-running-the-application">Running the Application</h2>
<p>Now, everything's ready and it's time to check out the app. Follow these instructions:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/article-image-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot from the terminal with all the necessary commands</em></p>
<ul>
<li>Build frontend assets (this is not a "forever" running command):<br><code>npm run build</code></li>
<li>Start listening to the Laravel events:<br><code>php artisan queue:listen</code></li>
<li>Start the WebSocket server:<br><code>php artisan reverb:start</code></li>
<li>Start the server (you may use an alternative for your app like a local running server):<br><code>php artisan serve</code></li>
</ul>
<p>After all the necessary commands are running, you can check out the app by visiting the default URL: <code>http://127.0.0.1:8000</code>.</p>
<p>For testing, you can register two different users, have those users log in, send messages from each of them, and see the chat box.</p>
<h2 id="heading-useful-reverb-resources">Useful Reverb Resources</h2>
<p>Now that we've reached the end of this article, it's worth listing some useful resources about Reverb:</p>
<ul>
<li><a target="_blank" href="https://laravel.com/docs/11.x/broadcasting">Laravel Broadcasting</a> (official documentation)</li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=0g7HqfsCX4Y">Taylor Otwel - Laravel Update</a> (talk on Laracon EU 2024)</li>
<li><a target="_blank" href="https://twitter.com/_joedixon">Joe Dixon on X</a> (creator of Reverb)</li>
<li><a target="_blank" href="https://laracasts.com/series/lukes-larabits/episodes/17">Laracast episode</a> (practical example with Reverb)</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Now you know how to build real-time applications with Laravel Reverb in the new version of Laravel. With this, you can implement WebSocket communications in your full-stack app and avoid using any additional 3rd-party services (like Pusher and Socket.io).</p>
<p>If you want to have a clear idea of how to integrate React.js into your Laravel app without using any additional Laravel tools (like Inertia), you can read through my previous <a target="_blank" href="https://www.freecodecamp.org/news/use-react-with-laravel/">freeCodeCamp article</a>, where you can build a single-page, full-stack Tasklist app.</p>
<p>The complete code for this article is here on my <a target="_blank" href="https://github.com/boolfalse/laravel-reverb-react-chat"><strong>GitHub</strong></a>⭐, where I actively publicize much of my work about various modern technologies.</p>
<p>For more information, you can visit my website: <a target="_blank" href="https://boolfalse.com/"><strong>boolfalse.com</strong></a></p>
<p>Feel free to share this article. 😇</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is a Linked list? Types of Linked List with Code Examples ]]>
                </title>
                <description>
                    <![CDATA[ A linked list is a linear data structure consisting of a sequence of nodes. Unlike arrays, linked lists do not require contiguous memory allocation. Instead, each node is dynamically allocated its own memory space.  Nodes are connected through refere... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-a-linked-list-types-and-examples/</link>
                <guid isPermaLink="false">66ba2fe64d935175898a7086</guid>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sule-Balogun Olanrewaju ]]>
                </dc:creator>
                <pubDate>Mon, 18 Mar 2024 15:25:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/john-petter-fagerhaug-nlT3NvhGKt8-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A linked list is a linear data structure consisting of a sequence of nodes. Unlike arrays, linked lists do not require contiguous memory allocation. Instead, each node is dynamically allocated its own memory space. </p>
<p>Nodes are connected through references, forming the linked structure. One advantage of linked lists is that insertion and deletion of elements at the beginning of the list can be done in constant time, denoted as O(1). </p>
<p>This efficiency stems from the ability to directly manipulate references without needing to shift elements as required in arrays. Data types in a linked list can be any of the available data types supported by a programming language.</p>
<p>In this tutorial, you'll learn the following:</p>
<ul>
  <li><a href="#understanding-linked-list">Understanding Linked list</a></li>
  <li><a href="#types-of-linked-list">Types of Linked List</a></li>
    <li><a href="#summary-of-operations">Summary of operations with their respective time and space complexities in tabular format.</a></li>
  <li><a href="#differentiate-between-array-and-linked-list">Differences Between Array and Linked list.</a></li>
  <li><a href="#how-to-solve-the-remove-duplicates-from-sorted-list-problem">Algorithm: Solve the Remove Duplicates from Sorted list in PHP and JavaScript.</a></li>
</ul>

<h2 id="understanding-linked-list"> Understanding Linked list </h2>

<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Untitled-2024-01-31-1554.png" alt="Untitled-2024-01-31-1554" width="600" height="400" loading="lazy"></p>
<p>head =&gt; Points to the first box in the list<br>tail =&gt; Points to the last box in the list</p>
<p>To access the data in the first box</p>
<p>head.data =&gt; 6</p>
<p>To access the data in the second box, we first need to set the pointer (arrow) to point to the box. Hence we need the (next)<br>head.next =&gt; This points to the next item on the list<br>head.next.data =&gt; 4</p>
<p>To access the data in the third box, we first need to set the pointer (arrow) to point to the box. Hence we need the (next.next)<br>head.next.next =&gt; This points to the next &gt; next item on the list<br>head.next.next.data =&gt; 5</p>
<h3 id="heading-what-is-a-node">What is a node ?</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/node.png" alt="node" width="600" height="400" loading="lazy"></p>
<p>A node in a linked list is an example of a self-referential structure in programming. This structure is comprised of elements called nodes, where each node contains both data and a reference to another node of the same type. This reference, often termed a 'pointer,' facilitates the creation of a chain-like structure, where nodes are interconnected, forming the linked list.</p>
<p>The self-referential nature of nodes allows for efficient traversal and manipulation of data within the linked list. The structure can be implemented using classes or arrays</p>
<h3 id="heading-how-to-implement-a-linked-list-using-classes">How to Implement a Linked List Using classes</h3>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Node</span> </span>{
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span>(<span class="hljs-params">
        <span class="hljs-keyword">public</span> $data,
        <span class="hljs-keyword">public</span> ?Node $next = <span class="hljs-literal">null</span>
    </span>) </span>{}
}

<span class="hljs-comment">// Creating nodes</span>

$node1 = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">10</span>);
$node2 = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">20</span>);
$node3 = <span class="hljs-keyword">new</span> Node(<span class="hljs-number">30</span>);

<span class="hljs-comment">// Linking nodes</span>

$node1-&gt;next = $node2;
$node2-&gt;next = $node3;

<span class="hljs-comment">// Traversing linked list</span>

$current = $node1;
<span class="hljs-keyword">while</span> ($current != <span class="hljs-literal">null</span>) {
    <span class="hljs-keyword">echo</span> $current-&gt;data . <span class="hljs-string">" "</span>;
    $current = $current-&gt;next;
}
</code></pre>
<h3 id="heading-how-to-implement-a-linked-list-using-using-arrays">How to Implement a Linked List Using Using arrays</h3>
<pre><code class="lang-php"><span class="hljs-comment">// creating nodes as an associative array</span>

$node1 = [<span class="hljs-string">'data'</span> =&gt; <span class="hljs-number">10</span>, <span class="hljs-string">'next'</span> =&gt; <span class="hljs-literal">null</span>];
$node2 = [<span class="hljs-string">'data'</span> =&gt; <span class="hljs-number">20</span>, <span class="hljs-string">'next'</span> =&gt; <span class="hljs-literal">null</span>];
$node3 = [<span class="hljs-string">'data'</span> =&gt; <span class="hljs-number">30</span>, <span class="hljs-string">'next'</span> =&gt; <span class="hljs-literal">null</span>];

<span class="hljs-comment">// linking nodes</span>

$node1[<span class="hljs-string">'next'</span>] = &amp;$node2;
$node2[<span class="hljs-string">'next'</span>] = &amp;$node3;

<span class="hljs-comment">// Traversing linked list</span>

$current = $node1;
<span class="hljs-keyword">while</span> ($current != <span class="hljs-literal">null</span>) {
  <span class="hljs-keyword">echo</span> $current[<span class="hljs-string">"data"</span>] . <span class="hljs-string">" "</span>;
  $current = &amp;$current[<span class="hljs-string">"next"</span>];
}
</code></pre>
<p>In both cases, we create a structure where each element (node) contains data and a reference (next) to another element of the same type. This creates a self-referential structure. We then link these elements together to form a data structure like a linked list. Finally, we traverse the structure to access and manipulate its elements.</p>
<p>Unlike an array, a linked list doesn't provide constant time access to a particular index within the list. This means that if you'd like to find the nth element in the list, you'll need to traverse through to the nth element. </p>
<p>Traversing a linked list means iterating through each node of the list until the end node is reached.</p>
<h2 id="types-of-linked-list"> Types of Linked list</h2>

<p>We'll discuss the types under the Traversal, Memory and Complexity categories.</p>
<h2 id="heading-singly-linked-list">Singly Linked List</h2>
<p>Each node has data and a reference to the next node. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/singly-2.png" alt="singly linked list" width="600" height="400" loading="lazy"></p>
<h3 id="heading-non-code-explanation">Non-code explanation</h3>
<p>Imagine taking a journey by train, where each train represents a part of your trip, and each station represents a point where you need to make a change.</p>
<ul>
<li>Train A represents the first part of your journey, taking you from Station A to Station B. When you arrive at Station B, there's a sign directing you to switch trains to continue your journey.</li>
<li>Train B represents the second part of your journey, taking you from Station B to Station C. Again, when you arrive at Station C, there's no sign for another train because you've reached your final destination.</li>
</ul>
<p>In this analogy:</p>
<ul>
<li>Each train segment (Train A, Train B, and Train C) represent a node in the singly linked list.</li>
<li>The task of each train is analogous to the data stored in each node, representing a segment of your journey.</li>
<li>The transition between trains at each station is analogous to the "next" pointer in a linked list, indicating the next segment of your journey.</li>
<li>At the final destination (Station C), there's no need for a pointer or sign to another train because it's the end of your journey.</li>
</ul>
<p>In simpler terms, a singly linked list is like a train journey with different segments, where each train (node) has the task of taking you from one station to the next until you reach your final destination. The transitions between trains are like pointers, guiding you through each segment of your journey.</p>
<h3 id="heading-performance-characteristics-of-singly-linked-list">Performance Characteristics of Singly Linked List</h3>
<ol>
<li><strong>Traversal:</strong> Traversal is allowed only in one direction (that is, forward only). You can move forward through the list, but you cannot easily move backward. </li>
<li><strong>Memory Efficiency:</strong> Singly linked list is generally more memory-efficient because it requires only one reference per node. </li>
<li><strong>Complexity:</strong> Insertion and Deletion operation is easier as you only need to update references in one direction.</li>
</ol>
<h3 id="heading-time-and-space-complexity">Time and Space Complexity</h3>
<p>I wrote about constant and linear time complexity <a target="_blank" href="https://www.freecodecamp.org/news/what-is-a-hash-map/">here</a>, and we'll be using that to discuss the general time and space complexities for some common operations:</p>
<h4 id="heading-traversal">Traversal</h4>
<p>Time complexity O(n), where n is the number of nodes in the list. Space complexity O(1), it doesn't require additional space proportional to the input size.</p>
<h4 id="heading-insertion-at-the-beginning">Insertion at the Beginning</h4>
<p>Time complexity O(1), it involves updating references at the head. Space complexity O(1), it doesn't require additional space proportional to the input size.</p>
<h4 id="heading-insertion-at-the-end">Insertion at the End</h4>
<p>Time complexity O(n), it may require traversing the entire list to reach the end. Space complexity O(1), it doesn't require additional space proportional to the input size.</p>
<h4 id="heading-deletion-at-the-beginning">Deletion at the Beginning</h4>
<p>Time complexity O(1), it involves updating references at the head. Space complexity O(1), constant.</p>
<h4 id="heading-deletion-at-the-end">Deletion at the End</h4>
<p>Time complexity O(n), it may require traversing the entire list to reach the end. Space complexity O(1), constant.</p>
<h2 id="heading-doubly-linked-list">Doubly Linked List</h2>
<p>In a doubly linked list, the <code>head</code> node typically does not have a <code>prev</code> reference because it is the first node and therefore has no previous node. </p>
<p>However, the <code>head</code> node does have a <code>next</code> reference pointing to the next node in the list. Each node has data and references to both the next and previous nodes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/doubly-1.png" alt="doubly-1inked-list" width="600" height="400" loading="lazy"></p>
<h3 id="heading-non-code-explanation-1">Non-code explanation</h3>
<p>Imagine that you have a book where each page represents a task you need to complete, just like items on your to-do list.</p>
<p>Each page does not only contain information about the task written on it but also has connections to the pages before and after it in the book.</p>
<ul>
<li>Page 1 (Task A) represents the first task in the book. It contains information about Task A and has an arrow pointing forward to Page 2 (Task B), indicating that Task B comes after Task A in the book. However, Page 1 does not have a backward arrow because it is the first page of the book and doesn't have a previous page.</li>
<li>Page 2 (Task B) contains information about Task B and has arrows pointing both forward to Page 3 (Task C) and backward to Page 1 (Task A), indicating that Task C comes after Task B and Task A comes before Task B in the book.</li>
<li>Page 3 (Task C) represents the last task in the book. It contains information about Task C and has an arrow pointing backward to Page 2 (Task B), indicating that Task B comes before Task C in the book.</li>
</ul>
<p>With this in mind, you can think of a doubly linked list as a book where each page not only contains information about a task but also provides easy navigation to the tasks before and after it. The first page, similar to the head of a doubly linked list, does not have a previous reference, while the last page, similar to the tail of a doubly linked list, does not have a next reference</p>
<h3 id="heading-performance-characteristics-of-doubly-linked-lists">Performance Characteristics of Doubly Linked Lists</h3>
<ol>
<li><strong>Traversal:</strong> Doubly linked lists allow traversal in both directions — forward and backward. This bidirectional traversal enables more flexible navigation through the list, allowing operations such as iterating in reverse order.</li>
<li><strong>Memory Efficiency</strong>: Doubly linked lists typically require more memory compared to singly linked lists because each node contains two references (pointers) — one for the next node and one for the previous node. This additional memory overhead per node can impact the overall memory efficiency, especially for large lists.</li>
<li><strong>Complexity</strong>: Doubly linked lists offer bidirectional traversal and flexibility. Insertion and deletion operations may require updating references in both directions (forward and backward), which can increase the complexity and potentially impact performance.</li>
</ol>
<h3 id="heading-time-and-space-complexity-1">Time and Space Complexity</h3>
<h4 id="heading-traversal-1">Traversal</h4>
<p>The time and space complexity for this operation is the same with the singly linked list.</p>
<h4 id="heading-insertion-at-the-beginning-1">Insertion at the Beginning</h4>
<p>The time and space complexity for this operation is the same with the singly linked list.</p>
<h4 id="heading-insertion-at-the-end-1">Insertion at the End</h4>
<p>Time complexity for this operation takes O(1) time. This is because you have direct access to the tail node, so you can update the references without needing to traverse the entire list. Space complexity O(1), it doesn't require additional space proportional to the input size.</p>
<h4 id="heading-deletion-at-the-beginning-1">Deletion at the Beginning</h4>
<p>The time and space complexity for this operation is the same with the singly linked list.</p>
<h4 id="heading-deletion-at-the-end-1">Deletion at the End</h4>
<p>Time complexity for this operation takes O(1) time. This is because you have direct access to the tail node, so you can update the references without needing to traverse the entire list. Space complexity O(1), it doesn't require additional space proportional to the input size.</p>
<h2 id="heading-circular-linked-list">Circular Linked List</h2>
<p>A circular linked list is a type of linked list where the last node of the list points back to the first node, forming a circle or loop. This characteristic distinguishes it from a traditional linked list, where the last node typically points to null, indicating the end of the list. In a circular linked list, there is no null pointer at the end; instead, the last node points back to the first node, creating a loop structure. This looping behavior allows for continuous traversal through the list. The below image shows how a singly circular linked list works.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/circular-linked-list-1.png" alt="circular-linked-list-1" width="600" height="400" loading="lazy"></p>
<h3 id="heading-non-code-explanation-2">Non-code explanation</h3>
<p>Imagine a train line that forms a loop, with passengers boarding and exiting at various stations along the way. This loop represents a circular linked list, where each station is a node and the train continuously travels around the loop, picking up and dropping off passengers. </p>
<p>Just like in a circular linked list, the loop ensures continuous traversal without an end point, and passengers (data) can be added or removed at any station (node).  </p>
<p>The circular linked list offers advantages in certain applications but requires careful handling of pointers and memory management to maintain its circular structure and prevent issues such as infinite loops.</p>
<h3 id="heading-performance-characteristics-of-circular-linked-lists">Performance Characteristics of Circular Linked Lists</h3>
<ol>
<li><strong>Traversal:</strong> Circular linked lists enable traversal in a loop, allowing seamless navigation from one node to another regardless of the direction. This circular structure facilitates efficient traversal without needing to iterate back to the beginning when reaching the end, enhancing traversal performance.</li>
<li><strong>Memory Efficiency</strong>: Singly circular linked lists typically offer similar memory efficiency to singly linked lists, as they require only one pointer per node to connect to the next node in the sequence. This single-pointer structure results in lower memory overhead per node compared to doubly linked lists, potentially improving memory efficiency for large lists.</li>
<li><strong>Complexity:</strong> In singly circular linked lists, insertion and deletion operations require updating references to maintain the circular structure, introducing moderate complexity compared to linear linked lists.</li>
</ol>
<h3 id="heading-time-and-space-complexity-2">Time and Space Complexity</h3>
<h4 id="heading-traversal-2">Traversal</h4>
<p>Time Complexity: O(n) – Since you have to traverse through all the nodes in the list to reach the end. </p>
<p>Space Complexity: O(1) – Only a constant amount of extra space is required for a temporary variable to traverse the list.</p>
<h4 id="heading-insertion-at-the-beginning-2">Insertion at the Beginning</h4>
<p>Time Complexity: O(1) – Insertion at the beginning simply involves updating the references at the head. </p>
<p>Space Complexity: O(1) – No additional space is required.</p>
<h4 id="heading-insertion-at-the-end-2">Insertion at the End</h4>
<p>Time Complexity: O(n) – It may require traversing the entire list to reach the end where insertion needs to take place.</p>
<p>Space Complexity: O(1) – No additional space is required.</p>
<h4 id="heading-deletion-at-the-beginning-2">Deletion at the Beginning</h4>
<p>Time complexity O(1), it involves updating references at the head. </p>
<p>Space complexity O(1), constant.</p>
<h4 id="heading-deletion-at-the-end-2">Deletion at the End</h4>
<p>Time complexity O(n), it may require traversing the entire list to reach the end.</p>
<p>Space complexity O(1), constant.</p>
<h2 id="summary-of-operations"> Summary of Operations for the Time Complexity </h2>

<table>
<thead>
<tr>
<th>Operation</th>
<th>Singly Linked List</th>
<th>Doubly Linked List</th>
<th>Circular Linked List</th>
</tr>
</thead>
<tbody>
<tr>
<td>Traversal</td>
<td>O(n)</td>
<td>O(n)</td>
<td>O(n)</td>
</tr>
<tr>
<td>Insertion at Beginning</td>
<td>O(1)</td>
<td>O(1)</td>
<td>O(1)</td>
</tr>
<tr>
<td>Insertion at End</td>
<td>O(n)</td>
<td>O(1)</td>
<td>O(n)</td>
</tr>
<tr>
<td>Deletion at Beginning</td>
<td>O(1)</td>
<td>O(1)</td>
<td>O(1)</td>
</tr>
<tr>
<td>Deletion at End</td>
<td>O(n)</td>
<td>O(1)</td>
<td>O(n)</td>
</tr>
</tbody>
</table>


<h2 id="summary-of-operations"> Summary of Operations for the Space Complexity </h2>

<table>
<thead>
<tr>
<th>Operation</th>
<th>Singly Linked List</th>
<th>Doubly Linked List</th>
<th>Circular Linked List</th>
</tr>
</thead>
<tbody>
<tr>
<td>Traversal</td>
<td>O(1)</td>
<td>O(1)</td>
<td>O(1)</td>
</tr>
<tr>
<td>Insertion at Beginning</td>
<td>O(1)</td>
<td>O(1)</td>
<td>O(1)</td>
</tr>
<tr>
<td>Insertion at End</td>
<td>O(1)</td>
<td>O(1)</td>
<td>O(1)</td>
</tr>
<tr>
<td>Deletion at Beginning</td>
<td>O(1)</td>
<td>O(1)</td>
<td>O(1)</td>
</tr>
<tr>
<td>Deletion at End</td>
<td>O(1)</td>
<td>O(1)</td>
<td>O(1)</td>
</tr>
</tbody>
</table>

<h2 id="differentiate-between-array-and-linked-list"> Differences Between Array and Linked list </h2>

<p>A linked list is a dynamic way to represent a list, where adding and removing items from the beginning of the list typically involves changing only a few pointers. This operation can be performed in constant time, denoted as O(1), regardless of the list's size.</p>
<p>On the other hand, arrays are a sequential representation of a list. Adding or removing items from the beginning of the list requires shifting all subsequent elements to accommodate the change. This operation has a time complexity of O(n), where n is the number of elements in the array. Therefore, for large arrays, adding or removing items from the beginning can be relatively slow compared to linked lists.</p>
<h2 id="how-to-solve-the-remove-duplicates-from-sorted-list-problem"> How to Solve the Remove Duplicates from Sorted List Problem </h2>

<p>Explanation of the problem: Given the <code>head</code> of a sorted linked list, <em>delete all duplicates such that each element appears only once</em>. Return <em>the linked list <strong>sorted</strong></em> as well.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/algo-sample-3.png" alt="algo-sample-3" width="600" height="400" loading="lazy"></p>
<h3 id="heading-solution-in-php">Solution in PHP</h3>
<pre><code class="lang-php"><span class="hljs-comment">/**
 * Definition for a singly-linked list.
 * class ListNode {
 *     public $val = 0;
 *     public $next = null;
 *     function __construct($val = 0, $next = null) {
 *         $this-&gt;val = $val;
 *         $this-&gt;next = $next;
 *     }
 * }
 */</span>


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span> </span>{

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> ListNode $head
     * <span class="hljs-doctag">@return</span> ListNode
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deleteDuplicates</span>(<span class="hljs-params">$head</span>) </span>{
        $node = $head;

        <span class="hljs-keyword">while</span>($node !== <span class="hljs-literal">null</span> &amp;&amp; $node-&gt;next !== <span class="hljs-literal">null</span>) {

            <span class="hljs-keyword">if</span> ($node-&gt;val == $node-&gt;next-&gt;val) {
                $node-&gt;next = $node-&gt;next-&gt;next;
            }<span class="hljs-keyword">else</span> {
                $node = $node-&gt;next;
            }   
        }

        <span class="hljs-keyword">return</span> $head;
    }
}
</code></pre>
<h3 id="heading-solution-in-javascript">Solution in JavaScript</h3>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */</span>
<span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{ListNode}</span> <span class="hljs-variable">head</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{ListNode}</span></span>
 */</span>


<span class="hljs-keyword">var</span> deleteDuplicates = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">head</span>) </span>{
    <span class="hljs-keyword">let</span> node = head;

    <span class="hljs-keyword">while</span>(node?.next) {

        <span class="hljs-keyword">if</span> (node.val === node.next.val) {
            node.next = node.next.next
        } <span class="hljs-keyword">else</span> {
            node = node.next
        }
    }

    <span class="hljs-keyword">return</span> head
};
</code></pre>
<p><strong>Code explanation</strong></p>
<p>Given the <code>deleteDuplicates</code> method:</p>
<ul>
<li><code>node</code> is initialized to the head of the linked list.</li>
<li>A while loop iterates through the linked list until the end or until the current node's <code>next</code> property is <code>null</code>.</li>
<li>Inside the loop, it checks if the current node's value is equal to the next node's value. If they are equal, it skips the next node by setting the current node's <code>next</code> property to the next node's <code>next</code> property.</li>
<li>If the values are not equal, it moves to the next node by updating the value of <code>node</code> to <code>node-&gt;next</code>.</li>
<li>Finally, the method returns the head of the modified linked list.</li>
</ul>
<p>The null safe operator (<code>?.</code>) used in the JS code solution is also available from PHP 8.0. </p>
<p>This code efficiently removes duplicates from a singly-linked list by adjusting pointers and has a time complexity of <code>_O_(_n_)</code> and a space complexity of <code>_O_(1)</code>, where <em><code>n</code></em> is the number of nodes in the linked list.</p>
<h2 id="heading-reference">Reference</h2>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-linked-lists-work/">How does a linked list work</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned about linked list, types of linked list and a real world problem that involves solving the removal of duplicates from sorted list.</p>
<p>Keep learning, and Happy Coding!</p>
<p>You can find me on <a target="_blank" href="https://www.linkedin.com/in/suleolanrewaju/">LinkedIn</a> and <a target="_blank" href="https://twitter.com/bigdevlarry">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Minimum Stability In Composer? ]]>
                </title>
                <description>
                    <![CDATA[ Composer is a dependency management tool for projects running on PHP. PHP frameworks like Laravel, Symfony, and CodeIgniter use Composer to manage libraries and packages. In this tutorial, you’ll learn the following: Introduction to Composer. Minimu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-minimum-stability-in-composer/</link>
                <guid isPermaLink="false">66ba2fe86e35b2ef1a340075</guid>
                
                    <category>
                        <![CDATA[ dependency management ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sule-Balogun Olanrewaju ]]>
                </dc:creator>
                <pubDate>Wed, 09 Aug 2023 17:31:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/08/javier-garcia-chavez-bdZ3bzRde5g-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Composer is a dependency management tool for projects running on PHP. PHP frameworks like Laravel, Symfony, and CodeIgniter use Composer to manage libraries and packages.</p>
<p>In this tutorial, you’ll learn the following:</p>
<ul>
<li>Introduction to Composer.</li>
<li>Minimum stability in Composer.</li>
<li>Levels of stability, and the recommended version for production code.</li>
</ul>
<p>One of the benefits of using a dependency tool is that it makes it easy to declare the key-value pair of packages you need for your project. This way, you can install dependencies via the <code>composer install</code> command or update them via the <code>composer update</code> command in the terminal.</p>
<h2 id="heading-introduction-to-composer">Introduction to Composer</h2>
<p>In Laravel, the <code>composer.json</code> is a JSON file located at the root of the project directory. It contains sample configurations used for dependency management, such as the project name, type (optional), description (optional), and the list of required packages.</p>
<p>These packages are represented using key-value pairs (name and version to be installed). Additionally, the <code>composer.json</code> file includes some required packages for the development environment which can be added as part of the configuration setup.</p>
<p>Here's what a <code>composer.json</code> file looks like:</p>
<pre><code>{
    <span class="hljs-string">"name"</span>: <span class="hljs-string">"laravel/laravel"</span>,    
    <span class="hljs-string">"type"</span>: <span class="hljs-string">"project"</span>,    
    <span class="hljs-string">"description"</span>: <span class="hljs-string">"The Laravel Framework."</span>,    
    <span class="hljs-string">"keywords"</span>: [        
        <span class="hljs-string">"framework"</span>,        
        <span class="hljs-string">"laravel"</span>    
    ],    
    <span class="hljs-string">"license"</span>: <span class="hljs-string">"MIT"</span>,    
    <span class="hljs-string">"require"</span>: {        
       <span class="hljs-string">"php"</span>: <span class="hljs-string">"^8.1"</span>,        
       <span class="hljs-string">"laravel/framework"</span>: <span class="hljs-string">"^10.0"</span>,    
    },    
    <span class="hljs-string">"require-dev"</span>: {    
         .    
         .     
    },    
    <span class="hljs-string">"config"</span>: {    
         .    
         .    
    },    
    <span class="hljs-string">"minimum-stability"</span>: <span class="hljs-string">"dev"</span>| <span class="hljs-string">"alpha"</span>| <span class="hljs-string">"beta"</span>| <span class="hljs-string">"RC"</span>|<span class="hljs-string">"stable"</span>, <span class="hljs-comment">//stable</span>
}
</code></pre><h2 id="heading-what-is-minimum-stability">What is Minimum Stability?</h2>
<p>In Composer, the “minimum-stability” configuration specifies the minimum stability level for all installed packages.</p>
<p>Packages to be installed or updated will use the <code>minimum-stability</code> value to determine version limitations during dependency resolution.</p>
<h3 id="heading-levels-of-stability">Levels of Stability</h3>
<p>The following are the different stability levels:</p>
<ul>
<li><code>dev</code>: This is the least stable version, and should never be used in production. It often includes packages under active development that may contain bugs or breaking changes and may still undergo significant modifications. It is only recommended for local development purposes.</li>
<li><code>alpha</code>: It's a version also undergoing development but in a more stable state. It usually contains fewer breaking changes and features nearing final completion or awaiting a beta release. However, it is also not highly recommended for production environments.</li>
<li><code>beta</code>: This version is currently being tested, and minor bugs, when noticed, will need to be fixed. However, it is more stable than the alpha and dev versions, but it's still not recommended for production purposes.</li>
<li><code>RC</code>: The RC (Release Candidate) is a version pending official release. It's the closest to being stable, but the version requires community testing and feedback prior to the final release. Undiscovered bugs can also be identified during this phase, so it's best practice not to use it for production purposes.</li>
<li><code>stable</code>: This is the required level for production purposes. It includes all packages that have gone through significant changes, bug fixes, community testing, feedback, and is now ready to use.</li>
</ul>
<p>In your <code>composer.json</code>, you can specify the minimum stability by doing the following:</p>
<pre><code>{
    <span class="hljs-string">"minimum-stability"</span>: <span class="hljs-string">"stable"</span>
}
</code></pre><h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you have learned about Composer, the <code>composer.json</code> file, minimum stability, and, most importantly, the levels of stability offered by Composer. </p>
<p>For your application, you should carefully choose the stability level that satisfies your production needs, while keeping security and downtime issues in mind. Remember, your application should only depend on stable and reliable packages.</p>
<p>I hope you now have a better understanding of minimum stability.</p>
<p>Keep learning, and Happy Coding!</p>
<p>You can find me on <a target="_blank" href="https://www.linkedin.com/in/suleolanrewaju/">LinkedIn</a> and <a target="_blank" href="https://twitter.com/bigdevlarry">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
