martes, 28 de octubre de 2014

PHP (07) POO (09) Métodos estáticos (04) Miembros estáticos y herencias

Para terminar con los métodos estáticos, vamos a ver de forma sencilla como funcionan las herencias entre ellos, siendo algo muy sencillo.
Para empezar vamos a declarar dentro de nuestra clase Mensaje una propiedad que se llame $adios, y que sea estática:
<?php
 class Mensaje
 {
  static $adios = 'Espero verle pronto';
  public static function saludo()
  {
   echo '<h3>Saludos desde Netrunning</h3>';
  }

  public static function personal($nombre)
  {
   echo '<h3>Hola ' . $nombre . ' Bienvenido!!!!';
  }
 }

 Mensaje::saludo();
 Mensaje::personal('Pepe');

?>

Y ahora declaramos una clase Despedida que herede de Mensaje, y en ella un método que estático que acceda a nuestra propiedad, y finalmente llamamos a este método:
<?php
 class Mensaje
 {
  static $adios = 'Espero verle pronto';
  public static function saludo()
  {
   echo '<h3>Saludos desde Netrunning</h3>';
  }

  public static function personal($nombre)
  {
   echo '<h3>Hola ' . $nombre . ' Bienvenido!!!!</h3>';
  }
 }

 class Despedida extends Mensaje
 {
  public static function mostrar_despedida()
  {
   echo '<p>' . Mensaje::$adios . '</p>';
  }
 }

 Mensaje::saludo();
 Mensaje::personal('Pepe');
 Despedida::mostrar_despedida();

?>

Con tan solo observarlos y conociendo ya como funcionan las herencias se puede intuir el resultado:

Saludos desde Netrunning

Hola Pepe Bienvenido!!!!

Espero verle pronto


PHP (07) POO (09) Métodos estáticos (03) Propiedades en métodos estáticos

Se pueden emplear propiedades trabajando con la clase en código y no con un objeto, siempre que estas propiedades sean estáticas.
Para ello lo único que hay que hacer es declarar la propiedad como estática, y un método set publico y estático.
<?php
 class Matematica
 {
  static $dato;

  public static function set_dato($valor)
  {
  ... 
  }
 }

?>

De este modo se pueden almacenar datos en $dato, pero no podemos utilizar $this-> ya que no tenemos un objeto de la clase, pero eso PHP lo solventa con la palabra reservada self, que se utiliza para trabajar con métodos y propiedades estáticos.
Su uso quedaría así:
<?php
 class Matematica
 {
  static $dato;

  public static function set_dato($valor)
  {
   self::$dato = $valor;
  }
 }

?>

De esta forma ya tenemos nuestro dato guardado, y para usarlo se hace utilizando la expresión self::$dato como vemos a continuación:
<?php
 class Matematica
 {
  static $dato;

  public static function set_dato($valor)
  {
   self::$dato = $valor;
   echo '<p>mostrando self::$dato = ' . self::$dato . '<p>';
  }
 }

 Matematica::set_dato(6);

?>

Lo cual nos da como resultado:
mostrando self::$dato = 6

Pero puede resultar tedioso estar todo el tiempo utilizando la secuencia del self, de modo que se puede guardar como si de una variable se tratase, y trabajar con ella de la forma habitual:
<?php
 class Matematica
 {
  static $dato;

  public static function set_dato($valor)
  {
   self::$dato = $valor;
   echo '<p>mostrando self::$dato = ' . self::$dato . '<p>';
   $numero = self::$dato;
   echo '<p><b>Ahora $numero es self::$dato = </b>' . $numero . '</p>';
   $cuadrado = $numero * $numero;
   echo '<p>' . $numero . '<sup>2</sup> = ' . $cuadrado . '</p>';
  }
 }

 Matematica::set_dato(6);

?>

En este caso hemos guardado el valor dentro de de una variable llamada $cuadrado, con la cual hemos hecho un cálculo y nos da como resultado:
mostrando self::$dato = 6
Ahora $numero es self::$dato = 6
62 = 36

lunes, 27 de octubre de 2014

PHP (07) POO (09) Métodos estáticos (02) Paso de datos a un método estático

Sin lugar a dudas, el lector de esta serie de artículos, donde hemos hablado de funciones, clases, metodos... intuirá de forma inmediata como se pasa un dato a un método estático, pero para aquellos que deseen confirmar sus sospechas o que no hayan seguido todo el "manual", lo veremos paso a paso.
Lo primero que haremos sobre nuestro script es crear un nuevo método estático, donde se necesite un argumento:
<?php
 class Mensaje
 {
  public static function saludo()
  {
   echo '<h3>Saludos desde Netrunning</h3>';
  }

  public static function personal($nombre)
  {
   echo '<h3>Hola ' . $nombre . ' Bienvenido!!!!';
  }
 }

 Mensaje::saludo();

?>

Una vez que tenemos el método preparado, tan solo hay que llamarlo como un método estático y publico con su argumento, de este modo:
<?php
 class Mensaje
 {
  public static function saludo()
  {
   echo '<h3>Saludos desde Netrunning</h3>';
  }

  public static function personal($nombre)
  {
   echo '<h3>Hola ' . $nombre . ' Bienvenido!!!!';
  }
 }

 Mensaje::saludo();
 Mensaje::personal('Pepe');

?>


De este modo llamamos al método y le enviamos el dato que necesita, ejecutandose normalmente y dándonos como resultado:

Saludos desde Netrunning

Hola Pepe Bienvenido!!!!

PHP (07) POO (09) Métodos estáticos (01) Creación

Cuando creamos un método estático, lo que estamos haciendo es que podamos acceder a él directamente sin necesidad de crear un objeto de la clase, es decir hacerlo llamando a la clase y el método.
Por ejemplo se puede crear una clase llamada Mensajes, en la cual vamos a incluir un método estático con un mensaje para que aparezca por pantalla:
<?php
 class Mensaje
 {
  public static function saludo()
  {
   echo '<h3>Saludos desde Netrunning</h3>';
  }
 }

?>

Hemos creado método saludo() publica, para que todo el código tenga acceso a él, y estático para que se pueda acceder sin necesidad de utilizar un objeto de la clase.
Pero para acceder al método no podemos utilizar el operador -> ya que no tenemos un objeto de la clase, en su lugar utilizaremos los dobles dos puntos :: ya conocidos por nosotros, y que reciben el nombre de Paamayim Nekudotayim que viene a significar dos puntos dobles en hebreo.

De este modo nuestro pequeño script quedaría así:
<?php
 class Mensaje
 {
  public static function saludo()
  {
   echo '<h3>Saludos desde Netrunning</h3>';
  }
 }

 Mensaje::saludo();

?>

Y el resultado sería:

Saludos desde Netrunning

domingo, 26 de octubre de 2014

PHP (07) POO (08) Carga automática de clases

Hasta ahora hemos visto todo lo relacionado con objetos dentro del mismo archivo, sin embargo la planificación en proyectos grandes donde las clases pueden ser muy grandes con multitud de métodos... pueden resultar más interesante, al igual que cuando hablamos de los includes, que tengamos nuestras clases en diferentes archivos, para que de ese modo pueda estar el código más estructurado y sencillo de entender.

Para este propósito PHP incluye una función que puede ser utilizada de forma muy sencilla, se trata de __autoload().
Su uso como veremos a continuación es sumamente sencillo y nos ayudará muchísimo a la hora de organizar nuestro trabajo.
function __autoload($nombre_clase)
{
 require $nombre_clase . '.php';
}

Vemos que esta función recibe el nombre de una clase como argumento y una vez recibido le añade la extensión del archivo .php y lo requiere, por lo que solo lo carga cuando es necesario.

De este modo podríamos tener dos archivos adicionales que recibirían el nombre de las clases, el primero llamado Person.php:
<?php
 class Person
 {
  var $nombre;
  var $edad;
  
  function set_nombre($dato)
  {
   $this->nombre = $dato;
  }
  
  function get_nombre()
  {
   return $this->nombre;
  }

  function set_edad($dato)
  {
   $this->edad = $dato;
  }
  
  function get_edad()
  {
   return $this->edad;
  }
 }

?>

Y el segundo llamado Ciudad.php:
<?php
class Ciudad extends Person
 {
  var $ciudad;

  function set_ciudad($dato)
  {
   $this->ciudad = $dato;
  }
  
  function get_ciudad()
  {
   return $this->ciudad;
  }

 }
?>

Aparte de nuestro index.php, donde tiene lugar la acción:
<?php
 function __autoload($nombre_clase)
 {
  require $nombre_clase . '.php';
 }

 $persona1 = new Ciudad;
 $persona1->set_nombre('Antonio');
 $persona1->set_edad('20');
 $persona1->set_ciudad('Burgos');

 echo '<p>Mostrando nombre con $persona1->get_nombre: ' . $persona1->get_nombre() . '</p>';
 echo '<p>Mostrando edad con $persona1->get_edad: ' . $persona1->get_edad() . '</p>';
 echo '<p>Mostrando ciudad con $persona1->get_ciudad: ' . $persona1->get_ciudad() . '</p>';

?>

Una vez que tenemos los tres archivos (que deben de estar en la misma carpeta), tan solo hace falta ejecutar el index.php y tendremos el siguiente resultado:
Mostrando nombre con $persona1->get_nombre: Antonio
Mostrando edad con $persona1->get_edad: 20
Mostrando ciudad con $persona1->get_ciudad: Burgos

Algo realmente sencillo.
Con todo lo visto hasta ahora ya estamos listos para afrontar la POO avanzada a partir del próximo articulo.

PHP (07) POO (07) Sobrecarga de métodos

Seguramente si conoces otros lenguajes de programación como JAVA, este apartado te resulte extraño, ya que PHP sobrecarga los métodos de forma muy diferente a como se hace de forma común a otros lenguajes.
Para ello se utiliza un método llamado __call() al que se le pasa como argumentos; el nombre del método y una lista con los argumentos que este método necesitaría. Este método __call, recibe aquellos métodos que no están definidos de forma independiente, comprobando que estén definidos en su interior.
function __call($metodo, $argumentos)
{
 ...
}  

De este modo imaginemos que queremos introducir una sobrecarga en nuestro método set_name, donde podría introducirse el nombre y los apellidos. Deberemos de crear nuestro método __call en relación a este objetivo.
Lo primero que habría que discernir es si el método pasado por argumento es el correcto, haciéndolo con un if:
function __call($metodo, $argumentos)
{
 if ($metodo = 'set_nombre'){
  ...
 }
}

De este modo controlamos que el método tenga el nombre correcto, pero ahora hay que comprobar el número de argumentos y que se debe de hacer en cada caso, ya que como se ha dicho $argumentos es una lista o array.
function __call($metodo, $argumentos)
{
 if ($metodo = 'set_nombre'){
  if (count($argumentos) == 1){
   $this->nombre = $argumentos[0];
  }
  if (count($argumentos) == 2){
   $this->nombre = $argumentos[0];
   $this->apellido = $argumentos[1];
  }
 }
}

El código comprueba el número de elementos enviados en la lista y dependiendo de cuantos haya crea el objeto con o sin apellido. (Recordemos que los arrays tienen como primer elemento el cero.)

De este modo ahora podemos comprobar como funciona con el siguiente código, donde se crean dos objetos, cada uno con un número diferente de argumentos:
<?php
 class Person
 {
  var $nombre;
  var $apellido;
  var $edad;

  //Funcion __call que recoge el nombre sobrecargado
  function __call($metodo, $argumentos)
  {
   if ($metodo = 'set_nombre'){
    if (count($argumentos) == 1){
     $this->nombre = $argumentos[0];
    }
    if (count($argumentos) == 2){
     $this->nombre = $argumentos[0];
     $this->apellido = $argumentos[1];
    }
   }
  }

  //Aquí comienzan los geters y seters de las propiedades. 
  function get_nombre()
  {
   return $this->nombre;
  }
  function get_apellido()
  {
   return $this->apellido;
  }

  function set_edad($dato)
  {
   $this->edad = $dato;
  }
  
  function get_edad()
  {
   return $this->edad;
  }
 }
 $persona1 = new Person;
 $persona1->set_nombre('Antonio');
 $persona1->set_edad('20');

 $persona2 = new Person;
 $persona2->set_nombre('Manuel', 'Gonzalez');
 $persona2->set_edad('28');

 echo '<h3>Persona1</h3>';
 echo '<p>Mostrando con $persona1->get_nombre: ' . $persona1->get_nombre() . '</p>';
 echo '<p>Mostrando con $persona1->get_edad: ' . $persona1->get_edad() . '</p>';
 echo '<h3>Persona2</h3>';
 echo '<p>Mostrando con $persona2->get_nombre: ' . $persona2->get_nombre() . '</p>';
 echo '<p>Mostrando con $persona2->get_apellido: ' . $persona2->get_apellido() . '</p>';
 echo '<p>Mostrando con $persona2->get_edad: ' . $persona2->get_edad() . '</p>';
?> 

En este código podemos ver como esta incluido nuestro método sobrecargado, y como creamos los dos objetos, el que solo lleva un argumento y el que lleva los dos.
Después solicitamos los datos de ambos objetos y obtenemos el siguiente resultado:

Persona1

Mostrando con $persona1->get_nombre: Antonio
Mostrando con $persona1->get_edad: 20

Persona2

Mostrando con $persona2->get_nombre: Manuel
Mostrando con $persona2->get_apellido: Gonzalez
Mostrando con $persona2->get_edad: 28

Como dije al principio, la forma de realizar los métodos sobrecargados en PHP es algo distinta a como se hace en otros lenguajes, pero no es mucho más difícil, tan solo hay que saber controlar el flujo a través de las instrucciones if.
Pero si reflexionamos sobre esto, llegamos a la conclusión de que con un método __call() se pueden controlar todos los métodos para crear un objeto... pero eso lo dejo en vuestras manos...

PHP (07) POO (06) Herencias (05) Sobreescribir métodos

Por sobreescribir métodos se considera que desde una clase heredada, se define un método que se llama igual que otro de la clase padre, de este modo cuando lo invocamos desde un objeto al que llamamos, es al de la clase hijo, haciendo que se ejecute ese código.
En el siguiente ejemplo puede verse claramente:
<?php
 class Person
 {
  var $nombre;
  var $edad;

  function __construct($nombre, $edad)
  {
   $this->nombre=$nombre;
   $this->edad=$edad;
  }

  function set_nombre($dato)
  {
   $this->nombre = $dato;
  }
  
  function get_nombre()
  {
   return $this->nombre;
  }

  function set_edad($dato)
  {
   $this->edad = $dato;
  }
  
  function get_edad()
  {
   return $this->edad;
  }
 }

 class Ciudad extends Person
 {
  var $ciudad;

  function __construct($nombre, $edad, $ciudad)
  {
   parent::__construct($nombre, $edad);
   $this->ciudad=$ciudad;
  }

  function set_ciudad($dato)
  {
   $this->ciudad = $dato;
  }
  
  function get_ciudad()
  {
   return $this->ciudad;
  }

  function get_nombre(){
   $this->nombre = strtoupper($this->nombre);
   return $this->nombre;
  }


 }

 $persona1 = new Ciudad('Angel', '24', 'Cordoba');

 echo '<p>Mostrando nombre con $persona1->get_nombre: ' . $persona1->get_nombre() . '</p>';
 echo '<p>Mostrando edad con $persona1->get_edad: ' . $persona1->get_edad() . '</p>';
 echo '<p>Mostrando ciudad con $persona1->get_ciudad: ' . $persona1->get_ciudad() . '</p>';
?>

Se ha introducido un función llamada get_nombre() en el hijo, de modo que cuando la llamamos es esta la que se ejecuta, en la cual para diferenciarla de la que se encuentra en el padre hemos transformado el string en mayúsculas, obteniendo como resultado:
Mostrando nombre con $persona1->get_nombre: ANGEL
Mostrando edad con $persona1->get_edad: 24
Mostrando ciudad con $persona1->get_ciudad: Cordoba