Link to home
Start Free TrialLog in
Avatar of rgb192
rgb192Flag for United States of America

asked on

Fatal error: Cannot access protected property Test::$protected in C:\wamp\www\phpvqp3_scripts\ch05\visibility.php on line 71

from oop php tutorial
why / how is this error

Fatal error: Cannot access protected property Test::$protected in C:\wamp\www\phpvqp3_scripts\ch05\visibility.php on line 71

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Visibility</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<?php # Script 5.4 - visibility.php
//  This page defines and uses the Test and LittleTest classes. 

# ***** CLASSES ***** #

/* Class Test.
 *  The class contains three attributes:
 *  - public $public
 *  - protected $protected
 *  - private $_private
 *  The class defines one method: printVar().
 */
class Test {

    // Declare the attributes:
    public $public = 'public';
    protected $protected = 'protected';
    private $_private = 'private';  

    // Function for printing a variable's value:
    function printVar($var) {
        echo "<p>In Test, \$$var: '{$this->$var}'.</p>";
    }

} // End of Test class.

/* LittleTest class extends Test.
 * LittleTest overrides printVar().
 */
class LittleTest extends Test {
    function printVar($var) {
        echo "<p>In LittleTest, \$$var: '{$this->$var}'.</p>";
    }
} // End of LittleTest class.

# ***** END OF CLASSES ***** #

// Create the objects:
$parent = new Test();
$child = new LittleTest();

// Print the current value of $public:
echo '<h1>Public</h1>';
echo '<h2>Initially...</h2>';
$parent->printVar('public');
$child->printVar('public');
// Also echo $parent->public or echo $child->public.

// Modify $public and reprint:
echo '<h2>Modifying $parent->public...</h2>';
$parent->public = 'modified';
$parent->printVar('public');
$child->printVar('public');

// Print the current value of $protected:
echo '<hr><h1>Protected</h1>';
echo '<h2>Initially...</h2>';
$parent->printVar('protected');
$child->printVar('protected');

// Attempt to modify $protected and reprint:
echo '<h2>Attempting to modify $parent->protected...</h2>';
$parent->protected = 'modified';
$parent->printVar('protected');
$child->printVar('protected');

// Print the current value of $_private:
echo '<hr><h1>Private</h1>';
echo '<h2>Initially...</h2>';
$parent->printVar('_private');
$child->printVar('_private');

// Attempt to modify $_private and reprint:
echo '<h2>Attempting to modify $parent->_private...</h2>';
$parent->_private = 'modified';
$parent->printVar('_private');
$child->printVar('_private');

// Delete the objects:
unset($parent, $child);

?>
</body>
</html>

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Insoftservice inso
Insoftservice inso
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Phil Phillips
It's because a "protected" variable can only be accessed by its own class or any extending classes.

The other variable scopes are "public" (accessible by anything), or "private" (accessible by ONLY its own class)

In that code sample, any functions that are part of the class "Test" or "LittleTest" are able to access the protected variable.  That's why the 'printVar()' function is working.  But, outside of those classes (like on line 71), the variable isn't accessible.
You can access a protected field of the parent class (Test) from a member method of the child (LittleTest) class. But what you try to do is to access the protected field from the global scope.

You can access $parent->protected from Test::printVar and from LittleTest::printVar, that's why printVar works.

Similarly, you can access $parent->private from Test::printVar but *not* from LittleTest::printVar.
Its a simple oops concept

Private: Only specified class can access them , even its child class or sub class can not access the data

Protected: Parent and sub class can only access the data.

Protected and private methods prevent outside calls to methods which may upset the internal state of an object.

To modify any protected variables method has to used . Did you tried my examples
Public, Protected and Private are "visibilities" associated with the properties and methods of a class.  Visibility is a logical extension of the concept of Variable Scope.  In the old ways of PHP, variable scope was basically either global or local.  In object-oriented PHP, variables (variables == properties) are scoped to be public by default.  The same is true of methods (methods == functions).

My preference for visibility, absent any other extenuating circumstances, is to make properties protected and methods public.  To inject data into the object, you must make a formal call to a setter() method.  To retrieve data from an object you must call the getter() method.  If you do it this way, you can use mock objects for unit testing.


Further reading:
Avatar of rgb192

ASKER

I know what public, protected, private are
and I think the best answer is the code sample

I added additional code

//public values
echo '<h1>Public values</h1>';
$parent->printVar('public');
$child->printVar('public');

now I learned it was variable variables

because of revised code sample I was able to learn the errored code sample

Thank you.