Aprender programación orientada a objetos es esencial para poder desarrollar con los frameworks modernos de PHP como Laravel o Symfony. PHP dejó hace bastante tiempo de ser un lenguaje de plantillas para construir sitios personales para convertirse en un poderoso lenguaje orientado a objetos y uno de los lenguajes más populares de la actualidad: Programming Languages and GitHub.
De hecho la mayoría de los sitios funcionan en PHP y hoy en día existen diferentes motores de plantillas escritos en PHP como Blade o Twig. Pero regresando al tema de OOP (Object Oriented Programming), primero que nada debemos entender el por qué necesitamos clases y objetos:
Las clases nos permiten agrupar información y acciones que podemos ejecutar con dicha información.
Veamos un ejemplo:
- Tenemos la siguiente información: nombre, apellido y fecha de nacimiento.
- Requerimos de las siguientes acciones:
- Mostrar el nombre completo de la persona
- Mostrar la edad de la persona
Como puedes ver las acciones que necesitamos ejecutar están ligadas a la información de la persona. Por ejemplo: nombre completo requiere obtener el primer nombre y el apellido, mientras que calcular la edad depende de la fecha de nacimiento.
Ahora suponiendo que sólo conoces programación estructurada resolverás el problema anterior de esta forma:
<?php $firstName = 'John'; $lastName = 'Doe'; $dateOfBirth = '1980-12-01'; function fullName($firstName, $lastName) { return "{$firstName} {$lastName}"; } function age($dateOfBirth) { // Calculate age... return $age; }
Aquí no hay forma de agrupar qué información y cuáles acciones van juntas. También tenemos otros problemas:
- No es posible prevenir que el programador cambie sin querer la fecha de nacimiento de la persona (es posible que tu nombre cambie si por ejemplo obtienes otra nacionalidad o te casas, pero tu fecha de nacimiento seguirá siendo siempre la misma).
- Siempre tendremos que recordar qué argumentos pasarle a cada función y en cual orden y esto se vuelve difícil si una función depende de 3 o más argumentos.
- Si quisiéramos crear una segunda persona entonces ¿Tendríamos que crear las variables
$firstName2
,$lastName2
,$dateOfBirth2
?
En algún momento descubrí los arrays y pensé ¡Claro! esto puede ayudarme:
<?php $person = array( 'firstName' => 'John', 'latsName' => 'Doe', 'dateOfBirth' => '1980-12-01', );
Pero de nuevo, esto no nos previene de hacer cambios en uno o más valores, también es difícil de recordar cuales «llaves» necesitamos y no cometer errores cuando estamos escribiéndolas ¿Te diste cuenta que escribí, a propósito, latsName
en vez de lastName
?
Además, los arrays no nos brindan valores por defecto. ¿Qué tal si quisiéramos que el usuario tenga un alias de «Guest» si no se ha registrado?
Por último, llamar a las funciones se haría más tedioso aún:
fullName($person['firstName'], $person['lastName']);
Introducción a los objetos y clases en PHP
Con los objetos y las clases ahora es posible agrupar información y acciones de una forma muy fácil. Lo único que tenemos que pensar es en un nombre genérico para nuestra clase, puesto que las clases y los objetos son conceptos diferentes:
Clase: es un término genérico que, como su nombre lo indica, representa una clase, tipo o conjunto. En mi ejemplo como quiero representar los datos y acciones de una o más personas, voy a llamar a la clase Persona o Person (es buena práctica escribir el código en inglés) y esto es todo lo que hace falta para hacer el «molde» de mi clase:
<?php class Person { }
Ahora todas las variables que necesito para representar el estado de cada persona (Person) las voy a declarar dentro de la clase y las voy a llamar propiedades:
<?php class Person { public $firstName = 'John'; public $lastName = 'Doe'; private $dateOfBirth = '1980-12-01; }
Nota que para declarar una propiedad estoy usando 2 palabras claves: public
y private
:
public
quiere decir que la propiedad se puede acceder y modificar fuera del «molde» (esqueleto o contexto) de la clase.private
indica que no es posible ni leer ni reescribir la propiedad fuera de la clase y esto nos trae un nuevo concepto muy importante llamado encapsulamiento.
Por otro lado todas las funciones o acciones que van a leer o interactuar con dichos datos (o propiedades) las voy también a convertir en métodos de la clase, tan sólo colocando dichas funciones dentro de la clase:
<?php class Person { public $firstName = 'John'; public $lastName = 'Doe'; private $dateOfBirth = '1980-12-01; public function fullName() { return "{$this->firstName} {$this->lastName}"; } public function age() { // Calculate age using $this->dateOfBirth... return $age; } }
¿A dónde fueron los parámetros?
Como puedes ver el código es similar a lo hecho en la programación estructurada, sin embargo en vez de aceptar argumentos externos ahora estoy trabajando con las propiedades dentro de la clase y esto lo logro utilizando $this->
.
Mientras que para trabajar con una variable usamos el signo de dólar $, para interactuar con una propiedad dentro de la clase usamos dólar, seguido de la palabra «this» y una flecha: $this->
Declarando un objeto
Mientras que la clase representa el concepto genérico, un objeto es la representación específica de una clase. Cuando tenemos una clase podemos declara uno o más objetos de dicha clase de esta forma:
<?php $john = new Person("John", "Doe", "1980-12-01");
Nota que en este caso usamos el operador «new», seguido del nombre de la clase y luego los argumentos que acepta el constructor de la clase.
Definiendo el constructor de una clase
Lo anterior no va a funcionar porque de hecho nuestra clase no tienen ningún constructor. Un constructor es un método mágico o especial que puede aceptar una serie de argumentos y nos permite inicializar el objeto, por ejemplo asignando las propiedades mínimas requeridas para que nuestro objeto pueda funcionar (por ejemplo tenga una identidad única), en nuestro ejemplo parecemos necesitar entonces el primer nombre, el apellido y la fecha de nacimiento:
<?php class Person { public $firstName = 'John'; public $lastName = 'Doe'; private $dateOfBirth = '1980-12-01; public function __construct($fisrtName, $lastName, $dateOfBirth) { $this->fisrtName = $firstName; $this->lastName = $lastName; $this->dateOfBirth = $dateOfBirth; } public function fullName() { return "{$this->firstName} {$this->lastName}"; } public function age() { // Calculate age using $this->dateOfBirth... return $age; } }
Los constructores de todas las clases de PHP son definidos con el mismo nombre __construct
y como puedes ver tal como las propiedades y el resto de los métodos, pueden ser públicos o privados, pero por ahora vamos a dejarlo como público. Con este código ya podemos proceder a instanciar nuestro objeto:
<?php $john = new Person("John", "Doe", "1980-12-01");
Nota que el constructor es el único método en nuestro ejemplo que está recibiendo argumentos, una vez que asignamos dichos argumentos a las propiedades de nuestra clase (uno por uno) entonces ya podemos usar dichas propiedades en el resto de los métodos:
<?php class Person { // [El resto del codigo iria aqui] public function fullName() { return "{$this->firstName} {$this->lastName}"; } }
En este caso dentro del método fullName
leemos firstName
y lastName
.
Ahora en algunas ocasiones queremos leer y/o modificar ciertas propiedades fuera de la clase. Si la propiedad es pública podemos lograrlo así:
<?php $duilio = new Person("John", "Doe", "1980-12-01"); $duilio->firstName = 'Duilio';
Pero si la propiedad es privada vamos a obtener una excepción, así que para acceder a ella fuera de la clase debemos declarar métodos conocidos como getters o setters:
<?php class Person { // [El resto del codigo iria aqui] public function getDateOfBirth() { return $this->dateOfBirth; } public function setDateOfBirth($date) { $this->dateOfBirth = $date; } }
Los getters o setters son métodos comunes que nos permiten obtener o reemplazar el valor de una propiedad, respectivamente:
- Con
getDateOfBirth
obtenemos la fecha de nacimiento de la persona. - Con
setDateOfBirth
reemplazaríamos la fecha de nacimiento de la persona.
Ahora ya no tenemos ninguna limitación para cambiar la fecha de nacimiento de alguien a cualquier otra fecha:
<?php $duilio = new Person("Duilio", "Doe", "1980-12-01"); $duilio->setDateOfBirth("2002-01-01");
Gracias al código anterior ahora tengo tan sólo unos 15 años así que puedo dejar de escribir este tutorial e ir a jugar con el Playstation. Lamentablemente esto no es posible en la vida real, así que tampoco debería permitirlo en mi programa, en este caso puedo solucionarlo dejando dateOfBirth como una propiedad privada y eliminando el setter, de esta manera sólo se puede leer el valor de la propiedad mas no modificarlo.
La programación orientada a objetos puede ser un tema fácil de aprender, sin embargo hay tantos conceptos (como abstracción, herencia, interfaces, polimorfismo, etc.) que son imposibles de cubrir en una sola lección, para ello necesitaría escribir un libro o mejor aún grabarlos en formato de video y de hecho ya lo hice, así que te recomiendo altamente que revises mi curso de programación orientada a objetos. Te prometo que a la final tu forma de programar cambiará para siempre y podrás sacarle el mayor provecho a Laravel (u otros frameworks) y a PHP.
Material Relacionado
- ¿Por qué necesitamos clases y objetos?
- Encapsulamiento, getters y setters
- Curso completo de programación orientada a objetos con PHP
Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.