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;
}
?>
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.
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
.
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
?>
Î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ă
?>
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ă.
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;
}
?>
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
?>
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"
?>
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
?>
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
?>
> 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.
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
}
?>