Visibility

The visibility of a property or method can be defined by prefixing the declaration with the keywords: public, protected or private. Public declared items can be accessed everywhere. Protected limits access to inherited and parent classes (and to the class that defines the item). Private limits visibility only to the class that defines the item.

Members Visibility

Class members must be defined with public, private, or protected.

例子 19-8. Member declaration

<?php
/**
* Define MyClass
*/
class MyClass
{
    
public $public = 'Public';
    
protected $protected = 'Protected';
    
private $private = 'Private';

    function
printHello()
    {
        echo
$this->public;
        echo
$this->protected;
        echo
$this->private;
    }
}

$obj = new MyClass();
echo
$obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private


/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
    
// We can redeclare the public and protected method, but not private
    
protected $protected = 'Protected2';

    function
printHello()
    {
        echo
$this->public;
        echo
$this->protected;
        echo
$this->private;
    }
}

$obj2 = new MyClass2();
echo
$obj->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, not Private

?>

注: The PHP 4 method of declaring a variable with the var keyword is no longer valid for PHP 5 objects. For compatibility a variable declared in php will be assumed with public visibility, and a E_STRICT warning will be issued.

Method Visibility

Class methods must be defined with public, private, or protected. Methods without any declaration are defined as public.

例子 19-9. Method Declaration

<?php
/**
* Define MyClass
*/
class MyClass
{
    
// Contructors must be public
    
public function __construct() { }

    
// Declare a public method
    
public function MyPublic() { }

    
// Declare a protected method
    
protected function MyProtected() { }

    
// Declare a private method
    
private function MyPrivate() { }

    
// This is public
    
function Foo()
    {
        
$this->MyPublic();
        
$this->MyProtected();
        
$this->MyPrivate();
    }
}

$myclass = new MyClass;
$myclass->MyPublic(); // Works
$myclass->MyProtected(); // Fatal Error
$myclass->MyPrivate(); // Fatal Error
$myclass->Foo(); // Public, Protected and Private work


/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
    
// This is public
    
function Foo2()
    {
        
$this->MyPublic();
        
$this->MyProtected();
        
$this->MyPrivate(); // Fatal Error
    
}
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Works
$myclass2->Foo2(); // Public and Protected work, not Private
?>


add a note add a note User Contributed Notes
stephane at harobed dot org
23-Aug-2006 05:22
A class A static public function can access to class A private function :

<?php
class A {
  
private function foo()
   {
       print(
"bar");
   }

   static
public function bar($a)
   {
      
$a->foo();
   }
}

$a = new A();

A::bar($a);
?>

It's working.
alberi at example dot com
17-Aug-2006 05:47
There is such nonstricted "feature" with self:: on dinamic & static calling of methods not declared as static:

<?

class foo
{
   static
$counter;

  
public function bar($i=0)
   {
       if (
$i) self::$counter = $i;

       echo
'  bar: $this var ', isset($this)?'exists':'missing', "\n";
      
      
self::mar();

       if (--
self::$counter)
          
self::bar();
   }

  
public function mar()
   {
       echo
'  mar: $this var ', isset($this)?'exists':'missing', "\n";
   }
}

$foo = new foo();

echo
"\nDINAMIC CALLING:\n";
$foo->bar(2);

echo
"\nSTATIC CALLING:\n";
foo::bar(2);

# OUTPUT:
#
# DINAMIC CALLING:
#  bar: $this var exists
#  mar: $this var exists
#  bar: $this var exists
#  mar: $this var exists
#
# STATIC CALLING:
#  bar: $this var missing
#  mar: $this var missing
#  bar: $this var missing
#  mar: $this var missing

#
# executed under PHP 5.1.1 (cli) (built: Nov 27 2005 21:39:02)
?>

In other words, in dinamic called function the "self::" selector will be interpreted as "$this->".
kakugo at kakugo dot com
13-Jul-2006 06:19
This refers to previous notes on protected members being manipulated externally:

It is obvious that if you were to allow methods the option of replacing protected variables with external ones it will be possible, but there is no reason not to simply use a protected method to define these, or not to write the code to allow it. Just because it is possible doesn't mean it's a problem, it simply does not allow you to be lax on the security of the class.
LoN_Kamikaze at gmx dot de
28-Mar-2006 05:26
About the previous note:

Of course you cannot declare public attributes/methods private, because it can break code relying on access to such an attribute/method. But of course your children can override private with protected/public.
c3 at epetersen dot org
07-Feb-2006 09:50
Note that you cannot change visibility in a child defined in the parent:

class A {
 public function f() {}
}

class B extends A {
 private function f() {}
}

Produces Fatal error: Access level to B::f() must be public (as in class A) in ...

jfk, visibility != security. Visibility prevents programmers from doing dumb things like:

class A {
 private function __construct() {}
 final public static &factory() { return new A(); }
}
$x = new A();

The use of "protected" as an identifier is unfortunate tradition as it really means "only me and my decedents" (and in the odd case of PHP my ancestors too).
r dot wilczek at web-appz dot de
05-Jan-2006 09:11
Beware: Visibility works on a per-class-base and does not prevent instances of the same class accessing each others properties!

<?php
class Foo
{
  
private $bar;

  
public function debugBar(Foo $object)
   {
      
// this does NOT violate visibility although $bar is private
      
echo $object->bar, "\n";
   }

  
public function setBar($value)
   {
      
// Neccessary method, for $bar is invisible outside the class
      
$this->bar = $value;
   }
  
  
public function setForeignBar(Foo $object, $value)
   {
      
// this does NOT violate visibility!
      
$object->bar = $value;
   }
}

$a = new Foo();
$b = new Foo();
$a->setBar(1);
$b->setBar(2);
$a->debugBar($b);        // 2
$b->debugBar($a);        // 1
$a->setForeignBar($b, 3);
$b->setForeignBar($a, 4);
$a->debugBar($b);        // 3
$b->debugBar($a);        // 4
?>
thc at forestfactory dot de
14-Dec-2005 01:38
To jfk...

Interessting and probably a bug?

Well, the workaround is not very hard: Just don't return the member directly:
<?
       public
function GetNum(){
            
$ret = $this->num;
             return
$ret;
       }
?>
jfk at 206-225-86-169 dot dedicated dot abac dot net
13-Dec-2005 09:14
BEWARE!!  The visibility of a class member can easily be compromised by attaining a reference to the protected member.  In C++ for example this can not be done unless specifically included in the declaration/definition.  However in PHP it is simple!!!!  Observe....

class MyClass{
       protected $num;

       public function MyClass(){
           $this->num = 0;
       }

       public function Increment(){
           $this->num++;
       }

       public function GetNum(){
             return $this->num;
       }
};

$c = new MyClass(); //create instance of class
$x = &$c->GetNum(); //create variable referencing protected member to keep track of value while avoiding repeat calls to GetNum().

$x++;

echo "CLASS VALUE: " . $c->GetNum() . " VAR VALUE: $x\n";

The output is:
CLASS VALUE: 1 VAR VALUE: 1

A protected member should be exactly what "protected" means,  protected.

I hope I am overlooking something.  If not I believe this feature should be corrected to improve transparency in syntax between the two "languages."

Additionally, please note that my email address is:
jkallen@206-225-86-169.dedicated.abac.net

I had to create the jfk alias because the form for submitting notes does not accept emails as long as mine!!!!  Ouch!
gugglegum at gmail dot com
02-Sep-2005 07:58
When you call parent method from child class, inside parent method $this contains object of child class, but private members depends on from which context you access private property:

<?php

class A
{
 
private $prop = "I am property of A!";
 
public function s() {
   echo
"\$this is object of class ".get_class($this)." but \$this->prop is '".$this->prop."'\n";
  }
}

class
B extends A
{
 
private $prop = "I am property of B!";
 
public function s() {
   echo
"\$this is object of class ".get_class($this)." but \$this->prop is '".$this->prop."'\n";
  }
 
public function z() {
  
parent::s();
  
$this->s();
  }
}

$b = new B();
$b->z();

?>

This will produce:

$this is object of class B but $this->prop is 'I am property of A!'
$this is object of class B but $this->prop is 'I am property of B!'

But when you use members with protected or public visibility - it not depends on context. If you replace "private" to "protected" in example above, you will get "I am property of B!" twice.

See ya!
gugglegum at gmail dot com
02-Sep-2005 06:14
Private visibility actually force members to be not inherited instead of limit its visibility. There is a small nuance that allows you to redeclare private member in child classes.

<?php

class A
{
private $prop = 'I am property of A!';
}

class
B extends A
{
public $prop = 'I am property of B!';
}

$b = new B();
echo
$b->prop; // "I am property of B!"

?>
gugglegum at gmail dot com
02-Sep-2005 02:01
Parent class can access protected members of its childs.

<?php
class A
{
 
public function getProtected()
  {
   return
B::$protected;
  }
}

class
B extends A
{
 
protected static $protected = 'Hi, I am protected property of class B!';
}

echo
A::getProtected();
?>

It works at least in PHP 5.0.4.
Miguel <miguel at lugopolis dot net>
21-Jul-2005 11:10
A note about private members, the doc says "Private limits visibility only to the class that defines the item" this says that the following code works as espected:

<?php
class A {
  
private $_myPrivate="private";

  
public function showPrivate()
   {
       echo
$this->_myPrivate."\n";
   }
}

class
B extends A {
  
public function show()
   {
      
$this->showPrivate();
   }
}

$obj=new B();
$obj->show(); // shows "private\n";
?>

this works cause A::showPrivate() is defined in the same class as $_myPrivate and has access to it.
David Rech
07-Jun-2005 06:14
You may define grouped variables separated by commas if they have the same visibility. This works for both initialized and uninitialized variables.

<?
class Window
{
  
public $x = 0, $y = 100, $width = 1024, $height = 768;
}
?>

Handy if no comments are required or you're inside a DocBlock.