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
134: The Singleton Pattern in PHP
Look, you've probably seen the word "Singleton" tossed around in design pattern discussions, and it often comes with a warning that it's an "anti-pattern." Before we get into the controversy, let's focus on what it actually does: it ensures a class has only one instance and provides a global point of access to it. In PHP, where every request starts from a blank slate, this is mostly about managing resources within a single execution cycle.
Why would I actually need this instead of just creating a new object?
Imagine you're building a system that connects to a database. Establishing a connection is "expensive"—it takes time and memory. If you're passing a database object around to twenty different classes in one request, you don't want each of those classes calling new DatabaseConnection(). If you do, you'll end up with twenty open connections to your MySQL server for a single page load. That's a great way to crash your server under moderate load.
The Singleton pattern solves this by saying: "If an instance already exists, just give me that one. If not, create it once and save it for later."
How do I stop someone from just using the new keyword?
This is the "secret sauce" of the Singleton. To prevent other developers (or your future self) from accidentally instantiating the class, you make the constructor private. If you try to call new DatabaseConnection() from outside the class, PHP will throw a fatal error.
We also need a static property to hold the instance. Because it's static, it belongs to the class itself, not to any specific object instance.
class DatabaseConnection {
// This holds our single instance
private static $instance = null;
// Private constructor prevents external instantiation
private function __construct() {
// Imagine heavy connection logic here
echo "Connecting to the database... ";
}
// We also need to stop people from cloning the object
private function __clone() {}
// And stop them from unserializing it
public function __wakeup() {
throw new \Exception("Cannot unserialize a singleton.");
}
}
How do I actually get the instance if I can't use new?
Since the constructor is locked away, we create a public static method—usually called getInstance(). This method acts as the gatekeeper. It checks if the static property is still null; if it is, it creates the object. Otherwise, it just hands back the one it already has.
class DatabaseConnection {
private static $instance = null;
private function __construct() {
// Connection logic...
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query($sql) {
return "Executing: $sql";
}
// ... (clone and wakeup methods from above)
}
// Usage:
$db1 = DatabaseConnection::getInstance();
$db2 = DatabaseConnection::getInstance();
// $db1 and $db2 are the exact same instance.
// The constructor was only called once.
Is it true that Singletons are "bad" or an "anti-pattern"?
I'll be honest with you: in modern PHP development, we tend to avoid writing our own Singletons. Why? Because they introduce "global state," which makes unit testing a nightmare. If a class depends on a Singleton, you can't easily swap that Singleton out for a "mock" object during a test.
Most professional projects now use a Dependency Injection Container (like the ones in Laravel or Symfony). The container manages the object's lifecycle for you—essentially acting as a Singleton manager without baking that rigid logic directly into your business classes. However, you'll still see Singletons in legacy code and small scripts, and understanding how they work is non-negotiable for any senior dev.
📋 Practical Task
Build a Global Application Configuration Manager
Your task is to create a class called AppConfig that implements the Singleton pattern. This class should be used to load system settings (like an API key or environment name) from an array, ensuring the file/array is only "loaded" into memory once per request.
- Make the constructor
private. - Create a static property
$instance. - Implement a public static method
getInstance(). - Add a private property
$settingswhich is initialized in the constructor with an associative array (e.g.,['api_key' => '12345', 'env' => 'production']). - Add a public method
get($key)that returns the value from the$settingsarray based on the provided key. - Verify that calling
AppConfig::getInstance()multiple times returns the same object and doesn't re-initialize the settings array.
There are no comments for now.