Visibilidad

La visibilidad de una propiedad, un método o (a partir de PHP 7.1.0) una constante se puede definir anteponiendo a su declaración una de las palabras reservadas public, protected o private. A los miembros de clase declarados como 'public' se puede acceder desde donde sea; a los miembros declarados como 'protected', solo desde la misma clase, mediante clases heredadas o desde la clase padre. A los miembros declarados como 'private' únicamente se puede acceder desde la clase que los definió.

Visibilidad de propiedades

Las propiedades de clases deben ser definidas como 'public', 'private' o 'protected'. Si se declaran usando var, serán definidas como 'public'.

Ejemplo #1 Declaración de propiedades

<?php
/**
* Definición de 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; // Funciona bien
echo $obj->protected; // Error Fatal
echo $obj->private; // Error Fatal
$obj->printHello(); // Muestra Public, Protected y Private


/**
* Definición de MyClass2
*/
class MyClass2 extends MyClass
{
// Se pueden redeclarar las propiedades pública y protegida, pero no la privada
public $public = 'Public2';
protected
$protected = 'Protected2';

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

$obj2 = new MyClass2();
echo
$obj2->public; // Funciona bien
echo $obj2->protected; // Error Fatal
echo $obj2->private; // Undefined
$obj2->printHello(); // Muestra Public2, Protected2, Undefined

?>

Nota: La forma de declaración de una variable de PHP 4 con la palabra clave var todavía es soportado (como un sinónimo de public) por razones de compatibilidad. En PHP 5 antes de 5.1.3, su uso genera un Warning E_STRICT.

Visibilidad de Métodos

Los métodos de clases pueden ser definidos como public, private, o protected. Aquellos declarados sin ninguna palabra clave de visibilidad explícita serán definidos como public.

Ejemplo #2 Declaración de métodos

<?php
/**
* Definición de MyClass
*/
class MyClass
{
// Declaración de un constructor public
public function __construct() { }

// Declaración de un método public
public function MyPublic() { }

// Declaración de un método protected
protected function MyProtected() { }

// Declaración de un método private
private function MyPrivate() { }

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

$myclass = new MyClass;
$myclass->MyPublic(); // Funciona
$myclass->MyProtected(); // Error Fatal
$myclass->MyPrivate(); // Error Fatal
$myclass->Foo(); // Public, Protected y Private funcionan


/**
* Definición de MyClass2
*/
class MyClass2 extends MyClass
{
// Esto es public
function Foo2()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate(); // Error Fatal
}
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Funciona
$myclass2->Foo2(); // Public y Protected funcionan, pero Private no

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
?>

Visibilidad de las constantes

A partir de PHP 7.1.0, las constantes de clase se pueden definir como públicas, privadas o protegidas. Las constantes declaradas sin una visibilidad explítica serán definidas como públicas.

Ejemplo #3 Declaración de constantes a partir de PHP 7.1.0

<?php
/**
* Definir MiClase
*/
class MiClase
{
// Declarar una constante pública
public const MY_PUBLIC = 'public';

// Declarar una constante protegida
protected const MY_PROTECTED = 'protected';

// Declarar una constante privada
private const MY_PRIVATE = 'private';

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

$myclass = new MiClase();
MiClase::MY_PUBLIC; // Funciona
MiClase::MY_PROTECTED; // Error fatal
MiClase::MY_PRIVATE; // Error fatal
$myclass->foo(); // Funcionan Public, Protected y Private


/**
* Definir MiClase2
*/
class MiClase2 extends MiClase
{
// Esta es pública
function foo2()
{
echo
self::MY_PUBLIC;
echo
self::MY_PROTECTED;
echo
self::MY_PRIVATE; // Error fatal
}
}

$myclass2 = new MiClase2;
echo
MiClase2::MY_PUBLIC; // Funciona
$myclass2->foo2(); // Funcionan Public y Protected, pero no Private
?>

Visibilidad desde otros objetos

Los objetos del mismo tipo tendrán acceso a los miembros private y protected entre ellos aunque no sean de la misma instancia. Esto es porque los detalles específicos de implementación ya se conocen cuando se encuentra dentro de estos objetos.

Ejemplo #4 Accediendo a miembros private del mismo tipo de objeto

<?php
class Test
{
private
$foo;

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

private function
bar()
{
echo
'Método private accedido.';
}

public function
baz(Test $other)
{
// Se puede cambiar la propiedad private:
$other->foo = 'hola';
var_dump($other->foo);

// También se puede invocar al método private:
$other->bar();
}
}

$test = new Test('test');

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

El resultado del ejemplo sería:

string(5) "hola"
Método private accedido.
add a note add a note

User Contributed Notes 7 notes

up
60
pgl at yoyo dot org
9 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
12 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
17 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
8 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
3 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