PHP Velho Oeste 2024

Vizibilitatea

Vizibilitatea unei propietăți sau a unei metode poate fi definită prefixând declarația cu unul din cuvintele cheie: public, protected sau private. Membrele claselor (proprietăți sau metode) declarate public pot fi accesate oriunde. Membrele declarate protected pot fi accesate doar în interiorul clasei, precum și de clasele moștenite. Membrele declarate private pot fi accesate doar de clasa care le definește.

Vizibilitatea proprietăților

Proprietățile unei clase trebuie definite ca public, private, sau protected. Dacă sunt declarate utilizând var, proprietatea va fi definită ca publică.

Example #1 Declarare proprietăților

<?php
/**
 * Definire ClassaMea
 */
class ClassaMea
{
    public 
$membru_public 'Eu sunt: Public';
    protected 
$membru_protected 'Eu sunt: Protected';
    private 
$membru_private 'Eu sunt: Private';

    function 
afiseazaBunaZiua()
    {
        echo 
$this->membru_public ", ";
        echo 
$this->membru_protected ", ";
        echo 
$this->membru_private;
    }
}

$obj = new ClassaMea();
echo 
$obj->membru_public;    // Funcționează
echo $obj->membru_protected// Eroare fatală
echo $obj->membru_private;   // Eroare fatală
$obj->afiseazaBunaZiua();    // Afișează Eu sunt: Public, Eu sunt: Protected, Eu sunt: Private

/**
 * Define ClassaMea2
 */
class ClassaMea2 extends ClassaMea
{
    
// Putem redeclara metodele publice și protected, dar nu și pe cele private
    
public $membru_public 'Public2';
    protected 
$membru_protected 'Eu sunt: Protected2';

    function 
afiseazaBunaZiua()
    {
        echo 
$this->membru_public ",";
        echo 
$this->membru_protected;
        echo 
$this->membru_private;
    }
}

$obj2 = new ClassaMea2();
echo 
$obj->membru_public;     // Funcționează
echo $obj2->membru_protected// Eroare fatală
echo $obj2->membru_private;   // Nedefinit
$obj2->afiseazaBunaZiua();    // Afișează Eu sunt: Public, Eu sunt: Protected2

?>

Notă: Metoda PHP 4 de a declara variabile folosind cuvântul cheie var este încă susținută din motive de compatibilitate (fiind sinonim cuvântului cheie public). În PHP 5 înainte de 5.1.3, utilizarea sa va emite o avertizare de tip E_STRICT.

Vizibilitatea metodelor

Metodele claselor pot fi definite ca public, private, sau protected. Metodele declarate fără un cuvânt-cheie de vizibilitate sunt definite ca publice.

Example #2 Declarație metode

<?php
/**
 * Definește MyClass
 */
class MyClass
{
    
// Declară un constructor public
    
public function __construct() { }

    
// Declară o metodă publică
    
public function MyPublic() { }

    
// Declară o metodă protected
    
protected function MyProtected() { }

    
// Declară o metodă private
    
private function MyPrivate() { }

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

$myclass = new MyClass;
$myclass->MyPublic(); // Funcționează
$myclass->MyProtected(); // Eroare fatală
$myclass->MyPrivate(); // Eroare fatală
$myclass->Foo(); // Cele Public, Protected și Private funcționează


/**
 * Definește MyClass2
 */
class MyClass2 extends MyClass
{
    
// Aceasta este public
    
function Foo2()
    {
        
$this->MyPublic();
        
$this->MyProtected();
        
$this->MyPrivate(); // Eroare fatală
    
}
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Funcționează
$myclass2->Foo2(); // Public și Protected funcționează, dar nu și 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
?>

Vizibilitatea Constantelor

Începând cu PHP 7.1.0, constantele dintr-o clasă pot fi definite publice, private, sau protejate. Constantele declarate fără o vizilibitate explicită sunt considerate publice.

Example #3 Declararea constantelor începând cu PHP 7.1.0

<?php
/**
 * Definește clasa MyClass
 */
class MyClass
{
    
// Declară o constantă publică
    
public const MY_PUBLIC 'public';

    
// Declară o constantă protejată
    
protected const MY_PROTECTED 'protected';

    
// Declară o constantă privată
    
private const MY_PRIVATE 'private';

    public function 
foo()
    {
        echo 
self::MY_PUBLIC;
        echo 
self::MY_PROTECTED;
        echo 
self::MY_PRIVATE;
    }
}

$myclass = new MyClass();
MyClass::MY_PUBLIC// Funcționează
MyClass::MY_PROTECTED// Eroare fatală
MyClass::MY_PRIVATE// Eroare fatală
$myclass->foo(); // Publice, protejate și private funcționează


/**
 * Definește clasa MyClass2
 */
class MyClass2 extends MyClass
{
    
// Metodă publică
    
function foo2()
    {
        echo 
self::MY_PUBLIC;
        echo 
self::MY_PROTECTED;
        echo 
self::MY_PRIVATE// Eroare fatală
    
}
}

$myclass2 = new MyClass2;
echo 
MyClass2::MY_PUBLIC// Funcționează
$myclass2->foo2(); // Publice, protejate și private funcționează
?>

Vizibilitatea din cadrul altor obiecte

Obiectele de același tip vor avea acces reciproc la membrele private și protejate, cu toate că nu reprezintă aceeași instanță. Aceasta se întâmplă din cauza că detaliile specifice de implementare se cunosc deja în interiorul acestor obiecte.

Example #4 Accesarea membrelor private ale unui obiect de același tip

<?php
class Test
{
    private 
$foo;

    public function 
__construct($foo)
    {
        
$this->foo $foo;
    }

    private function 
bar()
    {
        echo 
'S-a accesat metoda privată.';
    }

    public function 
baz(Test $other)
    {
        
// Putem modifica proprietatea privată:
        
$other->foo 'salut';
        
var_dump($other->foo);

        
// Putem de asemenea apela metoda privată:
        
$other->bar();
    }
}

$test = new Test('test');

$test->baz(new Test('other'));
?>

Exemplul de mai sus va afișa:

string(5) "salut"
S-a accesat metoda privată.
add a note add a note

User Contributed Notes 7 notes

up
60
pgl at yoyo dot org
8 years ago
Just a quick note that it's possible to declare visibility for multiple properties at the same time, by separating them by commas.

eg:

<?php
class a
{
    protected
$a, $b;

    public
$c, $d;

    private
$e, $f;
}
?>
up
19
r dot wilczek at web-appz dot de
18 years ago
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
?>
up
1
alperenberatdurmus at gmail dot com
1 year ago
Dynamic properties are "public".
<?php
class MyClass {
    public function
setProperty($value) {
       
$this->dynamicProperty = $value;
    }
}
$obj = new MyClass();
$obj->setProperty('Hello World');
echo
$obj->dynamicProperty; // Outputs "Hello World"
?>

This usage is the same as well:
<?php
class MyClass {
}
$obj = new MyClass();
$obj->dynamicProperty = 'Hello World';
echo
$obj->dynamicProperty; // Outputs "Hello World"
?>
up
6
jc dot flash at gmail dot com
11 years ago
if not overwritten, self::$foo in a subclass actually refers to parent's self::$foo
<?php
class one
{
    protected static
$foo = "bar";
    public function
change_foo($value)
    {
       
self::$foo = $value;
    }
}

class
two extends one
{
    public function
tell_me()
    {
        echo
self::$foo;
    }
}
$first = new one;
$second = new two;

$second->tell_me(); // bar
$first->change_foo("restaurant");
$second->tell_me(); // restaurant
?>
up
5
Joshua Watt
16 years ago
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
?>
up
2
bishop at php dot net
7 years ago
> Members declared protected can be accessed only within
> the class itself and by inherited classes. Members declared
> as private may only be accessed by the class that defines
> the member.

This is not strictly true. Code outside the object can get and set private and protected members:

<?php
class Sealed { private $value = 'foo'; }

$sealed = new Sealed;
var_dump($sealed); // private $value => string(3) "foo"

call_user_func(\Closure::bind(
    function () use (
$sealed) { $sealed->value = 'BAZ'; },
   
null,
   
$sealed
));

var_dump($sealed); // private $value => string(3) "BAZ"

?>

The magic lay in \Closure::bind, which allows an anonymous function to bind to a particular class scope. The documentation on \Closure::bind says:

> If an object is given, the type of the object will be used
> instead. This determines the visibility of protected and
> private methods of the bound object.

So, effectively, we're adding a run-time setter to $sealed, then calling that setter. This can be elaborated to generic functions that can force set and force get object members:

<?php
function force_set($object, $property, $value) {
   
call_user_func(\Closure::bind(
        function () use (
$object, $property, $value) {
           
$object->{$property} = $value;
        },
       
null,
       
$object
   
));
}

function
force_get($object, $property) {
    return
call_user_func(\Closure::bind(
        function () use (
$object, $property) {
            return
$object->{$property};
        },
       
null,
       
$object
   
));
}

force_set($sealed, 'value', 'quux');
var_dump(force_get($sealed, 'value')); // 'quux'

?>

You should probably not rely on this ability for production quality code, but having this ability for debugging and testing is handy.
up
0
kostya at eltexsoft dot com
2 years ago
I see we can redeclare private properties into child class
<?php  
class A{
        private
int $private_prop = 4;
        protected
int $protected_prop = 8;
    }

    class
B extends A{
        private
int $private_prop = 7; // we can redeclare private property!!!
       
public function printAll() {
            echo
$this->private_prop;
            echo
$this->protected_prop;
    }
    }

   
$b = new B;
   
$b->printAll(); // show 78
}
?>
To Top