PHP
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Object-Oriented PHP
-
Section 5: Working with Data
-
Section 6: Modern PHP (PHP 8)
-
Section 7: Working with Files and Networking
-
Section 8: Common PHP Frameworks Overview
-
Section 9: Tooling and Ecosystem
-
Section 10: Practical Projects
-
Section 11: Interview Practice
-
Section 12: More Standard Library
-
Section 13: Data Structures and Algorithms in PHP
-
Section 14: More Practice Exercises
-
Section 15: More Security and Best Practices
-
Section 16: More Testing and Tooling
-
Section 17: WordPress-Style CMS Concepts
-
Section 18: Advanced OOP Practice
-
Section 19: More Web Fundamentals
-
Section 20: Database Practice
-
Section 21: PHP Manual: Array Functions
-
Section 22: PHP Manual: Date and Calendar Functions
-
Section 23: PHP Manual: Filesystem and Directory Functions
-
Section 24: PHP Manual: Filter and Var Handling
-
Section 25: PHP Manual: Math Functions
-
Section 26: PHP Manual: JSON and XML
-
Section 27: PHP Manual: Network and Stream Functions
-
Section 28: PHP Manual: Error and Exception Handling
-
Section 29: PHP Manual: Output Control and Misc
-
Section 30: PHP Manual: FTP, Zip, and Mail
-
Section 31: Modern PHP Frameworks Deep Dive
-
Section 32: PHP Design Patterns
-
Section 33: More Practice Exercises
-
Section 34: PHP Performance and Deployment
-
Section 35: More Interview Practice
-
Section 36: More PHP Standard Library
-
Section 37: PHP Concurrency and Async
-
Section 38: More Web Development Practice
-
Section 39: PHP Testing Deep Dive
-
Section 40: Composer and Package Development
-
Section 41: PHP Security Deep Dive
-
Section 42: More Practical Projects
-
Section 43: Legacy PHP Maintenance
-
Section 44: More Algorithm Practice
-
Section 45: Final Practice and Review
-
Section 46: PHP for E-Commerce Patterns
-
Section 47: PHP API Design Deep Dive
-
Section 48: PHP Caching Strategies
-
Section 49: PHP Queue and Background Jobs
-
Section 50: PHP Multi-Tenancy Patterns
-
Section 51: PHP Real-Time Features
-
Section 52: PHP CMS and Content Modeling
-
Section 53: PHP Internationalization
-
Section 54: More Framework-Specific Practice
-
Section 55: PHP Legacy Code Refactoring
-
Section 56: More Practice Projects Round 2
-
Section 57: PHP Command-Line Applications
-
Section 58: PHP and Microservices
-
Section 59: More Interview and Review Round 2
224: Handling Multi-Language Routes
When you're scaling a site for a global audience, the most common debate is how to handle the URL. You could use cookies or session data, but that's a nightmare for SEO. Search engines want unique URLs for unique content. That's why we're going to implement "locale-prefixing," where the language code (like /en/ or /es/) sits right at the front of the URI.
Parsing the locale from the request
I like to keep my routing logic lean. Instead of a massive switch statement, I'll treat the first segment of the URL as the language identifier. If we're building a simple "Company Profile" page, we want /en/about and /es/about to hit the same controller but load different strings.
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = explode('/', trim($uri, '/'));
// Let's assume the first segment is our language code
$locale = $segments[0] ?? 'en';
$page = $segments[1] ?? 'home';
// A simple translation map for our example
$translations = [
'en' => ['about' => 'About Our Company', 'home' => 'Welcome'],
'es' => ['about' => 'Sobre Nuestra Empresa', 'home' => 'Bienvenido']
];
echo $translations[$locale][$page] ?? 'Page Not Found';
Handling the "Missing Prefix" blunder
I actually just ran this in my local environment and realized I made a classic mistake. If a user visits /about without a language prefix, my code thinks "about" is the language code. It looks for $translations['about'], finds nothing, and throws a warning. It's a common trap when you assume the URL structure will always be perfect.
To fix this, we need to verify if the first segment is actually a supported language. If it's not, we should treat it as the page name and fallback to a default language.
$supportedLocales = ['en', 'es', 'fr'];
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$segments = explode('/', trim($uri, '/'));
$firstSegment = $segments[0] ?? '';
if (in_array($firstSegment, $supportedLocales)) {
$locale = $firstSegment;
$page = $segments[1] ?? 'home';
} else {
$locale = 'en'; // Our default
$page = $firstSegment ?: 'home';
}
echo $translations[$locale][$page] ?? '404 Not Found';
Keeping the user in their chosen language
Now that the routing works, we have a new problem: links. If I'm on the Spanish version of the site and I click a link to "Contact," I don't want to be booted back to the English version. I need a way to generate URLs that preserve the current locale.
I usually wrap this in a small helper function. It feels a bit redundant at first, but it saves you from concatenating strings manually in every single blade or PHP template file across your project.
function url_for($page, $locale = 'en') {
return "/" . $locale . "/" . $page;
}
// If the current user is browsing in Spanish:
$currentLocale = 'es';
echo '<a href="' . url_for('contact', $currentLocale) . '">Contacto</a>';
// Output: Contacto
By centralizing the URL generation, you can change your entire URL structure—say, moving from /en/about to /language/en/about—in one single function rather than hunting through a hundred files.
📋 Practical Task
Build a Locale-Aware Navigation Menu
Create a PHP script that mimics a navigation bar for a multi-language site. Your task is to:
- Define an array of supported languages (e.g.,
'en', 'de', 'it'). - Detect the current locale from the URL using the logic we discussed (with a fallback to 'en').
- Create a navigation array containing page slugs and their translated names for at least two languages.
- Generate an HTML
<nav>list where every link automatically includes the current detected locale in the URL. - Add a "Language Switcher" section that provides links to the same current page but in the other supported languages.
There are no comments for now.