Modificadores de acceso en PHP OOP: Guía completa
Aprende los modificadores de acceso en PHP OOP: public, protected y private. Domina la encapsulación con ejemplos claros de herencia y getters/setters.
Los modificadores de acceso (también llamados palabras clave de visibilidad) determinan quién puede leer, modificar o invocar a un miembro de una clase. Son el mecanismo detrás de la encapsulación — una de las ideas fundamentales de la Programación Orientada a Objetos: se expone una superficie pública pequeña y segura, ocultando los detalles internos que los llamadores no deben tocar.
Este capítulo cubre las tres palabras clave de visibilidad de PHP — public, protected y private — qué permite cada una, qué ocurre cuando se rompen las reglas, cómo se comporta la visibilidad bajo la herencia, y los patrones comunes (getters, setters y promoción de constructores) que se basan en ellas. Si las clases son nuevas para ti, lee primero Clases y objetos en PHP.
Los tres modificadores de acceso de un vistazo
| Modificador | Dentro de la misma clase | En una clase hija | Desde fuera (p. ej. $obj->member) |
|---|---|---|---|
public | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ❌ |
private | ✅ | ❌ | ❌ |
Puedes aplicar un modificador a propiedades, métodos y constantes de clase. Si omites el modificador en un método, PHP lo establece como public por defecto; en una propiedad debes escribir uno explícitamente (la antigua palabra clave var es un alias de public).
Modificador de acceso public
public es el nivel más permisivo. Un miembro público puede ser accedido desde cualquier lugar — dentro de la clase, desde clases hijas y desde cualquier código que tenga el objeto. Úsalo para la interfaz prevista de tu clase: los métodos que los llamadores deben usar.
<?php
class User {
public $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
$user = new User();
$user->setName("Ada"); // calling a public method
echo $user->getName(); // Ada
echo "\n";
$user->name = "Grace"; // touching a public property directly
echo $user->name; // GraceLa salida es:
Ada
GraceComo $name es público, los llamadores pueden modificarlo directamente con $user->name = ..., sin pasar por setName(). Por eso las propiedades públicas suelen desaconsejarse: pierdes la oportunidad de validar el valor. Marcar la propiedad como protected o private y exponerla a través de métodos recupera ese control.
Modificador de acceso protected
protected ocupa el nivel intermedio. El miembro es accesible desde dentro de la clase y desde cualquier subclase, pero no desde código externo. Úsalo cuando una subclase necesita legítimamente los datos, pero los llamadores externos no deben acceder a ellos.
<?php
class User {
protected $email;
protected function setEmail($email) {
$this->email = $email;
}
public function getEmail() {
return $this->email;
}
}
$user = new User();
echo $user->getEmail(); // works: getEmail() is public
$user->setEmail("[email protected]"); // Fatal error: Call to protected method User::setEmail()Al ejecutar esto, la primera línea no imprime nada (el correo electrónico sigue siendo null) y luego se detiene con:
PHP Fatal error: Uncaught Error: Call to protected method User::setEmail() from global scopeEl error es precisamente el punto: los miembros protegidos protegen la clase del uso incorrecto por parte de código externo, mientras siguen cooperando con la cadena de herencia que se muestra a continuación.
Modificador de acceso private
private es el nivel más restrictivo. El miembro es visible únicamente dentro de la clase que lo declara — ni siquiera las subclases pueden verlo. Recurre a private cuando un detalle es puramente interno y podría cambiar en cualquier momento, como un hash de contraseña o un cálculo en caché.
<?php
class User {
private $password;
public function setPassword($password) {
// hide the real value behind validation
$this->password = password_hash($password, PASSWORD_DEFAULT);
}
public function check($attempt) {
return password_verify($attempt, $this->password);
}
}
$user = new User();
$user->setPassword("s3cret");
var_dump($user->check("s3cret")); // bool(true)
var_dump($user->check("wrong")); // bool(false)La salida es:
bool(true)
bool(false)Intentar leer $user->password desde fuera de la clase genera Error: Cannot access private property User::$password. El llamador solo puede interactuar a través de los métodos públicos setPassword() y check() — el hash en bruto queda sellado.
Modificadores de acceso y herencia
Cuando una clase hija extiende a una clase padre, hereda los miembros del padre junto con su visibilidad. Los miembros public y protected son utilizables dentro de la clase hija; los private no son visibles para la hija en absoluto.
<?php
class User {
protected $email;
protected function setEmail($email) {
$this->email = $email;
}
public function getEmail() {
return $this->email;
}
}
class Admin extends User {
// Admin can call the protected setEmail() because it is a subclass
public function updateEmail($email) {
$this->setEmail($email);
}
}
$admin = new Admin();
$admin->updateEmail("[email protected]");
echo $admin->getEmail(); // [email protected]La salida es:
Una clase hija también puede ampliar la visibilidad (protected → public) al sobreescribir un miembro, pero no puede reducirla — sobreescribir un método público como private provoca un error fatal. Para más información sobre la construcción de jerarquías de clases, consulta Herencia en PHP.
Visibilidad en constantes y promoción de constructores
Las constantes de clase aceptan los mismos modificadores (desde PHP 7.1). Esto permite exponer algunas constantes mientras se ocultan valores de configuración interna:
<?php
class Order {
public const STATUS_PAID = "paid";
private const TAX_RATE = 0.2; // internal detail
public function total(float $net): float {
return $net * (1 + self::TAX_RATE);
}
}
echo Order::STATUS_PAID; // paid
echo "\n";
echo (new Order())->total(100); // 120La salida es:
paid
120Desde PHP 8.0, la promoción de propiedades en el constructor permite declarar una propiedad y su visibilidad directamente en la firma del constructor, eliminando el repetitivo código repetitivo:
<?php
class Point {
public function __construct(
public int $x = 0,
private int $y = 0, // declared, assigned, and made private in one line
) {}
public function describe(): string {
return "x={$this->x}, y={$this->y}";
}
}
echo (new Point(3, 4))->describe(); // x=3, y=4La salida es:
x=3, y=4Consulta Constantes de clase en PHP y Constructor en PHP para obtener una visión completa de estas características.
Elegir el modificador adecuado
- Comienza con el nivel más restrictivo (
private) y relájalo solo cuando aparezca una necesidad real. Esto mantiene tu API pública pequeña y fácil de modificar más adelante. - Haz un miembro
publiccuando forme parte de la interfaz de la que dependen los llamadores. - Hazlo
protectedcuando las subclases — pero no el código externo — lo necesiten. - Hazlo
privatecuando sea un detalle de implementación que podría cambiar sin previo aviso. - Prefiere propiedades privadas/protegidas con métodos públicos getter/setter en lugar de propiedades públicas, para mantener el control sobre cómo se leen y escriben los valores. Esta idea forma parte de lo que trata la POO.
Resumen
Los modificadores de acceso controlan la visibilidad de los miembros de una clase: public permite el acceso desde cualquier lugar, protected desde la clase y sus subclases, y private solo desde la clase que lo declara. Se aplican a propiedades, métodos y constantes, y son el modo en que PHP hace cumplir la encapsulación. Utilizados correctamente — ocultando detalles detrás de una pequeña superficie pública — hacen que tu código sea más seguro de modificar y más fácil de razonar.