Está en la página 1de 46

PHP Orientado a Objetos

¿Por qué necesitamos clases y objetos? 4


Encapsulamiento, getters y setters en PHP 8
Herencia y abstracción con PHP 9
Interacción entre objetos 12
Repositorio 12
Interfaces y Polimorfismo 12
Repositorio 12
Notas 12
Diferencia entre clases abstractas e interfaces 14
Autocarga de clases y nombres de espacio con PHP 15
Repositorio 15
Continua aprendiendo 15
Autocarga de clases con Composer y PSR-4 15
Repositorio 15
Únete a la discusión 15
Repaso y solución a los ejercicios 15
Repositorio 15
Herencia: 16
Inyección de dependencias: 16
Refactorización: 16
Métodos VS propiedades: 16
Clases abstractas VS Interfaces: 16
Patrón Factory y Value Objects 17
Patrón Factory 17
Value Objects 17
Refactorización 17
Reducción de uso de condicionales IF y sentencias SWITCH 18
Repositorio 18
Null object 18
Herencia 18
Propiedades y métodos estáticos 18
Repositorio 18
Propiedades estáticas 18
Operador de resolución de ámbito 19
Métodos estáticos y código acoplado 19
Named constructors 19
Constructores semánticos e interfaces fluidas 20
Repositorio 20
Named constructors 20
Named constructors 20
Fluent interfaces 21
Qué son los facades y cómo implementarlos en tu proyecto 22
Repositorio 22
Notas 22
Actividad 22
Cómo declarar y usar constantes de clases 23
Repositorio 23
Notas 23
Uso de los métodos mágicos __get, __set, __isset y __unset con PHP 23
Repositorio 23
Notas 23
Llamadas dinámicas a métodos con PHP 24
Repositorio 24
Notas 24
Material relacionado 24
Llamadas a métodos mágicos con __call y __callStatic en PHP 25
Repositorio 25
Notas 25
Material relacionado 26
Uso de los métodos mágicos __toString y __invoke en PHP 26
Repositorio 26
Notas 26
Métodos mágicos __sleep y __wakeup en PHP 27
Repositorio 27
Notas 27
Continua aprendiendo: 28
Cómo clonar objetos y usar el método mágico __clone 29
Repositorio 29
Notas 29
Notas 29
Material relacionado 31
Iteración de objetos en PHP 31
Repositorio 31
Notas 31
Notas 32
¿Cuál es la diferencia? 33
Material relacionado 33
Objetos Inmutables en PHP 34
Repositorio 34
Notas 34
Material relacionado 34
Comparación entre objetos en PHP 34
Notas 35
Material relacionado 35
Traits en PHP 36
Notas 36
Conflictos de nombres de métodos 36
Material relacionado 37
Creación de macros en PHP usando traits, métodos estáticos y __call 38
Notas 38
Actividad 39
Material relacionado 39
Instalación y uso de componentes de terceros con Composer 39
Notas 39
Material relacionado 41
Desarrollo de clases y métodos con pruebas automatizadas 41
Notas 41
Material relacionado 42
Array Access en PHP – Parte 1 42
Repositorio 42
Notas 43
Material relacionado 44
Array Access en PHP – Parte 2 44
Repositorio 44
Compatibilidad con array_key_exists 44
Uso de ArrayAccess en el framework Laravel 45
Clases anónimas en PHP 45
Repositorio 45
Notas 46
¿Por qué necesitamos clases y objetos?
Aprender un framework como Laravel suena muy llamativo y emocionante, y realmente no
requieres más que de conocimientos básicos de PHP para comenzar. Sin embargo, si quieres crear
aplicaciones realmente profesionales y escribir un código de alta calidad, necesitarás aprender más a
detalle el lenguaje PHP y el paradigma de programación orientada a objetos del cual Laravel hace
uso extenso.
En Styde ya tenemos un curso de Primeros Pasos con Laravel (entre muchos otros cursos de este
framework) y tenemos un curso avanzado de creación de componentes para PHP que te explica
conceptos avanzados como la inyección de dependencias, uso de PHPUnit, etc.
Pero hoy quiero rebobinar un poco, y crear este curso dedicado a todos los desarrolladores que
quizás como tú, se confunden con los temas de OOP como clases abstractas o términos como
encapsulamiento, o quizás buscan la respuesta a una pregunta aún más sencilla:
¿Por qué necesitamos clases y objetos?
Repositorio
Ver el código de esta lección en GitHub
Notas
Notas por Sergio Ojeda.
¿Que es un objeto?
Pensar en objetos es muy parecido a como vemos el mundo, si observamos a nuestro alrededor todo
esta compuesto por objetos, sea una casa, un carro, una hoja, etc. Cada objeto está compuesto por
dos cosas fundamentalmente, sus propiedades y sus comportamientos. Por ejemplo, podemos decir
que un Teléfono tiene propiedades como color, modelo o compañía telefónica, y tiene
comportamientos como realizar llamadas, envío de mensajes de texto, entre otros. Podemos utilizar
esto como base para la Programación Orientada a Objetos, transformando un elemento de la vida
real en elementos utilizables dentro de la programación.
Como ya es sabido, un objeto aunque sea el mismo, puede tener distintos comportamientos o
propiedades, continuando con el ejemplo anterior, el objeto puede ser un Teléfono, pero existen una
gran cantidad de teléfonos de muchas marcas, colores, tamaños y características que lo hacen
distinto a los demás, esto define lo que es la identidad del objeto, porque aunque comparten
características similares, como las llamadas, encendido, apagado, entre otros, cada uno tiene algo
que lo hace diferente.
Los objetos dentro de la programación son muy parecidos a la realidad. Pues que un objeto en
programación tiene propiedades (o también llamados atributos) y comportamientos (que serían las
funciones también llamadas métodos).
Las Clases
Podemos ver las clases como una abstracción de un elemento de la vida real para transformarlos en
elementos utilizables dentro de la programación. Las clases están conformadas tanto por
propiedades (que son como variables dentro de la clase) como por métodos (que son como
funciones dentro de la clase).
Como se menciono anteriormente, las propiedades las podemos comparar con las variables dentro
de la clase, en el ejemplo del vídeo tenemos como propiedades de la Clase Persona el nombre y el
apellido

var $firstName, $lastName;

var $firstName, $lastName;


1

Un método es una acción realizada por un objeto, estos están definidos como las funciones de la
clase. Por ejemplo el método fullName me retorna el nombre completo de una Persona.

function fullName() { return $this->firstName . ' ' . $this->lastName; }

function fullName()
{
1 return $this-
2
3
>firstName . ' ' .
4 $this->lastName;
}

Se puede decir que las clases son solo plantillas cuyos métodos o acciones no serán ejecutados en
tanto no exista un objeto que requiera su aplicación.
Para crear una nueva instancia de un objeto tenemos la palabra reservada new:

$person1 = new Person('Duilio','Palacios');

$person1 = new Person('Duilio','Palacios');


1

Ahora veamos que funcion cumple el método constructor:

function __construct($firstName, $lastName) { $this->firstName = $firstName; $this->lastName = $lastName; }

function __construct($firstName, $lastName)


1 {
2
$this->firstName = $firstName;
3
4 $this->lastName = $lastName;
5 }

Dentro del código de un constructor se suelen asignar los valores de algunas o todas las propiedades
de dicho objeto, para conseguir que el objeto sea creado con valores iniciales. Por ende, un método
constructor se ejecuta cada vez que se instancia la clase. No es de carácter obligatorio contar con
uno, pero suelen ser bastante útiles. En nuestro ejemplo, cuando se inicia un objeto del tipo Persona
va asignar a las propiedades $firstName y $lastName con los datos que coloquemos cuando
instanciamos nuestro objeto.

$person1 = new Person('Duilio', 'Palacios');

$person1 = new Person('Duilio', 'Palacios');


1

Para asignar valores o referirnos a la propiedad dentro de una clase se utiliza $this, por ejemplo si
utilizamos $this->firstName nos referimos a la variable dentro de nuestra clase Persona.
Cada vez que se instancia una clase se crea un objeto nuevo:

$person2 = new Person('Ramon','Lapenze');

$person2 = new Person('Ramon','Lapenze');


1

Con esto creamos dos objetos del tipo persona, y cada uno tiene su propio nombre y apellido. De
esta manera podemos evitar la repetición de código.
Se puede acceder a los métodos de manera muy fácil, se utiliza la fecha (->) la cual nos permite
acceder a las propiedades o métodos de nuestra Clase.
echo "{$person1->fullName()} es amigo de {$person2->fullName()}";
echo "{$person1->fullName()} es amigo de {$person2→fullName()}";

Ejemplo
Hagamos un ejercicio con un Teléfono, que en este caso sería el objeto de la clase, algunas de las
características pueden ser modelo, color y compañía, por otro lado dentro de sus funciones tenemos
realizar llamadas y enviar mensajes. Partiendo de eso, podemos crear nuestro objeto:
/**
* Clase Telefono
*/
class Phone
{
var $model;
var $color;
var $company;

function __construct($model, $color, $company)


{
$this->model = $model;
$this->color = $color;
$this->company = $company;
}

function call()
{
return 'Estoy llamando a otro móvil';
}

function sms()
{
return "Estoy enviando un mensaje de texto";
}
}
$nokia = new Phone('Nokia', 'Blanco', 'Movistar');
Como se pudo observar, las características son parte de las propiedades del objeto, definidas en
variables, y las funciones son las acciones o métodos que dicho objeto puede realizar. Tenemos que
utilizar el símbolo -> para interactuar con dichas propiedades y métodos:
echo $nokia->call(); // Estoy llamando a otro móvil echo $nokia->color; // Imprimirá Blanco
echo $nokia->call(); // Estoy llamando a otro móvil
echo $nokia->color; // Imprimirá Blanco

Ejercicios Propuestos
1. Realiza una definición de algún objeto de tu preferencia, por ejemplo: Un carro. Tengo un
Toyota de color rojo, con cuatro puertas el cual puede acelerar y tocar la bocina.
2. A partir del ejercicio anterior, procede a crear una Clase con las propiedades y los métodos
que consideres que estén dentro de tu definición.
Encapsulamiento, getters y setters en PHP
Esta es la segunda lección de nuestro Curso de programación orientada a objetos en PHP, asegúrate
de haber visto la primera lección ¿Por qué necesitamos clases y objetos? antes de continuar.
Hoy vamos a hablar sobre uno de los objetivos más importantes de la Programación Orientada a
Objetos, el cuál es poder proteger y ocultar información, a dicho proceso se le denomina
encapsulamiento.
El encapsulamiento de datos previene que el desarrollador haga cambios inesperados al sistema,
como también ocultar la información para que no pueda ser modificada o vista por otras clases y
esto es muy útil pero además fácil de hacer, como aprenderemos en la lección de hoy.
¿Cómo accedemos a dicha información de forma segura? En el desarrollo de esta clase vamos a
explicarte cómo podemos modificar de forma segura las propiedades (o variables) de una clase y
cómo podemos presentar dicha información al usuario de una forma correcta con el uso de métodos
conocidos como Setters y Getters.
Repositorio
Ver el código de esta lección en GitHub
Recuerda tener siempre en cuenta:
Getter: Su función es permitir el obtener el valor de una propiedad de la clase y así poder utilizar
dicho valor en diferentes métodos.
Setter: Su función permite brindar acceso a propiedades especificas para poder asignar un valor
fuera de la clase.
exit($person1->firstName) //Imprime el valor y termina el script actual.
exit($person1->firstName) //Imprime el valor y termina el script actual.

Para tener una definición más clara de los niveles de acceso puedes dirigirte a la lección de
Encapsulamiento del curso teórico de OOP.
Ejercicios
Agrega validación adicional para que el usuario sólo pueda agregar nicknames que tengan al
menos 2 caracteres y no sean igual a su nombre o apellido.
Agrega la propiedad “fecha de nacimiento” a la clase persona, y que esta propiedad pueda
pasarse a través del constructor. Luego crea un método para obtener la edad del usuario
(getAge), por supuesto la edad la vas a calcular a partir de la fecha de nacimiento.
Herencia y abstracción con PHP
La herencia en programación orientada a objetos, nos permite tener clases que extiendan de otras,
heredando así sus propiedades y métodos no privados. En teoría esto puede sonar complicado, pero
en la práctica es muy sencillo como vamos a aprender en la clase de hoy.

La herencia en programación orientada a objetos, nos permite tener clases que extiendan de otras,
heredando así sus propiedades y métodos no privados. En teoría esto puede sonar complicado, pero
en la práctica es muy sencillo como vamos a aprender en la clase de hoy.
Repositorio
Ver el código de esta lección en GitHub
Notas
Recuerda que una clase puede heredar de otra usando la palabra reservada extends para heredar de
una clase:
class Child extends Parents {
//
}

Una clase Padre solo puede heredar sus variables y métodos con visibilidad publica (public) o
protegida (protected) y no privada (private) esto lo veremos con más calma más adelante.
class Parents {
protected $foo;
protected function bar()
{
//
}
public function diplay()
{
//
}
}
Para crear una clase Abstracta debes de utilizar la palabra reservada abstract antes de la palabra
class
abstract class Parents {
//
}

abstract class Parents {


//
}
Una clase abstracta solo puede heredar sus variables y métodos con visibilidad publica (public) o
protegida (protected) ademas de sus métodos abstractos(abstract).
abstract class Parents { abstract protected function foo() { // } abstract public function bar() { // } }

abstract class Parents {


abstract protected function foo()
{
//
}

abstract public function bar()


{
//
}
}
Las clases que heredan de otra clase pueden cambiar el comportamiento de la clase padre
sobreescribiendo sus métodos
class Parents {

public function say()


{
echo 'Hola!';
}
}

class Child extends Parents {

public function say()


{
echo 'Hola Mundo!';
}

$child = new Child();


$child->say(); // Hola mundo;

Finalmente hay que acotar que PHP no permite la herencia multiple, es decir que no puedes utilizar
extends de la siguiente forma:
class Chind extends Parent, Other {
//Esto no es válido!!!!
}

Pero de este tema hablaremos en lecciones siguientes.


Continua aprendiendo
Jerarquía en la programación orientada a objetos
Curso teórico de programación orientada a objetos
Interacción entre objetos
Una característica muy importante de la programación orientada a objetos es la capacidad que los
objetos tienen para interactuar con otros. En programación estructurada nuestro código se lee de
arriba hacia abajo y escribimos procedimientos de hasta cientos de líneas. En OOP dividimos las
responsabilidades de un procedimiento en pequeñas clases y métodos y logramos que un método
interactue con otros. De esta manera aunque ya no será posible leer nuestro código en línea recta,
podremos hacer cambios más fácilmente en el sistema, escribir pruebas, reusar código, etc.
Ahora bien aunque hayas aprendido a declarar clases y métodos, es muy posible que sigas teniendo
el paradigma de la programación estructura por mucho tiempo y que cometas ciertos errores que
afecten la calidad de tu proyecto y no te permitan aprovechar los beneficios de la OOP, es por ello
que en esta clase te enseñaré cómo puedes diseñar tus métodos para lograr una interacción correcta
entre objetos, siguiendo el principio “tell, don’t ask”. Además aprenderemos sobre la declaración
de tipos en PHP y veremos un repaso de herencia, getters y setters.
Repositorio
Ver el código de esta lección en GitHub
Pronto agregaremos más notas a esta lección.

Interfaces y Polimorfismo
La palabra polimorfismo significa “múltiples formas” y en programación orientada a objetos puede
tener varios significados, por ejemplo la habilidad que tiene un método dentro de un objeto con
interactuar con diferentes objetos de diferentes clases de la misma forma pero con resultados
diferentes. Esto se logra cuando creamos clases que tienen la misma interfaz (es decir los mismos
métodos públicos) pero se comportan de manera diferente.
En teoría suena complicado pero con los ejemplos del siguiente video lo aprenderás de manera muy
sencilla.
Repositorio
Ver el código de esta lección en GitHub
Notas
El polimorfismo es la habilidad de tomar multiples formas: imagina que tienes una Factura y la
factura requiere ser impresa como PDF, HTML o como texto plano. Quienes no comprenden estos
conceptos suelen hacer esto:
<?php class Invoice {} class HtmlInvoice extends Invoice {} class PdfInvoice extends Invoice {} class TextInvoice extends
Invoice {}

<?php

class Invoice {}
class HtmlInvoice extends Invoice {}
class PdfInvoice extends Invoice {}
class TextInvoice extends Invoice {}
Pero ¿Qué sucede si tenemos por ejemplo facturas para pago recurrente, para compra de un solo
producto, multiples productos, pagos a contados, pagos a crédito? No podemos seguir abusando de
la herencia:
<?php class RecurrentPaymentInvoice extends PdfInvoice {} //Esto ya es abuso de herencia y no tiene sentido

<?php

class RecurrentPaymentInvoice extends PdfInvoice {} //Esto ya es abuso de herencia y no tiene sentido

Aquí lo mejor es que una factura sea una sola clase:


class Invoice y la funcionalidad que pueda cambiar (tomar multiples formas, es decir, polimórfica)
se exprese como interfaces que puedan ser: implementadas en clases concretas, instanciadas e
inyectadas a la clase, como piezas de lego o de un automóvil que puedas reemplazar:

<?php interface ReportFormat {} interface InvoiceType {} interface PaymentType {}

<?php
1
2
interface ReportFormat {}
3
4 interface InvoiceType {}
5 interface PaymentType {}

Con esto ya es posible crear clases puntuales (para reportes, tipos de pago, tipos de factura, incluso
tipo de cliente, etc.) que ya no extenderán de Invoice sino que implementarán una interfaz
específica:

<?php class HtmlReportFormat implements ReportFormat

<?php
1
2
3 class HtmlReportFormat implements ReportFormat

Ahora si quieres una factura para pagos recurrentes, a crédito y en HTML ya no tienes que
enredarte con una herencia interminable ni repetir código, sino simplemente componerla, por
ejemplo de la siguiente forma (o usando el patrón factory que verás más adelante):
<?php $invoice = new Invoice(new RecurrentInvoice(Type::Monthly), new CreditPayment(Carbon::format('3
days')); $invoice->reportWith(new HtmlReport()); //o:
new HtmlReport($invoice);
<?php
1
2 $invoice = new Invoice(new RecurrentInvoice(Type::Monthly), new
3 CreditPayment(Carbon::format('3 days'));
4
5 $invoice->reportWith(new HtmlReport()); //o: new HtmlReport($invoice);
Advertencia: todo esto es un ejemplo inventado que podría adaptarse o no a un caso real, queda de
parte de cada desarrollador hacer el análisis correspondiente a cada problema específico.
Diferencia entre clases abstractas e interfaces
La interfaz es sólo un “contrato” que no contiene código. Como has podido ver en el video en la
interfaz sólo se define el encabezado de los métodos que deben ser implementados por la clase que
implemente dicha interfaz.
Una clase abstracta por el contrario es algo intermedio entre una clase y una interfaz: dado que
también contiene un “contracto” en este caso métodos abstractos que deben ser implementados por
la clase hija, pero también contiene métodos concretos con código. Más adelante veremos más
ejemplos de uso de clases abstractas.
Estas notas fueron agregadas para responder a dudas comunes de nuestros usuarios, si tienes otra
pregunta específica de este curso por favor hazla en el canal #php de nuestro Slack:
Autocarga de clases y nombres de espacio con
PHP
Tan importante como aplicar buenas prácticas y patrones de diseño en nuestro código, es
organizarlo en archivos de forma coherente. El estándar en PHP es crear un archivo por clases y
luego utilizar una función de autocarga (autoload) para cargar dichas clases. Además de ver esto en
la lección de hoy, aprenderás qué son los nombres de espacio (namespaces), cómo usarlos y porqué
son importantes

Repositorio
Ver el código de esta lección en GitHub
Pronto agregaremos más notas a esta lección.
Continua aprendiendo
Autocarga (autoload) de clases con PHP
Nombres de espacio en PHP

Autocarga de clases con Composer y PSR-4


Hace unos años, cada framework de PHP utilizaba las capacidades de auto-carga de PHP de forma
diferente. Esto llevaba a inconsistencias y a que resultara realmente difícil combinar unos
componentes o paquetes de PHP con otros. Afortunadamente hoy tenemos la recomendación de
estándar PSR-4 y además el manejador de dependencia Composer que también se encarga de
autocargar nuestras clases, y esto es lo que veremos en la clase de hoy.

Repositorio
Ver el código de esta lección en GitHub
Pronto agregaremos más notas a esta lección.
Únete a la discusión

Repaso y solución a los ejercicios


En la lección de hoy veremos un repaso de los conceptos de programación orientada a objetos que
hemos aprendido hasta ahora como PSR-4, herencia, clases abstractas, inyección de dependencias y
refactorización. Además veremos la solución a los principales ejercicios planteados durante la
lección 5.

Repositorio
Ver el código de esta lección en GitHub
Herencia:
Cuando trabajamos con herencia algunas veces notaremos que un método pertenece a una clase
padre o por el contrario no pertenece a la clase padre sino a la clase hija. Una manera sencilla de
deducir esto es preguntarte ¿Esta funcionalidad la necesitan todas las clases que heredan de ___ o
sólo una clase puntual? Si la respuesta es todas o la mayoría, puedes colocar la funcionalidad en la
clase padre, de lo contrario sitúala en la clase hija. Aunque a veces no necesitamos herencia en lo
absoluto sino composición.
Inyección de dependencias:
Con la inyección de dependencias podemos “componer” un objeto (en nuestro ejemplo una unidad)
para que aún siendo de la misma clase Unit pueda tener características totalmente diferentes (en
nuestro ejemplo armas o armaduras distintas). Este concepto lo seguiremos viendo más adelante.
Constructores y setters: podemos pasar dependencias (objetos) u otros valores a un objeto a través
de su constructor o a través de métodos setters.
Refactorización:
Es el término que usamos cuando cambiamos código para que mantenga la misma funcionalidad
pero esté más ordenado, sea más fácil de entender, mantener y extender.
Métodos VS propiedades:
Recuerda que las propiedades nos dan sólo un valor, mientras que con el método podemos
encapsular comportamiento.
Clases abstractas VS Interfaces:
Con ambas podemos forzar que las clases que extiendan de la clase abstracta o implementen de la
interfaz cumplan con un “contrato”. La diferencia es que las clases abstractas nos permiten agregar
funcionalidad extra (porque es una clase padre) y las interfaces sólo representan un contrato.
Algunas veces nos daremos cuenta que necesitamos una en vez de la otra, como veremos en una
lección más adelante.
***
En las siguientes lecciones seguiremos evolucionando nuestro juego para seguir otras buenas
prácticas y explicarte más patrones de diseño y técnicas de OOP y refactorización.
Patrón Factory y Value Objects
En la lección de hoy vamos a aprender sobre un par de patrones de la programación orientada a
objetos como lo son Factory y Value Object. También aprenderemos que muchas veces podemos
aplicar refactorización de nuestro código para simplificarlo en vez de hacerlo más complejo

En la lección de hoy vamos a aprender sobre un par de patrones de la programación orientada a


objetos como lo son Factory y Value Object. También aprenderemos que muchas veces podemos
aplicar refactorización de nuestro código para simplificarlo en vez de hacerlo más complejo.
Repositorio
Ver el código de esta lección en GitHub
Patrón Factory
En OOP, factory se refiere a un objeto o método que tiene por objetivo crear o instancias otros
objetos.
Esto es una buena práctica y no debe confundirse con el abuso del operador new dentro de clases.
Más sobre el tema en nuestro curso avanzado de creación de componentes con PHP.
Value Objects
Los value objects nos permiten agrupar grupos de valores que tienen sentido juntos pero no tienen
sentido separados. Por ejemplo:
Dinero: new Money(50, 'USD'); // cantidad y tipo de moneda
Coordenadas: new Coordinates('38.898648N', '77.037692W'); // latitud y longitud
Fecha: new Date(2016, 07, 21); //año, mes, día
Entre muchos otros.
Refactorización
Como habrás notado en esta lección, refactorizar no significa complicar el código, sino adaptarlo a
la lógica y requerimientos de nuestra aplicación, y esto implica muchas veces simplificar el código,
por ejemplo los cambios en la forma como manejamos las dependencias a través de polimorfismo
para las armas y armaduras de nuestro juego de ejemplo hizo innecesaria la herencia en la clase
Unit y este tipo de cambios sucede también muy a menudo en aplicaciones reales.
Al refactorizar tu código debes ser muy cuidadoso con no romper la funcionalidad
existente de tu aplicación, por ejemplo si estás eliminando una jerarquía asegúrate de
reemplazar las subclases en otras partes de tu app y de que realmente no son necesarias,
etc. Este tema lo veremos más adelante en uno nuevo curso de refactorización.

***
En la lección siguiente aprenderemos cómo utilizando OOP podemos reducir la cantidad de código
estructurado (como condicionales y sentencias switch) de nuestra aplicación.
Reducción de uso de condicionales IF y
sentencias SWITCH
Cuando trabajamos con programación estructurada, tomamos decisiones en nuestro código
utilizando condicionales IF o sentencias SWITCH, pero cuando trabajamos con programación
orientada a objetos, podemos desarrollar de manera que sean objetos y no decenas de condicionales
o switch / case los que tomen las decisiones sobre cómo se debe procesar nuestro programa. Por
ejemplo: cuánto descuento se le debe aplicar a un cliente. Esto lo vamos a ver en la lección de hoy
con un par de ejemplos sencillos pero muy útiles y fáciles de entender.

Repositorio
Ver el código de esta lección en GitHub
Null object
Un null object es una especie de placeholder con el cuál podremos evitar tener que preguntar si un
objeto está presente o no, dado que el objeto siempre estará presente así la versión del mismo no
cause ningún efecto sobre el programa.
Herencia
Podemos utilizar herencia para colocar los condicionales necesarios dentro de la clase padre y así en
las subclases no tendremos más que sobre-escribir los métodos correspondientes. Veremos más
sobre esto en una lección siguiente.
***
Con esto finalizamos la parte 1 de este curso, en la segunda parte veremos más características de la
OOP en PHP como son métodos y propiedades estáticas, métodos mágicos y más.

Propiedades y métodos estáticos


Para comenzar la segunda parte de nuestro curso de programación orientada a objetos, te enseñaré
no sólo a crear y usar métodos y propiedades estáticos, sino también a cuando es conveniente su uso
y cuando no y porqué. También aprenderemos sobre el uso del operador de ámbito ::

Repositorio
Ver el código de esta lección en GitHub
Propiedades estáticas
Mientras que los valores de las propiedades que hemos visto hasta ahora pertenecen a la instancia
de un objeto, una propiedad estática forma parte de la clase:
class Person {

protected static $name;

public function __construct($name)


{
static::$name = $name;
}

public function getName()


{
return static::$name;
}

$person1 = new Person('Duilio');


$person2 = new Person('Ramon');

$person1->getName(); // retornará Ramon

Quiere decir que todos los objetos que accedan a dicha propiedad estática podrán leer y modificar el
mismo valor, y esto la mayoría de las veces no es conveniente y puede traer resultados inesperados
y errores más difíciles de depurar.
Incluso en casos donde realmente queremos compartir una información a través de todo el sistema,
es mejor utilizar un contenedor de inyección de dependencias, como aprenderás en el curso
avanzado de PHP: creación de componentes.
Operador de resolución de ámbito
Para llamar a métodos estáticos, acceder a propiedades estáticas o constantes, usamos el operador
de resolución de ámbito ::. Ejemplos:
Str::camelCase('words_with_underscores'); debería retornar: wordsWithUnderscores
Unit::MAX_DAMAGE
Diccionario::$words
Métodos estáticos y código acoplado
Cuando llamamos a un método estático dentro de un método de otra clase, estamos atando una clase
a otra. En el ejemplo de la lección, ahora nuestra clase Attack requiere obligatoriamente de la clase
Styde\Translator debido al llamado a Translator::get() mientras que Armor y Weapon son
reemplazables dentro de la clase Unit puesto que se pasan por inyección de dependencias. Verás
más sobre este tema en nuestro curso avanzado de PHP: creación de componentes.
Named constructors
Los métodos estáticos son bastante útiles para crear los llamados named constructors, como por
ejemplo:
Unit::createSoldier('Silence') es el equivalente a new Soldier('Silence', new BasicSword());
Carbon::now() es el equivalente a new Carbon();
***
En las siguientes 2 lecciones aprenderás sobre buenas prácticas y trucos en el uso de métodos
estáticos.
Constructores semánticos e interfaces fluidas
A pesar de todo, los métodos estáticos tienen una serie de utilidades interesantes y hoy te voy a
explicar sobre una de ellas, que en inglés se denomina “named constructors” y nosotros podríamos
traducir por constructores semánticos, además veremos sobre los “fluent interfaces” o interfaces
fluidas que son bastante usadas dentro del framework Laravel.

Repositorio
Ver el código de esta lección en GitHub
Named constructors
Para crear un constructor semántico sólo tienes que crear un método estático que cree y retorne una
nueva instancia de una clase:

public static function createSoldier($name)


{
return new Unit($name, new BasicSword)
}

Aunque en el video no pasé el parámetro $name a través del método, fíjate cómo es perfectamente
posible. Así que te invito a hacer este cambio y a crear otro método para otro tipo de unidad.

public static function newAdmin(array $attributes)


{
$admin = new User($attributes);
$admin->role = 'admin'

return $admin;
}

A pesar de todo, los métodos estáticos tienen una serie de utilidades interesantes y hoy te voy a
explicar sobre una de ellas, que en inglés se denomina “named constructors” y nosotros podríamos
traducir por constructores semánticos, además veremos sobre los “fluent interfaces” o interfaces
fluidas que son bastante usadas dentro del framework Laravel.
Repositorio
Ver el código de esta lección en GitHub
Named constructors
Para crear un constructor semántico sólo tienes que crear un método estático que cree y retorne una
nueva instancia de una clase:

public static function createSoldier($name) { return new Unit($name, new BasicSword) }

1 public static function createSoldier($name)


2 {
3 return new Unit($name, new
4 BasicSword)
}

Aunque en el video no pasé el parámetro $name a través del método, fíjate cómo es
perfectamente posible. Así que te invito a hacer este cambio y a crear otro método para
otro tipo de unidad.

public static function newAdmin(array $attributes) { $admin = new User($attributes); $admin->role = 'admin'
return $admin; }

public static function newAdmin(array $attributes)


1 {
2 $admin = new User($attributes);
3
$admin->role = 'admin'
4
5
6 return $admin;
7 }

Como aprendiste en una lección anterior, un named constructor es a su vez un método factory.
Fluent interfaces
Para crear interfaces fluidas sólo tienes que recordar retornar $this luego de cada función. Las
interfaces fluidas suelen usarse para métodos que modifican el estado de un objeto (como un setter).
function setArmor(Armor $armor)
{
$this->armor = $armor;

return $this;
}

function setArmor(Armor $armor)


{
$this->armor = $armor;

return $this;
}

***
En la siguiente lección aprenderemos sobre el uso de métodos estáticos en la creación de “facades”.

Qué son los facades y cómo implementarlos en


tu proyecto
El uso de métodos estáticos es muy sencillo puesto que nos permite invocar a un método en
cualquier lugar de nuestro sistema, sin tener que preocuparnos por inyectar dependencias y ni
siquiera por crear una nueva instancia de una clase. Pero esta facilidad de uso viene con un costo:
terminamos con un sistema menos flexible y más acoplado. Aquí es donde entra el concepto de
facades en PHP, ideado por Taylor Otwell para Laravel 4, las cuáles son el punto intermedio entre
una buena arquitectura y una interfaz fácil de usar como aprenderás en esta lección.

Repositorio
Ver el código de esta lección en GitHub
Notas
Por Clemir Rondón.
Los principios SOLID, acrónimo de Single responsibility, Open-closed, Liskov substitution,
Interface segregation and Dependency inversion, representan cinco principios básicos de la
programación orientada a objetos.
En caso que quieras eliminar el archivo helpers.php recuerda eliminarlo también del archivo
composer.json y, luego ejecuta en consola:
composer dump-autoload

Para guardar el contenido del mensaje del Log en un archivo usa el


método file_put_contents de PHP con la bandera FILE_APPEND para en caso que ya el
archivo exista, añada la información en él, en vez de sobrescribirlo.
El principio SOLID: Open-closed (principio abierto/cerrado) establece que las clases u otra
entidad de software deben estar abiertas para su extensión y cerradas para su modificación.
El principio SOLID Dependency inversion (principio de inversión de la dependencia) nos
indica que debemos depender de abstracciones en vez de implementaciones concretas.
En el curso Curso de creación de componentes para PHP y Laravel puedes estudiar cómo el
framework Laravel implementa la inyección de dependencias, facades y muchos otros
temas que te ayudarán a entender cómo funciona Laravel por dentro.
Actividad
Implementa el concepto de facade para la clase translator que se desarrolló en la lección Métodos y
propiedades estáticos.
***
En la siguiente lección aprenderemos sobre el uso de constantes en PHP.

Cómo declarar y usar constantes de clases


En esta lección aprenderás a declarar constantes dentro de tus clases y a usarlas en cualquier lugar
de tu aplicación. Además hablaremos del anti-patrón de números mágicos, y algunos adelantos de la
versión 7.1 de PHP.

Repositorio
Ver el código de esta lección en GitHub
Notas
Pronto agregaremos notas a esta lección.
***
En la siguiente parte de este curso aprenderemos sobre el uso de métodos mágicos en PHP y
algunos trucos usados por el ORM Eloquent de Laravel

Uso de los métodos mágicos __get, __set,


__isset y __unset con PHP
PHP es un lenguaje muy dinámico y ofrece a los desarrolladores la posibilidad de declarar cualquier
lógica para acceder a propiedades o llamar a métodos dentro de una clase, aunque estos no estén
definidos previamente. Esto es lo que se conoce como métodos mágicos y algunos componentes de
PHP como por ejemplo el ORM Eloquent de Laravel, hacen uso de esta característica para
mostrarnos una API más dinámica y fácil de usar, y por supuesto este tema lo veremos a partir de
hoy en nuestro curso de programación orientada a objetos con PHP.

Repositorio
Ver el código de esta lección en GitHub
Notas
Por Clemir Rondón.
Puedes trabajar con las propiedades dinámicamente, por ejemplo, si se llama a $this-
>$key = $value; PHP está considerando a $key como una variable que será evaluada
antes de asignarle un valor.
Los métodos mágicos en PHP son aquellos métodos especiales que se llaman
automáticamente. Estos comienzan con el símbolo (__) seguido de una palabra
reservada tales como:__construct, __get, __set, __isset, etc. Estos debe ser
declarados y definidos por el desarrollador dentro de la clase y no serán llamados
explícitamente sino que se invocarán según el evento que ocurra.
__get() es el método mágico con el cual podemos obtener el valor de una propiedad
de una clase dinámicamente, cuando ésta es inaccesible (la propiedad está declarada
como private o protected) o no existe en la clase.
public __get ( string $name )

__set() es el método mágico que PHP llamará automáticamente (si está declarada en la clase)
cuando queremos definir una propiedad inaccesible o inexistente. Este método recibe dos
argumentos: el nombre de la propiedad que intentas acceder y el valor que le quieres asignar.

public __set (string $name, mixed $value)


Llamadas dinámicas a métodos con PHP
Además de disponer de métodos mágicos, PHP posee mecanismos para comprobar si un método
está definido en una clase y llamarlo aunque el nombre de dicho método sea variable, y esta es otra
de las técnicas que usa el ORM Eloquent para crear los modificadores de atributos get*Attribute y
set*Attribute, como veremos en la lección de hoy.

Repositorio
Ver el código de esta lección en GitHub
Notas
Por Clemir Rondón.
En la lección Herencia y abstracción con PHP puedes repasar sobre por qué usamos
una clase abstracta para la clase Model.
Por defecto, si una función en PHP se omite el return, el valor retornado será NULL.
Con la función de PHP method_exists() podemos comprobar si existe un método de una
clase, la cual recibe como argumentos el objeto o nombre de la clase y el nombre del método
a evaluar.
Cuando una cadena o string contiene variable escalar, un elemento de un arreglo o la
propiedad de un objeto que queremos sea evaluada podemos usar la sintaxis compleja de
PHP, encerrando entre llaves la expresión a evaluar:
"<p>Nickname: {$user->nickname}</p>"
Puedes estudiar cómo la clase Model del framework Laravel implementa los modificadores
de atributos vistos en esta lección.
Material relacionado
Uso de los métodos mágicos __get, __set, __isset y __unset con PHP
Encapsulamiento, getters y setters en PHP

Llamadas a métodos mágicos con __call y


__callStatic en PHP
PHP nos permite interactuar con propiedades de objetos aunque éstas no estén definidas dentro de
la clase, a través del uso de los métodos mágicos __get, __set, etc. como aprendimos en la lección
anterior. Pero… ¿No sería genial si además pudiésemos interactuar con métodos dinámicos aunque
estos no estén definidos en la clase? Esto quizás nos pueda ser útil para desarrollar algunas API y
afortunadamente es posible con el uso de __call y __callStatic que veremos en detalle en la lección
de hoy.
Repositorio
Ver el código de esta lección en GitHub
Notas
Por Clemir Rondón.
__call() es el método mágico de PHP que se invocará cuando se intenta llamar a un método
que no está definido en el objeto.
__callStatic() es el método mágico que se invocará cuando se intenta llamar a un inaccesible
o no disponible método en el contexto de una clase, es decir, estamos llamando un método
estático que no existe en la clase.
Tanto __call() como __callStatic() reciben dos argumentos: un string o cadena con el
nombre del método y un array que contiene los argumentos que se están llamando con el
método.
Toma en cuenta que siempre que definas el método __callStatic() en la clase, éste debe ser
también un método estático, es decir,
public static __callStatic (string $name, array $arguments)

Un ejemplo básico del uso de estos métodos mágicos es:


class UnaClase
{
public function __call($metodo, array $args)
{
var_dump($metodo, $args);
}

public static function __callStatic($metodo, array $args)


{
var_dump($metodo, $args);
}
}

$unObjeto = new UnaClase;

//Llama al método mágico __call


$unObjeto->unMetodo('Un argumento', 'otro argumento');

//Llama al método mágico __callStatic


UnaClase::unMetodo('todos', 'los', 'argumentos');

Con sprintf de PHP podemos devolver una cadena según un formato dado.
Como PHP no verifica que el método llamado, que invoca a los métodos mágicos __call() o
__callStatic(), necesita de al menos un argumento, entonces se puede lanzar una excepción
para dar mayor información al momento de la depuración o para ayudar al entendimiento de
la clase y sus métodos.
Recuerda retornar $this luego de cada función para crear interfaces fluidas como vimos en la
lección Constructores semánticos e interfaces fluidas.
Para el ejemplo de la lección se usó el método mágico __callStatic() para crear un nodo
HTML, es decir, llamamos un método estático cuyo nombre es la etiqueta que queremos
crear, por ejemplo:
HTMLNode::input();
y para agregarle los atributos y su correspondiente valor al nodo HTML se usó el método mágico
__call(), es decir, encadenamos un método con un argumento, donde el método es el atributo y el
argumento es su valor, por ejemplo:
HTMLNode::input()
->name('content')
→type('text');
Material relacionado
Uso de los métodos mágicos __get, __set, __isset y __unset con PHP
Autocarga de clases y nombres de espacio con PHP
Propiedades y métodos estáticos

Uso de los métodos mágicos __toString y


__invoke en PHP
En la lección de hoy aprenderemos a usar 2 nuevos métodos mágicos con PHP. Primero el método
__toString el cual nos permite transformar un objeto en una cadena, y segundo el método __invoke
que nos permite “invocar” o llamar a un objeto como si se tratara de una función. Todo esto junto
con algunos tips adicionales lo podrás ver detalladamente en el siguiente video tutorial:

Repositorio
Ver el código de esta lección en GitHub

Notas
Por Clemir Rondón
Las lecciones anteriores sobre métodos mágicos:
Uso de los métodos mágicos __get, __set, __isset y __unset con PHP
Llamadas dinámicas a métodos con PHP
Llamadas a métodos mágicos con __call y __callStatic en PHP
Con el método mágico __toString() una clase puede decidir qué comportamiento tendrá
cuando sea usada como si fuera una cadena o transformada en una cadena.
Importante: el método __toString() no debe lanzar una excepción pues se producirá un
error fatal.
Si estás usando PHP 7 sabrás que puedes usar el operador de fusión de null (??) , donde en
vez de escribir:

$attribute = isset($this->attributes[$name]) ? $this->attributes[$name] : null;


$attribute = isset($this->attributes[$name])
1
? $this->attributes[$name]
2
3 : null;

Puedes usar:

$attribute = isset($this->attributes[$name]) ?? null;

$attribute = isset($this->attributes[$name]) ?? null;


1

Cuando se intenta llamar a un objeto como si fuera una función se invoca


al método __invoke.

Métodos mágicos __sleep y __wakeup en PHP


La serialización es una técnica que nos permite convertir un valor, por ejemplo un objeto, en una
representación que facilite su almacenamiento en una base de datos, en un archivo o su
transferencia a través de la red, como en el caso de una API. En esta lección aprenderás a trabajar
con los métodos mágicos __sleep() y __wakeup() que son llamados cuando un objeto en PHP es
serializado y deserializado.
Repositorio
Ver el código de esta lección en GitHub

Notas
Por Clemir Rondón
La serialización de objetos en PHP se realiza con la función serialize() que devuelve un string que
contiene un flujo de bytes que representa el valor que se pueda almacenar en PHP, esto sin perder
su estructura y tipo.
Cuando el método __sleep() está definido en una clase, éste será llamado antes de realizar la
serialización con el fin de limpiar el objeto y serializar solo lo que se necesite. Este método no
acepta ningún argumento y debe devolver un array con los nombres de las propiedades del
objeto que deben ser tomadas en cuenta al serializarlo. Por ejemplo:
public function __sleep()
{
return ['attributes', 'table'];
}

Es decir, si no quieres que una propiedad en particular del objeto sea serializada, se debe omitir en
el array que se está retornando. Recuerda además que solo se serializan las propiedades de un
objeto, no sus métodos.
Un objeto serializado sigue la siguiente estructura:
O:strlen(nombre del objeto):"nombre del objeto":tamaño del objeto:{s:strlen(nombre de propiedad):
"nombre de propiedad":s:strlen(valor propiedad):"valor de propiedad";(repite por cada propiedad)}

Por ejemplo:
O:10:"Styde\User":1{s:13:"*attributes";a:2{s:4:"name";s:6:"Duilio";s:5:"email";s:15:"admin@styd
e.net"}}

Con el resultado obtenido de la función serialize() podemos persistirlo en la base de datos o


almacenarlo en un archivo como se hizo en la lección con la función file_put_contents de PHP
La función complementaria a serialize() es unserialize(), es decir, que nos permite reconstruir una
variable serializada a un valor PHP. En cuyo caso, si el valor es un objeto se ejecutará el método
mágico __wakeup() (si dicho método está definido en la clase), con la finalidad de realizar
operaciones de reinicialización o de restablecimiento que pudieron haberse dejado a un lado en el
proceso de serializar el objeto.
El método __wakeup() no recibe ningún parámetro ni devuelve nada, simplemente realiza las
operaciones necesarias luego de deserializar el objeto, como por ejemplo, hacer un llamado a la
base de datos para recuperar las propiedades que fueron omitidas al serializarlo.
Como alternativa al método mágico __sleep y __wakeup se puede usar la interface Serializable de
PHP para el proceso de serialización de un objeto.

Continua aprendiendo:
Autocarga de clases y nombres de espacio con PHP
Autocarga de clases con Composer y PSR-4
Uso de los métodos mágicos __toString y __invoke en PHP

Cómo clonar objetos y usar el método mágico


__clone
En la lección siguiente aprenderemos más sobre cómo los objetos colaboran y trabajan entre sí
cuando se pasa un objeto como argumento del método de otro objeto, además aprenderemos cómo
clonar objetos y sobre el uso del método mágico __clone:

Repositorio
Ver el código de esta lección en GitHub

Notas
Por Clemir Rondón
En esta lección se sigue trabajando con la clase User que se empezó a trabajar en Uso de los
métodos mágicos __get, __set, __isset y __unset con PHP
Como recomendación evita usar condicionales else para simplificar tu código, es decir, en vez de
hacer:
if ($esCorrecto) {
//proceso
} else {
//otro proceso
}

Te recomendamos escribir lo siguiente:


if (! $esCorrecto) {
// finaliza con un return o una excepción.
}
// proceso
En la lección siguiente aprenderemos más sobre cómo los objetos colaboran y trabajan entre sí
cuando se pasa un objeto como argumento del método de otro objeto, además aprenderemos cómo
clonar objetos y sobre el uso del método mágico __clone:

Repositorio
Ver el código de esta lección en GitHub

Notas
Por Clemir Rondón
En esta lección se sigue trabajando con la clase User que se empezó a trabajar en Uso de los
métodos mágicos __get, __set, __isset y __unset con PHP
Como recomendación evita usar condicionales else para simplificar tu código, es decir, en vez de
hacer:

if ($esCorrecto) { //proceso } else { //otro proceso }

if ($esCorrecto) {
1 //proceso
2
} else {
3
4 //otro proceso
5 }

Te recomendamos escribir lo siguiente:

if (! $esCorrecto) { // finaliza con un return o una excepción. } // proceso

if (! $esCorrecto) {
1 // finaliza con un return o una excepción.
2
3
}
4 // proceso
Por otro lado, con la función array_shift de PHP obtienes y eliminas el primer elemento de un array.
Para repasar sobre el uso del método parent::__construct puedes ver la lección Interacción entre
objetos.
Los objetos son pasados por referencia, ya sea cuando hacemos asignación o cuando son pasados
a través de un método, es decir, no funciona como una variable que cuando hacemos $b = $a, $b
contiene el valor que tiene $a, sino que al hacer $objeto2 = $objeto1 estamos guardando es la
referencia al objeto original, es decir, que $objeto1 y $objeto2 están apuntando al mismo espacio de
memoria, por tanto, si se cambia una propiedad, ésta también cambiaría en el objeto original.
Así que si queremos clonar un objeto, es decir, duplicarlo sin que altere el original, debemos usar la
palabra reservada clone de PHP:
$objetoCopia = clone $objeto;

Con ello estamos creando $objetoCopia con en un nuevo espacio de memoria con las mismas
propiedades que tiene $objeto.
Si la clase del objeto tiene definido el método mágico __clone entonces se invocará para realizar los
cambios necesarios a las propiedades del objeto clonado.
Nota adicional: no se puede llamar al método mágico __clone directamente, en este caso __clone
solo se invocará cuando se use la palabra reservada clone.
Con esta lección terminamos de estudiar los principales métodos mágicos en las clases de PHP, si
quieres conocer el resto puedes hacerlo desde la documentación de PHP:
__destruct()
__set_state()
__debugInfo()
Si aún tienes dudas sobre este tema, por favor escríbenos para complementar el material.
Nos vemos en la parte 4 del curso.

Material relacionado
Uso de los métodos mágicos __get, __set, __isset y __unset con PHP
Llamadas dinámicas a métodos con PHP
Llamadas a métodos mágicos con __call y __callStatic en PHP
Uso de los métodos mágicos __toString y __invoke en PHP
Métodos mágicos __sleep y __wakeup en PHP

Iteración de objetos en PHP


A partir de PHP 5 es posible iterar objetos como si se tratara de un array asociativo. En este caso la
iteración se hará por defecto sobre las propiedades públicas del objeto. Pero en algunos
casos queremos un comportamiento diferente y para ello PHP ofrece 2 interfaces: Iterator
y IteratorAggregate las cuales aprenderemos a usar en la siguiente lección.
Repositorio
Ver el código de esta lección en GitHub

Notas
Por Clemir Rondón.
La iteración es el proceso de recorrer una lista de elementos. Con PHP se puede iterar objetos
usando la sentencia foreach y por defecto, se podrá acceder a todas propiedades del objeto que
tengan visibilidad pública.
Es decir, si quisieramos iterar también sobre las propiedades del objeto con visibilidad protected o
private tendríamos que hacerlos públicos, pero esto iría en contra del encapsulamiento en la
programacion orientada a objetos.
La solución a esto es usar un iterador, el cual es un objeto que puede recorrer una lista. Para ello
PHP tiene una Biblioteca Estándar (SPL por las siglas de Standard PHP Library en inglés) que nos
proporciona una colección de interfaces y clases pensadas para solucionar problemas comunes.
Así que en caso de iterar un objeto podemos implementar una de las interfaces de la biblioteca
Estándar de PHP con las cuales se le permite a una clase decidir qué y cómo sus objetos serán
iterados:
A partir de PHP 5 es posible iterar objetos como si se tratara de un array asociativo. En este caso la
iteración se hará por defecto sobre las propiedades públicas del objeto. Pero en algunos
casos queremos un comportamiento diferente y para ello PHP ofrece 2 interfaces: Iterator
y IteratorAggregate las cuales aprenderemos a usar en la siguiente lección.
Repositorio
Ver el código de esta lección en GitHub

Notas
Por Clemir Rondón.
La iteración es el proceso de recorrer una lista de elementos. Con PHP se puede iterar objetos
usando la sentencia foreach y por defecto, se podrá acceder a todas propiedades del objeto que
tengan visibilidad pública.
Es decir, si quisieramos iterar también sobre las propiedades del objeto con visibilidad protected o
private tendríamos que hacerlos públicos, pero esto iría en contra del encapsulamiento en la
programacion orientada a objetos.
La solución a esto es usar un iterador, el cual es un objeto que puede recorrer una lista. Para ello
PHP tiene una Biblioteca Estándar (SPL por las siglas de Standard PHP Library en inglés) que nos
proporciona una colección de interfaces y clases pensadas para solucionar problemas comunes.
Así que en caso de iterar un objeto podemos implementar una de las interfaces de la biblioteca
Estándar de PHP con las cuales se le permite a una clase decidir qué y cómo sus objetos serán
iterados:
Interfaz Iterator
class MiClase implements Iterator { }

class MiClase implements Iterator


1
{
2
3 }

Interfaz IteratorAggregate

class MiClase implements IteratorAggregate { }

class MiClase implements IteratorAggregate


1
{
2
3 }

Con la interfaz Iterator se deben definir los siguientes 5 métodos públicos en la clase que la está
implementando:
current(): devuelve el elemento actual.
key(): devuelve la clave del elemento actual.
next(): Avanza al siguiente elemento.
rewind(): Rebobine la Iterator al primer elemento.
valid(): Comprueba si la posición actual es válida.
Es decir que cuando se usa un foreach con un objeto que implementa la interfaz Iterator
internamente hace lo siguiente:
1. Al comienzo de la ejecución del foreach llama al método rewind() para reiniciar la iteración.
2. Antes de cada iteración se llama al método valid() para comprobar si hay un dato válido.
3. Dependiendo del resultado de valid() toma una decisión:
Si devuelve falso el bucle termina.
Si devuelve verdadero llama a los métodos current() y key() para devolver el
elemento actual y su clave.
4. Se ejecutan las operaciones del bucle con los elementos devueltos.
5. Después de cada iteración se llama al método next() hallar el siguiente elemento y se repiten
las instrucciones desde el paso 2.
La implementación de los métodos de esta interfaz usada en el video se encuentra en
http://php.net/manual/es/language.oop5.iterations.php
Como alternativa se puede usar la interfaz IteratorAggregate que solo tiene un método que se debe
definir getIterator() el cual devuelve un iterador que se encargará de hacer las operaciones para
iterar el objeto.

¿Cuál es la diferencia?
La diferencia entre las 2 interfaces es que un objeto que implemente Iterator puede iterar
directamente con las propiedades del objeto o crear un iterador externo, en cambio con un objeto
que implementa IteratorAggregate solo crea un iterador externo que se encargará de iterar las
propiedades del objeto.
Por tanto si se quiere tener un mayor control y personalización del comportamiento de la iteración
de las propiedades de un objeto se usa la interfaz Iterator pero si las propiedades del objeto son
sencillas como por ejemplo un array, podemos resolverlo usando la interfaz IteratorAggregate que
de manera sencilla y fácil se delega la iteración a otra clase para así reusar métodos de iteración
comunes como por ejemplo la clase ArrayIterator.
ArrayIterator es una clase que te permite crear un iterador de cualquier array de PHP. Esta clase
también es proveída por la biblioteca SPL.
Countable es una interfaz también perteneciente a la Biblioteca Estándar de PHP con la cual
podemos contar el número de elementos de un objeto. Se implementa de la siguiente manera:

class MiClase implements Countable { }

class MiClase implements Countable


1
{
2
3 }

y se debe definir el método público count() que retorne el número de elementos del objeto.

Material relacionado
Encapsulamiento, getters y setters en PHP
Interfaces y Polimorfismo

Objetos Inmutables en PHP


Cuando trabajamos con objetos algunas veces es necesario que los métodos que interactuan con
ellos no modifiquen su estado, esto es lo que llamamos objetos inmutables. En la lección de hoy
veremos como crear y trabajar con objetos de este tipo.
Repositorio
Ver el código de esta lección en GitHub

Notas
En caso de que no estés trabajando con PHP 7 donde tenemos el operador de fusión de null (??) esto

return $this->attributes['beverage'] ?? null;

return $this->attributes['beverage'] ?? null;


1

lo puedes sustituir con:

return $this->attributes['beverage'] ? $this->attributes['beverage'] : null;


return $this->attributes['beverage']
1
? $this->attributes['beverage']
2
3 : null;

Aunque te recomendamos que actualices para aprovechar las mejoras y las nuevas funcionalidades
que trae.
Con la función array_filter de PHP obtenemos un array resultante luego de iterar cada elemento del
array pasándolo a un callback que evalúa si permanecerá en el array resultante o no.
El problema presentado en la lección también se puede solucionar usando el método mágico
__clone.
Material relacionado
Cómo clonar objetos y usar el método mágico __clone
Uso de los métodos mágicos __toString y __invoke en PHP

Comparación entre objetos en PHP


En la lección de hoy conoceremos cómo trabajar con la comparación de objetos en PHP mediante
los operadores == y ===. También aprenderás sobre la manera adecuada de comparar objetos
dependiendo de si son value objetos o si representan una entidad del mundo real.

Notas
Por Clemir Rondón
En PHP la comparación de objetos se puede hacer por medio de:
Operador de comparación (==) donde dos objetos son iguales si tienen los mismos atributos
y valores y son instancias de una misma clase.
Operador de igualdad (===) es una comparación estricta, es decir, dos variables serán
iguales solo si hacen referencia a la misma instancia de la misma clase.
Recuerda que los objetos se pasan y se asignan por referencia como vimos en la lección Cómo
clonar objetos y usar el método mágico __clone
Sobre Value Objects se habló en la lección 9 de este curso.
Otro ejemplo de un value object es un objeto dirección donde:

$address = new Address('Avenida 1'); $address2 = new Address('Avenida 1'); $address == $address2; // true son
iguales $address === $address2; // false pero no son idénticos

$address = new Address('Avenida 1');


1 $address2 = new Address('Avenida 1');
2
3
4 $address == $address2; // true son iguales
5 $address === $address2; // false pero no son idénticos
La forma de distinguir si un objeto es Value Object o no es comprobando si posee un atributo de
identificación como un id que sea único y lo diferencie de otro objeto aunque tenga los demás
atributos iguales. Por ejemplo, el número de cédula o pasaporte en una clase Person.
La forma para comparar a objetos que tiene un atributo de identificación es comparando ese atributo
de cada objecto para así estar seguro que haga referencia al mismo objeto o entidad del mundo real,
es decir, dos objetos instancias de Person serán iguales si y solo si su atributo passport son
idénticos.

$person1->passport == $person2->passport

$person1->passport == $person2->passport
1

Material relacionado
Patrón Factory y Value Objects
Cómo clonar objetos y usar el método mágico __clone

Traits en PHP
PHP como muchos de los lenguajes de programación no permite el uso de herencia múltiple;
por ello recurre a un mecanismo llamado Traits o rasgos que hace posible que clases
independientes y pertenecientes a distintas jerarquías puedan disponer de los mismos métodos.
En la lección de hoy aprenderás a crear y trabajar con traits, y sus particularidades como el orden
preferencia de los métodos y la resolución de conflictos cuando dos traits implementan métodos con
el mismo nombre.

Notas
Por Clemir Rondón
Algunas características de los Traits son:
Están disponible desde PHP 5.4
Un Trait es similar a una clase, pero con el único objetivo de agrupar funcionalidades muy
específicas y de una manera coherente.
No se puede instanciar directamente un Trait.
Habilita la composición horizontal de comportamientos, es decir, permite reusar código sin
tener que usar herencia y así evitando los problemas de duplicidad para clases que tienen los
mismos comportamientos pero no pueden derivarse de una única clase padre.
Orden de precedencia para los métodos: los métodos de la clase actual sobrescriben los
métodos del Trait, que a su vez sobrescriben los métodos heredados.
Se pueden insertar múltiples Traits en una clase, mediante una lista separada por comas en la
sentencia use
class Post {
use Trait1, Trait2;
}
Recuerda tener presente que los traits también usan nombres de espacio (namespaces), por
los tanto debes importarlos igual que las clases cuando no compartan el mismo namespace.
Si un trait define una propiedad, en la clase no se puede redefinir dicha propiedad o se
producirá un error.
Los traits soportan el uso de métodos abstractos para imponer requisitos a las clases que
implementen dicho trait.
Conflictos de nombres de métodos
Si dos o más traits poseen un método con el mismo nombre y ambos traits se asignan a una clase, se
producirá un error fatal como resultado del conflicto. Para resolverlo se debe indicar explícitamente
cual método usar con el operador insteadof, ejemplo:
trait CanWalk {
public function move() {
echo 'camina';
}
}

trait CanRun {
public function move() {
echo 'corre';
}
}

class Person {
use CanWalk, CanRun {
CanRun::move insteadof CanWalk;
}
}
y en caso de querer trabajar con los 2 métodos debes asignarle un alias, sin olvidar usar el operador
insteadof para resolver el conflicto, de esta manera:
class Person {
use CanWalk, CanRun {
CanRun::move insteadof CanWalk;
CanWalk::move as walk
CanRun::move as run
}
}

Material relacionado
Herencia y abstracción con PHP
Interfaces y Polimorfismo
Documentación oficial sobre traits en PHP
Uso de Traits en Laravel

Creación de macros en PHP usando traits,


métodos estáticos y __call
En esta lección pondrás en práctica los conocimientos adquiridos durante este curso sobre métodos
estáticos, el método mágico __call y Traits en PHP para aprender a agregar nuevos métodos a una
clase por medio de un concepto llamado macros que es usado en frameworks como Laravel o
Symfony.

Notas
Por Clemir Rondón
La primera opción para agregar nuevos métodos a una clase que no podemos modificar
directamente (porque, por ejemplo, pertenece a un paquete de terceros) es crear una clase con el
mismo nombre y que extendida la clase que queremos modificar, haciendo uso de los namespace y
la herencia simple como ya hemos aprendido.
Recuerda siempre que toda clase que se encuentre en el directorio vendor, generado por
Composer, no debe ser modifica directamente porque los cambios se borrarán al hacer
composer update

.
El concepto de macro explicado en está lección es un conjunto de instrucciones que realizan
alguna tarea, que Laravel implementa como una manera de poder dar opción a los desarrolladores
para que puedan agregar nuevas funcionalidades o métodos dinámicos a clases como
Collection, Filesystem, Arr, Translator, etc. del framework sin necesidad de tener que extender
dichas clases.
Closure es una clase de PHP para representar las funciones anónimas por tanto para llamarla
correctamente se debe importar la clase:
use Closure;
1

o usar la barra invertida \ para indicarle a PHP que la busque en el namespace global, de esta
manera \Closure
Con la función de PHP call_user_func_array se llama a un callback o llamada de retorno que es
enviada como primer parámetro a la función y el segundo parámetro un array que se pasará como
argumentos al callback.
Si quieres repasar el concepto del método mágico __call que ya vimos en este curso consulta la
lección relacionada.
La clase BadMethodCallException de PHP trabaja junto con el método mágico __call para lanzar
una excepción cuando el método llamado por el callback no existe o no es válido o falta alguno de
los argumentos. Al igual que Closure es una clase de PHP por tanto debes agregar la barra invertida
para que PHP la busque es su nombre de espacio global.
Usando un trait para agregar toda funcionalidad de macro que vimos está lección podemos reutilizar
el código y hacer que cualquier otra clase del proyecto se pueda crear métodos dinámicos, tan solo
agregando el macro a la clase como se vio en la lección anterior.
Con el método Closure::bindTo estamos atando el Closure que usaremos en el método mágico
__call al ámbito de la clase actual.
Actividad
Puedes revisar el trait Macroable de Laravel y ver que clases del framework lo usan.
Material relacionado
Propiedades y métodos estáticos
Llamadas a métodos mágicos con __call y __callStatic en PHP
Traits en PHP
PHP Traits en Laravel 5.1

Instalación y uso de componentes de terceros


con Composer
Cuando escribes aplicaciones con PHP no es necesario que escribas todo el código por ti mismo,
pues hay problemas comunes que ya tienen una o varias soluciones y no tiene sentido que dediques
parte de tu tiempo a recrear las mismas soluciones desde cero. En vez de esto, podemos apoyarnos
en paquetes de terceros y por medio de Composer (el manejador de dependencias de PHP)
podemos integrarlos a nuestra aplicación de forma sencilla como veremos en la lección de hoy.

Notas
Por Clemir Rondón.
Walter White (personaje principal de Breaking Bad) nació el 7 de Septiembre de 1959.Esperamos
que te haya gustado esta nueva parte del curso, si tienes dudas o quieres aprender algo nuevo, por
favor escríbenos en el canal #php de nuestro Slack:
Recuerda que estamos usando propiedades y métodos mágicos al estilo de Eloquent como
aprendimos con el uso del método mágico __get y llamadas dinámicas a métodos.
Composer a parte de ayudarnos con la autocarga de clases como vimos en una lección
anterior también nos permite la gestión de dependencias, es decir, nos ayuda a instalar los paquetes
de terceros y sus respectivas dependencias, sin necesidad que nosotros intervengamos en el proceso.
Con esto podremos usar casi sin esfuerzo las clases y métodos de componentes de terceros que
además serán cargados de forma automática, gracias nuevamente al autoloader incluido con
Composer.
Para trabajar con Composer como manejar de dependencias en un proyecto de PHP (como vimos en
la lección Autocarga de clases con Composer y PSR-4) debemos:
Instalar Composer ya sea local o globalmente.
Agregar el archivo composer.json con los datos del proyecto (autoload, paquetes, etc.).
Agregar la siguiente línea en el archivo inicial de tu proyecto: require '/vendor/autoload.php';
autoload.php es el archivo creado por Composer que se encarga de la autocarga de
clases de tu proyecto y las dependencias del mismo.

Las 2 maneras de instalar un paquete con Composer son:


En la consola: ejecutando composer require nombre-vendor/nombre-paquete, donde
nombre-vendor es el nombre del grupo, empresa o desarrollador que creó el paquete y
nombre-paquete es el nombre del proyecto en sí. Por ejemplo:
$ composer require nesbot/carbon

Agregando manualmente en el archivo composer.json en la opción 'require' el nombre del paquete y


la versión a instalar. Por ejemplo:

{
"require": {
"nesbot/carbon": "~1.18"
}
}

y luego ejecutar composer install en la consola.


Para conocer cómo Composer maneja las versiones puedes consultar Controla las
versiones de los componentes de tu proyecto con Composer

Al instalarse el paquete en un proyecto con Composer, éste se encontrará en directorio vendor. Algo
importante a tomar en cuenta es que no debes modificar los archivos que se encuentren en ese
directorio puesto que al volver a ejecutar composer install o composer update se perderán los
cambios hechos.
Si tienes dudas revisa sobre Diferencias entre composer install y composer update.
Carbon es un componente que extiende la clase de PHP DateTime y su documentación oficial se
encuentra en http://carbon.nesbot.com/docs/. También en Styde hemos hablado de este
componente: Manipular fechas con el componente Carbon en Laravel 5
Para usar las clases o archivos de un paquete instalado con Composer debemos importar la clase a
utilizar usando la sentencia use de PHP con el nombre de la clase incluyendo su namespace. Por
ejemplo para usar Carbon:
use Carbon\Carbon

y de esta manera empezar a usar el componente para resolver lo que necesitamos.


El principal repositorio donde puedes encontrar paquetes o componentes instalables
con Composer que puedes usar en tus proyectos de PHP es Packagist.org. Además, en Styde
tenemos el Curso de creación de componentes para PHP y Laravel donde aprenderás a crear tus
propios componentes y la última parte se dedica a explicar cómo crearlos y publicarlos en
Packagist.
Material relacionado
Composer, el gestor de dependencias de PHP
Autocarga de clases con Composer y PSR-4
Manipular fechas con el componente Carbon en Laravel 5

Desarrollo de clases y métodos con pruebas


automatizadas
Cuando desarrollamos debemos asegurarnos que las clases y métodos que creamos funcionen
correctamente, por lo tanto, es necesario probar siempre el código escrito pero en algunos casos no
es tan fácil o resulta una tarea tediosa de hacer de forma manual. En la lección de hoy te
explicaremos cómo desarrollar usando pruebas automatizadas con PHPUnit en minutos.
Notas
Por Clemir Rondón.
En este curso trabajamos con la clase Str para convertir cadenas como por ejemplo de full_name a
FullName durante las lecciones sobre métodos mágicos en PHP, es decir, a partir de la lección Uso
de los métodos mágicos __get, __set, __isset y __unset con PHP sin embargo, en ese momento no
nos detuvimos a ver detalladamente cómo estaba desarrollada.
La función de PHP ucfirst convierte el primer carácter de una cadena a mayúsculas.
Para crear pruebas podemos hacer uso del componente PHPUnit que podemos instalar con
Composer como vimos en la lección anterior de esta manera agregando al composer.json:
{
"require-dev": {
"phpunit/phpunit": "5.5.*"
}
}

Lo agregamos en la opción require-dev puesto que es un componente que solo


necesitamos durante el desarrollo del proyecto.

y luego ejecutamos composer update en la consola para que se instale.


El siguiente paso es crear el directorio tests en la raíz del proyecto donde colocaremos las clases que
se encargarán de probar el código automáticamente. Además, estas clases deben extender de la clase
PHPUnit\Framework\TestCase del componente PHPUnit
Para correr las pruebas ejecutamos en consola:

vendor/bin/phpunit tests/

vendor/bin/phpunit tests/
1

donde tests/ es el directorio donde le indicamos a PHPUnit que busque las pruebas a ejecutar.
Adicionamente, puedes agregar alguna otra opción disponible como por ejemplo –colors para
indicar que el resultado use colores.
Las Aserciones o Assertions son un conjunto de métodos que nos permiten ejecutar las pruebas de
una mejor manera y proporcionando resultados con mayor información sobre la ejecución de
prueba.
En PHPUnit disponemos de un gran conjunto de aserciones que podemos ver en su documentación
oficial. Para esta lección usamos el método assertSame() que acepta como argumentos el valor
esperado, el valor que está produciendo nuestro código y opcionalmente un mensaje que se
mostrará en caso que falle la aserción.
Se recomienda que cada método que creamos en una clase de prueba tenga un nombre descriptivo
de lo que se está evaluando, así como el nombre de la clase.
Con la función de PHP ucwords podemos convertir a mayúsculas el primer carácter de cada palabra
de una cadena y con la función str_replace reemplazamos todas las apariciones de la cadena que
enviamos como primer argumento con la cadena de reemplazo que enviamos como segundo
argumento en la cadena a evaluar enviada como tercer argumento.
Bien, con esta lección culminamos el curso Curso de programación orientada a objetos con
PHP esperamos que hayas disfrutado del contenido y te invitamos a continuar preparándote con
el Curso de creación de componentes para PHP y Laravel donde aprenderás a crear tus propios
componentes y conocerás temas más avanzados como la inyección de dependencias, patrones de
diseño, el uso de pruebas unitarias, entre otros.
Material relacionado
Las pruebas automatizadas son perfectas para tus proyectos personales
Cómo escribir pruebas unitarias y de aplicación y por qué es importante
Introducción al diseño de clases con pruebas unitarias en PHPUnit
Array Access en PHP – Parte 1
Con PHP, es posible interactuar con un objeto como si éste fuese un array, y esto lo podemos lograr
de forma muy sencilla implementando la interfaz ArrayAccess. A partir de esta lección aprenderás
cómo usar esta interfaz de forma detallada, para agregar esta funcionalidad a la clase Model que
hemos venido usando. Además vamos a aplicar los conocimientos de la lección 27 (Desarrollo de
clases y métodos con pruebas automatizadas) para crear esta funcionalidad con el apoyo de una
prueba unitaria escrita en PHPUnit
Repositorio
Ver el código de esta lección en GitHub
Si cometes un error en el código, cuando ejecutes la prueba es posible que no lo veas, y esto no es
lo más óptimo para depurar y corregir errores. Así que puedes solucionar esto agregando este
archivo bootstrap.php en la raíz de tu proyecto y haciendo referencia a éste desde el archivo
phpunit.xml. De esta forma podrás ver los errores que arroje PHP (en caso de que exista alguno)
directamente desde tu terminal.
Notas
Por Clemir Rondón.
Las correcciones que debes hacer en la lección Desarrollo de clases y métodos con pruebas
automatizadas son:
Agregar el archivo phpunit.xml, el cual es el archivo de configuración que permite definir
que acciones se realizarán al ejecutar las pruebas.
Además, puedes configurar tu entorno de desarrollo para crear un alias del comando de la
ejecución de las pruebas: Alias de comandos para la consola Windows/Linux/Mac
Por otro lado, ArrayAccess es una interfaz predefinida de PHP como Iterator e IteratorAgreggate
que vimos en la lección Iteración de objetos en PHP, la cual nos permite dar acceso a objetos como
si fuesen arrays.
Para trabajar con ArrayAccess la clase debe implementar dicha interfaz, como por ejemplo:
class User implements ArrayAccess {
}
Sin embargo, como toda interfaz es un contrato, tenemos que además implementar cuatro métodos
que nos permitirán simular trabajar con objetos usando la sintaxis de array:
abstract public boolean offsetExists ( mixed $offset ) que se ejecutará cuando queremos comprobar
si existe un índice.
abstract public mixed offsetGet ( mixed $offset ) que nos permitirá recuperar el valor de una clave o
$offset.
abstract public void offsetSet ( mixed $offset , mixed $value ) para asignar una clave $offset con
valor $value al objeto.
abstract public void offsetUnset ( mixed $offset ) que destruye un $offset o clave.
Para crear una nueva prueba usando PHPUnit, creamos un nuevo archivo con nombre
ArrayAccessTest.php dentro del directorio test
Revisa cómo configurar PHPUnit en un proyecto de PHP con la lección: Desarrollo de clases y
métodos con pruebas automatizadas
Además, crea la clase llamada ArrayAccessTest sin olvidar extender de la
clase PHPUnit\Framework\TestCase que nos proporciona los métodos para escribir las pruebas.
Al ser la clase Model una clase abstracta no la podemos instanciar directamente, es por ello que
para probar el uso de la interfaz ArrayAccess creamos una clase UserTest que extienda de la clase
Model, la cual si podemos instanciar en la prueba.
Para repasar sobre clases abstractas consulta la lección Herencia y abstracción con PHP
Puesto que el método offsetGet a implementar nos permite obtener el valor de una propiedad, en ese
método debemos colocar la manera con el objeto permite acceder a una propiedad de forma
dinámica y esto es a través del método getAttribute visto en las lecciones: Uso de los métodos
mágicos __get, __set, __isset y __unset con PHP y Llamadas dinámicas a métodos con PHP
Laravel, como framework de PHP, implementa la interfaz ArrayAccess en algunas de sus clases
para acceder a las propiedad como si fuese un array como por ejemplo: Illuminate\Http\Request, y
es por ello que para poder acceder a las variables de la petición de esta manera $request['name'] que
es equivalente a $request->input('name') o $request->name. Otras clases que implementan la
interfaz son Illuminate\Database\Eloquent\Model,
Illuminate\Support\Collection, Illuminate\Container\Container, etc.
Material relacionado
Curso básico de Terminal
Desarrollo de clases y métodos con pruebas automatizadas
Iteración de objetos en PHP
Llamadas dinámicas a métodos con PHP

Array Access en PHP – Parte 2


En esta segunda parte acerca de la interfaz ArrayAccess estudiaremos cómo implementar los
métodos offsetExists, offsetSet y offsetUnset para completar la funcionalidad de acceso de array en
nuestra clase de prueba. Además seguiremos utilizando PHPUnit y pruebas automatizadas para
comprobar nuestro progreso en el desarrollo de la funcionalidad y veremos algunos tips sobre cómo
nombrar y especificar los métodos de nuestras pruebas unitarias.

Repositorio
Ver el código de esta lección en GitHub
Compatibilidad con array_key_exists
Es importante tener en cuenta que la función array_key_exists no funciona con objetos que tengan
la interfaz ArrayAccess, solamente con arrays. Puedes comprobarlo tú mismo en una prueba
unitaria con el siguiente código:
<?php

$user = new UserTest(['name' => 'Duilio Palacios']);

$this->assertFalse(array_key_exists('name', $user));

$user = ['name' => 'Duilio'];

$this->assertTrue(array_key_exists('name', $user));

Uso de ArrayAccess en el framework Laravel


Es interesante notar que los modelos de Eloquent implementan la interfaz ArrayAccess, por lo que
lo que has aprendido en estas 2 últimas lecciones es posible usarlo en Eloquent. Sin embargo es más
común ver el acceso con propiedades mágicas:
<?php

$user = new User(['name' => 'Duilio']);

echo $user->name; //Esto funciona y es muy comun

echo $user['name']; //Pero esto tambien va a funcionar

También es posible usar ArrayAccess en el contenedor de inyección de dependencias de Laravel:


<?php

$app = app();

$app['message'] = new Message; //es equivalente a:

$app->bind('message', function () {
return new Message;
});

$app['message']->show('Styde Rules!'); //es equivalente a:

$app->make('message')->show('Styde Rules!');

En la próxima lección vamos a aprender sobre clases anónimas y a mover el código creado hasta
ahora a nuestra clase abstracta Model.

Clases anónimas en PHP


Como vimos en las lecciones sobre la interfaz ArrayAccess no podíamos probar la implementación
de esta interfaz directamente con la clase Model. Debido a que la clase Model por ser una clase
abstracta no se puede instanciar directamente. Cuando esto ocurre, la solución más común es crear
una clase que extienda de la clase abstracta. Sin embargo a partir de PHP 7 podemos sacarle
provecho a un nuevo tipo de clase llamada Clase Anónima y esto es lo que vamos a aprender en
esta lección: el uso de clases anónimas en pruebas unitarias.

Repositorio
Ver el código de esta lección en GitHub
Notas
Por Clemir Rondón.
Para hacer que todas las clases que extiendan de la clase Model tengan la facultad de poder acceder
a sus propiedades como si fuera un array, debemos trasladar lo desarrollado en las lecciones
anteriores a la clase Model, esto es: que implemente la interfaz ArrayAccess y además tenga los 4
métodos de la interfaz.
Las clases anónimas fueron incluidas en la versión 7 de PHP y permiten crear objetos de una clase
abstracta, o una interfaz, o de cualquier otra clase de forma sencilla.
Lo usual para instanciar una clase es $objeto = new UnaClaseAbstracta(); pero cuando la clase que
queremos instanciar no nos permite hacerlo directamente o nos interesa crear otras clases para poder
instanciarlas podemos hacer lo siguiente:
$objeto = new class ($foo, $bar) extends UnaClaseAbstracta implements UnaInterfaz {}
donde new class son las palabras reservadas para indicar que queremos crear una nueva clase e
instanciarla, pero sin indicar el nombre de la clase, tal y como sucede con las funciones anónimas.
($foo, $bar) son las variables que pasamos a través del constructor, si no es necesario simplemente
se omiten.
Luego podemos extender o implementar otras clases en caso de ser requerido. Como por ejemplo en
nuestro caso:
$user = new class ($attribute) extends Model { };
De igual forma, podemos sobrescribir atributos y métodos de las otras clases a las que extiende o
implementan.
Puedes hacer la prueba en el navegador con el siguiente código:
<?php

require "../vendor/autoload.php";

use Styde\User;

$user = new User([


'first_name' => 'Walter',
'last_name' => 'White',
'birthDate' => '07/09/1959',
]);
echo "{$user['full_name']} tiene {$user['age']} años";

Esperamos que te haya gustado esta nueva parte del curso, si tienes dudas o quieres aprender algo
nuevo, por favor escríbenos en el canal #php de nuestro Slack:

También podría gustarte