When and why should I use public
, private
, and protected
functions and variables inside a class? What is the difference between them?
Examples:
// Public
public $variable;
public function doSomething() {
// ...
}
// Private
private $variable;
private function doSomething() {
// ...
}
// Protected
protected $variable;
protected function doSomething() {
// ...
}
17 s
Public:
When you declare a method (function) or a property (variable) as public
, those methods and properties can be accessed by:
- The same class that declared it.
- The classes that inherit the above declared class.
- Any foreign elements outside this class can also access those things.
Example:
<?php
class GrandPa
{
public $name="Mark Henry"; // A public variable
}
class Daddy extends GrandPa // Inherited class
{
function displayGrandPaName()
{
return $this->name; // The public variable will be available to the inherited class
}
}
// Inherited class Daddy wants to know Grandpas Name
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
// Public variables can also be accessed outside of the class!
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Prints 'Mark Henry'
Protected:
When you declare a method (function) or a property (variable) as protected
, those methods and properties can be accessed by
- The same class that declared it.
- The classes that inherit the above declared class.
Outsider members cannot access those variables. “Outsiders” in the sense that they are not object instances of the declared class itself.
Example:
<?php
class GrandPa
{
protected $name="Mark Henry";
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
The exact error will be this:
PHP Fatal error: Cannot access protected property GrandPa::$name
Private:
When you declare a method (function) or a property (variable) as private
, those methods and properties can be accessed by:
- The same class that declared it.
Outsider members cannot access those variables. Outsiders in the sense that they are not object instances of the declared class itself and even the classes that inherit the declared class.
Example:
<?php
class GrandPa
{
private $name="Mark Henry";
}
class Daddy extends GrandPa
{
function displayGrandPaName()
{
return $this->name;
}
}
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Results in a Notice
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
The exact error messages will be:
Notice: Undefined property: Daddy::$name
Fatal error: Cannot access private property GrandPa::$name
Dissecting the Grandpa Class using Reflection
This subject is not really out of scope, and I’m adding it here just to prove that reflection is really powerful. As I had stated in the above three examples, protected
and private
members (properties and methods) cannot be accessed outside of the class.
However, with reflection you can do the extra-ordinary by even accessing protected
and private
members outside of the class!
Well, what is reflection?
Reflection adds the ability to reverse-engineer classes, interfaces,
functions, methods and extensions. Additionally, they offers ways to
retrieve doc comments for functions, classes and methods.
Preamble
We have a class named Grandpas
and say we have three properties. For easy understanding, consider there are three grandpas with names:
- Mark Henry
- John Clash
- Will Jones
Let us make them (assign modifiers) public
, protected
and private
respectively. You know very well that protected
and private
members cannot be accessed outside the class. Now let’s contradict the statement using reflection.
The code
<?php
class GrandPas // The Grandfather's class
{
public $name1 = 'Mark Henry'; // This grandpa is mapped to a public modifier
protected $name2 = 'John Clash'; // This grandpa is mapped to a protected modifier
private $name3 = 'Will Jones'; // This grandpa is mapped to a private modifier
}
# Scenario 1: without reflection
$granpaWithoutReflection = new GrandPas;
# Normal looping to print all the members of this class
echo "#Scenario 1: Without reflection<br>";
echo "Printing members the usual way.. (without reflection)<br>";
foreach($granpaWithoutReflection as $k=>$v)
{
echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
echo "<br>";
#Scenario 2: Using reflection
$granpa = new ReflectionClass('GrandPas'); // Pass the Grandpas class as the input for the Reflection class
$granpaNames=$granpa->getDefaultProperties(); // Gets all the properties of the Grandpas class (Even though it is a protected or private)
echo "#Scenario 2: With reflection<br>";
echo "Printing members the 'reflect' way..<br>";
foreach($granpaNames as $k=>$v)
{
echo "The name of grandpa is $v and he resides in the variable $k<br>";
}
Output:
#Scenario 1: Without reflection
Printing members the usual way.. (Without reflection)
The name of grandpa is Mark Henry and he resides in the variable name1
#Scenario 2: With reflection
Printing members the 'reflect' way..
The name of grandpa is Mark Henry and he resides in the variable name1
The name of grandpa is John Clash and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3
Common Misconceptions:
Please do not confuse with the below example. As you can still see, the private
and protected
members cannot be accessed outside of the class without using reflection
<?php
class GrandPas // The Grandfather's class
{
public $name1 = 'Mark Henry'; // This grandpa is mapped to a public modifier
protected $name2 = 'John Clash'; // This grandpa is mapped to a protected modifier
private $name3 = 'Will Jones'; // This grandpa is mapped to a private modifier
}
$granpaWithoutReflections = new GrandPas;
print_r($granpaWithoutReflections);
Output:
GrandPas Object
(
[name1] => Mark Henry
[name2:protected] => John Clash
[name3:GrandPas:private] => Will Jones
)
Debugging functions
print_r
, var_export
and var_dump
are debugger functions. They present information about a variable in a human-readable form. These three functions will reveal the protected
and private
properties of objects with PHP 5. Static class members will not be shown.
More resources:
- The PHP Manual – OOP Properties
- The PHP Manual – OOP Visibility
- Techflirt.com – Visibility in PHP Classes
- Jordizle.com – Public, Private, Protected in PHP 5