PHP Visibility Modifiers

Navigating Logic’s Shadows with Visibility Keys

It seems like I’ve mentioned visibility modifiers in most of the previous articles; it’s finally time to tackle them. We’ll continue where we left off with our classes in the previous article.

Up until now, we’ve used the public visibility modifier for each of our properties and methods; that just means that everyone has access to it. You can access them inside and outside of the object. The default visibility modifier is public, which means that if we created any of the properties or methods and omitted the visibility modifier, PHP would automatically assume you meant public.

We’re going to be modifying our existing GermanShepherd and Car classes to contain proper visibility modifiers. If we do make a change, it will be going from public to private. The protected modifier will be covered when we tackle inheritance. The protected visibility modifier acts like a private modifier in the sense that you can’t access it outside of the class, so if we instantiate the class and use the object operator (->), we will not be able to access it. However, classes that inherit from the class containing the protected modifier will have access to it. For example, if we create a Dog class and extend it from our GermanShepherd class, we’ll have access to the protected properties inside of our Dog class.

private property or method can only be accessed from within the object itself. If we instantiate the class and try to access the method using the object operator, we will get an error; we will similarly not be able to access private properties through inheritance. Methods inside of the class can access other private properties and methods with the help of $this keyword.

<?php

// Destructor
class GermanShepherd{

const HAS_HEART = true;
const HAS_TAIL = true;

public $eye_color;
public $dob;
public $does_shed = true;
public $kingdom = "Animalia";
public $phylum = "Chordata";
public $class = "Mammalia";
public $order = "Carnivara";
public $family = "Canidae";
public $genus = "Canis";
public $species = "Canis Lupus";
public $subspecies = "Canis Lupus Familiaris";
public $breed = "German Shepherd Dog";
public $fur_color;

public function __construct(string $eye_color,
string $dob,
string $fur_color)
{
$this->eye_color = $eye_color;
$this->dob = $dob;
$this->fur_color = $fur_color;
    }

public function walk() {
echo "I'm walking";
    }

public function bark() {
echo "I'm barking";
    }

public function sleep(int $energy_level = 100) {
if ( $energy_level < 40 ) {
echo "I'm sleeping";
        } else {
echo "I don't want to sleep";
        }
    }

public function get_eye_color(): string
{
return $this->eye_color;
    }

public function does_shed(): string
{
return ( $this->does_shed ) ? "Yes" : "No";
    }

public function get_scientific_classification(): array
{
return [
"kingdom" => $this->kingdom,
"phylum" => $this->phylum,
"class" => $this->class,
            "order" => $this->order,
            "family" => $this->family,
            "genus" => $this->genus,
            "species" => $this->species,
            "subspecies" => $this->subspecies,
            "breed" => $this->breed
        ];
    }

public function __destruct()
{
var_dump(
            [
"eye_color" => $this->eye_color,
"dob" => $this->dob,
"does_shed" => $this->does_shed = true,
"kingdom" => $this->kingdom = "Animalia",
"phylum" => $this->phylum = "Chordata",
"class" => $this->class = "Mammalia",
"order" => $this->order = "Carnivara",
"family" => $this->family = "Canidae",
"genus" => $this->genus = "Canis",
"species" => $this->species = "Canis Lupus",
"subspecies" => $this->subspecies = "Canis Lupus Familiaris",
"breed" => $this->breed = "German Shepherd Dog",
"fur_color" => $this->fur_color,
            ]
        );
    }
}
Looking at our GermanShepherd class, we can see that all of the properties and methods are labeled as public. None of the public properties actually need to be public. We’ll want to use our accessors and mutator methods, which we’ll cover later, to access and modify our properties. We can safely change each of our public properties to private.
<?php

class GermanShepherd
{
//...

private $eye_color;
private $dob;
private $does_shed = true;
private $kingdom = "Animalia";
private $phylum = "Chordata";
private $class = "Mammalia";
private $order = "Carnivara";
private $family = "Canidae";
private $genus = "Canis";
private $species = "Canis Lupus";
private $subspecies = "Canis Lupus Familiaris";
private $breed = "German Shepherd Dog";
private $fur_color;

//...
}
Now that everything has been changed to private, we will not be able to access them anymore with the object operator after object instantiation. We can still access a few of them with the use of our public methods.
<?php

$gs_dog = new GermanShepherd("Brown", "Jan 20, 2018", "Brown");
echo $gs_dog->get_eye_color();

Even though our GermanShepherd’s $eye_color property is private, we can still access it with the get_eye_color() accessor method. If we tried to echo out the $eye_color private property directly, we’ll get an error.

echo $gs_dog->eye_color;

Similar to our GermanShepherd class, we’ll also make a few modifications to our Car class.
<?php

// Car Class
class Car{

const HAS_HEADLIGHTS = true;
const HAS_TAIL_LIGHTS = true;
const HAS_TURN_SIGNALS = true;

public string $color;
public string $make;
public string $model;
public int $year;
public int $fuel_type;
public int $hp;
public int $tq;
public string $transmission;
public string $vehicle_type;
public float $exterior_height;
public float $exterior_width;
public float $exterior_length;
public string $exterior_um;
public float $weight;
public string $weight_um;
public bool $car_on;

public function __construct(int $year,
string $make,
string $model,
string $color = "",
int $fuel_type = 93,
int $hp = -1,
int $tq = -1,
string $transmission = "5 Speed Manual",
string $vehicle_type = "",
float $exterior_height = -1,
float $exterior_width = -1,
float $exterior_length = -1,
string $exterior_um = "in",
float $weight = -1,
string $weight_um = "lbs",
bool $car_on = false
)
{
$this->year = $year;
$this->make = $make;
$this->model = $model;
$this->color = $color;
$this->fuel_type = $fuel_type;
$this->hp = $hp;
$this->tq = $tq;
$this->transmission = $transmission;
$this->vehicle_type = $vehicle_type;
$this->exterior_height = $exterior_height;
$this->exterior_width = $exterior_width;
$this->exterior_length = $exterior_length;
$this->exterior_um = $exterior_um;
$this->weight = $weight;
$this->weight_um = $weight_um;
$this->car_on = $car_on;

echo "Connection Successfully Established";
    }

public function turnOn(): string
{
if ( $this->car_on ) {
return "The " . $this->get_make_and_model() . " is already on.";
        }

$this->car_on = true;
return $this->get_make_and_model() . " has been turned on.";
    }

public function turnOff(): string
{
if ( $this->car_on ) {
$this->car_on = false;
return "The " . $this->get_make_and_model() . " has been turned off.";
        }

return "The " . $this->get_make_and_model() . " is already off.";
    }

public function drive(): string
{
if ( $this->car_on ) {
return "I'm driving";
        } else {
return "You gotta turn me on";
        }
    }

public function get_make_and_model(): string
{
return $this->make . " " . $this->model;
    }

public function get_car_details(): array
{
return [
"year" => $this->year,
"make" => $this->make,
"model" => $this->model,
"color" => $this->color,
"fuel_type" => $this->fuel_type,
"hp" => $this->hp,
"torque" => $this->tq,
"transmission" => $this->transmission
        ];
    }

public function __destruct()
{
echo "Connection Successfully Closed";
    }
}
The Car class public properties can be, and should be, converted to private properties.
<?php

// Car Class
class Car
{
    //...

    private string $color;
    private string $make;
    private string $model;
    private int $year;
    private int $fuel_type;
    private int $hp;
    private int $tq;
    private string $transmission;
    private string $vehicle_type;
    private float $exterior_height;
    private float $exterior_width;
    private float $exterior_length;
    private string $exterior_um;
    private float $weight;
    private string $weight_um;
    private bool $car_on;
  
    //...
}
Looking at our class, we can now access all of our methods, but we can no longer access our properties. We can also convert specific public methods to private methods. When would you want to do this? There are helper methods that are present in most classes. These helper methods usually contain some repeating code that’s used by other methods. In our Car example, that method is the get_make_and_model() method; this method is never going to be accessed outside of our class. If it needed to be, we would leave it as public;however, since it’s not, we’re going to change it to private.
<?php

class Car{

// ...
private function get_make_and_model(): string
{
return $this->make . " " . $this->model;
    }
}
If we try to access our get_make_and_model() method now, we’ll get our Call to private method error.

One final thing to note is that the constructor and destructor must always be public. That completes this tutorial. We’ll cover protected methods in more detail soon.

Continue your learning with these articles

PHP Destructor

ENDING CHAPTERS IN CODE WITH DESTRUCTIVE GRACE

PHP – P50: DESTRUCTORS

Destructors are the opposite of constructors…go figure. The destructor method is called after the object is not referenced any more

Navigating Logic’s Shadows with Visibility Keys

PHP – P51: visibility modifiers

All about visibility modifiers. We tackled public, private, and protected visibility modifiers previously, but we get to understand what they are now.

PHP Getters and Setters

SAFEGUARDING AND SCULPTING WITH GETTERS AND SETTERS

PHP – P52: GETTERS AND SETTERS

If we wanted to access those properties or modify them in their current state, we wouldn’t be able to. That’s where getters and setters, or accessors and mutators, come into play.

Leave a Reply