Understanding Access Modifiers in PHP
Like many OOP-capable languages, PHP has a feature called Access Modifiers. These help with principles of encapsulation, maintainability, and reducing complexity.
What do they do? They define the visibility of class properties and methods (members of a class), controlling how these members are accessed by other parts of your code.
There are three access modifiers that can be used in a class:
1. Public
Members declared as public can be accessed from anywhere, both inside and outside the class.
class Example {
public $name = "Public Property";
}
$example = new Example();
echo $example->name; // Accessible
2. Private
Members declared as private can only be accessed within the class where they are defined.
The following code would throw an error:
class Example {
private $name = "Private Property";
}
$example = new Example();
echo $example->name; // WILL THROW ERROR (Cannot access private property)
It's typical for a PHP developer to want to have a property that cannot be modified by outside code but can still be read. A common way to do this is to make a "getter" method such as this:
class Example {
private $name = "Private Property";
public function getName() {
return $this->name; // Accessible within the class
}
}
$example = new Example();
echo $example->getName(); // Accessible through a public method
3. Protected
Members declared as protected can only be accessed within the class itself and by classes that inherit from it.
class ParentClass {
protected $name = "Protected Property";
}
class ChildClass extends ParentClass {
public function getName() {
return $this->name; // Accessible within child class
}
}
$child = new ChildClass();
echo $child->getName(); // Accessible through a public method
What's this useful for?
There are many reasons access modifiers are useful, but here is one good example:
Let’s say you want to make a service in PHP that handles a team draft. You might write something like this:
<?php
class TeamDraft
{
private array $names;
private array $pickedNames = [];
public function __construct(array $names = [])
{
// Default list of names if none are provided
$this->names = !empty($names) ? $names : [
'Alice',
'Bob',
'Charlie',
'Diana',
'Eve',
'Frank'
];
}
public function selectName(string $name): string
{
// Validate that the name exists in the list
if (!in_array($name, $this->names)) {
throw new Exception("The name '{$name}' does not exist in the list.");
}
// Check if the name has already been picked
if (in_array($name, $this->pickedNames)) {
throw new Exception("The name '{$name}' has already been picked.");
}
// Add the name to the pickedNames list and remove it from the available names
$this->pickedNames[] = $name;
$this->names = array_diff($this->names, [$name]);
return $name;
}
public function getPickedNames(): array
{
return $this->pickedNames;
}
public function getRemainingNames(): array
{
return $this->names;
}
}
So now, if we use this class, we can do a few things. We can select names and, therefore, indirectly manipulate the values of the two private members of the class. However, the class defines the rules for doing so. As a user of this code, I can't just change the list myself and potentially make mistakes, like adding names that don't exist. I'm restricted, and that's a good thing—it avoids unintentional misuse of the class.
Summary
- Use public for members that need to be accessed outside the class.
- Use protected for members that should only be accessible within the class or classes that extend it.
- Use private for members that should remain strictly internal to the class.
Thanks for reading! I encourage you to think about how you can apply this to code you've already written to make it better and easier for others to use!