<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        
        
            <title>How to Build a Routing System for a PHP App from Scratch</title>
        
        <meta name="HandheldFriendly" content="True">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <link rel="preconnect" href="https://fonts.googleapis.com">
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
        <link rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,300;0,400;0,700;1,400&family=Roboto+Mono:wght@400;700&display=swap">
        

        
        
    <link rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" href="https://cdn.freecodecamp.org/news-assets/prism/1.29.0/themes/prism.min.css">
<noscript>
  <link rel="stylesheet" href="https://cdn.freecodecamp.org/news-assets/prism/1.29.0/themes/prism.min.css">
</noscript>
<link rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" href="https://cdn.freecodecamp.org/news-assets/prism/1.29.0/plugins/unescaped-markup/prism-unescaped-markup.min.css">
<noscript>
  <link rel="stylesheet" href="https://cdn.freecodecamp.org/news-assets/prism/1.29.0/plugins/unescaped-markup/prism-unescaped-markup.min.css">
</noscript>

<script defer="" src="https://cdn.freecodecamp.org/news-assets/prism/1.29.0/components/prism-core.min.js"></script>
<script defer="" src="https://cdn.freecodecamp.org/news-assets/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>



        
        <link rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'" href="/news/assets/css/global-5a272ab5e0.css">
        <link rel="stylesheet" type="text/css" href="/news/assets/css/screen-73acb3583e.css">
        <link rel="stylesheet" type="text/css" href="/news/assets/css/search-bar-124f5f949c.css">

        
        <script defer="" src="https://cdn.freecodecamp.org/news-assets/algolia/algoliasearch-3-33-0/algoliasearch.min.js"></script>
        <script defer="" src="https://cdn.freecodecamp.org/news-assets/algolia/autocomplete-0-36-0/autocomplete.min.js"></script>

        
        <script defer="" src="https://cdn.freecodecamp.org/news-assets/dayjs/1.10.4/dayjs.min.js"></script>
        <script defer="" src="https://cdn.freecodecamp.org/news-assets/dayjs/1.10.4/localizedFormat.min.js"></script>
        <script defer="" src="https://cdn.freecodecamp.org/news-assets/dayjs/1.10.4/relativeTime.min.js"></script>

        
        
            <script defer="" src="https://cdn.freecodecamp.org/news-assets/dayjs/1.10.4/locale/en.min.js"></script>
        

        
        <script>let client,index;document.addEventListener("DOMContentLoaded",()=>{client=algoliasearch("QMJYL5WYTI","89770b24481654192d7a5c402c6ad9a0"),index=client.initIndex("news")}),document.addEventListener("DOMContentLoaded",()=>{const e=window.screen.width,t=window.screen.height,n=e>=767&&t>=768?8:5,o=document.getElementById("search-form"),s=document.getElementById("search-input"),a=document.getElementById("dropdown-container");let i,d,c;s.addEventListener("input",e=>{i=e.target.value}),o.addEventListener("submit",e=>{e.preventDefault(),function(){if(d=document.getElementsByClassName("aa-cursor")[0],d&&i){const e=d.querySelector("a").href;window.location.assign(e)}else!d&&i&&c&&window.location.assign(`https://www.freecodecamp.org/news/search?query=${i}`)}()});const l=autocomplete("#search-input",{hint:!1,keyboardShortcuts:["s",191],openOnFocus:!0,appendTo:a,debug:!0},[{source:autocomplete.sources.hits(index,{hitsPerPage:n}),debounce:250,templates:{suggestion:e=>(c=!0,`\n            <a href="${e.url}">\n              <div class="algolia-result">\n                <span>${e._highlightResult.title.value}</span>\n              </div>\n            </a>\n          `),empty:()=>(c=!1,'\n            <div class="aa-suggestion footer-suggestion no-hits-footer">\n              <div class="algolia-result">\n                <span>\n                  No results found\n                </span>\n              </div>\n            </div>\n          '),footer:e=>{if(!e.isEmpty)return`\n              <div class="aa-suggestion footer-suggestion">\n                <a id="algolia-footer-selector" href="https://www.freecodecamp.org/news/search?query=${i}">\n                  <div class="algolia-result algolia-footer">\n                    See all results for ${i}\n                  </div>\n                </a>\n              </div>\n            `}}}]).on("autocomplete:selected",(e,t,n,o)=>{d=t?t.url:`https://www.freecodecamp.org/news/search?query=${i}`,"click"!==o.selectionMethod&&"tabKey"!==o.selectionMethod&&c&&window.location.assign(d)});document.addEventListener("click",e=>{e.target!==s&&l.autocomplete.close()})}),document.addEventListener("DOMContentLoaded",()=>{dayjs.extend(dayjs_plugin_localizedFormat),dayjs.extend(dayjs_plugin_relativeTime),dayjs.locale("en")});const isAuthenticated=document.cookie.split(";").some(e=>e.trim().startsWith("jwt_access_token=")),isDonor=document.cookie.split(";").some(e=>e.trim().startsWith("isDonor=true"));</script>

        
            <script src="https://securepubads.g.doubleclick.net/tag/js/gpt.js" crossorigin="anonymous" async=""></script>
        

        
        
    
        
            <script>
document.addEventListener('DOMContentLoaded', function() {
    var sidebar = document.querySelector('.sidebar');
    var isSideBarDisplayed = window.getComputedStyle(sidebar).display !== 'none';
    function prepareAdSlot(elementId) {
        // Get the element by ID
        const targetElement = document.getElementById(elementId);

        // Ensure the element exists before proceeding
        if (!targetElement) {
            console.error(`Element with ID ${elementId} not found`);
            return;
        }

        const parentElement = targetElement.parentElement;
        // Change the background color of the parent element

        if (parentElement) {
            console.log(elementId)

            if (elementId === 'gam-ad-bottom' ) {
                parentElement.style.backgroundColor = '#eeeef0';
                if(getComputedStyle(parentElement).visibility === 'hidden') {
                    parentElement.style.visibility = 'inherit'; 
                }
            }

            // Get the sibling elements
            const siblingElements = parentElement.children;

            for (let i = 0; i < siblingElements.length; i++) {
                const sibling = siblingElements[i];

                // Skip the element itself
                if (sibling === targetElement) continue;

                // Log the sibling or perform any other action
                console.log('Found sibling:', sibling);

                // Check visibility
                if(getComputedStyle(sibling).visibility === 'hidden') {
                    sibling.style.visibility = 'inherit'; 
                }

                // Check if display is 'none', then change it to 'block'
                if (getComputedStyle(sibling).display === 'none') {
                    sibling.style.display = 'block'; 
                }
            }
        } else {
            console.warn('No parent element found');
        }
    }

    
    window.googletag = window.googletag || {cmd: []};
    googletag.cmd.push(function() {

        if(isSideBarDisplayed){
            var sidebarHeight = sidebar.offsetHeight;
            var adTextSideBarHeight = 0;
            var sideBarAdContainert = 600 + 17;
        
            var styles = window.getComputedStyle(sidebar);
            var avaiableSideAdSpace = sidebarHeight - adTextSideBarHeight - parseFloat(styles.paddingTop) - parseFloat(styles.paddingBottom);
            var numSideElements = Math.floor(avaiableSideAdSpace / sideBarAdContainert);
            for (var i = 0; i < numSideElements; i++) {
                // container element
                var containerElement = document.createElement('div');
                containerElement.classList.add('ad-wrapper');

                //text element
                var textElement = document.createElement('div');
                textElement.classList.add('ad-text');
                textElement.innerText = localizedAdText;

                // ad element
                var adElement = document.createElement('div');
                var sideAdElementId = 'side-gam-ad-' + i;
                adElement.id = sideAdElementId;
                adElement.classList.add('side-bar-ad-slot');

                // finalize setup
                containerElement.appendChild(textElement);
                containerElement.appendChild(adElement);
                sidebar.appendChild(containerElement);
                googletag.defineSlot('/23075930536/post-side', [[292, 30], [240, 400], [300, 75], [216, 54], [250, 360], [300, 50], 'fluid', [300, 31], [120, 20], [300, 250], [120, 30], [180, 150], [200, 446], [168, 42], [200, 200], [160, 600], [120, 90], [125, 125], [240, 133], [120, 60], [1, 1], [120, 240], [220, 90], [216, 36], [250, 250], [168, 28], [234, 60], [120, 600], [300, 600], [88, 31], [300, 100]], sideAdElementId).addService(googletag.pubads());
            }
        }

        // Define bottom ad
        googletag.defineSlot('/23075930536/post-bottom', ['fluid'], 'gam-ad-bottom').addService(googletag.pubads());

        // Enable lazy loading with default settings.
        googletag.pubads().enableLazyLoad();

        googletag.pubads().addEventListener("slotRequested", (event) => {
            console.log(`Slot ${event.slot.getSlotElementId()} fetched`);
        });

        googletag.pubads().addEventListener("slotOnload", (event) => {
            const elementId = event.slot.getSlotElementId();
            prepareAdSlot(elementId);
            console.log(`Slot ${event.slot.getSlotElementId()} rendered`);
        });

        googletag.pubads().enableSingleRequest();
        googletag.enableServices();


        // Trigger lazy loading
        googletag.display('gam-ad-bottom');

    });
});
</script>

        
    


        
            <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-5D6RKKP');</script>

        
        
        
        
    
        
    
        
    


        
        
        

        
        

        <link rel="icon" href="https://cdn.freecodecamp.org/universal/favicons/favicon.ico" type="image/png">
        
        
            <link rel="canonical" href="https://www.freecodecamp.org/news/how-to-build-a-routing-system-in-php/">
        
        <meta name="referrer" content="no-referrer-when-downgrade">

        

        
    <meta name="description" content="By Abel Lifaefi Mbula If you’re just at the beginning of your journey in PHP development, chances are that you use complete file names in the URL to navigate your application, like server/contact.php. No worries, we all started that way, and it’s how...">

    
    <meta property="og:site_name" content="freeCodeCamp.org">
    <meta property="og:type" content="article">
    <meta property="og:title" content="How to Build a Routing System for a PHP App from Scratch">
    
        <meta property="og:description" content="By Abel Lifaefi Mbula If you’re just at the beginning of your journey in PHP development, chances are that you use complete file names in the URL to navigate your application, like server/contact.php. No worries, we all started that way, and it’s how...">
    
    <meta property="og:url" content="https://www.freecodecamp.org/news/how-to-build-a-routing-system-in-php/">
    <meta property="og:image" content="https://www.freecodecamp.org/news/content/images/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png">
    <meta property="article:published_time" content="2023-05-02T08:36:11.000Z">
    <meta property="article:modified_time" content="2023-05-02T08:36:11.000Z">
    
        <meta property="article:tag" content="PHP">
    
        <meta property="article:tag" content="routing">
    
    <meta property="article:publisher" content="https://www.facebook.com/freecodecamp">
    

    
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="How to Build a Routing System for a PHP App from Scratch">
    
        <meta name="twitter:description" content="By Abel Lifaefi Mbula If you’re just at the beginning of your journey in PHP development, chances are that you use complete file names in the URL to navigate your application, like server/contact.php. No worries, we all started that way, and it’s how...">
    
    <meta name="twitter:url" content="https://www.freecodecamp.org/news/how-to-build-a-routing-system-in-php/">
    <meta name="twitter:image" content="https://www.freecodecamp.org/news/content/images/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png">
    <meta name="twitter:label1" content="Written by">
    <meta name="twitter:data1" content="freeCodeCamp">
    <meta name="twitter:label2" content="Filed under">
    <meta name="twitter:data2" content="PHP, routing">
    <meta name="twitter:site" content="@freecodecamp">
    
        <meta name="twitter:creator" content="@freecodecamp">
    

    <meta property="og:image:width" content="600">
    <meta property="og:image:height" content="400">


        
    <script type="application/ld+json">{
	"@context": "https://schema.org",
	"@type": "Article",
	"publisher": {
		"@type": "Organization",
		"name": "freeCodeCamp.org",
		"url": "https://www.freecodecamp.org/news/",
		"logo": {
			"@type": "ImageObject",
			"url": "https://cdn.freecodecamp.org/platform/universal/fcc_primary.svg",
			"width": 2100,
			"height": 240
		}
	},
	"image": {
		"@type": "ImageObject",
		"url": "https://www.freecodecamp.org/news/content/images/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png",
		"width": 600,
		"height": 400
	},
	"url": "https://www.freecodecamp.org/news/how-to-build-a-routing-system-in-php/",
	"mainEntityOfPage": {
		"@type": "WebPage",
		"@id": "https://www.freecodecamp.org/news/"
	},
	"datePublished": "2023-05-02T08:36:11.000Z",
	"dateModified": "2023-05-02T08:36:11.000Z",
	"keywords": "PHP, routing",
	"description": "By Abel Lifaefi Mbula\nIf you’re just at the beginning of your journey in PHP development, chances are that you use complete file names in the URL to navigate your application, like server/contact.php. No worries, we all started that way, and it’s how...",
	"headline": "How to Build a Routing System for a PHP App from Scratch",
	"author": {
		"@type": "Person",
		"name": "freeCodeCamp",
		"url": "https://www.freecodecamp.org/news/author/freeCodeCamp/",
		"sameAs": [
			"https://www.freecodecamp.org",
			"https://x.com/freecodecamp"
		],
		"image": {
			"@type": "ImageObject",
			"url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1712072540742/C7c8AOPN6.png",
			"width": 600,
			"height": 600
		}
	}
}</script>


        <meta name="generator" content="Eleventy">
        <link rel="alternate" type="application/rss+xml" title="freeCodeCamp.org" href="https://www.freecodecamp.org/news/rss/">

        
        

        
  <meta name="x-fcc-source" data-test-label="x-fcc-source" content="Hashnode">

    </head>

    
        <body class="home-template">
    

    
        <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5D6RKKP" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>

    

        <div class="site-wrapper">
            <nav class="site-nav nav-padding">
    <div class="site-nav-left">
        
<form id="search-form" data-test-label="search-bar">
    <div role="search" class="searchbox__wrapper">
        <label class="fcc_sr_only" for="search-input">
            Search
        </label>
        <input type="search" placeholder="
    Search our news articles, tutorials, and books
" id="search-input">
        <button type="submit" class="ais-SearchBox-submit">
            <svg class="ais-SearchBox-submitIcon" xmlns="https://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 40 40">
    <path d="M26.804 29.01c-2.832 2.34-6.465 3.746-10.426 3.746C7.333 32.756 0 25.424 0 16.378 0 7.333 7.333 0 16.378 0c9.046 0 16.378 7.333 16.378 16.378 0 3.96-1.406 7.594-3.746 10.426l10.534 10.534c.607.607.61 1.59-.004 2.202-.61.61-1.597.61-2.202.004L26.804 29.01zm-10.426.627c7.323 0 13.26-5.936 13.26-13.26 0-7.32-5.937-13.257-13.26-13.257C9.056 3.12 3.12 9.056 3.12 16.378c0 7.323 5.936 13.26 13.258 13.26z"></path>
</svg>

            <span class="fcc_sr_only">Submit your search query</span>
        </button>
        <div id="dropdown-container"></div>
    </div>
</form>

    </div>
    <div class="site-nav-middle">
        <a class="site-nav-logo" href="https://www.freecodecamp.org/news/" data-test-label="site-nav-logo"><img src="https://cdn.freecodecamp.org/platform/universal/fcc_primary.svg" alt="freeCodeCamp.org"></a>
    </div>
    <div class="site-nav-right">
        <div class="nav-group">
            <a class="nav-forum" id="nav-forum" rel="noopener noreferrer" href="https://forum.freecodecamp.org/" target="_blank" data-test-label="forum-button">Forum</a>
            <a class="toggle-button-nav" id="nav-donate" rel="noopener noreferrer" href="https://www.freecodecamp.org/donate/" target="_blank" data-test-label="donate-button">Donate</a>
        </div>
    </div>
</nav>


            
            <a class="banner" id="banner" data-test-label="banner" rel="noopener noreferrer" target="_blank">
    <p id="banner-text"></p>
</a>


    
    <script>document.addEventListener("DOMContentLoaded",()=>{const e=document.getElementById("banner"),t=document.getElementById("banner-text");if(isAuthenticated){t.innerHTML=isDonor?"Thank you for supporting freeCodeCamp through <span>your donations</span>.":"Support our charity and our mission. <span>Donate to freeCodeCamp.org</span>.",e.href=isDonor?"https://www.freecodecamp.org/news/how-to-donate-to-free-code-camp/":"https://www.freecodecamp.org/donate";const o=isDonor?"donor":"authenticated";e.setAttribute("text-variation",o)}else t.innerHTML="Learn to code — <span>free 3,000-hour curriculum</span>",e.href="https://www.freecodecamp.org/",e.setAttribute("text-variation","default")});</script>


            <div id="error-message"></div>

            
    <main id="site-main" class="post-template site-main outer">
        <div class="inner ad-layout">
            <article class="post-full post">
                <header class="post-full-header">
                    <section class="post-full-meta">
                        <time class="post-full-meta-date" data-test-label="post-full-meta-date" datetime="2023-05-02T08:36:11.000Z">
                            May 2, 2023
                        </time>
                        
                            <span class="date-divider">/</span>
                            <a dir="ltr" href="/news/tag/php/">
                                #PHP
                            </a>
                        
                    </section>
                    <h1 class="post-full-title" data-test-label="post-full-title">How to Build a Routing System for a PHP App from Scratch</h1>
                </header>
                
                <figure class="post-full-image">
                    
    <picture>
      <source media="(max-width: 700px)" sizes="1px" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7 1w">
      <source media="(min-width: 701px)" sizes="(max-width: 800px) 400px, (max-width: 1170px) 700px, 1400px" srcset="https://www.freecodecamp.org/news/content/images/size/w300/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png 300w, https://www.freecodecamp.org/news/content/images/size/w600/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png 600w, https://www.freecodecamp.org/news/content/images/size/w1000/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png 1000w, https://www.freecodecamp.org/news/content/images/size/w2000/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png 2000w">
      <img onerror="this.style.display='none'" src="https://www.freecodecamp.org/news/content/images/size/w2000/2023/04/Pink-8-March-Happy-Woman-s-Day-Facebook-Post-1-.png" alt="How to Build a Routing System for a PHP App from Scratch" ,="" width="600" height="400" data-test-label="feature-image">
    </picture>
  
                </figure>
                <section class="post-full-content">
                    <div class="post-and-sidebar">
                        <section class="post-content " data-test-label="post-content">
                            
<p>By Abel Lifaefi Mbula</p>
<p>If you’re just at the beginning of your journey in PHP development, chances are that you use complete file names in the URL to navigate your application, like <code>server/contact.php</code>. No worries, we all started that way, and it’s how we learn.</p>
<p>Today, I want to help you improve how you navigate files in your application. We’ll be talking about routing, as it’s crucial in any modern application. It'll help you take a step forward in your professional PHP development. </p>
<p>A routing system simply maps an <a target="_blank" href="https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html">HTTP</a> request to a request handler (function or method). In other words, it defines how we navigate or access different parts of an app without the need to type the file name. You can do this by creating or setting routes (or paths). For example, the route <code>server/contact</code> lets us access the <code>contact.php</code> file.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To get the most out of this tutorial, you'll need the following:</p>
<ul>
<li>A basic understanding of PHP.</li>
<li>A basic understanding of HTTP and networking.</li>
<li>An Apache or NGINX server, and a basic understanding of how to configure those.</li>
</ul>
<p>And with that, let's jump in.</p>
<h2 id="heading-how-routing-works">How Routing Works</h2>
<p>First thing first, let me recall you what a routing is. Routing allows us to structure our app in a better way and get rid of messy URLs. These are two main features offered by any good routing system:</p>
<ul>
<li>Defines which action to run for each incoming request.</li>
<li>Generates SEO-friendly URLs (e.g. <code>/views/users</code> instead of <code>views/user.php?all</code>).</li>
</ul>
<p>To do a routing system, we need a router, which is no more than the entry file to our app. By default, this entry file is named as <code>index.php</code>. Inside the file, we define the routing system thanks to <code>[switch](https://www.php.net/manual/en/control-structures.switch.php)</code> or <code>[match](https://www.php.net/manual/en/control-structures.match.php)</code> statements. </p>
<p>Last but not least, we must redirect all requests to the router. This is done in the configuration file of the PHP server.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Before moving forward, let’s see what the project will look like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/file-tree-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>File structure</em></p>
<p>Use the shell commands below to initiate the project:</p>
<pre><code class="lang-bash">mkdir php-routing &amp; <span class="hljs-built_in">cd</span> php-routing
touch index.php .htaccess
</code></pre>
<ul>
<li><code>.htaccess</code>: A directory-level Apache configuration file. You don’t need it if you use an NGINX server.</li>
<li><code>index.php</code>: This is the router and entry file of the project. All incoming requests will be redirected here.</li>
<li><code>views</code>: This folder holds all the UIs for the project.</li>
</ul>
<h2 id="heading-how-to-redirect-all-http-requests-to-the-router"><strong>How to Redirect All HTTP Requests to the Router</strong></h2>
<p>We've said earlier that the redirection is done in the PHP server config file. So you'll need to make some tweaks depending on whether you use an Apache or NGINX server.</p>
<h3 id="heading-redirect-using-apache">Redirect Using Apache</h3>
<p>Here, we can easily use the <code>.htaccess</code> file that we have already created in the root of the project. Add the directives below:</p>
<pre><code class="lang-bash">RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php
</code></pre>
<ul>
<li><em>line 1</em>: We activate the Apache server’s runtime rewriting engine. </li>
<li><em>line 2</em>: We limit access to physical files. </li>
<li><em>line 3</em>: We redirect all the upcoming requests to the <code>index.php</code>.</li>
</ul>
<p>Note: If the site or app is note at the root of the server (or if we don’t have a virtual host), here's what the <code>.htaccess</code> should look like:</p>
<pre><code class="lang-bash">RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</code></pre>
<p>In the code above, replace <code>/folder/</code> with the name of the folder containing your site.</p>
<h3 id="heading-redirect-using-nginx">Redirect Using NGINX</h3>
<p>The default configuration file is name <code>nginx.conf</code>. This file can be found in <code>etc/nginx</code>, <code>usr/local/nginx/conf</code>, or <code>/usr/local/etc/nginx</code>.</p>
<p>To redirect to <code>index.php</code> use the command below:</p>
<pre><code class="lang-nginx"><span class="hljs-attribute">location</span> / {
        <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php
}
</code></pre>
<p>The <code>location /</code> block specifies that this is a match for all locations unless explicitly specified <code>location /&lt;name&gt;</code>.</p>
<p>The <code>try_files</code> directive tells the server that for any request to the URI that matches the block in the location, try the <code>$uri</code> (or <code>$uri/</code>) first, and if the file is present, serve the file. Otherwise, the fallback option (<code>index.php</code>) is used. And this last behavior is what we want.</p>
<p>Reload the server after the modification.</p>
<h2 id="heading-how-to-create-the-routing-system"><strong>How to Create the Routing System</strong></h2>
<p>We now know how routing works, and we are even sending all requests to the router. Now is the time to write the code for the router in <code>index.php</code>.</p>
<p>First, create a variable to hold the HTTP request string:</p>
<pre><code class="lang-php">$request = $_SERVER[<span class="hljs-string">'REQUEST_URI'</span>];
</code></pre>
<p>This variable will help us to compare with many routes (paths) and call the appropriate view interface. </p>
<pre><code class="lang-php"><span class="hljs-keyword">switch</span> ($request) {
     <span class="hljs-keyword">case</span> <span class="hljs-string">'/views/users'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/views/users.php'</span>;

     <span class="hljs-keyword">case</span> <span class="hljs-string">'/views/department'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . <span class="hljs-string">'/views/dep.php'</span>;
}
</code></pre>
<p>What's happening here? The <code>switch</code> statement is similar to a series of <code>if</code> statements on the same expression (variable). It executes a code only when a <code>case</code> statement is found whose expression evaluates to a value that matches the value of the <code>switch</code> expression. Let me illustrate this so that you can get it well. </p>
<p>Let's consider that our variable holds the value <code>/views/users/</code>. When the piece of the code above will be run, PHP will check if the value <code>/views/users</code> equals to the value of <code>case</code> statement, which in our case is <code>/views/users</code>. So, this condition will evaluate to <code>true</code>, PHP will call the file <code>/views/users.php</code>. If the condition evaluates to <code>false</code>, PHP will check for the next <code>case</code> statement until the end of the <code>switch</code> block. </p>
<p><strong>Note</strong>: Every time the <code>case</code> statement evaluates to <code>true</code> PHP will continue to execute the code in the following <code>case</code> statements without necessary evaluating those <code>case</code> statements. In our case, PHP also requires <code>views/dep.php</code>. To avoid this "bad behavior", you must add <code>break</code> statement after each <code>case</code> statement.</p>
<p>Let now put everything together into our <code>index.php</code> file:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

$request = $_SERVER[<span class="hljs-string">'REQUEST_URI'</span>];
$viewDir = <span class="hljs-string">'/views/'</span>;

<span class="hljs-keyword">switch</span> ($request) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">''</span>:
    <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . $viewDir . <span class="hljs-string">'home.php'</span>;
        <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">case</span> <span class="hljs-string">'/views/users'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . $viewDir . <span class="hljs-string">'users.php'</span>;
        <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">case</span> <span class="hljs-string">'/contact'</span>:
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . $viewDir . <span class="hljs-string">'contact.php'</span>;
        <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">default</span>:
        http_response_code(<span class="hljs-number">404</span>);
        <span class="hljs-keyword">require</span> <span class="hljs-keyword">__DIR__</span> . $viewDir . <span class="hljs-string">'404.php'</span>;
}
</code></pre>
<p>As you already know, we start off by storing a user request in the <code>$request</code> variable, then we use it in the <code>switch</code> statement. For the sake of clean code, I have created a variable to hold the view directory name.</p>
<p>You'll also notice two other things:</p>
<ul>
<li>Both <code>''</code> and <code>'/'</code> are used to match <code>site.com</code> as well as <code>site.com/</code> for when users are in the root of the app or website.</li>
<li>There's a special <code>case</code> statement, <code>default</code>, to match anything that wasn't matched by the other cases, i.e. when the route is unknown.</li>
</ul>
<p>Let's now add some dummy data in our views.</p>
<h2 id="heading-add-dummy-data-in-the-views-files"><strong>Add Dummy Data in the Views Files</strong></h2>
<p>We have already created all files in the <code>views</code> directory. Let's just move to this directory and add some content in each file.</p>
<p>Just put some content in each file:</p>
<pre><code class="lang-php">&lt;h1&gt;Home&lt;/h1&gt;
&lt;p&gt;Welcome in my app.&lt;/p&gt;
</code></pre>
<pre><code class="lang-php">&lt;h1&gt;Users&lt;/h1&gt;
&lt;p&gt;<span class="hljs-keyword">List</span> of our users.&lt;/p&gt;
</code></pre>
<pre><code class="lang-php">&lt;h1&gt;Conct us&lt;/h1&gt;
&lt;p&gt;Getting in touch is easy. Just email us&lt;/p&gt;
</code></pre>
<pre><code class="lang-php">&lt;h1&gt;<span class="hljs-number">404</span>&lt;/h1&gt;
&lt;p&gt;You<span class="hljs-string">'ve reached the end of Internet.&lt;/p&gt;</span>
</code></pre>
<p>As you can see, each file just contains a title and a paragraph. Feel free to add whatever content you like and test the router.</p>
<h2 id="heading-final-thoughts"><strong>Final thoughts</strong></h2>
<p>In this tutorial, you learned how to create a basic routing system from scratch, including:</p>
<ul>
<li>How to create a file named <code>index.php</code> at the root of the project. This is the router for your app.</li>
<li>How to redirect all incoming requests to the router. You do this in the configuration file of your server.</li>
<li>How to create the routing system with a <code>switch</code> statement in the router.</li>
</ul>
<p>Happy coding!</p>


                        </section>
                        
                            <div class="sidebar">
                                
                                    
                                    <script>var localizedAdText = "ADVERTISEMENT";</script>
                                
                            </div>
                        
                    </div>
                    <hr>
                    

                    
                    
                        
    


<p data-test-label="social-row-cta" class="social-row">
    If you read this far, thank the author to show them you care. <button id="tweet-btn" class="cta-button" data-test-label="tweet-button">Say Thanks</button>
</p>


    
    <script>document.addEventListener("DOMContentLoaded",()=>{const t=document.getElementById("tweet-btn"),e=window.location,o="How%20to%20Build%20a%20Routing%20System%20for%20a%20PHP%20App%20from%20Scratch".replace(/&#39;/g,"%27"),n="",r="@freecodecamp",i=Boolean("");let a;if(i&&(n||r)){const t={originalPostAuthor:"",currentPostAuthor:"freeCodeCamp"};a=encodeURIComponent(`Thank you ${n||t.originalPostAuthor} for writing this helpful article, and ${r||t.currentPostAuthor} for translating it.`)}else!i&&r&&(a=encodeURIComponent(`Thank you ${r} for writing this helpful article.`));const c=`window.open(\n    '${a?`https://x.com/intent/post?text=${a}%0A%0A${o}%0A%0A${e}`:`https://x.com/intent/post?text=${o}%0A%0A${e}`}',\n    'share-twitter',\n    'width=550, height=235'\n  ); return false;`;t.setAttribute("onclick",c)});</script>


                        

<div class="learn-cta-row" data-test-label="learn-cta-row">
    <p>
        Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. <a href="https://www.freecodecamp.org/learn/" class="cta-button" id="learn-to-code-cta" rel="noopener noreferrer" target="_blank">Get started</a>
    </p>
</div>

                    
                </section>
                
                    <div class="banner-ad-bottom">
                        
                            

<div class="ad-text" data-test-label="ad-text">ADVERTISEMENT</div>
<div style="display: block; height: auto" id="gam-ad-bottom">
</div>

                        
                    </div>
                
            </article>
        </div>
    </main>


            


<footer class="site-footer">
    <div class="footer-top">
        <div class="footer-desc-col">
            <p data-test-label="tax-exempt-status">freeCodeCamp is a donor-supported tax-exempt 501(c)(3) charity organization (United States Federal Tax Identification Number: 82-0779546)</p>
            <p data-test-label="mission-statement">Our mission: to help people learn to code for free. We accomplish this by creating thousands of videos, articles, and interactive coding lessons - all freely available to the public.</p>
            <p data-test-label="donation-initiatives">Donations to freeCodeCamp go toward our education initiatives, and help pay for servers, services, and staff.</p>
            <p class="footer-donation" data-test-label="donate-text">
                You can <a href="https://www.freecodecamp.org/donate/" class="inline" rel="noopener noreferrer" target="_blank">make a tax-deductible donation here</a>.
            </p>
        </div>
        <div class="trending-guides" data-test-label="trending-guides">
            <h2 id="trending-guides" class="col-header">Trending Books and Handbooks</h2>
            <ul class="trending-guides-articles" aria-labelledby="trending-guides">
                <li>
                    <a href="https://www.freecodecamp.org/news/build-consume-and-document-a-rest-api/" rel="noopener noreferrer" target="_blank">REST APIs
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/how-to-write-clean-code/" rel="noopener noreferrer" target="_blank">Clean Code
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/learn-typescript-with-react-handbook/" rel="noopener noreferrer" target="_blank">TypeScript
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/learn-javascript-for-beginners/" rel="noopener noreferrer" target="_blank">JavaScript
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/how-to-build-an-ai-chatbot-with-redis-python-and-gpt/" rel="noopener noreferrer" target="_blank">AI Chatbots
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/command-line-for-beginners/" rel="noopener noreferrer" target="_blank">Command Line
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/building-consuming-and-documenting-a-graphql-api/" rel="noopener noreferrer" target="_blank">GraphQL APIs
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/complete-guide-to-css-transform-functions-and-properties/" rel="noopener noreferrer" target="_blank">CSS Transforms
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/how-to-build-scalable-access-control-for-your-web-app/" rel="noopener noreferrer" target="_blank">Access Control
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/rest-api-design-best-practices-build-a-rest-api/" rel="noopener noreferrer" target="_blank">REST API Design
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/the-php-handbook/" rel="noopener noreferrer" target="_blank">PHP
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/the-java-handbook/" rel="noopener noreferrer" target="_blank">Java
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/learn-linux-for-beginners-book-basic-to-advanced/" rel="noopener noreferrer" target="_blank">Linux
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/react-for-beginners-handbook/" rel="noopener noreferrer" target="_blank">React
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/learn-continuous-integration-delivery-and-deployment/" rel="noopener noreferrer" target="_blank">CI/CD
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/the-docker-handbook/" rel="noopener noreferrer" target="_blank">Docker
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/learn-golang-handbook/" rel="noopener noreferrer" target="_blank">Golang
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/the-python-handbook/" rel="noopener noreferrer" target="_blank">Python
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/get-started-with-nodejs/" rel="noopener noreferrer" target="_blank">Node.js
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/build-crud-operations-with-dotnet-core-handbook/" rel="noopener noreferrer" target="_blank">Todo APIs
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/how-to-use-classes-in-javascript-handbook/" rel="noopener noreferrer" target="_blank">JavaScript Classes
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/front-end-javascript-development-react-angular-vue-compared/" rel="noopener noreferrer" target="_blank">Front-End Libraries
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/the-express-handbook/" rel="noopener noreferrer" target="_blank">Express and Node.js
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/python-code-examples-sample-script-coding-tutorial-for-beginners/" rel="noopener noreferrer" target="_blank">Python Code Examples
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/clustering-in-python-a-machine-learning-handbook/" rel="noopener noreferrer" target="_blank">Clustering in Python
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/an-introduction-to-software-architecture-patterns/" rel="noopener noreferrer" target="_blank">Software Architecture
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/what-is-programming-tutorial-for-beginners/" rel="noopener noreferrer" target="_blank">Programming Fundamentals
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/learn-to-code-book/" rel="noopener noreferrer" target="_blank">Coding Career Preparation
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/become-a-full-stack-developer-and-get-a-job/" rel="noopener noreferrer" target="_blank">Full-Stack Developer Guide
                    </a>
                </li>
                <li>
                    <a href="https://www.freecodecamp.org/news/learn-python-for-javascript-developers-handbook/" rel="noopener noreferrer" target="_blank">Python for JavaScript Devs
                    </a>
                </li>
            </ul>
            <div class="spacer" style="padding: 15px 0;"></div>
            <div>
                <h2 id="mobile-app" class="col-header">
                    Mobile App
                </h2>
                <div class="min-h-[1px] px-[15px] md:w-2/3 md:ml-[16.6%]">
                    <ul aria-labelledby="mobile-app" class="mobile-app-container">
                        <li>
                            <a href="https://apps.apple.com/us/app/freecodecamp/id6446908151?itsct=apps_box_link&itscg=30200" rel="noopener noreferrer" target="_blank">
                                <img src="https://cdn.freecodecamp.org/platform/universal/apple-store-badge.svg" lang="en" alt="Download on the App Store">
                            </a>
                        </li>
                        <li>
                            <a href="https://play.google.com/store/apps/details?id=org.freecodecamp" rel="noopener noreferrer" target="_blank">
                                <img src="https://cdn.freecodecamp.org/platform/universal/google-play-badge.svg" lang="en" alt="Get it on Google Play">
                            </a>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
    <div class="footer-bottom">
        <h2 class="col-header" data-test-label="our-nonprofit">Our Charity</h2>
        <div class="our-nonprofit">
             
                <span data-test-label="powered-by">
                    Publication powered by Hashnode
                </span>
            
            <a href="https://www.freecodecamp.org/news/about/" rel="noopener noreferrer" target="_blank" data-test-label="about">
                About
            </a>
            <a href="https://www.linkedin.com/school/free-code-camp/people/" rel="noopener noreferrer" target="_blank" data-test-label="alumni">
                Alumni Network
            </a>
            <a href="https://github.com/freeCodeCamp/" rel="noopener noreferrer" target="_blank" data-test-label="open-source">
                Open Source
            </a>
            <a href="https://www.freecodecamp.org/news/shop/" rel="noopener noreferrer" target="_blank" data-test-label="shop">
                Shop
            </a>
            <a href="https://www.freecodecamp.org/news/support/" rel="noopener noreferrer" target="_blank" data-test-label="support">
                Support
            </a>
            <a href="https://www.freecodecamp.org/news/sponsors/" rel="noopener noreferrer" target="_blank" data-test-label="sponsors">
                Sponsors
            </a>
            <a href="https://www.freecodecamp.org/news/academic-honesty-policy/" rel="noopener noreferrer" target="_blank" data-test-label="honesty">
                Academic Honesty
            </a>
            <a href="https://www.freecodecamp.org/news/code-of-conduct/" rel="noopener noreferrer" target="_blank" data-test-label="coc">
                Code of Conduct
            </a>
            <a href="https://www.freecodecamp.org/news/privacy-policy/" rel="noopener noreferrer" target="_blank" data-test-label="privacy">
                Privacy Policy
            </a>
            <a href="https://www.freecodecamp.org/news/terms-of-service/" rel="noopener noreferrer" target="_blank" data-test-label="tos">
                Terms of Service
            </a>
            <a href="https://www.freecodecamp.org/news/copyright-policy/" rel="noopener noreferrer" target="_blank" data-test-label="copyright">
                Copyright Policy
            </a>
        </div>
    </div>
</footer>

        </div>

        
        
        

        
        
    </body>
</html>