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
21: Magic Methods
By now, you've spent plenty of time writing standard classes and methods. But PHP has this set of "magic" methods—functions that start with a double underscore—that allow you to hook into the internal workings of the engine. They aren't called by you directly; instead, PHP triggers them automatically when certain events happen to an object.
What's the deal with the double underscores and why use them?
The double underscore __ is just PHP's way of saying, "This isn't a normal method; this is a system hook." Think of them as event listeners for your objects. I've seen a lot of junior devs avoid them because they feel like "black magic," but when used correctly, they remove a massive amount of boilerplate code.
For example, instead of writing a dozen different getters and setters for a data-heavy object, you can use magic methods to handle those requests dynamically. It keeps your class definitions clean and your code more flexible.
How do I stop writing twenty different getters and setters?
This is where __get() and __set() come in. These are triggered whenever you try to access or assign a property that is either private or doesn't exist at all. I usually use this pattern when I'm building a "Settings" or "Session" class where the properties are stored in an internal array rather than as defined class members.
class UserProfile {
private array $data = [];
public function __set($name, $value) {
echo "Setting $name to $value\n";
$this->data[$name] = $value;
}
public function __get($name) {
return $this->data[$name] ?? "Property $name not found";
}
}
$user = new UserProfile();
$user->firstName = "Jane"; // Triggers __set
echo $user->firstName; // Triggers __get
echo $user->age; // Triggers __get (returns "Property age not found")
Can I make an object act like a string or a function?
Yes, and this is actually incredibly useful for logging or creating specialized callback objects. __toString() is called when you try to echo an object or treat it as a string. __invoke() is called when you try to call the object as if it were a function.
I personally love __invoke() for creating "Action" classes—single-purpose classes that do one thing. It makes the intent of the class very clear.
class Logger {
public function __toString() {
return "[Log Entry: " . date('Y-m-d H:i:s') . "]";
}
public function __invoke($message) {
echo "Logging message: $message\n";
}
}
$log = new Logger();
echo $log; // Triggers __toString: [Log Entry: 2023-...]
$log("Error!"); // Triggers __invoke: Logging message: Error!
What happens if I call a method that doesn't even exist?
Normally, PHP would throw a fatal error. But if you define __call(), you can intercept that failure. This is a powerful tool for creating "wrappers." If you're building a class that wraps a third-party API, you can use __call() to forward any method call directly to that API without having to manually map every single possible endpoint in your own code.
class ApiWrapper {
private $apiClient;
public function __construct($client) {
$this->apiClient = $client;
}
public function __call($method, $args) {
echo "Forwarding call to $method...\n";
return call_user_func_array([$this->apiClient, $method], $args);
}
}
Just a word of caution: don't overdo it. If you make everything "magic," your IDE will stop being able to provide autocomplete, and other developers (or you, six months from now) will have a hard time figuring out where a method is actually defined.
📋 Practical Task
Exercise: Building a Dynamic Configuration Wrapper
You need to create a class called AppConfig that stores configuration settings in a private array. Instead of creating a method for every possible setting, implement the following:
- Use
__set($name, $value)to allow adding settings to the internal array. - Use
__get($name)to retrieve settings. If the setting doesn't exist, return the string"Setting not defined". - Implement
__toString()so that when the object is echoed, it returns a comma-separated list of all the keys currently stored in the configuration (e.g.,"db_host, db_user, api_key").
Test your class by setting three different configuration values and then echoing the object itself to verify the list of keys.
There are no comments for now.