Making Sense of Variable Scope in PHP 5 OOP

I’ve learned a lot about PHP5 OOP visibility recently.  I’m posting a test script that will share some of my discoveries.

Take away:

  1. Private really does mean private.
  2. Visibility keywords are honored while cloning
  3. PHP does not enforce the visibility keywords on variables using a fatal error.
    It uses an E_NOTICE : Notice: Undefined property
define( 'SCRIPT_EOL', '<br>' );

abstract class a_base_class
{
    private $name = 'Johannes Kepler';
    protected $color = 'Green';

    public function __set($name, $value)
    {
        throw new Exception( 'a_base_class - Undefined or private property: ' . $name );
    }

    public function __clone()
    {
        // this does work - $this->name is private but is accessible in this class
        $this->name = 'Isaac Newton';
    }

    public function getName()
    {
        return $this->name;
    }

    public function echoName()
    {
        echo $this->name;
    }
}

class exampleClass1 extends a_base_class
{
    function __clone()
    {
        // this does not work - $this->name is private to ac and can't be modified here
        $this->name = 'Isaac Newton';
    }

    function echoName()
    {
        // this will issue an E_NOTICE because the variable is undefined in this class (private variables do not carry through to descendants)
        echo $this->name;
    }

    function echoColor()
    {
        echo $this->color;
    }
}

class exampleClass2 extends a_base_class
{
    public function __clone()
    {
        $this->color = 'Red';
        // without this, $this->name will not get changed to Isaac Newton
        parent::__clone();
    }

    public function echoColor()
    {
        echo $this->color;
    }
}

echo '</pre>

<hr />

<pre>
';
echo '</pre>
<h2>exampleClass1</h2>
<pre>
';
$instance = new exampleClass1();
echo 'calling echoName()' . SCRIPT_EOL;
$instance->echoName();
echo 'echo $instance->name' . SCRIPT_EOL;
echo $instance->name . SCRIPT_EOL;
echo SCRIPT_EOL;
echo 'echoing getName()' . SCRIPT_EOL;
echo $instance->getName(); // calling public method on base class
echo SCRIPT_EOL;
echo 'calling echoColor()' . SCRIPT_EOL;
$instance->echoColor();
echo SCRIPT_EOL;

try
{
    $newInstance = clone $instance;
}
catch( Exception $e )
{
    echo SCRIPT_EOL . '------------------------------------------------' . SCRIPT_EOL;
    echo "Exception Thrown: " . $e->getMessage();
    echo SCRIPT_EOL;
echo '
';
    echo $e->getTraceAsString();
    echo '

';
    echo SCRIPT_EOL . '------------------------------------------------' . SCRIPT_EOL;
}
echo SCRIPT_EOL;
echo 'var_dump' . SCRIPT_EOL;
var_dump( $newInstance );

echo '</pre>

<hr />

<pre>
';
echo '</pre>
<h2>exampleClass2</h2>
<pre>
';

$instance = new exampleClass2();
echo 'calling echoName()' . SCRIPT_EOL;
$instance->echoName();
echo SCRIPT_EOL;
echo 'echo $instance->name' . SCRIPT_EOL;
echo $instance->name . SCRIPT_EOL;
echo 'echoing getName()' . SCRIPT_EOL;
echo $instance->getName(); // calling public method on base class
echo SCRIPT_EOL;
echo 'calling echoColor()' . SCRIPT_EOL;
$instance->echoColor();
echo SCRIPT_EOL;

try
{
    $newInstance = clone $instance;
}
catch( Exception $e )
{
    echo SCRIPT_EOL . '------------------------------------------------' . SCRIPT_EOL;
    echo "Exception Thrown: " . $e->getMessage();
    echo SCRIPT_EOL;
    echo $e->getTraceAsString();
    echo SCRIPT_EOL . '------------------------------------------------' . SCRIPT_EOL;
}

echo '
';
var_dump( $newInstance );
echo '

';

Output


exampleClass1

calling echoName()

Notice: Undefined property: exampleClass1::$name in /Users/timgallagher/Desktop/xampp/se/php5oop.php on line 43
echo $instance->name

Notice: Undefined property: exampleClass1::$name in /Users/timgallagher/Desktop/xampp/se/php5oop.php on line 73

echoing getName()
Johannes Kepler
calling echoColor()
Green

————————————————
Exception Thrown: a_base_class – Undefined or private property: name

#0 /Users/timgallagher/Desktop/xampp/se/php5oop.php(37): a_base_class->__set('name', 'Isaac Newton')
#1 /Users/timgallagher/Desktop/xampp/se/php5oop.php(84): exampleClass1->__clone()
#2 {main}

————————————————

var_dump

Notice: Undefined variable: newInstance in /Users/timgallagher/Desktop/xampp/se/php5oop.php on line 98
NULL


exampleClass2

calling echoName()
Johannes Kepler
echo $instance->name

Notice: Undefined property: exampleClass2::$name in /Users/timgallagher/Desktop/xampp/se/php5oop.php on line 108

echoing getName()
Johannes Kepler
calling echoColor()
Green

object(exampleClass2)#1 (2) {
  ["name:private"]=>
  string(12) "Isaac Newton"
  ["color:protected"]=>
  string(3) "Red"
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s