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
185: Implementing a Graph and BFS/DFS in PHP
I've been thinking about how we track prerequisites for our course modules. Right now, it's just a list, but in reality, learning is a graph. To learn "Advanced Design Patterns," you might need "OOP Basics" and "SOLID Principles," and "SOLID" itself requires "OOP Basics." If we want to programmatically figure out a learning path, a simple array won't cut it. We need a Graph.
Mapping the dependencies
I'll start by sketching out a simple adjacency list. In PHP, the easiest way to represent a graph is an associative array where the keys are our nodes and the values are arrays of the nodes they connect to. Let's try this:
$graph = [
'Logic' => ['Basic Math'],
'Basic Math' => [],
'JavaScript' => ['Logic'],
'React' => ['JavaScript', 'HTML/CSS'],
'HTML/CSS' => ['Basic Math'],
'Next.js' => ['React'],
];
It looks fine on paper, but if I want to find every single thing I need to know before I touch Next.js, I can't just look at the 'Next.js' key. I have to follow the chain. This is where traversal comes in. I'm going to try a Depth-First Search (DFS) first, because it feels natural to just "dive deep" into one prerequisite before moving to the next.
Falling down the rabbit hole with DFS
I'll write a recursive function. The idea is: start at a node, visit its first neighbor, then that neighbor's neighbor, and so on, until I hit a dead end.
function dfs($graph, $node, &$visited = []) {
if (in_array($node, $visited)) return;
echo "Visiting: $node\n";
$visited[] = $node;
foreach ($graph[$node] as $neighbor) {
dfs($graph, $neighbor, $visited);
}
}
dfs($graph, 'Next.js');
Running this, I see: Next.js → React → JavaScript → Logic → Basic Math. Then it backtracks to HTML/CSS → Basic Math. Wait, it visited Basic Math twice. That's why I added the $visited array—without it, if I had a circular dependency (like A depends on B, and B depends on A), this script would crash my server with a stack overflow. Always track where you've been.
Switching gears to BFS
DFS is great for finding the "bottom" of a dependency chain, but what if I want to know the shortest path? Or maybe I just want to see the immediate layers of requirements? For that, DFS is the wrong tool. I need Breadth-First Search (BFS). Instead of diving deep, BFS explores all immediate neighbors first.
I can't use recursion easily for BFS. I need a queue. PHP has SplQueue, which is much more efficient than using array_shift() on a standard array (which re-indexes the whole array every time). Let's see if we can implement this.
function bfs($graph, $startNode) {
$queue = new SplQueue();
$queue->enqueue($startNode);
$visited = [$startNode => true];
while (!$queue->isEmpty()) {
$currentNode = $queue->dequeue();
echo "Exploring: $currentNode\n";
foreach ($graph[$currentNode] as $neighbor) {
if (!isset($visited[$neighbor])) {
$visited[$neighbor] = true;
$queue->enqueue($neighbor);
}
}
}
}
bfs($graph, 'Next.js');
Now the output changes. It hits Next.js, then React, then it hits JavaScript and HTML/CSS before it ever touches Logic. It's moving in ripples. If this were a social network, BFS would be how you find "friends of friends" or the shortest distance between two people.
When to use which?
After playing with both, the distinction is clear to me. If I'm trying to solve a puzzle or find a path to a leaf node (like "what is the very first thing I need to learn?"), DFS is my go-to. If I'm looking for the closest target or scanning a neighborhood, BFS is the winner. The key implementation difference is simply the data structure: DFS uses a Stack (implicitly via recursion), and BFS uses a Queue.
📋 Practical Task
Building a Movie Recommendation Path-Finder
You are building a feature for a movie app. Movies are nodes in a graph, and an edge exists between two movies if they share the same director or lead actor. Your goal is to find the "degrees of separation" between two movies.
The Task:
Implement a function findShortestPath($graph, $start, $target) using a Breadth-First Search. Instead of just visiting nodes, your function must keep track of the path taken.
Requirements:
- Use an adjacency list (associative array) to represent the movie connections.
- Use
SplQueuefor the traversal. - The function should return an array representing the shortest path from the start movie to the target movie (e.g.,
['Inception', 'Interstellar', 'The Prestige']). - If no path exists, return
null.
Starter Graph:
$movieGraph = [
'Inception' => ['Interstellar', 'The Dark Knight'],
'Interstellar' => ['Inception', 'The Prestige'],
'The Dark Knight' => ['Inception', 'Batman Begins'],
'The Prestige' => ['Interstellar', 'Tenet'],
'Batman Begins' => ['The Dark Knight'],
'Tenet' => ['The Prestige'],
];
There are no comments for now.