Las propiedades y los métodos representan el estado y el comportamiento que define una clase.
Pero no queremos que cualquier parte del código pueda modificar variables críticas sin control. Para eso existen los Modificadores de Visibilidad.
Los tres niveles de acceso
En PHP (y en la mayoría de lenguajes POO), tenemos tres palabras clave para definir quién puede ver y tocar una propiedad o un método:
Acceso total. Se puede leer y modificar desde cualquier sitio: desde dentro de la clase y desde fuera.
- Uso: Métodos que quieres que el usuario use (
volar(),encender()) o datos triviales.
Acceso exclusivo. Solo la propia clase puede ver esta propiedad. Desde fuera es invisible.
- Uso: El estado interno crítico (batería, contraseñas, lógica interna). Si intentas acceder desde fuera, PHP dará un Error Fatal.
Acceso familiar. Es como private, pero con una excepción: las clases que hereden de esta (hijos) también pueden acceder.
- Uso: Lo veremos a fondo en la lección de “Herencia”. De momento, quédate con que es un “privado compartido con la familia”.
Aplicando seguridad a nuestro dron
Vamos a arreglar el desastre de la lección anterior. Vamos a hacer que la batería sea private para que nadie pueda poner valores absurdos.
class Dron {
// PUBLIC: Cualquiera puede ver el modelo
public string $modelo;
// PRIVATE: Solo el Dron puede tocar la batería
private int $bateria = 100;
// Método para LEER la batería de forma segura (Getter)
public function getBateria(): int {
return $this->bateria;
}
// Método para VOLAR (Modifica la batería internamente)
public function volar(): void {
if ($this->bateria >= 10) {
$this->bateria -= 10; // AQUÍ sí podemos tocarla (estamos dentro)
echo "Volando... Batería restante: {$this->bateria}%\n";
} else {
echo "Batería baja. Aterrizando.\n";
}
}
}Probemos el código blindado:
$miDron = new Dron();
$miDron->modelo = "SkyHunter X";
// Intentar hackear la batería desde fuera
// $miDron->bateria = 5000;
// ❌ ERROR FATAL: Cannot access private property Dron::$bateria
// Forma correcta: Usar los métodos públicos
$miDron->volar(); // ✅ Funciona, baja a 90%
echo $miDron->getBateria(); // ✅ Leemos el valor (90)Así hemos forzado que la única forma de gastar batería sea volando y protegemos la integridad del dato.
Propiedades readonly (PHP 8.1+)
A veces tienes datos que no deberían ser privados (quieres que se vean), pero que nunca deberían cambiar una vez creados. Por ejemplo: el número de serie de un Dron o el ID de un usuario.
Antes de PHP 8.1, tenías que ponerlos private y hacer un método get... solo para leerlos. Era mucho código aburrido.
Ahora tenemos readonly.
Reglas de readonly:
- Solo se puede escribir una vez (normalmente en el constructor).
- Después de eso, la propiedad no puede reasignarse. Si contiene un objeto, el estado interno de ese objeto sí podría cambiar.
- No puede tener un valor por defecto en la definición.
class Dron {
// Puede leerse desde fuera, pero JAMÁS modificarse
public readonly string $numeroSerie;
public function __construct(string $serie) {
$this->numeroSerie = $serie; // Primera y única asignación
}
}
$dron = new Dron("SN-12345");
echo $dron->numeroSerie; // ✅ "SN-12345"
// Intentar cambiarlo después
// $dron->numeroSerie = "SN-99999";
// ❌ ERROR FATAL: Cannot modify readonly propertyEs perfecto para Data Transfer Objects (DTOs), un patrón que usarás muchísimo para mover datos de forma segura entre capas de tu aplicación.
Tipado de propiedades
Desde PHP 7.4, siempre debes poner el tipo a las propiedades.
- Mal (Estilo 2010):
class Usuario {
public $nombre; // ¿Qué es esto? ¿Un string? ¿Un array?
}- Bien (con una propiedad tipada):
class Usuario {
public string $nombre;
public ?int $edad; // Puede ser int o null
}Si intentas meter un array en $nombre, PHP te avisará inmediatamente. El código robusto empieza por definir bien qué datos manejamos.