Hello! Welcome to the final lesson in our module on Object-Oriented PHP Fundamentals.
In our last lesson, we covered class constants. We learned that constants are values that belong to the class itself, not to any specific object, and are accessed using the scope resolution operator (::). This was our first look at a class-level member.
Today, we'll expand on that idea by exploring static properties and methods. You'll learn how to create properties (variables) and methods (functions) that are also shared across all instances of a class. Understanding statics is key to recognizing different architectural patterns and writing utility code in an object-oriented way.
By the end of this lesson, you will be able to create and use static properties and methods, and you'll understand when they are appropriate—and when they should be avoided.
1. Defining and Accessing Static Members
A static property or method is declared with the static keyword. Just like a class constant, it belongs to the class, not to an instance of the class. This means you can access it without creating an object first.
Let's start with a video that clearly explains the syntax for declaring static members and the fundamental way to access them.
Static Properties & Methods In Object Oriented PHP - Full PHP 8 Tutorial
The video 'Static Properties & Methods' from Program With Gio will introduce the core concepts. It shows you how to declare static members and access them from outside the class.
Watch from the beginning (00:13) to 01:34. Focus on: The static keyword and its placement. How to access a static property using the class name and the scope resolution operator (ClassName::$propertyName). The key idea that you do not need an object instance to access static members.
As the video demonstrated, you access static members using the same scope resolution operator (::) that we used for constants.
- Static Property:
ClassName::$propertyName - Static Method:
ClassName::methodName()
Notice the $ is used when accessing a static property. This is a key difference from constants.
2. The Core Difference: Class vs. Instance
The most important concept to grasp is the difference between a static member and a regular (instance) member.
- Instance Members (non-static): Each object created from a class gets its own unique copy of these properties. Modifying a property on
$object1does not affect the same property on$object2. You access them using$thisfrom inside the class. - Static Members: There is only one copy of a static property, which is shared by all objects of the class. If
$object1changes a static property,$object2will see that change. They are essentially global variables scoped to a class.
The next segment of the video provides an excellent practical example of this by creating a counter that tracks how many objects have been created.
Static Properties & Methods In Object Oriented PHP - Full PHP 8 Tutorial
Let's continue with the video to see this 'shared' nature in action and learn how to refer to static members from inside the class.
Watch from 01:34 to 02:56. Pay close attention to: How the static $count property is shared across all Transaction objects. The use of the self keyword to access the static property from within the class (self::$count).
This introduces our second important keyword: self.
$this: Refers to the current object instance. Used for non-static members (e.g.,$this->amount).self: Refers to the current class. Used for static members (e.g.,self::$count) and constants (self::STATUS_PAID).
3. The Rules of static
Because static methods aren't tied to a specific object, there's a crucial rule you must always remember.
Rule: $this is Not Available in Static Methods
A static method is executed on the class, not an object. Since $this refers to the current object, it simply doesn't exist in a static context. Attempting to use $this inside a static method will result in a fatal error.
Let's see this demonstrated.
Static Properties & Methods In Object Oriented PHP - Full PHP 8 Tutorial
The following clip from the same video explicitly demonstrates the error you get when trying to use $this in a static method.
Watch from 03:13 to 03:55. This short segment is vital for understanding the primary limitation of static methods.
This also implies that you cannot call a non-static method from a static method directly, because doing so would require an object context ($this).
4. Use Cases: When (and When Not) to Use Statics
Static members are powerful but can be easily misused, leading to code that is hard to test and maintain. Your goal as a professional developer is to use them judiciously.
How to Understand PHP Static Methods, Properties, & Classes
The article 'How to Understand PHP Static Methods, Properties, & Classes' from WPShout gives a great overview of appropriate use cases and the common criticisms of statics.
Read the sections 'When to Use Static Methods in PHP' and 'Why People Dislike Static Methods'. These sections provide clear examples and explain the concept of 'global state'.
Here's a summary of the key points:
Good Use Cases for Statics:
- Utility/Helper Methods: Methods that don't depend on an object's state are perfect candidates. For example, a
Mathclass with static methods likeMath::add($a, $b)or aConverterclass withConverter::inchesToCm($inches). You don't need an object to perform these operations. - Factories: A static method can be used to construct and return objects. For example,
User::createAdmin('Alice')could be a static method that creates aUserobject with pre-configured admin permissions. - Counters and State Management: As seen in the video, tracking the number of instances or managing a shared state (like a logger or application settings) can be done with static properties.
Why Statics Are Often Discouraged:
- Global State: Static properties act like global variables. They can be changed from anywhere in your code, which can lead to unpredictable behavior and "spooky action at a distance." This makes debugging difficult.
- Testability: Code that relies on global state is hard to test in isolation. You can't easily reset a static property between tests, so one test can affect the outcome of another.
- Breaks OOP Principles: Heavy use of statics can be a sign of procedural code disguised in a class. The core idea of OOP is encapsulated objects with their own state and behavior.
A modern best practice to avoid overusing statics for managing resources is Dependency Injection, which we will cover later in this course. For now, focus on using statics for simple, stateless utility functions.
Hands-on Practice
Let's build a simple Logger class, a classic and valid use case for static members. The logger should be able to record messages from anywhere in the application without needing to pass a logger object around.
- Create the
LoggerClass:- Define a
private static array $messagesand initialize it as an empty array. This will store all our log entries. - Since we don't want anyone creating an instance of our
Logger, create aprivate __construct() {}. This preventsnew Logger()from being called.
- Define a
- Create Static Methods:
- Create a
public static function log(string $message)method. This method should add the provided message to theself::$messagesarray. - Create a
public static function getMessages(): arraymethod. This method should simply return theself::$messagesarray.
- Create a
- Use the Logger:
- You don't need to create an object. Call
Logger::log('Application started.'); - Call it again from a different context:
Logger::log('User performed an action.'); - Finally, retrieve all messages using
Logger::getMessages()and useprint_r()to display them.
- You don't need to create an object. Call
Click to see a possible solution
<?php
class Logger
{
// 1. Private static property to hold messages
private static array $messages = [];
// Private constructor to prevent creating instances
private function __construct() {}
/**
* 2. Public static method to add a message.
*/
public static function log(string $message): void
{
// Add timestamp for more useful logs
$timestamp = date('Y-m-d H:i:s');
self::$messages[] = "[{$timestamp}] {$message}";
}
/**
* Public static method to retrieve all messages.
*/
public static function getMessages(): array
{
return self::$messages;
}
}
// 3. Use the Logger from anywhere
echo "Logging events...\n";
Logger::log('Application started.');
// Simulate some time passing
sleep(1);
Logger::log('User performed an action.');
echo "Retrieving logs:\n";
$allLogs = Logger::getMessages();
print_r($allLogs);
?>
Expected Output:
Logging events...
Retrieving logs:
Array
(
[0] => [2023-10-27 10:30:00] Application started.
[1] => [2023-10-27 10:30:01] User performed an action.
)
(Note: Your timestamps will vary.)
Conclusion
Congratulations on completing the "Object-Oriented PHP Fundamentals" module! You've built a strong foundation, moving from basic classes to visibility, object lifecycle, and now class-level members.
Key Takeaways from this Lesson:
- Static properties and methods belong to the class, not an object instance.
- They are declared with the
statickeyword and accessed with the scope resolution operator (::). - From inside the class, use
self::to refer to static members. - The
$thiskeyword is unavailable in a static context because there is no object instance. - Statics are best used for stateless utility functions or managing a single, shared state (like a counter or logger).
- Overuse of statics leads to global state, making code hard to test and maintain.
Preview of the Next Module:
In our next module, "Advanced OOP Concepts," we will start by exploring one of the most powerful features of OOP: inheritance. You will learn how to create a class that inherits properties and methods from a parent class, allowing you to create more specialized objects while reusing code. We'll also see how inheritance interacts with the static keyword through a concept called "late static binding."