Orientado a objetos

Es un estilo de programacion que permite a los desarrolladores agrupar informacion, acciones y/o tareas similares en clases. Orientada a objecto es esencial para desarrollar con los frameworks modernos de PHP como Laravel o Symfony.

Objetos

Es la representacion de algun elemento real en nuestro mundo. Cada objeto contiene atributos el cual crea una diferencia entre otros objetos. Los objetos con atributos similares los clasificamos por clases para englobal estos objectos similares con atributos similares y comportamiento similares.

Clases

Es la definicion de como un objeto debe ser al momento de crearse. Para crear una clase en PHP necesitamos primero utilizar la palabra reservada class luego el nombre de la clase y prosigue llaves (bloque de codigo) el cual es el contenido de la definicion de la clase para crear un objeto.

<?php

class Book {}

class Customer {}

Para inicial una instancias de la clases y poder crear un objeto utilizamos la palabra reservada new.

<?php

$book = new Book();
$customer = new Customer();

Propiedades

Las variables dentro de una definición de clase se le conocen como propiedades, tambien utilizan el nombre de atributos o campo. La propiedades pueden definirse dentro de la clase utilizando cualquiera de las siguiente palabras reservada public private protected. Cada una de estas palabras reservada especifica como debemos manejar estas propiedades dentro y fuera del objeto o otras clases.

<?php

class Book {
  public $isbn;
  public $title;
  public $author;
  public $available;
}

$book = new Book();
$book->isbn = 9785267006323;
$book->title = "1986";
$book->author = "George Orwell";
$book->available = true;

print_r($book);
//-> Book Object ( [isbn] => 9785267006323 [title] => 1986 [author] => George Orwell [available] => 1 )

Configurar valor de propiedades de objeto

<?php

$book->isbn = 9785267006323;
$book->title = "1986";
$book->author = "George Orwell";
$book->available = true;

Acceso a propiedades de objeto

<?php

print_r($book->author);

Metodos

Las funciones el cual definimos dentro de las clases, les llamamos metodo.

<?php

class Book {
  public $isbn;
  public $title;
  public $author;
  public $available;

  public function getCopy(): bool {
    if($this->available < 1) {
      return false;
    }
    else {
      $this->available--;
      return true;
    }
  }
}

$book = new Book();
$book->available = 12;

if($book->getCopy()) {
  echo 'Here, your copy.';
}
else {
  echo 'I am afraind that book is not available.';
}

//-> Here, your copy.

Acceso a propiedades y metodos

Las palabras reservadas tambien la utilizamos con los metodos de una clase, estas palabra especifican la visibilidad o uso de las propiedades y metodos cuando combinamos clases o queremos utilizar propiedades de los objetos creados por la clases.

  • public

Esta especifica que esa propiedad o metodo no tiene restriccion de uso, puede ser utilizada o llamada de cualquier punto de la aplicacion. Tambien puede ser modificada en cualquier punto.

  • protected

Esta especifica que la propiedad o metodo puede ser utilizado o modificada exclusivamente dentro de la misma clase el cual fue definida, o clases derivadas de la cual la propiedad fue definida.

  • private

Esta especifica que la propiedad o metodo puede ser utilizado o modificada exclusivamente dentro de la misma clase el cual fue defenida, no puede ser modificada o usada fuera de la misma clase en la cual se formo.

Constructores

Constructor es un tipo de funcion el cual es invocada al momento de una instancia de un objeto, esta funcion es invocada desde la clase y pasada al objeto el cual se esta creando la instancia. Esta funcion es muy similar a los metodos, la unica excepcion es el nombre el cual utiliza el cual es __construct. Los constructores son utilizado para pasar al objeto que estemos iniciando en el momento sus valores por defectos.

<?php

class Book {
  public function __construct(
    int $isbn,
    string $title,
    string $author,
    int $available) {
      $this->isbn = $isbn;
      $this->title = $title;
      $this->author = $author;
      $this->available = $available;
  }

  public function getCopy(): bool {
    if($this->available < 1) {
      return false;
    }
    else {
      $this->available--;
      return true;
    }
  }
}

$book = new Book("1984", "George Orwell", 97852670063, 12);

if($book->getCopy()) {
  echo 'Here, your copy.';
}
else {
  echo 'I am afraind that book is not available.';
}

PHP magic methods

Si examinamos codigo fuente PHP de otros colegas, podemos observar dentro de sus definicion de clases funciones lo cual empienzan con doble guion bajo (__) y luego el nombre de la funcion. Este tipo de funciones les conocemos como metodos magicos.

Estos metodos estan ya predefinidos por el lenguage de programacion PHP y nos ayuda a manejar los objetos en diferentes tipos de evento que ocurran durante la programacion. Anteriormente ya hemos usado uno de estas funciones por ejemplo __construct, este es el metodo magico mas comun y usado dentro de nuestras clases en PHP.

Getting Setting

Cuando queremos tener acesso a propiedades de un objeto, muchas veces se nos hace complicado hacerlo de manera directa ya que por alguna regla de negocio tenemos que definirla dentro de la clase como propiedades protegida o privada. Los metodos magicos get y set nos proveen la habilidad de acceder a estas propiedades.

  • __get Este metodo presta atencion al momento que hacemos una solicitud de alguna propiedad dentro de la clase que no sea publica.

  • __set No permite efectuar cambio a propiedades el cual tenemos protegidas o privada dentro de nuestra definicion de clases.

<?php

class Customer {
  private $id;
  private $firstName;
  private $lastName;
  private $email;

  public function __construct(
    int $id,
    string $firstName,
    string $lastName,
    string $email) {
      $this->id = $id;
      $this->firstName = $firstName;
      $this->lastName = $lastName;
      $this->email = $email;
  }

  public function getFirstName() {
    return $this->firstName;
  }

  public function setFirstName(string $firstName) {
    $this->firstName = $firstName;
  }

  public function getFullName() {
    return "$this->firstName $this->lastName";
  }
}

$customer = new Customer(1, "Steve", "Miller", "[email protected]");

// Without getter and setter you will receive.
// Cannot access private property.
// print_r($customer->firstName);

print_r($customer->getFirstName());
//-> Steve

print_r($customer->getFullName());
//-> Steve Miller

$customer->setFirstName("Johnny");

print_r($customer->getFullName());
//-> Johnny Miller

Set

Esta funcion la hemos utilizado fuera de nuestras clases, isset es una funcion el cual verifica si determinada variable esta inicializada. __isset nos permite verificar si determinada propiedad existe dentro de nuestra clase o objeto.

<?php

class Customer {
  private $firstName;
  private $lastName;

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

  public function __isset($property) {
    if(isset($this->$property)) {
      echo "Property existent.";
    }
    else {
      echo "Non-existent property.";
    }
  }
}

$customer = new Customer("Steve", "Miller");

print_r(isset($customer->firstName));
//-> Property existent.

print_r(isset($customer->fullName));
//-> Non-existent property.

To String

Este metodo nos permite devolver algun objeto en su representacion en cadena de caracteres.

<?php

class Customer {
  private $firstName;
  private $lastName;

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

  public function __toString() {
    $result = "<b>$this->firstName $this->lastName";
    return $result;
  }
}

$customer = new Customer("Steve", "Miller");

print_r((string)$customer);
//-> <b>Steve Miller</b>

Encapsulacion (Encapsulation)

Este termino en su forma mas sencillo de definir, significa envolver data dentro de una simple unidad. Encapsulacion es el metodo el cual utilizamos para estructurar nuestras clases. Nuestras clases estan basada en propiedades y metodos, con la encapsulacion podemos organizar propiedades, metodos y definir que tipos de restricciones tienen cada uno de estos elementos de la clase.

Uso y restricciones de encapsulamiento consiste de 3 tipos de permisos por ejemplo: publico, protegido y privado. Estos nos ayuda a evitar errores en el codigo, como otros beneficion.

<?php

class Customer {
  private $id;
  private $firstName;
  private $lastName;
  private $email;
  protected $age;

  public function __construct(
    int $id,
    string $firstName,
    string $lastName,
    string $email,
    int $age) {
      $this->id = $id;
      $this->firstName = $firstName;
      $this->lastName = $lastName;
      $this->email = $email;
      $this->age = $age;
  }

  public function getId(): id {
    return $this->id;
  }

  public function getFirstName(): string {
    return $this->firstName;
  }
}

Propiedade o metodo estatico (Static)

Metodos o propiedades estatica nos permite de definir propiedades o funciones dentro de clases el cual podemos utilizar o acceder sin tener que instanciar la clase en algun objeto. Para definir propiedades o metodos estaticos usamos la palabra reservada static.

<?php

// Definir metodo estatico
public static function static_method() {}

// Definir propiedades estatico
private static $static_property;

// Invocar propiedad o function estatica usamos el operador "::"
MyClass::static_method();
MyClass::$static_property;

En las propiedades y metodos estaticos hacemos uso de la siguiente palabra reservada self, esta es muy diferente a la palabra reservada $this. $this representa al cierto valor dentro de la instancia de la clase o en el objeto al contrario de self que representa similar a $this pero en la clase no en el objeto iniciado. $this inicia con el simbolo de dolar $ al contrario a self nunca inicia con simbolo de dolar. A $this le sigue el operador->al contrario que self le sigue el operador :: . Para terminar, la propiedad al final de $this es llamada por su nombre sin utilizar el simbolo de dolar, al contrario de self que la propiedad se llama con el simbolo de dolar.

<?php

class Counter {
  private $count;
  public static $instance;

  public function __construct($count = 0) {
    $this->count = $count;
    self::$instance++;
  }

  public function count() {
    $this->count++;
    return $this;
  }

  public function __toString() {
    return (string)$this->count;
 }

 public static function countInstance() {
   return self::$instance;
 }
}

$c1 = new Counter();
$c1->count()
   ->count();

echo "Counter 1 value: $c1 <br/>";

$c2 = new Counter();
$c2->count()->count()->count();

echo "Counter 2 value: $c2 <br/>";

echo "The number of counter instances:". Counter::countInstance();

// Counter 1 value: 2 
// Counter 2 value: 3 
// The number of counter instances:2

Herencia (Inheritance)

Herencias nos permite expandir nuestras clases a otras el cual son clases descendientes o hijos. Las clases padres pueden pasar a otras clases descendientes propiedades y metodos publicos como protegidas, no privada. Para expandir nuestras clases utilizamos conjunto a la clase hijo la palabra reservada extends.

<?php

class Person {
  protected $firstName;
  protected $lastName;

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

  public function getFirstName(): string {
    return $this->firstName;
  }

  public function getLastName(): string {
    return $this->lastName;
  }
}

class Customer extends Person {
  private static $lastId = 0;
  private $id;
  private $email;

  public function __construct(
    $id,
    string $email) {
      if(empty($id)) {
        self::$lastId++;
        $this->id = self::$lastId;
      }
      else {
        $this->id = $id;
        if($id > self::$lastId) {
          self::$lastId = $id;
        }
      }
      $this->email = $email;
  }

  public static function getLastId() {
    return self::$lastId;
  }

  public function getId() {
    return $this->id;
  }

  public function getEmail() {
    return $this->email;
  }

  public function setEmail(string $email) {
    $this->email = $email;
  }
}

$customer1 = new Customer(3, 'John', 'Doe', '[email protected]');
echo $customer1->getId(); //-> 3

$customer2 = new Customer(null, 'Mary', 'Poppins', '[email protected]');
echo $customer2->getId(); //-> 4

$customer3 = new Customer(7, 'James', 'Doe', '[email protected]');
echo $customer3->getId(); //-> 7

Método de anulación (Overriding method)

Anulación de método es simplemente reemplazar un método pariente de una clase por una nueva en la clase descendiente.

<?php

class Pops {
  public function sayHi() {
    echo "Hi, I am pops";
  }
}

class Child {
  public function sayHi() {
    echo "Hi, I am child";
  }
}

$pops = new Pops();
$child = new Child();

echo $pops->sayHi();
// Hi, I am pops

echo $child->sayHi();
// Hi, I am child

Clases Abstracta (Abstract Class)

Clase abstracta nos permite aislar un elemento de su contexto. Es un tipo de clase el cual no podemos instanciar, pero podemos usarla como clase modelo a unas clases descendiente. Siempre deben heredarse.

<?php

class Book {
  public function __construct(
    int $isbn,
    string $title,
    string $author,
    int $available = 0) {
      $this->isbn = $isbn;
      $this->title = $title;
      $this->author = $author;
      $this->available = $available;
  }

  public function getCopy(): bool {
    if($this->available < 1) {
      return false;
    }
    else {
      $this->available--;
      return true;
    }
  }

  public function getIsbn(): int {
    return $this->isbn;
  }

  public function getTitle(): string {
    return $this->title;
  }

  public function getAuthor(): string {
    return $this->author;
  }

  public function isAvailable(): bool {
    return $this->available;
  }

  public function addCopy() {
    $this->available++;
  }
}

class Person {
  protected $firstName;
  protected $lastName;

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

  public function getFirstName(): string {
    return $this->firstName;
  }

  public function getLastName(): string { 
    return $this->lastName;
  }
}

abstract class Customer extends Person {
  private static $lastId = 0;
  private $id;
  private $email;

  public function __construct(
    int $id,
    string $email) {
      if(empty($id)) {
        $this->id = ++self::$lastId;
      }
      else {
        $this->id = $id;
        if($id > self::$lastId) {
          self::$lastId - $id;
        }
      }
      $this->email = $email;
  }

  public static function getLastId(): int {
    return self::$lastId;
  }

  public function getId(): id {
    return $this->id;
  }

  public function getEmail(): string {
    return $this->email;
  }

  public function setEmail(string $email) { 
    $this->email = $email;
  }

  abstract public function getMonthlyFee();
  abstract public function getAmountToBorrow();
  abstract public function getType();
}

class Basic extends Customer {
  public function getMonthlyFee(): float {
    return 5.0;
  }

  public function getAmountToBorrow(): int {
    return 3;
  }

  public function getType(): string {
    return 'Basic';
  }
}

class Premium extends Customer {
  public function getMonthlyFee(): float {
    return 10.0;
  }

  public function getAmountToBorrow(): int {
    return 10;
  }

  public function getType(): string {
    return 'Premium';
  }
}

$book1 = new Book(1, "Ready Player One", "Ernest Cline", 9785267006323, 10);
$book2 = new Book(2, "The Sun and Her Flowers", "Rupi Kaur", 9785267006322, 10);

function checkIfValid(Customer $customer, array $books): string {
  $valid = ($customer->getAmountToBorrow() >= count($books)
            ? "Yes you can"
            : "No you cannot");

  return $valid;
}

$customer1 = new Basic(5, 'John', 'Doe', '[email protected]');
echo checkIfValid($customer1, [$book1, $book2]);

// Without abstract class the following class will fail
// $customer2 = new Customer(5, 'John', 'Doe', '[email protected]');

Interface (Interface)

Interfaces nos permite especificar una lista de metodos el cual luego una clase puede implementar, las interfaces podemos definirla utilizando la palabra reservada interface. Con las interfaces podemos solo definir metodos sin el contenido que luego podemos ampliar a clases descendiente.

<?php

class Book {
  public function __construct(
    int $isbn, 
    string $title, 
    string $author, 
    int $available = 0) {
      $this->isbn = $isbn;
      $this->title = $title;
      $this->author = $author;
      $this->available = $available;
  }

  public function getCopy(): bool {
    if($this->available < 1) {
      return false;
    }
    else {
      $this->available--;
      return true;
    }
  }

  public function getIsbn(): int {
    return $this->isbn;
  }

  public function getTitle(): string {
    return $this->title;
  }

  public function getAuthor(): string {
    return $this->author;
  }

  public function isAvailable(): bool {
    return $this->available;
  }

  public function addCopy() {
    $this->available++;
  }
}

class Person {
  private static $lastId = 0;
  protected $id;
  protected $firstName;
  protected $lastName;
  protected $email;

  public function __construct(
    int $id,
    string $firstName,
    string $lastName,
    string $email) {
      if(empty($id)) {
        $this->id = ++self::$lastId;
      }
      else {
        $this->id = $id;
        if($id > self::$lastId) {
          self::$lastId - $id;
        }
      }
      $this->firstName = $firstName;
      $this->lastName = $lastName;
      $this->email = $email;
  }

  public static function getLastId(): int {
    return self::$lastId;
  }

  public function getId(): int {
    return $this->id;
  }

  public function getFirstName(): string {
    return $this->firstName;
  }

  public function getLastName(): string {
    return $this->lastName;
  }

  public function getEmail(): string {
    return $this->email;
  }

  public function setEmail(string $email) {
    $this->email = $email;
  }
}

interface Customer {
  public function getMonthlyFee(): float;
  public function getAmountToBorrow(): int;
  public function getType(): string;
}

interface Payer {
  public function pay(float $amount);
  public function isExtentOfTaxes(): bool;
}

class Basic extends Person implements Customer {
  public function getMonthlyFee(): float {
    return 5.0;
  }

  public function getAmountToBorrow(): int {
    return 3;
  }

  public function getType(): string {
    return 'Basic';
  }

  public function pay(float $amount) {
    echo "Paying $amount.";
  }

  public function isExtentOfTaxes(): bool {
    return false;
  }
}

class Premium extends Person implements Customer {
  public function getMonthlyFee(): float {
    return 10.0;
  }

  public function getAmountToBorrow(): int {
    return 10;
  }

  public function getType(): string {
    return 'Premium';
  }

  public function pay(float $amount) {
    echo "Paying $amount.";
  }

  public function isExtentOfTaxes(): bool {
    return true;
  }
}

$book1 = new Book("1984", "George Orwell", 9785267006323, 10);

Polimorfismo (Polymorphism)

Es la capacidad que tiene un objeto de tener las mismas propiedades y metodos de la clase padre.

Característica Especial (Traits)

Traits nos ayuda al momento que tenemos multiples herencias, en PHP las clases solo pueden heredar de una sola clase, los traits nos ayuda en este momento que necesitamos varias herencia. Traits son similares a los Mixin, nos permite unir diferente metodos en una sola clase el cual podemos compartir.

<?php

class Book {
  public function __construct(
    int $isbn, 
    string $title, 
    string $author, 
    int $available = 0) {
      $this->isbn = $isbn;
      $this->title = $title;
      $this->author = $author;
      $this->available = $available;
  }

  public function getCopy(): bool {
    if($this->available < 1) {
      return false;
    }
    else {
      $this->available--;
      return true;
    }
  }

  public function getIsbn(): int {
    return $this->isbn;
  }

  public function getTitle(): string {
    return $this->title;
  }

  public function getAuthor(): string {
    return $this->author;
  }

  public function isAvailable(): bool {
    return $this->available;
  }

  public function addCopy() {
    $this->available++;
  }
}

trait Unique {
  private static $lastId = 0;
  protected $id;

  public function setId($id) {
    if(empty($id)) {
      $this->id = ++self::$lastId;
    }
    else {
      $this->id = $id;
      if($id > self::$lastId) {
        self::$lastId = $id;
      }
    }
  }

  public static function getLastId(): int {
    return self::$lastId;
  }

  public function getId(): int {
    return $this->id;
  }
}

class Person {
  use Unique;

  protected $firstName;
  protected $lastName;
  protected $email;

  public function __construct(
    $id,
    string $firstName,
    string $lastName,
    string $email) {
      $this->firstName = $firstName;
      $this->lastName = $lastName;
      $this->email = $email;
      $this->setId($id);
  }

  public function getFirstName(): string {
    return $this->firstName;
  }

  public function getLastName(): string {
    return $this->lastName;
  }

  public function getEmail(): string {
    return $this->email;
  }

  public function setEmail(string $email) {
    $this->email = $email;
  }
}

interface Customer {
  public function getMonthlyFee(): float;
  public function getAmountToBorrow(): int;
  public function getType(): string;
}

interface Payer {
  public function pay(float $amount);
  public function isExtentOfTaxes(): bool;
}

class Basic extends Person implements Customer {
  public function getMonthlyFee(): float {
    return 5.0;
  }

  public function getAmountToBorrow(): int {
    return 3;
  }

  public function getType(): string {
    return 'Basic';
  }

  public function pay(float $amount) {
    echo "Paying $amount.";
  }

  public function isExtentOfTaxes(): bool {
    return false;
  }
}

class Premium extends Person implements Customer {
  public function getMonthlyFee(): float {
    return 10.0;
  }

  public function getAmountToBorrow(): int {
    return 10;
  }

  public function getType(): string {
    return 'Premium';
  }

  public function pay(float $amount) {
    echo "Paying $amount.";
  }

  public function isExtentOfTaxes(): bool {
    return true;
  }
}

$basic1 = new Basic(1, 'Name', 'Last', 'Email');
$basic2 = new Basic(null, 'Name', 'Last', 'Email');
$premium = new Premium(null, 'Name', 'Last', 'Email');

var_dump($basic1->getId());
//-> 1

var_dump($basic2->getId());
//-> 2

var_dump($premium->getId());
//-> 3

results matching ""

    No results matching ""