PHP Pandas: Scope

← Back to Index

We've all got secrets, haven't we? Mine is that I've stolen countless red pandas from Cardiff Zoo. I've got them all stashed away in my basement, where I'm training them for a third world war. Actually, just pretend you didn't hear all that.

If you've got something that you don't want people messing with, you're going to want to keep it private. Some things are meant to be shared, and will be publicly available. Sometimes, you're willing to share your secrets, but you'll want to protect them so that they can't damage you.

Your code is no different. Others may want to use your class, and that's just fine, but you don't want them fiddling with things that might break its functionality. We can help others to use our code in a sensible manner by defining scope on our methods and properties.

Public

Up until now, we've been using var to declare class properties, and only function to create our class methods. Declaring variables in this way makes them public.

A public property can be accessed from outside a class instance by using the object -> operator. For example:

<?php

$panda = new Panda;
echo $panda->name;

Public methods can be called on an instance using the object -> operator once more.

<?php

$panda = new Panda;
echo $panda->squeak();

Since our properties and methods so far have been public, why don't we start indicating their scope with a more descriptive keyword?

The truth is, most programmers won't use var to declare their class properties. Instead, it's better to use the public keyword. Let's take a look at an example, shall we?

<?php

class Panda
{
    public $coat = 'fluffy';
}

This is how you're going to declare your public class properties from now on, isn't it? Go on, promise me! It's just a better way of doing it!

How about those public methods? Well we can apply the public keyword to those too, and you definitely should. Let's take a look at a quick example.

<?php

class Panda
{
    public $coat = 'fluffy';

    public function getCoat()
    {
        return $this->coat;
    }
}

We've put the keyword public just before the keyword function. It won't make any difference, but it's now clearer that the function is a public one.

So we haven't really learned any new tricks in this section, have we? At least we found a way to make our code more descriptive. Don't worry! In the next section we'll be learning something new. I promise!

Private

In the previous section, we used the public keyword to mark our class properties and methods as public. Let's try marking a class property as private instead, shall we?

We'll start by modifying our previous example.

<?php

class Panda
{
    // Declare a private property...
    private $coat = 'fluffy';

    // ... and a public method.
    public function getCoat()
    {
        return $this->coat;
    }
}

In the above example, you'll notice that the $coat property has now been marked as private by using the private keyword. For now, we'll leave the getCoat() method as public.

Let's try to play with that private $coat property. We'll just try to echo it out.

<?php

// Create a new panda.
$panda = new Panda;

// Try to echo the coat property.
echo $panda->coat;

What do you think will happen when we execute the above piece of code? Well let's find out already!

Fatal error: Cannot access private property Panda::$coat

Because our property is now marked as private, we can't access it from outside the class. We'll receive a fatal error if we decide to do so. We've protected that $coat property from our grubby little hands!

You can't set the property either! Let's give it a go.

<?php

// Create a new panda.
$panda = new Panda;

// Try to set the coat property.
$panda->coat = 'slimey';

Let's execute the code once again.

Fatal error: Cannot access private property Panda::$coat

We receive the same error message as when we tried to retrieve the value of the property.

Let's try accessing that public method. I'll attach the class to the example once again to refresh your memory.

<?php

class Panda
{
    // Declare a private property...
    private $coat = 'fluffy';

    // ... and a public method.
    public function getCoat()
    {
        return $this->coat;
    }
}

// Create a new panda.
$panda = new Panda;

// Try to echo the coat property.
echo $panda->getCoat();

The method is public, so when we try to call it, we receive the following result.

fluffy

If the $coat property is private, then how is the getCoat() method able to access it? Well you see, the scope of a method or property, only applies to retrieving, setting, or calling it from outside of the class. Class methods have access to all of the other properties and other methods, regardless of the scope.

Let's change the getCoat() method to private.

<?php

class Panda
{
    // Declare a private property...
    private $coat = 'fluffy';

    // ... and a private method.
    private function getCoat()
    {
        return $this->coat;
    }
}

// Create a new panda.
$panda = new Panda;

// Try to echo the coat property.
echo $panda->getCoat();

Let's execute the code once more.

Fatal error: Call to private method Panda::getCoat()

Since our method has now been given private scope, we are unable to call it on our method instance.

Let's add a public method alongside our private one.

<?php

class Panda
{
    // Declare a private property...
    private $coat = 'fluffy';

    // ... and a private method...
    private function getCoat()
    {
        return $this->coat;
    }

    // ... and a public one.
    public function noReallyGetCoat()
    {
        return $this->getCoat();
    }
}

// Create a new panda.
$panda = new Panda;

// Try to echo the coat property.
echo $panda->noReallyGetCoat();

We've added a new method called noReallyGetCoat(), which makes an internal call to the getCoat() method. Let's see what happens when that method is executed.

fluffy

As we discovered earlier, scope does not affect internal calls to methods, or accessing properties from within the class. For this reason, the public noReallyGetCoat() method is able to make a call to the private getCoat() method.

You can make a class constructor private, but then you won't be able to instantiate it. This might be useful later when you learn more about the static keyword.

Protected

Protected properties are a little different. From the outset they look to function exactly like properties within the private scope. If you were to try and access them directly, you would be unable to.

So why do we have two types of scope that are the same? Well, this is one of those sithations where being an author is really difficult. I'd like to teach you about the protected scope now, however, it's hugely related to a future chapter on abstract classes. Difficult, right? Let's instead share a light overview of protected, and we'll examine it in detail later.

In a later chapter, you'll learn about abstract classes. Ones which can be extended by other classes so that they can share common functionality. If you have a private property or method on the abstract class or "base class" (the base template), then any classes that extend the class are unable to modify the methods or properties directly. However, if you were to instead define these methods and properties as protected, then you'd be able to overwrite their purpose within your extending classes.

Does this sound complicated? Don't worry! It will become much clearer in the Abstract chapter which will arrive later.

Static

There's another scope for variables and methods called static, but this one is a little more complicated, and is best saved for an entire chapter of its own.

My books are available online for free to encourage learning. However, if you'd like for me to keep writing, then please consider buying a digital copy over at Leanpub.com.

It's available in PDF, ePub, and Kindle format, and contains a bunch of extras that you won't find on the site. I have a full-time job, and I write my books in my spare time. Please consider buying a copy so that I can continue to write new books from the comfort of my sofa!