Advertisement
  1. Code
  2. Back-End

Programación Orientada a Objetos en PHP para Principiantes

Scroll to top
Read Time: 29 min

Spanish (Español) translation by Viviana Brito (you can also view the original English article)

Para muchos programadores de PHP, la programación orientada a objetos es un tema aterrador, lleno de sintaxis complicada y otros obstáculos. Como lo detalla mi libro "Pro PHP and jQuery", aprenderás los conceptos detrás de la programación orientada a objetos (POO), un estilo de programación en el que las acciones relacionadas se agrupan en clases; para lograr la creación de un código más compacto y eficáz.

Entendiendo La Programación Orientada a Objetos

Programación Orientada a Objetos es un estilo de programación que le permite a los desarrolladores agrupar tareas similares en clases. Esto nos ayuda a mantener el código de acuerdo al principo de "No te repitas" (NTR) facilitándo también su mantenimiento.

"Programación Orientada a Objetos es un estilo de programación que permite a los desarrolladores agrupar tareas similares en clases."

Uno de los mayores beneficios de la programación NTR es que; si alguna parte de la información cambia en tu programa, generalmente solo un cambio es requerido para actualizar el código. Una de las más grandes pesadillas para los desarrolladores es el mantenimiento de código donde los datos son declarados uno tras otro, es decir, cualquier cambio al programa se convierte en un juego infinitamente más frustrante de ¿Donde está Waldo?, mientras continuan persiguiendo datos y funcionalidad duplicada.

La POO es intimidante para muchos desarrolladores porque introduce nueva sintaxis, y a primera vista, pareciera ser mucho más compleja que simple programación procedimental, o lineal. Sin embargo, observando más de cerca, la POO es al final un enfoque  más simple y sencillo a la programación.

Comprendiendo Objetos y Clases

Antes de profundizar en los puntos más avanzados de la POO, un entendimiento básico de las diferencias entre objetos y clases es necesario. Esta sección tratará los componetes básicos de las clases, sus diferentes capacidades y algunos de sus usos

Reconociendo las Diferencias Entre Objetos y Clases

Fotos por: Istant Jefferson y John Wardell

Programadores comienzan hablando de objetos y clases, como si estos fueran términos intercambiables Sin embargo, esto no es cierto.

A primera instancia, hay confusión en la POO: programadores con experiencia comienzan a hablar acerca de objetos y clases, y parecieran ser terminos intercambiables. Sin embargo, este no es el caso, aunque la diferencia puede ser dificil de apreciar al principio.

Una clase, por ejemplo, es como los planos de una casa. Define la forma de la casa en papel, con las relaciones entre diferentes partes de la casa planeadas y definidas de manera precisa, aun cuando la casa no existe.

En cambio, un objeto es la casa construida de acuerdo a el plano. los datos almacenados en el objeto son como la madera, los cables y el concreto que conforman la casa: si no son colocados de acuerdo al plano, solo formarán un montón de cosas inútiles. No obstante, cuando todo se junta, se convierte en una organizada y útil casa.

Las Clases forman la estructura de los datos y las acciones y usan esa información para construir objetos. Más de un objeto puede ser construido de la misma clase al mismo tiempo, cada uno de manera independiente de los otros. Continuando con nuestra analogia de construcción, es similar al modo en que una subdivision puede ser construida del mismo plano: 150 casas diferetes que lucen iguales pero tienen diferentes
familias y decoraciones en el interior.

Estrcturación de una Clase

La sintaxis para crear una clase es bastante sencilla: se declara una clase usando la palabra reservada class , seguida del nombre de la clase y un par de corchetes ({}):

Después de la creación, una nueva clase puede ser instanciada y almacenada en una variable usando la palabra reservada new:

para ver el contenido de la clase, usa var_dump():

Prueba este proceso colocando todo el código anterior en un archivo nuevo llamado test.php en tu carpeta [local] de prueba:

Carga la página en tu navegador colocando la dirección http://localhost/test.php y debería mostrarse lo siguiente:

En su forma más simple, has completado tu primer script de POO.

Definiendo Propiedades de una Clase

Para agregar datos a una clase; propiedades o variables específicas de la clase, son utilizadas. Estas trabajan igual que variables regulares, solo que están unidas al objeto y por lo tanto solo puede accederse a ellas usando el objeto

Para agregar una propiedad a MyClass, añade el siguiente scipt de código:

La palabra reservada public determina la visibilidad de la propiedad, de la cual aprenderás más adelante en este capítulo. Después, la propiedad es llamada usando la sintaxis estándar de variable, y se le asigna un valor (aunque las propiedades de clase no necesitan un valor inicial).

Para leer esta propiedad y mostrarla en el navegador, referencia el objeto desde el cual leer y la propiedad a ser leída:

Dado que pueden existir múltiples instancias de una clase, si el objeto individual no está referenciado, el script sería incapaz de determinar de qué objeto leer. El uso de la flecha (->) es una construcción de la POO que accede a las propiedades y métodos contenidos de un objeto dado.

Modifica el script en test.php para leer la propiedad en lugar de volcar el contenido entero de la clase modificando el código como se muestra: 

Recargando tu navegador ahora mostrará la siguiente salida:

Definiendo Métidos de Clase

Los Métodos son funciones específicas de la clase Las acciones individuales que un objeto será capaz de realizar son definidas en el interior de la clase como métodos

Por ejemplo, para crear métodos que establecerán(set) y devolverán(get) el valor de la la propiedad de clase $prop1, añade el siguiente código

Nota — POO permite que los objetos se referencien a sí mismos usando $this. Cuando se trabaja dentro de un método, usa $this de la misma forma que utilizarías el nombre del objeto fuera de la clase

Para usar estos métodos, llámalos tal y como a las funciones nomales, pero primero, referencia el objeto al que pertenecen. Lee la propiedad de MyClass, cambia su valor, y léelo de nuevo haciendo las modificaciones mostradas abajo:

Recarga tu navegador, y verás lo siguiente:

"El poder de la POO se hace patente cuando se usan múltiples instancias de la
misma clase."

Cuando cargas los resultados en tu navegador, se leen como sigue:

Como puedes ver, la POO mantiene los objetos como entidades separadas, lo que hace más fácil la separación de diferentes trozos de código en lotes pequeños y relacionados.

Métodos Mágicos en POO

Para hacer el uso de objetos más fácil, PHP también provee un número de métodos mágicos, o métodos especiales que son llamados cuando ciertas acciones comunes ocurren dentro de los objetos. Esto permite a los desarrolladores llevar a cabo un número de tareas útiles con relativa facilidad

Usando Constructores y Destructores

Cuando un objeto es instanciado, es a menudo deseable establecer algunas cosas de inmediato. Para manejar esto, PHP nos da el método mágico __construct(), el cual es llamado automáticamente en cuanto un nuevo objeto es
creado.

Con el propósito de ilustrar el concepto de constructores, añade un constructor a MyClass que mostrará un mensaje siempre que una nueva instancia de la clase sea creada:

Nota — __CLASS__ devuelve el nombre de la clase desde la que es llamada; a esto es lo que se conoce como constante mágica. Hay muchas constantes mágicas disponibles, sobre la que puedes leer más en el manuel de PHP.

Recargando el archivo en tu navegador se producirá el siguiente resultado:

Para llamar a una función cuando el objeto es destruido, el método mágico __destruct() está disponible. Esto es útil para hacer limpieza de la clase (cerrar conexiones a la base de datos, por ejemplo).

Muestra un mensaje cuando el objeto es destruido definiendo el método mágico
__destruct() en MyClass:

Con un destructor definido, recargando el archivo file muestra la siguiente salida:

"Cuando se alcanza el final de un archivo, PHP libera automáticamente todos los recursos."

Para lanzar explícitamente el destructor, puedes destruir los objetos usando la
función unset():

Ahora los resultados cambian por lo siguiente cuando recargas tu navegador:

Convertir a un String

Para evitar errores si un script intenta escribir MyClass como una cadena, se usa otro método mágico llamado __toString().

Sin __troString(), intentar escribir el objeto como una cadena provoca un error fatal. Trata de usar echo para escribir el objeto sin usar un método mágico en su lugar:

Esto produce el siguiente resultado:

Para evitar este error, añade un método __toString():

En este caso, intentar convertir el objeto en una cadena acaba con una llamada al método getProperty(). Carga el script test en tu navegador para ver el resultado:

Consejo — Además de los métodos mágicos tratados en esta sección, hay otros muchos disponibles. Para una lista completa de los métodos mágicos, mira la página del manual PHP

Usando Herencia de Clase

Las clases pueden heredar los métodos y propiedades de otra clase usando la palabra reservada extends. Por ejemplo, para crear una segunda clase que extienda MyClass y añada un método, añadirías lo siguiente en tu archivo test:

En cuanto recargues tu archivo test en tu navegador, se mostrará lo siguiente:

Sobreescribiendo Propiedades y Métodos Heredados

Para cambiar el comportamiento de una propiedad o método existente en la nueva clase, simplemente sobreescríbelo declarando de nuevo en la nueva clase:

Esto cambia la salida en el navegador a:

Preservar la Funcionalidad Original del Método Mientras se Sobreescriben Métodos

Para añadir una nueva funcionalidad a un método heredado mientras se mantiene el método original intacto, usa la palabra reservada parent con el operador de resolución de ámbito (::):

Esto muestra el resultado tanto del constructor de la clase padre como el del constructor de la nueva clase:

Asignando el Ámbito de Propiedades y Métodos

Para añadir control sobre los objetos, se asigna un ámbito a los métodos y propiedades. Esto controla cómo y desde dónde se puede acceder a las propiedades y los métodos- Hay tres palabras reservadas de ámbito: public, protected, y private. Además de su ámbito, un método o propiedad puede ser declarado como static, lo que les permite ser accedidos sin una instanciación de la clase

"Para añadir control sobre objetos, a los métodos y propiedades se les asigna un ámbito."

Nota — El ámbito es una nueva característica de PHP 5. Para información sobre compatibilidad en POO con PHP 4, ver la página del manual de PHP.

Propiedades y Métodos Públicos

Todos los métodos y propiedades que has usado hasta ahora eran públicos. Esto significa que pueden ser accedidos desde cualquier parte, tanto desde el interior como el exterior de la clase.

Propiedades y Métodos Protegidos

Cuando una propiedad o método se declara protected, sólo puede ser accedido desde el interior de la propia clase o de sus hijas (clases que extiendan a la clase que contenga el método protegido)

Declara el método getProperty() como protegido en MyClass e intenta accederlo directamente desde fuera de la clase:

En cuanto intentes ejecutar este script, se mostrarán los siguientes errores:

Ahora, crea un nuevo método en MyOtherClass para llamar al método getProperty():

Esto genera el resultado deseado:

Propiedades y Métodos Privados

Una propiedad o método declarado private es accesible sólo desde el interior de la clase que lo define. Esto significa que incluso aunque una nueva clase extienda la clase que define la propiedad privada, esta propiedad o método no estarán disponibles ni siquiera en el interior de la clase hija.

Para demostrar esto, declara getProperty() como privada en MyClass, e intenta llamar a callProtected() desde
MyOtherClass:

Recarga tu navegador, y el siguiente error aparecerá:

Propiedades y Métodos Estáticos

Un método o propiedad declarado static puede ser accedido sin instanciar primero la clase; simplemente provee el nombre de la clase, el operador de resolución de ámbito, y el nombre de la propiedad o método.

"Uno de los mayores beneficios de usar propiedades estáticas es que mantienen sus valores almacenados a lo largo de la ejecución del script."

Para demostrar esto, añade una propiedad estática llamada $count y un método estático llamado plusOne() en MyClass. Después inserta un bucle do...while para aumentar el valor de $count mientras el valor sea menor que 10:

Nota — Cuando se acceden a propiedades estáticas, el símbolo de dolar
($) va después del operador de resolución de ámbito.

Cuando cargas este script en tu navegador, sale lo siguiente:

Comentando con DocBlocks (Bloques de documentación)

"El estilo de comentarios DockBlock es un método
ampliamente aceptado de documentación de clases."

Aunque no es una parte oficial de la POO, el estilo de comentarios DockBlock es un método ampliamente aceptado de documentar clases. A parte de proveer un estándar para
los desarrolladores para escribir código, también ha sido adoptado por muchos de los kits de desarrollo de software (SDKs) más populares como Eclipse y NetBeans, y se utilizará para generar sugerencias de código.

Un DocBlock se define usando un bloque de comentario que empieza con un asterisco adicional:

El poder real de los DocBlocks reside en la posibilidad de usar tags(etiquetas), que empiezan con el símbolo (@) inmediatamente seguido por el nombre de la etiqueta y el valor de la etiqueta. Las etiquetas de DocBlock permiten a los desarrolladores a definir autores para el archivo, la licencia para la clase, la información de la propiedad o el método, y otra información útil.

Las etiquetas más comunes se usan como sigue:

  • @author: El autor del elemento actual (como podría ser una clase, archivo, método, o cualquier pedazo de código) se lista usando esta etiqueta Se pueden usar múltiples etiquetas de autor en el mismo DocBlock si hay más de un autor involucrado. El formato del nombre de autor es John Doe <john.doe@email.com>
  • @copyright: Esto detalla el año y nombre del copyright del propietario de los derechos del elemento actual. El formato es 2010 Propietario de los Derechos.
  • @license: Esto enlaza con la licencia del elemento actual. El formato para la información de licencia es
    http://www.example.com/path/to/license.txt Nombre de la licencia.
  • @var: Mantiene el tipo y descripción de una variable o propiedad de clase. El formato es tipo elemento descripción.
  • @param: Esta etiqueta muestra el tipo y descripción de los parámetros de una función o método. El formato es tipo $nombre_del_elemento descripción_del_elemento.
  • @return: El tipo y descripción del valor de retorno de una función o método se detallan en esta etiqueta. El formato es tipo return elemento descripción.

Un ejemplo de clase comentada con DockBlocks tendría este aspecto:

Una vez analizas la clase anterior, los beneficios de los DocBlock son aparentes: todo está claramente definido de tal forma que el siguiente desarrollador que trate el código nunca tendrá que suponer qué hace un fragmento de código o qué debería contener.

Comparando Código de Orientación a Objetos y Procedural

En realidad no hay una forma correcta e incorrecta de escribir código. Como se ha dicho, esta sección resume un sólido argumento para adoptar una aproximación a la orientación a objetos en el desarrollo de software, especialmente en aplicaciones grandes.

Razón 1: Facilidad de Implementación

"Mientras que puede abrumar al principio, la POO en realidad otorga una aproximación más sencilla para tratar con datos."

Mientras que puede abrumar al principio, la POO en realidad otorga una aproximación más sencilla para tratar con datos. Dado que un objeto puede almacenar datos internamente, las variables no necesitan pasar de función en función para funcionar apropiadamente.

Además, dado que pueden existir simultáneamente múltiples instancias de la misma clase, tratar con grandes conjuntos de datos es infinitamente más fácil. Por ejemplo, imagina que tenemos información de dos personas siendo procesadas en un archivo. Sus nombres, trabajos, y edades.

La Aproximación Procedural

Aquí tenemos la aproximación procedural a nuestro ejemplo:

Cuando lo ejecutamos, el código muestra lo siguiente:

Mientras que este código no es necesariamente malo, hay un montón de cosas a tener en cuenta mientras se codifica. El array de los atributos de las personas afectadas debe ser pasado y devuelta en cada llamada a función, lo cual deja margen para el error.

Para reformar este ejemplo, sería deseable dejar el mínimo de cosas para el desarrollador como sea posible. Sólo la información absolutamente necesaria para la operación actual debería ser pasada a las funciones.

Aquí es donde la POO se impone y te ayuda a depurar las cosas.

La Aproximación con POO

Aquí está la aproximación con POO a nuestro ejemplo:

Esto muestra la siguiente salida en el navegador:

Hay una poco más de organización involucrada de cara a la aproximación orientada a objetos, pero tras definir la clase, crear y modificar personas es pan comido, la información de una persona no necesita ser pasada o devuelta desde los métodos, y sólo la información absolutamente esencial se pasa a cada método.

"La POO reducirá significativamente tu carga de trabajo si se implementa apropiadamente"

A pequeña escala, esta diferencia puede no parecer gran cosa, pero al crecer tus aplicaciones en tamaño, la POO reducirá significativamente tu carga de trabajo si se implementa apropiadamente.

Consejo — No todo necesita ser orientado a objetos. Una función rápida que maneja algo pequeño en un lugar dentro de la aplicación no necesita necesariamente estar envuelto en una clase. Usa tu mejor juicio al decidir entre aproximación con orientación a objetos y procedural.

Razón 2: Mejor Organización

Otro beneficio de la POO es cómo de bien  se presta a ser fácilmente empaquetado y catalogado. Cada clase puede ser contenida generalmente dentro de su propio archivo por separado, y si se usa una nomenclatura uniforme, acceder a las clases es extremadamente simple.

Asume que tieness una apliación con 150 clases que son llamadas dinámicamente a través de un archivo controlador en la raíz del sistema de archivos de tu aplicación. Todas las 150 clases siguen la nomenclatura class.classname.inc.php y reside en la carpeta inc de tu aplicación.

El controlador puede implementar la función de PHP _autoload() para acceder dinámicamente sólo a las clases que necesita llamar, en lugar de incluir todas las 150 clases en el archivo del controlador por si acaso o dar con alguna forma inteligente de incluir los archivos en tu propio código:

Teniendo cada clase en un archivo separado también hace el código más portable y más fácil de reusar en aplicaciones nuevas sin un montón de copia y pega.

Razón 3: Facilidad de Mantenimiento

Debido a la naturaleza más compacta de la POO cuando se usa correctamente, los cambios en el código son normalmente más fáciles de localizar y hacer que en un largo código espagueti de la implementación procedural.

Si un array particular de información añade un nuevo atributo, una parte de código de un software procedural podría requerir (en el peor de los escenarios) que el nuevo atributo deba ser añadido a cada función que use el array.

En una aplicación de POO podría ser potencialmente actualizada facilmente añadiendo una nueva propiedad y después añadiendo métodos que manejen dicha propiedad.

Muchos de los beneficios cubiertos en esta sección son fruto de la POO combinados con prácticas de programación NTR. Definitivamente es posible crear código procedural fácil de mantener que no cause pesadillas, y es igualmente posible crear un horrible código orientado a objetos. [Pro PHP y jQuery] intentarán demostrar una combinación de buenos hábitos de codificación junto a la POO para generar código que sea fácil de leer y mantener.

Resumen

En este punto, deberías sentirte cómodo con el estilo de programación orientado a objetos. Aprender POO es una gran manera de llevar tu programación al siguiente nivel. Cuando se implementa apropiadamente, la POO te ayudará a producir código fácil de leer, mantener y portable que te ahorrará (y a los desarrolladores con quien trabajes) horas de trabajo extra. ¿Estás atascado en algo que no se haya cubierto en este artículo? ¿Ya utilizas POO y tienes algún consejo para principiantes? ¡Compártelos en los comentarios!

Nota del Autor — Este tutorial es un fragmento de Pro PHP y jQuery (Apress, 2010).

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.