WHEN do I use public, protected or private keyword? Here's the default behavior.
<?php
class Example
{
/* use PUBLIC on variables and functions when:
* 1. outside-code SHOULD access this property or function.
* 2. extending classes SHOULD inherit this property or function.
*/
public $var1;
public function someFunction_1() { }
/* use PROTECTED on variables and functions when:
* 1. outside-code SHOULD NOT access this property or function.
* 2. extending classes SHOULD inherit this property or function.
*/
protected $var2;
protected function someFunction_2() { }
/* use PRIVATE on variables and functions when:
* 1. outside-code SHOULD NOT access this property or function.
* 2. extending classes SHOULD NOT inherit this property or function.
*/
private $var3;
private function someFunction_3() { }
}
# these are the only valid calls outside-code can make on Example objects:
$obj1 = new Example(); // instantiate
$var1 = $obj1->var1; // get public data
$obj1->var1 = 35; // set public data
$obj1->someFunction_1(); // call public function
?>
Now try extending the class...
<?php
class Example_2 extends Example
{
// this class inherits the following properties and functions.
public $var1;
public function someFunction_1() { }
protected $var2;
protected function someFunction_2() { }
}
# these are the only valid calls outside-code can make on Example_2 objects:
$obj2 = new Example_2(); // instantiate
$var2 = $obj2->var1; // get public data
$obj2->var1 = 45; // set public data
$obj2->someFunction_1(); // call public function
?>
Visibilité
La visibilité d'une propriété ou d'une méthode peut être définie en préfixant la déclaration avec un mot-clé : public, protected ou private. Les éléments déclarés publics (public) peuvent être utilisés par n'importe quelle partie du programme. L'accès aux éléments protégés (protected) est limité aux classes et parents hérités (et à la classe qui a défini l'élément). L'accès aux éléments privés (private) est uniquement réservé à la classe qui les a définis.
Visibilité des membres
Les classes membres doivent être définies comme publiques, protégées ou privées.
Exemple #1 Déclaration des membres
<?php
/**
* Définition de MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->private;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Fonctionne
echo $obj->protected; // Erreur fatale
echo $obj->private; // Erreur fatale
$obj->printHello(); // Affiche Public, Protected et Private
/**
* Définition de MyClass2
*/
class MyClass2 extends MyClass
{
// On peut redéclarer les éléments publics ou protégés, mais pas ceux privés
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Fonctionne
echo $obj2->private; // Indéfini
echo $obj2->protected; // Erreur fatale
$obj2->printHello(); // Affiche Public, Protected2 et Indéfini
?>
Note: La méthode de déclaration de variable en PHP 4 avec le mot-clé var est toujours supportée pour des raisons de compatibilité (en tant que synonyme du mot-clé public). Depuis PHP 5.1.3, son utilisation génère une erreur de niveau E_STRICT.
Visibilité des méthodes
Les méthodes des classes doivent être définies en tant que publiques, privées ou protégées. Les méthodes sans déclaration seront automatiquement définies comme étant publiques.
Exemple #2 Déclaration d'une méthode
<?php
/**
* Définition de MyClass
*/
class MyClass
{
// Déclare un contructeur public
public function __construct() { }
// Déclaration d'une méthode publique
public function MyPublic() { }
// Déclaration d'une méthode protégée
protected function MyProtected() { }
// Déclaration d'une méthode privée
private function MyPrivate() { }
// Celle-ci sera publique
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
$myclass = new MyClass;
$myclass->MyPublic(); // Fonctionne
$myclass->MyProtected(); // Erreur fatale
$myclass->MyPrivate(); // Erreur fatale
$myclass->Foo(); // Public, Protected et Private fonctionnent
/**
* Définition de MyClass2
*/
class MyClass2 extends MyClass
{
// Celle-ci sera publique
function Foo2()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate(); // Erreur fatale
}
}
$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Fonctionne
$myclass2->Foo2(); // Public et Protected fonctionnent, non pas Private
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "Bar::testPublic\n";
}
private function testPrivate() {
echo "Bar::testPrivate\n";
}
}
class Foo extends Bar
{
public function testPublic() {
echo "Foo::testPublic\n";
}
private function testPrivate() {
echo "Foo::testPrivate\n";
}
}
$myFoo = new foo();
$myFoo->test(); // Bar::testPrivate
// Foo::testPublic
?>
Visibilité
10-Oct-2008 02:48
06-Oct-2008 01:33
PHP 5.2.3, windows
The comment in this example is invalid
<?php
/**
* 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;
}
}
?>
Just try this:
<?php
class MyClass2 extends MyClass
{
// We CAN redeclare the public, protected and private PROPERTIES in this example
public $public = 'Public2';
protected $protected = 'Protected2';
private $private = 'Private2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
?>
10-Sep-2008 11:21
UNDERSTANDING PHP's OBJECT VISIBILITY
Sometimes it's good to see a list of many extended classes, one right after the other - just for the sole purpose of looking at their inherited members. Maybe this will help:
class MyClass_1{
public $pubVal = 'Hello World!';
protected $proVal = 'Hello FROM MyClass_1';
private $priVal = 'Hello TO MyClass_1';
public function __toString(){
return "MyClass_1[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_2 extends MyClass_1{
public function __toString(){
return "MyClass_2[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_3 extends MyClass_2{
private $priVal = 'Hello TO MyClass_3';
public function __toString(){
return "MyClass_3[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_4 extends MyClass_3{
protected $proVal = 'Hello FROM MyClass_4';
public function __toString(){
return "MyClass_4[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_5 extends MyClass_4{
public function __toString(){
return "MyClass_5[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
class MyClass_6 extends MyClass_5{
private $priVal = 'Hello TO MyClass_6';
public function __toString(){
return "MyClass_6[public=$this->pubVal, protected=$this->proVal, private=$this->priVal]";
}
}
echo (new MyClass_1()) . '<br>';
echo (new MyClass_2()) . '<br>';
echo (new MyClass_3()) . '<br>';
echo (new MyClass_4()) . '<br>';
echo (new MyClass_5()) . '<br>';
echo (new MyClass_6()) . '<br>';
The list of extended objects:
MyClass_1[public=Hello World!, protected=Hello FROM MyClass_1, private=Hello TO MyClass_1]
MyClass_2[public=Hello World!, protected=Hello FROM MyClass_1, private=]
MyClass_3[public=Hello World!, protected=Hello FROM MyClass_1, private=Hello TO MyClass_3]
MyClass_4[public=Hello World!, protected=Hello FROM MyClass_4, private=]
MyClass_5[public=Hello World!, protected=Hello FROM MyClass_4, private=]
MyClass_6[public=Hello World!, protected=Hello FROM MyClass_4, private=Hello TO MyClass_6]
Notice in the class definitions, I made absolutly no attempt to change protected members to private, etc. - that gets too confusing and is not necessary - though I did redeclare a few members with the same var name and visibility strength. One other noteworthy: the output for MyClass_2, there seems to be a private property with value of empty string. Here, $priVal was not inherited from MyClass_1 because it is private in MyClass_1, instead, because of PHP's relaxed syntax, it was actually created right there in MyClass2::__toString() method... not only that, it is not a private member either. Watch out for this kind of thing, as PHP can sometimes give confusing impressions.
13-Dec-2007 03:34
Please note that if a class has a protected variable, a subclass cannot have the same variable redefined private (must be protected or weaker). It seemed to be logical for me as a subsubclass would not know if it could see it or not but even if you declare a subclass to be final the restriction remains.
11-Oct-2007 09:52
Re: ference at super_delete_brose dot co dot uk
"If eval() is the answer, you’re almost certainly asking the wrong question."
<?php
eval('$result = $this->'.$var.';'); //wrong
$result = $this->$var; //right way
$var = "foo";
$this->var = "this will assign to member called 'var'.";
$this->$var = "this will assign to member called 'foo'.";
?>
29-May-2007 09:09
I couldn't find this documented anywhere, but you can access protected and private member varaibles in different instance of the same class, just as you would expect
i.e.
<?php
class A
{
protected $prot;
private $priv;
public function __construct($a, $b)
{
$this->prot = $a;
$this->priv = $b;
}
public function print_other(A $other)
{
echo $other->prot;
echo $other->priv;
}
}
class B extends A
{
}
$a = new A("a_protected", "a_private");
$other_a = new A("other_a_protected", "other_a_private");
$b = new B("b_protected", "ba_private");
$other_a->print_other($a); //echoes a_protected and a_private
$other_a->print_other($b); //echoes b_protected and ba_private
$b->print_other($a); //echoes a_protected and a_private
?>
22-May-2007 07:10
Sometimes you may wish to have all members of a class visible to other classes, but not editable - effectively read-only.
In this case defining them as public or protected is no good, but defining them as private is too strict and by convention requires you to write accessor functions.
Here is the lazy way, using one get function for accessing any of the variables:
<?php
class Foo {
private $a;
private $b;
private $c;
private $d;
private $e;
private $f;
public function __construct() {
$this->a = 'Value of $a';
$this->b = 'Value of $b';
$this->c = 'Value of $c';
$this->d = 'Value of $d';
$this->e = 'Value of $e';
$this->f = 'Value of $f';
}
/* Accessor for all class variables. */
public function get($what) {
$result = FALSE;
$vars = array_keys(get_class_vars('Foo'));
foreach ($vars as $var) {
if ($what == $var) {
eval('$result = $this->'.$var.';');
return $result;
}
}
return $result;
}
}
class Bar {
private $a;
public function __construct() {
$foo = new Foo();
var_dump($foo->get('a')); // results in: string(11) "Value of $a"
}
}
$bar = new Bar();
?>
08-Apr-2007 03:49
If you always thought how can you use a private method in php4 classes then try the following within your class.
<?php
function private_func($func)
{
$this->file = __FILE__;
if (PHPVERS >= 43) {
$tmp = debug_backtrace();
for ($i=0; $i<count($tmp); ++$i) {
if (isset($tmp[$i]['function'][$func])) {
if ($this->file != $tmp[$i]['file']) {
trigger_error('Call to a private method '.__CLASS__.'::'.$func.' in '.$tmp[$i]['file'], E_USER_ERROR);
}
}
}
}
}
?>
Then inside the private function add:
<?php
function foo() {
$this->private_func(__FUNCTION__);
# your staff goes here
}
?>
14-Mar-2007 06:33
Uh... to atitthaker at gmail dot com -- It is *meant* to be available under C as well, since A is a superclass of C, and any proctected methods in a superclass is always available to a subclass, no matter how many "generations" you have to traverse, it is available to C.
01-Mar-2007 10:34
<?
class A
{
protected $b=20;
private $a=10;
//protected method and shall not be accessible under class C
protected function access()
{
print("here");
}
}
class B extends A
{
public function test()
{
$this->access() ;
}
}
class C extends B
{
function temp()
{
$this->access(); // access variable and prints "here"
}
}
$abc= new C();
$abc->temp();
?>
Above code shall generate error as protected method of class A is accessible in class C which is directly not inheriting class A.
23-Aug-2006 11: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.
13-Jul-2006 12: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.
28-Mar-2006 11: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.
07-Feb-2006 02: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).
05-Jan-2006 02: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
?>
02-Sep-2005 12: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!"
?>
21-Jul-2005 05: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.
