Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
com
Manual de PHP 5
Explicamos al detalle todas las caractersticas de PHP5, la nueva versin de
PHP, con caractersticas avanzadas de orientacin a objetos.
www.desarrolloweb.com
Introduccin a PHP 5
Con las primeras 2 versiones de PHP, PHP 3 y PHP 4, se haba conseguido una plataforma potente
y estable para la programacin de pginas del lado del servidor. Estas versiones han servido de
mucha ayuda para la comunidad de desarrolladores, haciendo posible que PHP sea el lenguaje
ms utilizado en la web para la realizacin de pginas avanzadas.
Sin embargo, todava existan puntos negros en el desarrollo PHP que se han tratado de solucionar
con la versin 5, aspectos que se echaron en falta en la versin 4, casi desde el da de su
lanzamiento. Nos referimos principalmente a la programacin orientada a objetos (POO) que, a
pesar de que estaba soportada a partir de PHP3, slo implementaba una parte muy pequea de
las caractersticas de este tipo de programacin.
Nota: la orientacin a objetos es una manera de programar que trata de modelar los procesos de
programacin de una manera cercana a la realidad: tratando a cada componente de un programa
como un objeto con sus caractersticas y funcionalidades. Podemos ver una pequea introduccin
en el artculo Qu es la programacion orientada a objetos.
El principal objetivo de PHP5 ha sido mejorar los mecanismos de POO para solucionar las carencias
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
de las anteriores versiones. Un paso necesario para conseguir que PHP sea un lenguaje apto para
todo tipo de aplicaciones y entornos, incluso los ms exigentes.
pgina
de
Wamp
Server,
que
es
la
siguiente:
Como haba comentado, Wamp Server es un programa que instala en un slo paso Apache + PHP +
MySQL y los configura para trabajar juntos.
Habra que hacer la descarga de la
http://www.wampserver.com/en/download.php
ltima
versin
de
Wamp
Server
en:
Apache 2.2.8
PHP 5.2.6 + PECL
SQLitemanager
MySQL 5.0.51b
Phpmyadmin
Una vez descargado el programa, lo ejecutamos para realizar la instalacin de Wamp Server 2. La
instalacin se basa en un asistente normal que nos solicitar varios datos tpicos de instalaciones,
como que aceptemos los trminos de la licencia. Luego nos saldr la ventana para acabar que
marcaremos que ejecute Wamp Server inmediatamente.
www.desarrolloweb.com
Pulsamos el icono con el ratn (botn izquierdo, clic normal) y veremos abajo del todo una
instruccin que pone Put Online, que pondr todos los servicios en funcionamiento.
Ahora, para comprobar que los servicios funcionan slo nos queda abrir un navegador. Vamos a
escribir la siguiente direccin URL en la barra de direcciones:
www.desarrolloweb.com
http://localhost
Entonces nos tiene que salir la pgina de inicio del servidor Apache con PHP 5, personalizada por
Wamp, que es algo como esto:
Si no no sale nada puede que haya habido un problema o un error al iniciar los servicios,
generalmente el Apache, que utiliza el puerto 80 que a veces est ocupado por otro programa
como Skype o IIS. Lee la FAQ: No funciona el Wamp Server 2.
Ahora podremos colocar en nuestro servidor todas las pginas PHP que queramos probar o los
proyectos que hayamos creado anteriormente. El directorio donde generalmente se localiza la raz
de publicacin es: C:\wamp\www
En esa carpeta podramos subir cualquier archivo PHP 4 o PHP 5 y debera ejecutarse
perfectamente. Otra cosa que puede fallar es que los inicios de bloques de cdigo PHP que debis
utilizar son con <?php y no slo con <?, que est deshabilitado por defecto.
Os aseguro que leer este artculo os llevar ms tiempo que instalar PHP 5 en vuestro ordenador.
Con Wamp Server 2 es muy fcil.
www.desarrolloweb.com
www.desarrolloweb.com
Primero veamos una declaracin de un objeto muy simple. Se trata de una "caja" que tiene un
atributo que es el contenido y dos mtodos, uno para introducir nuevos contenidos en la caja y
otro para mostrar el contenido actual de la caja.
class Caja{
var $contenido;
function introduce($cosa){
$this->contenido = $cosa;
}
function muestra_contenido(){
echo $this->contenido;
}
}
Ahora vamos a ver unas pocas lneas de cdigo que hacen uso de la clase Caja para ilustrar el
modo de trabajo de los objetos en PHP 4. Vamos a instanciar el objeto, luego lo asignamos a otra
variable, con lo que se crear un clon de ese objeto, continuamos modificando el clon y veremos
que pasa.
$micaja = new Caja();
$micaja->introduce("algo");
$micaja->muestra_contenido();
echo "<br>";
$segunda_caja = $micaja;
$segunda_caja->introduce("contenido en segunda caja");
$segunda_caja->muestra_contenido();
echo "<br>";
$micaja->muestra_contenido();
En la primera lnea de cdigo se instancia la caja y se aloja el objeto en la variable $micaja. En la
segunda lnea se introduce el string "algo" en el contenido de la caja. Luego se muestra el
contenido, con lo que saldr el string "algo" en la pgina web.
En el segundo bloque de cdigo se asigna el objeto $micaja a la variable $segunda_caja, con lo que
se crea el mencionado clon del objeto $micaja y se asigna a la nueva variable. Luego se introduce
un nuevo contenido a la instancia alojada en la variable $segunda_caja. Atencin aqu, porque se
ha modificado el clon alojado en la variable $segunda_caja, dejando inalterable el objeto original
$micaja.
Para comprobarlo, se muestra el contenido del objeto $segunda_caja, con lo que aparece en la
pgina web el string "contenido en segunda caja". Tambin se muestra el contenido de $micaja,
que no se ha modificado a pesar de actualizar el contenido de su clon, con lo que se muestra el
string "algo".
Espero que no sea demasiado difcil de entender. Podis hacer la prueba por vosotros mismos
para comprender bien el ejercicio. De todos modos, vamos a hacer otro ejemplo en el que se
utiliza la clase Caja, que esperamos sirva para aclarar mejor el trabajo con objetos en PHP 3 y 4.
$micaja = new Caja();
$micaja->introduce("algo");
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
$micaja->muestra_contenido();
echo "<br>";
function vacia_caja($caja_vaciar){
$caja_vaciar->introduce("polvo");
}
vacia_caja($micaja);
$micaja->muestra_contenido();
En este ejemplo hemos creado una funcin que recibe por parmetro un objeto de la clase caja.
Como los parmetros en las funciones se reciben por valor en lugar de referencia, cuando se pasa
el parmetro del objeto caja, en el fondo lo que se est realizando es una copia de ese objeto, de
modo que dentro de la funcin se trabaja con un clon del objeto, en lugar del objeto mismo.
En el cdigo se instancia el objeto caja y se introduce "algo" en su contenido. Luego, se declara
una funcin que recibe el objeto y modifica su contenido, introduciendo el string "polvo" en el
contenido de la caja. En las siguientes lneas de cdigo, se llama a la funcin declarada
anteriormente, pasando por parmetro el objeto $micaja. Dentro de la funcin, como deca, se
modifica el contenido de la caja, aunque realmente se est modificando el contenido de un clon.
Por ltimo, se muestra el contenido del objeto $micaja. En este caso aparece "algo", a pesar de
que en la funcin ese "algo" se modific por "polvo". A pesar de poder parecer pesado, vuelvo a
repetir que en la funcin se modific un clon del objeto y no el objeto original.
Los comportamientos descritos anteriormente no son muy habituales en otros lenguajes de
programacin orientada a objetos, como Java, donde el objeto no se duplica cada vez que se
realiza una asignacin o paso por parmetro.
Para evitar el comportamiento que hemos descrito, PHP dispone de la opcin de paso de
parmetros por referencia, que se realiza con el carcter "&". Por ejemplo, para asignar el propio
objeto y no un clon podramos haber utilizado este cdigo:
$segunda_caja = &$micaja;
Para recibir un parmetro por referencia en lugar de por valor en una funcin utilizaramos esta
declaracin de funcin:
function vacia_caja(&$caja_vaciar){
La posibilidad de utilizar el carcter "&" para forzar un paso por referencia no deja de ser un
problema, puesto que nos obliga a utilizar ese mecanismo en mltiples lugares y es muy fcil
olvidarse del "&" en algn sitio, con lo que nuestro programa ya no realizar los resultados
esperados. Muchos programadores han gastado horas en encontrar el problema y en cualquier
caso, es una molestia tener que estar pendientes de incluir constantemente el signo "&" en el
cdigo para hacer que funcione como ellos desean.
www.desarrolloweb.com
Como decamos, uno de los problemas ms bsicos de las versiones anteriores de PHP era la
clonacin de objetos, que se realizaba al asignar un objeto a otra variable o al pasar un objeto por
parmetro en una funcin. Para solventar este problema PHP5 hace uso de los manejadores de
objetos (Object handles), que son una especie de punteros que apuntan hacia los espacios en
memoria donde residen los objetos. Cuando se asigna un manejador de objetos o se pasa como
parmetro en una funcin, se duplica el propio object handle y no el objeto en si.
Nota: Tambin se puede realizar una clonacin de un objeto, para obtener una copia exacta,
pero que no es el propio objeto. Para ello utilizamos una nueva instruccin llamada "clone", que
veremos ms adelante.
www.desarrolloweb.com
Clases en PHP 5
Las clases en Programacin orientada a objetos (POO) son definiciones de los elementos que
forman un sistema, en este caso, definiciones de los objetos que van a intervenir en nuestros
programas.
Un objeto se define indicando qu propiedades y funcionalidades tiene. Justamente esas
declaraciones son lo que es una clase. Cuando se hace una clase simplemente se especifica qu
propiedades y funcionalidades tiene. Por ejemplo, un hombre podra tener como propiedades el
nombre o la edad y como funcionalidades, comer, moverse o estudiar.
En la clase hombre declararamos dos atributos: la edad o el nombre, que seran como dos
variables. Tambin deberamos crear tres mtodos, con los procedimientos a seguir para que el
hombre pueda comer, moverse o estudiar. Estos mtodos se definen declarando funciones dentro
de la clase.
El cdigo para definir una clase se puede ver a continuacin:
www.desarrolloweb.com
class hombre{
var $nombre;
var $edad;
function comer($comida){
//aqu el cdigo del mtodo
}
function moverse($destino){
//aqu el cdigo del mtodo
}
function estudiar($asignatura){
//aqu el cdigo del mtodo
}
}
Podr comprobarse que este cdigo no difiere en nada del de las versiones anteriores de PHP, que
ya soportaban ciertas caractersticas de la POO. Esta situacin cambiar a poco que exploremos las
caractersticas ms avanzadas de PHP 5, que implicarn mejoras que no estaban presentes en las
versiones anteriores
Conclusin
Es importante darse cuenta de la diferencia entre un objeto y una clase. La clase es una definicin
de unas caractersticas y funcionalidades, algo abstracto que se concreta con la instanciacin de un
objeto
de
dicha
clase.
Un objeto ya tiene propiedades, con sus valores concretos, y se le pueden pasar mensajes (llamar
a los mtodos) para que hagan cosas.
www.desarrolloweb.com
a sus atributos y eso es de lo que se encarga el constructor. Los constructores pueden recibir unos
datos para inicializar los objetos como se desee en cada caso.
La sintaxis para la creacin de constructor vara con respecto a la de PHP 3 y 4, pues debe llamarse
con un nombre fijo: __construct(). (Son dos guiones bajos antes de la palabra "construct")
A lo largo de los ejemplos de este manual vamos a ir creando un cdigo para gestin de un
videoclub. Vamos a empezar definiendo una clase cliente, que utilizaremos luego en nuestro
programa.
class cliente{
var $nombre;
var $numero;
var $peliculas_alquiladas;
function __construct($nombre,$numero){
$this->nombre=$nombre;
$this->numero=$numero;
$this->peliculas_alquiladas=array();
}
function dame_numero(){
return $this->numero;
}
}
El constructor en esta clase recibe el nombre y nmero que asignar al cliente, que introduce luego
en sus correspondientes propiedades. Adems inicializa el atributo pelculas_alquiladas como un
array, en este caso vaco porque todava no tiene ninguna pelcula en su poder.
Nota: En programacin orientada a objetos $this hace referencia al objeto sobre el que se est
ejecutando el mtodo. En este caso, como se trata de un constructor, $this hace referencia al
objeto que se est construyendo. Con $this->nombre=$nombre; estamos asignando al atributo
nombre del objeto que se est construyendo el valor que contiene la variable $nombre, que se
ha recibido por parmetro.
Luego hemos creado un mtodo muy sencillo para poder utilizar el objeto. Vamos a ver unas
acciones simples para ilustrar el proceso de instanciacin y utilizacin de los objetos.
//instanciamos un par de objetos cliente
$cliente1 = new cliente("Pepe", 1);
$cliente2 = new cliente("Roberto", 564);
//mostramos el numero de cada cliente creado
echo "El identificador del cliente 1 es: " . $cliente1->dame_numero();
echo "El identificador del cliente 2 es: " . $cliente2->dame_numero();
Este ejemplo obtendra esta salida como resultado de su ejecucin:
El identificador del cliente 1 es: 1
El identificador del cliente 2 es: 564
www.desarrolloweb.com
En este artculo estudiaremos una alternativa muy sencilla, pero totalmente funcional para poder
simular la sobrecarga de mtodos, de modo que aprovechemos sus posibilidades tal como si fuera
algo nativamente soportado por PHP. En concreto, encararemos el problema con los mtodos
constructores, de modo que podamos construir objetos con distintos juegos de parmetros.
www.desarrolloweb.com
El truco est en tener un mtodo "genrico" que no recibe parmetros y un mtodo especfico
para cada nmero de parmetros que pensemos aceptar. El mtodo "genrico" lo declaramos sin
indicar ningn parmetro y dentro de su cdigo utilizar la funcin de PHP func_get_args(), que nos
permite de manera genrica extraer todos los parmetros que pueda estar recibiendo la funcin.
Una vez sabemos el nmero de parmetros que nos han enviado en tiempo de ejecucin,
podemos invocar a la funcin especfica que tiene el cdigo a ejecutar cuando se recibe ese
nmero concreto de parmetros.
Viendo el cdigo del siguiente ejemplo y leyendo sus comentarios podremos entender mejor esta
tcnica.
class jugador
{
private $nombre;
private $equipo;
function __construct()
{
//obtengo un array con los parmetros enviados a la funcin
$params = func_get_args();
//saco el nmero de parmetros que estoy recibiendo
$num_params = func_num_args();
//cada constructor de un nmero dado de parmtros tendr un nombre de
funcin
//atendiendo al siguiente modelo __construct1() __construct2()...
$funcion_constructor ='__construct'.$num_params;
//compruebo si hay un constructor con ese nmero de parmetros
if (method_exists($this,$funcion_constructor)) {
//si exista esa funcin, la invoco, reenviando los parmetros que recib en el
constructor original
call_user_func_array(array($this,$funcion_constructor),$params);
}
}
//ahora declaro una serie de mtodos constructores que aceptan diversos nmeros de
parmetros
function __construct0()
{
$this>__construct1("Annimo");
}
function __construct1($nombre)
{
$this>__construct2($nombre, "Sin equipo");
}
function __construct2($nombre, $equipo)
{
$this>nombre = $nombre;
$this>equipo = $equipo;
}
}
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
Podran existir otros mecanismos para obtener sobrecarga de constructores en PHP, pero ste que
hemos visto creo que es el ms limpio y el que mejor respeta la filosofa de la Programacin
Orientada a Objetos.
www.desarrolloweb.com
Modificador public
Es el nivel de acceso ms permisivo. Sirve para indicar que el mtodo o atributo de la clase es
pblico. En este caso se puede acceder a ese atributo, para visualizarlo o editarlo, por cualquier
otro elemento de nuestro programa. Es el modificador que se aplica si no se indica otra cosa.
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
Veamos un ejemplo de clase donde hemos declarado como public sus elementos, un mtodo y
una propiedad. Se trata de la clase "dado", que tiene un atributo con su puntuacin y un mtodo
para tirar el dado y obtener una nueva puntuacin aleatoria.
class dado{
public $puntos;
function __construct(){
srand((double)microtime()*1000000);
}
public function tirate(){
$this->puntos=$randval = rand(1,6);
}
}
$mi_dado = new dado();
for ($i=0;$i<30;$i++){
$mi_dado->tirate();
echo "<br>Han salido " . $mi_dado->puntos . " puntos";
}
Vemos la declaracin de la clase dado y luego unas lneas de cdigo para ilustrar su
funcionamiento. En el ejemplo se realiza un bucle 30 veces, en las cuales se tira el dado y se
muestra la puntuacin que se ha obtenido.
Como el atributo $puntos y el mtodo tirate() son pblicos, se puede acceder a ellos desde fuera
del objeto, o lo que es lo mismo, desde fuera del cdigo de la clase.
Modificador private
Es el nivel de acceso ms restrictivo. Sirve para indicar que esa variable slo se va a poder acceder
desde el propio objeto, nunca desde fuera. Si intentamos acceder a un mtodo o atributo
declarado private desde fuera del propio objeto, obtendremos un mensaje de error indicando que
no es posible a ese elemento.
Si en el ejemplo anterior hubiramos declarado private el mtodo y la propiedad de la clase dado,
hubiramos recibido un mensaje de error.
Aqu tenemos otra posible implementacin de la clase dado, declarando como private el atributo
puntos y el mtodo tirate().
class dado{
private $puntos;
function __construct(){
srand((double)microtime()*1000000);
}
private function tirate(){
$this->puntos=$randval = rand(1,6);
}
public function dame_nueva_puntuacion(){
$this->tirate();
return $this->puntos;
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
}
}
$mi_dado = new dado();
for ($i=0;$i<30;$i++){
echo "<br>Han salido " . $mi_dado->dame_nueva_puntuacion() . " puntos";
}
Hemos tenido que crear un nuevo mtodo pblico para operar con el dado, porque si es todo
privado no hay manera de hacer uso de l. El mencionado mtodo es dame_nueva_puntuacin(),
que realiza la accin de tirar el dado y devolver el valor que ha salido.
Modificador protected
Este indica un nivel de acceso medio y un poco ms especial que los anteriores. Sirve para que el
mtodo o atributo sea pblico dentro del cdigo de la propia clase y de cualquier clase que herede
de aquella donde est el mtodo o propiedad protected. Es privado y no accesible desde cualquier
otra parte. Es decir, un elemento protected es pblico dentro de la propia clase y en sus
heredadas.
Ms adelante explicaremos la herencia y podremos ofrecer ejemplos con el modificador
protected.
Conclusin
Muchas veces el propio desarrollador es el que fija su criterio a la hora de aplicar los distintos
modificadores de acceso a atributos y mtodos. Poca proteccin implica que los objetos pierdan
su encapsulacin y con ello una de las ventajas de la POO. Una proteccin mayor puede hacer ms
laborioso de generar el cdigo del programa, pero en general es aconsejable.
www.desarrolloweb.com
3.Herencia en PHP 5
Los mecanismos de herencia son una de las herramientas fundamentales que disponen los
desarrolladores en la programacin orientada a objetos. Vemos cmo funciona en PHP 5.
www.desarrolloweb.com
El esquema de herencia que vamos a realizar en este ejemplo se puede ver en la siguiente imagen.
www.desarrolloweb.com
Nota: Como se ha definido como private el atributo precio, este atributo slo se podr acceder
dentro del cdigo de la clase, es decir, en la propia definicin del objeto. Si queremos acceder al
precio desde fuera de la clase (algo muy normal si tenemos en cuenta que vamos a necesitar el
precio de un soporte desde otras partes de la aplicacin) ser necesario crear un mtodo que
nos devuelva el valor del precio. Este mtodo debera definirse como public, para que se pueda
acceder desde cualquier sitio que se necesite.
En todos los mtodos se hace uso de la variable $this. Esta variable no es ms que una referencia
al objeto sobre el que se est ejecutando el mtodo. En programacin orientada a objetos, para
ejecutar cualquiera de estos mtodos, primero tenemos que haber creado un objeto a partir de
una clase. Luego podremos llamar los mtodos de un objeto. Esto se hace con $mi_objeto>metodo_a_llamar(). Dentro de mtodo, cuando se utiliza la variable $this, se est haciendo
referencia al objeto sobre el que se ha llamado al mtodo, en este caso, el objeto $mi_objeto. Con
$this->titulo estamos haciendo referencia al atributo "titulo" que tiene el objeto $mi_objeto.
Si queremos probar la clase soporte, para confirmar que se ejecuta correctamente y que ofrece
resultados coherentes, podemos utilizar un cdigo como el siguiente.
$soporte1 = new soporte("Los Intocables",22,3);
echo "<b>" . $soporte1->titulo . "</b>";
echo "<br>Precio: " . $soporte1->dame_precio_sin_iva() . " euros";
echo "<br>Precio IVA incluido: " . $soporte1->dame_precio_con_iva() . " euros";
En este caso hemos creado una instancia de la clase soporte, en un objeto que hemos llamado
$soporte1. Luego imprimimos su atributo titulo (como el ttulo ha sido definido como public,
podemos acceder a l desde fuera del cdigo de la clase.
Luego se llaman a los mtodos dame_precio_sin_iva() y dame_precio_con_iva() para el objeto
creado.
Nos dara como resultado esto:
Los Intocables
Precio: 3 euros
Precio IVA incluido: 3.48 euros
En siguientes captulos vamos a ver cmo definir clases que hereden de la clase soporte.
www.desarrolloweb.com
Sobrescribir mtodos
Antes de mostrar el cdigo de la clase cinta_video, vamos a hablar sobre la sobrescritura o
sustitucin de mtodos, que es un mecanismo por el cual una clase que hereda puede redefinir los
mtodos que est heredando.
Pensemos en una cafetera. Sabemos que existen muchos tipos de cafeteras y todas hacen caf,
pero el mecanismo para hacer el caf es distinto dependiendo del tipo de cafetera. Existen
cafeteras express, cafeteras por goteo y hasta se puede hacer caf con un calcetn. Nuestra
cafetera "padre" (de la que va a heredar todas las cafeteras) puede tener definido un mtodo
hacer_cafe(), pero no necesariamente todas las cafeteras que puedan heredar de esta hacen el
caf siguiendo el mismo proceso.
Entonces podemos definir un mtodo para hacer caf estndar, que tendra la clase cafetera. Pero
al definir las clases cafetera_express y cafetera_goteo, deberamos sobrescribir el mtodo
hacer_cafe() para que se ajuste al procedimiento propio de estas.
La sobrescritura de mtodos es algo bastante comn en mecanismos de herencia, puesto que los
mtodos que fueron creados para una clase "padre" no tienen por qu ser los mismos que los
definidos en las clases que heredan.
Veremos cmo sobrescribir o sustituir mtodos en un ejemplo de herencia, siguiendo nuestro
ejemplo de videoclub.
www.desarrolloweb.com
www.desarrolloweb.com
www.desarrolloweb.com
else
echo "<br>Para " . $this->min_num_jugadores . " jugadores";
}else{
echo "<br>De " . $this->min_num_jugadores . " a " . $this->max_num_jugadores . "
Jugadores.";
}
}
public function imprime_caracteristicas(){
echo "Juego para: " . $this->consola . "<br>";
parent::imprime_caracteristicas();
echo "<br>" . $this->imprime_jugadores_posibles();
}
}
Nos fijamos en el constructor, que llama al constructor de la clase padre para inicializar algunos
atributos propios de los soportes en general.
Luego nos fijamos en el mtodo imprime_jugadores_posibles(), que muestra los jugadores
permitidos. Ha sido declarada como public, para que se pueda acceder a ella desde cualquier
lugar. Nos da un mensaje como "Para un jugador" o "De 1 a 2 Jugadores", dependiendo de los
valores min_num_jugadores y max_num_jugadores.
Por su parte, se sobrescribe la funcin imprime_caracteristicas(), para mostrar todos los datos de
cada juego. Primero se muestra la consola para la que se ha creado el juego. Los datos generales
(propios de la clase "soporte") se muestran llamando al mismo mtodo de la clase "parent" y el
nmero de jugadores disponibles se muestra con una llamada al mtodo
imprime_jugadores_posibles().
Podramos utilizar un cdigo como el que sigue, si es que queremos comprobar que la clase
funciona correctamente y que nos ofrece la salida que estbamos pensando.
$mijuego = new juego("Final Fantasy", 21, 2.5, "Playstation",1,1);
$mijuego->imprime_caracteristicas();
//esta lnea dara un error porque no se permite acceder a un atributo private del objeto
//echo "<br>Jugadores: " . $mijuego->min_num_jugadores;
//habria que crear un mtodo para que acceda a los atributos private
$mijuego->imprime_jugadores_posibles();
echo "<p>";
$mijuego2 = new juego("GP Motoracer", 27, 3, "Playstation II",1,2);
echo "<b>" . $mijuego2->titulo . "</b>";
$mijuego2->imprime_jugadores_posibles();
Este cdigo que utiliza la clase "juego" dar como salida:
Juego para: Playstation
Final Fantasy
2.5 (IVA no incluido)
Para un jugador
Para un jugador
GP Motoracer
De 1 a 2 Jugadores.
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
www.desarrolloweb.com
www.desarrolloweb.com
}
}
El constructor de la clase cliente recibe los datos para inicializar el objeto. Estos son $nombre,
$numero y $max_alquiler_concurrente. Si nos fijamos, se ha definido por defecto a 3 el nmero
mximo de alquileres que puede tener un cliente, de modo que, en el caso de que la llamada al
constructor no enve el parmetro $max_alquiler_concurrente se asumir el valor 3.
El atributo soportes_alquilados, como habamos adelantado, ser un array que tendr tantas
casillas como el mximo de alquileres concurrentes. En las ltimas lneas se inicializan a null el
contenido de las casillas del array.
==
$soporte-
Este recibe un soporte y devuelve true si est entre los alquileres del cliente. Devuelve false en
caso contrario.
A este mtodo lo llamamos desde dentro de la clase cliente, en la codificacin de otro mtodo.
Podramos haber definido entonces el mtodo como private, si penssemos que slo lo vamos a
utilizar desde dentro de esta clase. En este caso lo hemos definido como public (el modificador por
defecto) porque pensamos que puede ser til para otras partes del programa.
Este mtodo recibe un soporte (cualquier tipo de soporte, tanto cintas de vdeo, como DVDs o
juegos). Realiza un recorrido por el array de soportes alquilados preguntando a cada soporte que
tenga alquilado el cliente si su nmero de identificacin es igual que el del soporte recibido por
parmetro. Como el nmero de identificacin del soporte est definido como private en la clase
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
valor
tenemos
que
utilizar
el
mtodo
de
soporte
Otra cosa importante. Como no es seguro que en el array de soportes alquilados haya algn
soporte (recordamos que si el cliente no tiene nada alquilado las casillas estn a null), antes de
llamar a ningn mtodo del soporte debemos comprobar que realmente existe. Esto se hace con
la funcin is_null() a la que le enviamos la casilla del array donde queremos comprobar si existe un
soporte. Si la funcin is_null() devuelve true es que tiene almacenado el valor null, con lo que
sabremos que no hay soporte. De manera contraria, si la casilla almacena un soporte, la funcin
is_null() devolver false.
Mtodo alquila($soporte)
function alquila($soporte){
if ($this->tiene_alquilado($soporte)){
echo "<p>El cliente ya tiene alquilado el soporte <b>" . $soporte->titulo . "</b>";
}elseif ($this->num_soportes_alquilados==$this->max_alquiler_concurrente){
echo "<p>Este cliente tiene " . $this->num_soportes_alquilados . " elementos alquilados. ";
echo "No puede alquilar ms en este videoclub hasta que no devuelva algo";
}else{
//miro en el array a ver donde tengo sitio para meter el soporte
$cont = 0;
while (!is_null($this->soportes_alquilados[$cont])){
$cont++;
}
$this->soportes_alquilados[$cont]=$soporte;
$this->num_soportes_alquilados++;
echo "<p><b>Alquilado soporte a: </b>" . $this->nombre . "<br>";
$soporte->imprime_caracteristicas();
}
}
Este mtodo sirve para alquilar una pelcula o juego por parte del cliente. Recibe el soporte a
alquilar y, en caso que el alquiler se pueda producir, debe introducir el objeto soporte recibido en
el array de soportes alquilados del cliente.
Lo primero que hace es comprobar que el cliente no tiene alquilado ese mismo soporte, utilizando
el mtodo tiene_alquilado() de la clase soporte. Si no lo tiene alquilado comprueba que todava
tiene capacidad para alquilar otro soporte, es decir, que no ha llegado al mximo en el nmero de
soportes alquilados.
Si se puede alquilar el soporte, lo introduce dentro del array soportes_alquilados en una posicin
vaca (una casilla donde antes hubiera un null), incrementa en uno el nmero de soportes
alquilados e imprime las caractersticas del soporte que se ha alquilado.
Mtodo devuelve($identificador_soporte)
function devuelve($identificador_soporte){
if ($this->num_soportes_alquilados==0){
echo "<p>Este cliente no tiene alquilado ningn elemento";
return false;
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
}
//recorro el array a ver si encuentro el soporte con identificador recibido
for ($i=0;$i<$this->max_alquiler_concurrente;$i++){
if (!is_null($this->soportes_alquilados[$i])){
if ($this->soportes_alquilados[$i]->dame_numero_identificacion() == $identificador_soporte){
echo "<p>Soporte devuelto: " . $identificador_soporte;
echo " <b>" . $this->soportes_alquilados[$i]->titulo . "</b>";
$this->soportes_alquilados[$i]=null;
$this->num_soportes_alquilados--;
return true;
}
}
}
//si estoy aqui es que el cliente no tiene ese soporte alquilado
echo "<p>No se ha podido encontrar el soporte en los alquileres de este cliente";
return false;
}
El mtodo devuelve recibe el identificador del soporte que debe devolver el cliente. Devuelve true
si se consigui devolver el soporte, false en caso contrario. Lo primero que hace es comprobar si el
cliente tiene alquilado algn soporte, comprobando que la variable num_soportes_alquilados no
sea cero.
Luego hace un recorrido por el array de soportes alquilados para ver si encuentra el soporte que
se desea devolver. Para cada soporte alquilado (cada casilla del array que no contenga el valor
null) comprueba si el identificador es el mismo que el recibido por parmetro. Cuando encuentra
el soporte, muestra un mensaje por pantalla y lo devuelve simplemente poniendo a null la casilla
correspondiente del array soportes_alquilados y decrementando en uno el atributo
num_soportes_alquilados.
Si se encuentra el soporte, se sale de la funcin devolviendo true. Por lo que, si no se ha salido de
la funcin despus de hacer el recorrido por el array, sabemos que no se ha encontrado ese
soporte. Entonces mostramos un mensaje en pantalla y devolvemos false.
Mtodo lista_alquileres()
function lista_alquileres(){
if ($this->num_soportes_alquilados==0){
echo "<p>Este cliente no tiene alquilado ningn elemento";
}else{
echo "<p><b>El cliente tiene " . $this->num_soportes_alquilados . " soportes alquilados</b>";
//recorro el array para listar los elementos que tiene alquilados
for ($i=0;$i<$this->max_alquiler_concurrente;$i++){
if (!is_null($this->soportes_alquilados[$i])){
echo "<p>";
$this->soportes_alquilados[$i]->imprime_caracteristicas();
}
}
}
}
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
Este mtodo hace un recorrido por el array de soportes alquilados y muestra las caractersticas de
cada soporte. Comprueba que el cliente tiene algo alquilado antes de hacer el recorrido.
Recordar siempre, antes de llamar a un mtodo del soporte almacenado en cada casilla del array,
comprobar que el contenido de esa casilla no es null.
Mtodo imprime_caracteristicas()
function imprime_caracteristicas(){
echo "<p><b>Cliente " . $this->numero . ":</b> " . $this->nombre;
echo "<br>Alquileres actuales: " . $this->num_soportes_alquilados
}
Simplemente muestra algunos de los datos del cliente. Es un mtodo para obtener algn dato por
pantalla de un cliente.
Comprobar el funcionamiento de la clase cliente
Es importante sealar que, para que la clase cliente funcione, debe disponer de los cdigos de las
distintas clases de las que hace uso (la clase soporte, cinta_video, juego y dvd). Estos cdigos se
pueden haber escrito en el mismo archivo o bien incluirse con unas instrucciones como estas:
include "soporte.php";
include "dvd.php";
include "juego.php";
include "cinta_video.php";
La clase cliente se puede poner en funcionamiento, para probar su correcta implementacin, con
un cdigo como este:
//instanciamos un par de objetos cliente
$cliente1 = new cliente("Pepe", 1);
$cliente2 = new cliente("Roberto", 564);
//mostramos el numero de cada cliente creado
echo "El identificador del cliente 1 es: " . $cliente1->dame_numero();
echo "<br>El identificador del cliente 2 es: " . $cliente2->dame_numero();
//instancio algunos soportes
$soporte1 = new cinta_video("Los Otros", 1, 3.5, "115 minutos");
$soporte2 = new juego("Final Fantasy", 2, 2.5, "Playstation",1,1);
$soporte3 = new dvd("Los Intocables", 3, 3, "Ingls y espaol","16:9");
$soporte4 = new dvd("El Imperio Contraataca", 4, 3, "Ingls y espaol","16:9");
//alquilo algunos soportes
$cliente1->alquila($soporte1);
$cliente1->alquila($soporte2);
$cliente1->alquila($soporte3);
//voy a intentar alquilar de nuevo un soporte que ya tiene alquilado
$cliente1->alquila($soporte1);
//el cliente tiene 3 soportes en alquiler como mximo
//este soporte no lo va a poder alquilar
$cliente1->alquila($soporte4);
//este soporte no lo tiene alquilado
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
$cliente1->devuelve(4);
//devuelvo un soporte que s que tiene alquilado
$cliente1->devuelve(2);
//alquilo otro soporte
$cliente1->alquila($soporte4);
//listo los elementos alquilados
$cliente1->lista_alquileres();
La ejecucin de este cdigo, si todo funciona correctamente, debera devolvernos como
resultado esta salida:
El identificador del cliente 1 es: 1
El identificador del cliente 2 es: 564
Alquilado soporte a: Pepe
Pelcula en VHS:
Los Otros
3.5 (IVA no incluido)
Duracin: 115 minutos
Alquilado soporte a: Pepe
Juego para: Playstation
Final Fantasy
2.5 (IVA no incluido)
Para un jugador
Alquilado soporte a: Pepe
Pelcula en DVD:
Los Intocables
3 (IVA no incluido)
Ingls y espaol
El cliente ya tiene alquilado el soporte Los Otros
Este cliente tiene 3 elementos alquilados. No puede alquilar ms en este videoclub hasta que no
devuelva algo
No se ha podido encontrar el soporte en los alquileres de este cliente
Soporte devuelto: 2 Final Fantasy
Alquilado soporte a: Pepe
Pelcula en DVD:
El Imperio Contraataca
3 (IVA no incluido)
Ingls y espaol
El cliente tiene 3 soportes alquilados
Pelcula en VHS:
Los Otros
3.5 (IVA no incluido)
Duracin: 115 minutos
Pelcula en DVD:
El Imperio Contraataca
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
3 (IVA no incluido)
Ingls y espaol
Pelcula en DVD:
Los Intocables
3 (IVA no incluido)
Ingls y espaol
www.desarrolloweb.com
El atributo $productos ser un array con los distintos soportes en alquiler. $num_productos lo
utilizaremos para llevar la cuenta del nmero de productos que tenemos disponibles. De modo
similar, $socios ser un array de clientes y $num_socios llevar la cuenta de los socios que
tenemos dados de alta. Aparte, nuestro videoclub tendr un nombre, que almacenaremos en la
variable $nombre.
Constructor
function __construct($nombre){
$this->nombre=$nombre;
$this->productos=array();
$this->num_productos=0;
$this->socios=array();
$this->num_socios=0;
}
Este mtodo inicializar los atributos del objeto que se est construyendo. Recibe nicamente el
nombre del videoclub. Como tareas destacables estn las inicializaciones de los arrays de
productos y socios y la puesta a cero de los contadores que vamos a utilizar.
Mtodo incluir_producto()
private function incluir_producto($nuevo_producto){
$this->productos[$this->num_productos]=$nuevo_producto;
echo "<p>Incluido soporte " . $this->num_productos;
$this->num_productos++;
}
Este mtodo ha sido declarado como private, porque slo queremos que se llame desde dentro de
la clase. Recibe el nuevo producto que se quiere dar de alta y lo guardar en el array de productos,
en la posicin marcada por el atributo num_productos. Luego muestra un mensaje por pantalla y
por ltimo incrementa a uno el atributo num_productos
www.desarrolloweb.com
Podemos fijarnos que el nmero de identificacin del soporte, que recibe el constructor de las
cintas de vdeo, DVDs o juegos, lo generamos por medio del atributo de la clase de videclub
num_productos, que guarda el nmero de productos dados de alta.
Mtodo incluir_socio()
Este mtodo hace las tareas de instanciacin del socio nuevo y su inclusin en el array de socios.
function incluir_socio($nombre,$max_alquiler_concurrente=3){
$socio_nuevo = new cliente($nombre,$this->num_socios,$max_alquiler_concurrente);
$this->socios[$this->num_socios]=$socio_nuevo;
echo "<p>Incluido socio " . $this->num_socios;
$this->num_socios++;
}
Reciben los datos del nuevo socio: nombre y el mximo nmero de pelculas que puede alquilar
(siendo 3 el valor por defecto). Una vez instanciado el nuevo socio, lo introduce en el array, en la
posicin marcada por el atributo num_socios. Luego muestran un mensaje por pantalla y por
ltimo incrementan a uno los atributos num_productos o num_socios.
El nmero de socio, que recibe entre otros parmetros, el constructor de la clase socio lo
generamos por medio del contador de socios num_socios, de la clase videclub.
Mtodo alquila_a_socio()
Realiza las acciones necesarias para alquiler un producto a un socio.
function alquila_a_socio($numero_socio,$numero_producto){
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
if (is_null($this->socios[$numero_socio])){
echo "<p>No existe ese socio";
}elseif(is_null($this->productos[$numero_producto])){
echo "<p>No existe ese soporte";
}else{
$this->socios[$numero_socio]->alquila($this->productos[$numero_producto]);
}
}
Este mtodo recibe el identificador del socio y del producto en alquiler. Antes de proceder, realiza
un par de comprobaciones. La primera para ver si existe un socio con el nmero de socio indicado
por parmetro y la segunda para ver si tambin existe un producto con el nmero de producto
dado.
Si todo fue bien, llama al mtodo alquila() del socio, envindole el producto que desea alquilar.
Nota:El mtodo alquila() del socio tiene cierta complejidad, pero ya la vimos cuando
explicamos la clase socio. En este momento, por el principio de encapsulacin de la POO,
debemos abstraernos de su dificultad y no prestarle atencin porque sabemos que
funciona y no nos debe preocupar cmo lo hace.
Para probar la clase videoclub podramos utilizar un cdigo como este:
$vc = new videoclub("La Eliana Video");
//voy a incluir unos cuantos soportes de prueba
$vc->incluir_juego("Final Fantasy", 2.5, "Playstation",1,1);
$vc->incluir_juego("GP Motoracer", 3, "Playstation II",1,2);
$vc->incluir_dvd("Los Otros", 4.5, "Ingls y espaol","16:9");
$vc->incluir_dvd("Ciudad de Dis", 3, "Portugus, ingls y espaol","16:9");
$vc->incluir_dvd("Los Picapiedra", 3, "Espaol","16:9");
$vc->incluir_cinta_video("Los Otros", 4.5, "115 minutos");
$vc->incluir_cinta_video("El nombre de la Rosa", 1.5, "140 minutos");
//listo los productos
$vc->listar_productos();
//voy a crear algunos socios
$vc->incluir_socio("Jos Fuentes");
$vc->incluir_socio("Pedro Garca",2);
$vc->alquila_a_socio(1,2);
$vc->alquila_a_socio(1,3);
//alquilo otra vez el soporte 2 al socio 1.
// no debe dejarme porque ya lo tiene alquilado
$vc->alquila_a_socio(1,2);
//alquilo el soporte 6 al socio 1.
//no se puede porque el socio 1 tiene 2 alquileres como mximo
$vc->alquila_a_socio(1,6);
//listo los socios
$vc->listar_socios();
www.desarrolloweb.com
Se hace una carga de datos y una llamada a todos los mtodos que hemos visto para el videoclub.
Este cdigo dar como resultado una salida como la siguiente:
Incluido soporte 0
Incluido soporte 1
Incluido soporte 2
Incluido soporte 3
Incluido soporte 4
Incluido soporte 5
Incluido soporte 6
Listado de los 7 productos disponibles:
Juego para: Playstation
Final Fantasy
2.5 (IVA no incluido)
Para un jugador
Juego para: Playstation II
GP Motoracer
3 (IVA no incluido)
De 1 a 2 Jugadores.
Pelcula en DVD:
Los Otros
4.5 (IVA no incluido)
Ingls y espaol
Pelcula en DVD:
Ciudad de Dis
3 (IVA no incluido)
Portugus, ingls y espaol
Pelcula en DVD:
Los Picapiedra
3 (IVA no incluido)
Espaol
Pelcula en VHS:
Los Otros
4.5 (IVA no incluido)
Duracin: 115 minutos
Pelcula en VHS:
El nombre de la Rosa
1.5 (IVA no incluido)
Duracin: 140 minutos
Incluido socio 0
www.desarrolloweb.com
Incluido socio 1
Alquilado soporte a: Pedro Garca
Pelcula en DVD:
Los Otros
4.5 (IVA no incluido)
Ingls y espaol
Alquilado soporte a: Pedro Garca
Pelcula en DVD:
Ciudad de Dis
3 (IVA no incluido)
Portugus, ingls y espaol
El cliente ya tiene alquilado el soporte Los Otros
Este cliente tiene 2 elementos alquilados. No puede alquilar ms en este videoclub hasta que no
devuelva algo
Listado de 2 socios del videoclub:
Cliente 0: Jos Fuentes
Alquileres actuales: 0
Cliente 1: Pedro Garca
Alquileres actuales: 2
Hasta aqu ha llegado por ahora el desarrollo de este videoclub, que no es muy funcional pero
esperamos que haya servido para empezar a conocer las caractersticas de la programacin
orientada a objetos.
En adelante, seguiremos este manual comentando otras particularidades de la POO en PHP 5, que
tambin hay que conocer.
www.desarrolloweb.com
www.desarrolloweb.com
Las clases que incorporan mtodos abstractos se deben declarar como abstractas. Es una
condicin forzosa. Las clases abstractas no se pueden instanciar. Es decir, no podemos crear
objetos a partir de ellas. Es algo lgico. Pensemos en los productos lcteos, estos no existen ms
que como una idea general. Slo podremos encontrar productos lcteos de un tipo en concreto,
como leche o yogur, pero no la idea de producto lcteo en general.
Una clase que herede de un producto lcteo debe definir los mtodos abstractos declarados en la
clase abstracta. De lo contrario, la clase que hereda estara obligada a declararse como abstracta.
En nuestro ejemplo de videoclub, tratado a lo largo de los distintos captulos del manual de PHP 5,
tenemos una clase que tambin sera un buen ejemplo de clase abstracta. Se trata de la clase
soporte. De esta clase heredaban los distintos productos del videoclub, como pelculas en DVD,
cintas de vdeo o juegos. No hubiera sido mala idea declarar como abstracta la clase soporte, dado
que no se van a utilizar, ni existen, soportes en general, sino que lo que existen son los distintos
soportes concretos.
La sintaxis de la abstraccin
Para declarar clases y mtodos abstractos se utiliza la siguiente sintaxis.
abstract class nombre_clase{
//propiedades
public x;
private y;
//mtodos
public function __construct(){
}
public abstract function nombre_metodo();
}
Nos fijamos que se utiliza la palabra clave "abstract" para definir las clases o mtodos abstractos.
Adems, los mtodos abstractos no llevan ningn cdigo asociado, ni siquiera las llaves para abrir
y cerrar el mtodo.
www.desarrolloweb.com
zapatillas, pero todos los productos disponibles deben implementar una funcin para poder
venderse.
Otro ejemplo. Una bombilla, un coche y un ordenador son clases muy distintas que no pertenecen
al mismo sistema de herencia, pero todas pueden encenderse y apagarse. En este caso, podramos
construir una interfaz llamada "encendible", que incluira las funcionalidades de encender y
apagar. En este caso, la interfaz contendra dos funciones o mtodos, uno encender() y otro
apagar().
Cuando se define una interfaz, se declaran una serie de mtodos o funciones sin especificar ningn
cdigo fuente asociado. Luego, las clases que implementen esa interfaz sern las encargadas de
proporcionar un cdigo a los mtodos que contiene esa interfaz. Esto es seguro: si una clase
implementa una interfaz, debera declarar todos los mtodos de la interfaz. Si no tenemos cdigo
fuente para alguno de esos mtodos, por lo menos debemos declararlos como abstractos y, por
tanto, la clase tambin tendr que declararse como abstracta, porque tiene mtodos abstractos.
Implementacin de interfaces
Ahora veamos el cdigo para implementar una interfaz en una clase.
class bombilla implements encendible{
public function encender(){
echo "<br>Y la luz se hizo...";
}
public function apagar(){
echo "<br>Estamos a oscuras...";
}
}
Para implementar una interfaz, en la declaracin de la clase, se debe utilizar la palabra
implements, seguida del nombre de la interfaz que se va a implementar. Se podran implementar
varias interfaces en la misma clase, en cuyo caso se indicaran todos los nombres de las interfaces
separadas por comas.
En el cdigo de la clase estamos obligados a declarar y codificar todos los mtodos de la interfaz.
www.desarrolloweb.com
Nota: en concreto, PHP 5 entiende que si una clase implementa una interfaz, los mtodos de
esa interfaz estarn siempre en la clase, aunque no se declaren. De modo que si no los
declaramos explcitamente, PHP 5 lo har por nosotros. Esos mtodos de la interfaz sern
abstractos, as que la clase tendr que definirse como abstracta. Se puede encontrar ms
informacin sobre la abstraccin en el artculo Mtodos y clases abstractos en PHP 5.
Ahora veamos el cdigo de la clase coche, que tambin implementa la interfaz encendible. Este
cdigo lo hemos complicado un poco ms.
class coche implements encendible{
private $gasolina;
private $bateria;
private $estado = "apagado";
function __construct(){
$this->gasolina = 0;
$this->bateria = 10;
}
public function encender(){
if ($this->estado == "apagado"){
if ($this->bateria > 0){
if ($this->gasolina > 0){
$this->estado = "encendido";
$this->bateria --;
echo "<br><b>Enciendo...</b> estoy encendido!";
}else{
echo "<br>No tengo gasolina";
}
}else{
echo "<br>No tengo batera";
}
}else{
echo "<br>Ya estaba encendido";
}
}
public function apagar(){
if ($this->estado == "encendido"){
$this->estado = "apagado";
echo "<br><b>Apago...</b> estoy apagado!";
}else{
echo "<br>Ya estaba apagado";
}
}
public function cargar_gasolina($litros){
$this->gasolina += $litros;
echo "<br>Cargados $litros litros";
}
}
www.desarrolloweb.com
A la vista del anterior cdigo, se puede comprobar que no hay mucho en comn entre las clases
bombilla y coche. El cdigo para encender una bombilla era muy simple, pero para poner en
marcha un coche tenemos que realizar otras tareas. Antes tenemos que ver si el coche estaba
encendido previamente, si tiene gasolina y si tiene batera. Por su parte, el mtodo apagar hace
una nica comprobacin para ver si estaba o no el coche apagado previamente.
Tambin hemos incorporado un constructor que inicializa los atributos del objeto. Cuando se
construye un coche, la batera est llena, pero el depsito de gasolina est vaco. Para llenar el
depsito simplemente se debe utilizar el mtodo cargar_gasolina().
Llamadas polimrficas pasando objetos que implementan una interfaz
Las interfaces permiten el tratamiento de objetos sin necesidad de conocer las caractersticas
internas de ese objeto y sin importar de qu tipo son... simplemente tenemos que saber que el
objeto implementa una interfaz.
Por ejemplo, tanto los coches como las bombillas se pueden encender y apagar. As pues,
podemos llamar al mtodo encender() o apagar(), sin importarnos si es un coche o una bombilla lo
que hay que poner en marcha o detener.
En la declaracin de una funcin podemos especificar que el parmetro definido implementa una
interfaz, de modo que dentro de la funcin, se pueden realizar acciones teniendo en cuenta que el
parmetro recibido implementa un juego de funciones determinado.
Por ejemplo, podramos definir una funcin que recibe algo por parmetro y lo enciende.
Especificaremos que ese algo que recibe debe de implementar la interfaz encendible, as
podremos llamar a sus mtodos enciende() o apaga() con la seguridad de saber que existen.
function enciende_algo (encendible $algo){
$algo->encender();
}
$mibombilla = new bombilla();
$micoche = new coche();
enciende_algo($mibombilla);
enciende_algo($micoche);
Si tuviramos una clase que no implementa la interfaz encendible, la llamada a esta funcin
rovocara un error. Por ejemplo, un CD-Rom no se puede encender ni apagar.
class cd{
public $espacio;
}
$micd = new cd();
enciende_algo($micd); //da un error. cd no implementa la interfaz encendible
Esto nos dara un error como este: Fatal error: Argument 1 must implement interface encendible
in c:\www\ejphp5\funcion_encender.php on line 6. Queda muy claro que deberamos
implementar la interfaz encendible en la clase cd para que la llamada a la funcin se ejecute
correctamente.
www.desarrolloweb.com
con
la
Cambios profundos
La llegada de PHP5 vino emparejada de una reestructuracin del Core de PHP, lo que los creadores
de PHP llama Zend Engine.
As como el lejano PHP3 incluye su Zend Engine 0.5, y PHP4 el Zend Engine 1.0, tenemos Zend
Engine 2.0 en PHP5. El cambio de versin no fue trivial; incluye la reescritura casi total del modelo
de objetos, entre sus cambios ms sustanciales.
Esto repercute directamente en los scripts de PHP4 que utilizan clases, tanto en la compatibilidad
como en performance de ejecucin. Posteriormente en este artculo nos referiremos nuevamente
a este tema.
Veamos un ejemplo que nos muestra un cambio sustancial en la implementacin del modelo de
objetos:
<?
class Persona {
function setNombre($nombre) {
$this->nombre = $nombre;
}
function getNombre() {
return $this->nombre;
}
}
function Algo($p) {
$persona->setNombre("Daniel");
}
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
www.desarrolloweb.com
En ese caso la modificacin del nombre que hace la funcin Algo al objeto Persona no se ve
reflejada cuando hacemos echo $persona->getNombre().
En nuestro browser veremos "Pichongol".
Este es solo un ejemplo del porque de la reestructuracin tan importante en el Core de PHP. Es
claro que toda reestructuracin barre con cuestiones de compatibilidad, para ganar en otros skills;
en este caso claramente estamos ganando en performance, al liberarnos del overhead que implica
la constante copia de objetos que son argumentos de mtodos y funciones.
En artculos posteriores trataremos en mayor detalle y profundidad los distintos aspectos que
fueron modificados, haciendo una comparativa entre como se logran en PHP4 y como se logran en
PHP5. Adems de explicar profundamente las diferencias en el modelo de objetos nos quedan
temas pendientes como Opciones de configuracin (php.ini), Conexin a MySQL (mysqli), cambios
en los mdulos, etc.
Hecha esta introduccin, estamos en condiciones de definir las distintas situaciones en las que se
puede encontrar el desarrollador, y que aspectos juegan a su favor o en contra segn la situacin
en la que se encuentre.
Cual es mi escenario?
En el momento de plantearse la pregunta, el desarrollador seguramente se ubicar en alguno de
los dos escenarios posibles:
" Newbie (Iniciacin en PHP).
" Experimentado.
Newbie
En el planteo de esta discusin, podramos decir que es la situacin ideal, o por lo menos la ms
beneficiosa. Si eres una persona que quiere arrancar en PHP, no lo dudes, PHP5 es para ti. Tus
aplicaciones gozaran de las nuevas capacidades en OOP, obtendrs el beneficio de una mejor
performance de ejecucin (esta comprobado experimentalmente que PHP5 corre un 25% ms
rpido que PHP4) y tu cdigo estar muy bien acondicionado en cuanto a la compatibilidad con el
nuevo hijo que asoma: PHP6.
Por cierto, no todo es color de rosas. Una de los mayores beneficios a la hora de elegir PHP para
trabajar en nuestro proyecto es la gran cantidad de cdigo que podemos encontrar en Internet, y
utilizarlo para nuestros trabajos. Tenemos una gran probabilidad de que ante alguna tarea que se
nos plantea, podamos encontrar algn script que nos solucione la vida, obviamente adaptndolo a
nuestras necesidades.
Ahora bien, no todo el cdigo que vamos a encontrar es compatible con PHP5. De hecho la gran
mayora todava no se ha adaptado. Es cierto que con algn setting en nuestro php.ini podemos
ayudar a darle mayor compatibilidad, pero como contrapartida muchas de estas settings se
eliminaran en PHP6.
www.desarrolloweb.com
Qu queda? Hacerlo compatible modificando el cdigo, una tarea que para un desarrollador que
se inicia no siempre es sencillo. De todas formas a no alarmarse, que los grandes proyectos
(PHPNuke, PHPBB, etc.) ofrecen compatibilidad.
Experimentado
En este caso, el optar por quedarse con PHP4 o pasar a PHP5 depende de nuestra aplicacin.
Las interrogantes que el desarrollador se puede plantear podran ser:
- Mi aplicacin usa clases y objetos?
- Mi motor de Base de datos es MySQL?
- Utilizo un hosting externo?
- Mi aplicacin sufre modificaciones en cuanto a los requerimientos y lgica de negocios?
Pasemos a discutir ventajas y desventajas en cada uno de los interrogantes:
www.desarrolloweb.com
mucho mejor parados frente a tal reescritura. En caso contrario el tiempo invertido ser
sensiblemente mayor.
Utilizo un hosting externo?
En caso de no disponer de un hosting propio, y tener que depender de un hosting externo que nos
provea de PHP, seguramente el hecho de pensar en migrar a PHP5 puede ser un problema. De
hecho, estadsticas de principio de 2006 nos indican que solo alrededor del 5% de los hosting que
proporcionan PHP, tienen PHP5.
Esto no hace mas que reflejar la lentitud con la que se esta moviendo el proceso de traspaso de
PHP4 hacia PHP5.
Una pregunta que surge directamente sobre este tema es Por qu?
Bueno, si uno tomo una distribucin de Linux, es poco probable que la versin de PHP5 sea la
incluida.
La conformidad de los programadores con PHP4 es grande, y mucha de la documentacin
existente esta escrita para PHP4.
De todas formas, a no dormirse con PHP4. Un tema que se trata en la segunda parte de este
artculo es lo nuevo que nos trae PHP6. Veremos que PHP5 en muchos aspectos es una transicin
mientras que la confirmacin se llama PHP6.
www.desarrolloweb.com
Variables globales
En muchas lenguajes debes crear explcitamente un variable para utilizarlas. En PHP, hay una
opcin, las register_globals, que puedes fijar en php.ini y que permite que utilices variables
globales.
Considera el cdigo siguiente:
if ($password == "my_password") {
$authorized = 1;
}
if ($authorized == 1) {
echo "Mis cosas importantes ";
}
A muchos de vosotrosos puede parecer que este cdigo esta funcionando perfectamente. Sin
embargo, si un servidor tiene register_globals encendidos, entonces simplemente agregando?
authorized=1 " al URL dar a cualquier persona el acceso libre a exactamentelo que no quisieras
que todo el mundo viera. ste es uno de los problemas mas comunes de la seguridad de PHP.
Afortunadamente, esto tiene un par de soluciones simples y posibles. La primera, y quizs la
mejor, es fijar desactivar register_globals. La segunda es asegurarse de que utilizas solamente
las variables que has fijado explcitamente t mismo. En el ejemplo anterior, eso significara la
adicin $authorized = 0; al principio de la escritura:
$authorized = 0;
if ($password == "my_password") {
$authorized = 1;
}
if ($authorized == 1) {
echo "Lots of important stuff.";
}
www.desarrolloweb.com
Mensajes de error
Los mensajes de error son una herramienta muy til para los programadores y hackers. Un
desarrollador los necesita para detectar bugs. Un hacker puede utilizarlos para descubrir todas las
clases de informacin sobre un sitio, desde la estructura del directorio del servidor a la
informacin de la conexin de la base de datos.En PHP para evitar esto puedes utilizar .htaccess o
php.ini, fijando error_reporting a 0.
www.desarrolloweb.com
podemos evitar que cualquier persona utilize su propio cdigo del SQL en nuestra base de datos.
La funcin que sigue sera la adecuada:
function make_safe($variable) {
$variable = addslashes(trim($variable));
return $variable;
}
Ahora debemos modificar nuestra consulta. En vez de usar variables _POST como en la consulta de
arriba, ahora utilizamos todos los datos del usuario con la funcin make_safe, dando por resultado
el cdigo siguiente:
$username = make_safe($_POST['username']);
$password = make_safe($_POST['password']);
$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username =
'".$username."' and Password = '".$password."'");
Ahora, si un usuario incorpor los datos anteriormente citados, la consulta ser la siguiente, que
es totalmente inofensiva. La consulta siguiente seleccionar de una base de datos los registros
donde el usuario es igual a \ 'O o 1=1 #.
SELECT Username, Password, UserLevel FROM Users WHERE Username = '\' OR 1=1 #' and
Password = ''
Ahora, a menos que tengas un usuario con un nombre muy inusual y una contrasea en blanco, tu
malvolo atacante no podr hacer ningn dao en tu sitio Web. Es importante comprobar todos
los datos pasados a tu base de datos. Las cabeceras de HTTP enviados por elusuario pueden ser
falsificadas. Su direccin de remitente tambien puede ser falsificada. No confies en los datos
enviados por el usuario, y tu y tu sitio estareis a salvo
www.desarrolloweb.com
En este artculo te resumimos los detalles para entender qu es Composer, cmo funciona y para
instalarlo en tu sistema. Primero comenzaremos explicando qu es un gestor de dependencias,
luego veremos cmo funciona Composer para darnos cuenta qu aspectos de nuestro da a da
nos va a simplificar. Por ltimo veremos cmo instalarlo y cmo usar libreras gestionadas con
Composer en nuestro cdigo PHP.
www.desarrolloweb.com
Luego nos pondremos a desgranar este cdigo para que se entienda cada una de sus partes, as
como veremos qu otra informacin podemos colocar en este JSON. La idea es ver lo sencillo que
es declarar qu libreras o software ests utilizando y con ello dejar nuestro proyecto listo para la
"magia" de Composer.
Una vez tenemos definidas las dependencias en nuestro proyecto debemos instalarlas. Esto lo
conseguimos con un simple comando en el terminal en el que le pedimos a Composer que las
instale:
composer install
Nota: Ese comando puede variar segn la instalacin que tengas en tu sistema de Composer.
Especificaremos en un futuro artculo diversas situaciones en las que tengamos que generar
variantes de este mismo comando. De momento nos vamos a quedar en una presentacin de
Composer, pero en seguida nos ponemos a aprender en detalle aqu en DesarrolloWeb.com
Lanzado ese comando Composer se encargar de ir a los repositorios de paquetes de software y
descargar aquellas libreras mencionadas, copindolas en la carpeta de tu proyecto.
Una vez finalizado el proceso en tu consola de comandos podrs encontrar en la carpeta de tu
proyecto un directorio llamado "vendor" donde estarn las libreras declaradas. Ya solo nos queda
hacer los includes para que estn disponibles en tus aplicaciones y para ello tambin nos ayuda
Composer.
Simplemente tendremos que hacer un nico include o require en nuestro cdigo y todas las
libreras estarn disponibles para usar.
require 'vendor/autoload.php';
Packagist
Para terminar de convencerte y contarte la introduccin completa, debes echar un vistazo a
Packagist. Se trata del repositorio de paquetes que son instalables por medio de Composer.
En la pgina de Packagist encontrars un buscador que te puede dar una idea de la cantidad de
material que encuentras disponible para usar en cualquier proyecto PHP.
https://packagist.org/
Simplemente busca por cualquier concepto que te interese, como email, template, wysiwyg, etc.
Vers que te aparecen varias opciones clasificadas por popularidad, descargas, etc. Adems sobre
cada paquete encuentras informacin y el cdigo necesario para declarar tu dependencia en el
JSON de Composer.
Conclusin
Espero que con lo que hemos visto hasta ahora te haya llamado la atencin esta herramienta. La
verdad es que es muy til y como decimos, una vez comienzas a usarla te das cuenta de todo el
trabajo que te quita del medio, no solo en la descarga de los paquetes, sino tambin en las
actualizaciones de las libreras con el comando "composer update" que veremos ms adelante.
www.desarrolloweb.com
Sabemos que nos hemos dejado muchas cosas en el tintero, como el proceso de instalacin y el
detalle del JSON, pero lo veremos ya en prximos artculos. De momento queramos presentarte el
gestor de dependencias y que sepas por qu los desarrolladores de PHP lo hemos adoptado con
tanto entusiasmo.
En el prximo artculo vamos a detallar el proceso de instalacin de Composer.
Adems de los prximos artculos donde vamos a explicarlos los detalles del flujo de trabajo con
Composer para la gestin de dependencias, vamos a presentaros ahora un vdeo de nuestro canal
de Youtube donde encuentras resumidos algunos de los pasos bsicos de uso de Composer.
www.desarrolloweb.com
funcin en otra parte del cdigo, ambas funciones entraran en conflicto, pues deberan tener
nombres distintos.
Hasta la creacin de los namespaces, para evitar colisiones de nombres, los desarrolladores
estaban obligados a ser un poco imaginativos con los nombres que ponan a sus piezas de
software, creando nombres extra largos para sus clases, evitando as que otras personas en el
futuro pudieran usar esos mismos nombres.
Obviamente, esa solucin no era la mejor, as que PHP incorpor los espacios de nombres, que nos
permiten reservar nombres para las funciones, clases, interfaces, traits, constantes, etc, que solo
tienen validez en cierto namespace. Al crear una librera, colocaras tus funciones dentro de un
espacio de nombres, de manera que otros desarrolladores puedan usar los mismos nombres de
piezas de software sin que colisionen, por estar en distintos espacios de nombres.
www.desarrolloweb.com
Constantes
Funciones
Clases y otros elementos de programacin orientada a objetos, como interfaces, traits o
clases abstractas.
Por tanto las variables globales que creas en un namespace se van al mbito global. Es decir, si
dentro de un archivo donde has declarado estar en un espacio de nombres usas variables sueltas
(sin ser locales a funciones o mtodos, osea, variables globales de toda la vida), esas variables se
quedan en el mbito global.
Siguiendo con la declaracin de nuestro primer namespace, podemos ver el cdigo completo de
un archivo con su espacio de nombres.
<?php
namespace Deswebcom;
const PI = 3.14;
function avisa(){
echo "Te estoy avisando";
}
class MiClase{
public function probando(){
echo "Esto es una prueba";
}
}
Ese cdigo lo meters en un archivo de tu proyecto, por ejemplo "primer-namespace.php".
Nota: La localizacin donde lo pongas ese archivo, o su nombre en si, es indiferente. Es decir, por
el hecho de haber definido un namespace no ests obligado a colocar el cdigo fuente en una ruta
determinada. Aunque como veremos ms adelante, muchos programadores con base en las
buenas prcticas colocan los archivos del espacio de nombres en carpetas que tienen los mismos
nombres que el namespace declarado.
www.desarrolloweb.com
www.desarrolloweb.com
donde han sido creados, como si esa constante, funcin o clase que se hubiera declarado de
manera global.
Fjate que al usar una constante tenemos que informar "use const" y si es una funcin "use
function", mientras que si es una clase usamos "use" a secas.
Nota: La posibilidad de declarar el uso de una funcin o constante de un namespace est
disponible solo a partir de PHP 5.6.
Conclusin
Con esto ya conoces las bases sobre los espacios de nombres en PHP. Como introduccin creo que
est bastante bien y que ya tienes informacin suficiente para usarlos sin problemas. No obstante,
el lenguaje PHP nos permite diversas otras alternativas de uso que estudiaremos en futuros
artculos.
Crear Sub-namespaces
Es habitual que los desarrolladores creen espacios de nombres dentro de otros espacios de
nombres. Por ejemplo, todos los namespaces de una empresa o desarrollador pueden comenzar
con su "nick" y luego dentro puedes tener espacios de nombres para cada tipo de utilidad que
ests desarrollando.
Imagina que DesarrolloWeb.com se dedicase a fabricar libreras con cdigo PHP, pues todas las
libreras podran estar dentro del espacio de nombres "Deswebcom". Luego podramos tener
libreras que se encargan del trabajo con sesiones, cookies, bases de datos, etc. Podran estar en
sub-namespaces como Deswebcom\Sesiones, Deswebcom\Cookies, Deswebcom\BBDD. Ya dentro
de Deswebcom\Sesiones podras tener una serie de clases, funciones y constantes, o a su vez
otros espacios de nombres donde organizas otra serie de libreras. El orden es el que t necesites y
esta organizacin resulta muy popular. De hecho la puedes ver reproducida en numerosos
paquetes de libreras o en la organizacin de las clases de un framework potente.
La definicin de los namespaces y sub-namespaces es prcticamente la que hemos comentado en
artculos anteriores. Comienzas el cdigo indicando tu namespace (recuerda que debe ser la
primera instruccin del archivo).
www.desarrolloweb.com
<?php
namespace Deswebcom\Galaxias\Andromeda;
Como puedes apreciar, la jerarqua de namespaces se indica con una barra invertida (contrabarra).
Puede llegar a tantos niveles como necesites y en cada nivel puedes tener miembros del espacio
de nombres. Es decir, en el namespace "Deswebcom" puedo tener clases, funciones, constantes,
traits, interfaces y otros namespaces. Dentro de los otros namespaces puedo tener otra vez lo
mismo: clases, funciones, otros namespaces, etc.
www.desarrolloweb.com
www.desarrolloweb.com
La tercera posibilidad es tambin fcil de entender y funcionar siempre, puesto que si indicamos
la ruta completa de toda la jerarqua de namespaces, no importa en qu espacio de nombres
estamos trabajando. Es decir, indicando el espacio de nombres completo, siempre vamos a poder
referirnos a cualquier elemento, independientemente de nuestra posicin.
Deswebcom\Galaxias\Andromeda\localizar();
Deswebcom\Galaxias\Andromeda\Estrella::pertenece();
Deswebcom\Galaxias\observar("Via Lactea");
En este caso tambin admitira comenzar por una contrabarra toda la ruta jerrquica para el
acceso a los namespaces, indicando que el primer namespace "Deswebcom" es de primer nivel.
\Deswebcom\Galaxias\Andromeda\localizar();
\Deswebcom\Galaxias\Andromeda\Estrella::pertenece();
\Deswebcom\Galaxias\observar("Via Lactea");
cualificado,
www.desarrolloweb.com
Nota: Recuerda que tambin puedes declarar que vas a usar funciones o constantes de otros
espacios de nombres. En ese caso la cosa cambia algo, porque tienes que mencionar "use
function" o "use const".
Por ejemplo tengo este namespace.
<?php
namespace Midesweb;
function quien(){
echo "Soy @midesweb";
}
Y en otro archivo quiero usar la funcin quien, tambin por un alias.
use function Midesweb\quien as q;
Ahora esa funcin est disponible con el alias "q". Luego podr invocarla as:
q();
Realmente este tema de los alias ya lo venas utilizando, aunque no lo habamos mencionado
todava. Esto es porque cualquier sentencia "use" lo que hace realmente es crear un alias.
Solamente que, si no le indicamos un alias diferente, crea ese recurso con su nombre original. Por
ejemplo:
use Deswebcom\Galaxias\Andromeda\Estrella;
Es una lnea de cdigo equivalente a:
use Deswebcom\Galaxias\Andromeda\Estrella as Estrella;
Antes de acabar este punto quisiera dar dos aclaraciones, igual son cosas obvias, pero creo que
podr solventar las dudas de algunos lectores:
Una sentencia use con un alias (o sin l, pues realmente ya sabemos que el alias siempre lo crea al
declarar un "use") pone a disposicin un cdigo tan solo para el archivo .php donde hemos creado
ese alias.
Esto se deriva de lo anterior: Si ests dentro de un espacio de nombres y declaras un "use" para
crear un alias de una clase, funcin o cualquier otra cosa, no significa que ests agregando ese
elemento al espacio de nombres en el que ests. Aquella funcin o clase, interfaz o lo que sea,
permanece en el espacio de nombres donde fue definida y con ese "use" simplemente ests
indicando que dentro de este fichero eres capaz de referirte a ese elemento por su alias.
www.desarrolloweb.com
www.desarrolloweb.com
Todas las funciones nativas de PHP estn definidas dentro del mbito global, por lo que en
ocasiones podemos necesitar referirnos al mbito global en vez del mbito del namespace.
Por ejemplo, tengo el namespace "Deswebcom\Galaxia" y dentro de l he definido una funcin
llamada explode(). En ese caso, dentro del namespace "Galaxia", explode() har referencia al
mtodo expolde() que hemos definido en este mbito.
<?php
namespace Deswebcom\Galaxias;
function explode($estrella){
echo "La estrella $estrella va a explotar";
}
explode("Sol");
Ese cdigo te devolver "La estrella Sol va a explotar", porque se est invocando al explode()
recin definido.
Nota: Puedes reparar que si no estuviramos dentro de un namespace PHP no nos habra
permitido crear una funcin llamada explode(), porque ya existe una funcin nativa del API de PHP
con ese nombre, que se encarga en separar partes del string en un array.
Ahora bien, si necesitas por algn motivo acceder a la funcin explode() de PHP, la nativa definida
en el mbito global, entonces tendra que especificar que esa funcin es aquella del mbito global
y no la definida en el namespace. Para ello no hay ms que agregarle una contrabarra antes del
nombre de la funcin (o cualquier otra cosa del mbito global a la que queremos acceder).
$arraymarcas = \explode("|", "desarrolloweb|escuelait");
Conclusin
Con todo esto tienes bastante informacin sobre namespaces. Realmente ya sabes todo lo que
necesitas, as que a partir de ahora procura usarlos.
www.desarrolloweb.com
Cmo es que decimos que OK? Eso es algo que se puede evitar enviando el error correctamente
en la cabecera del HTTP.
Para enviar un cdigo de error 404 por las cabeceras del HTTP con PHP tenemos que hacer lo
siguiente:
<?
header("HTTP/1.0 404 Not Found");
?>
Con la funcin header() de PHP enviamos informacin en la cabeceras del http. En este caso
hemos enviado una cabecera 404 Not Found. Atencin, porque la funcin header() debe invocarse
antes de haber escrito nada en la pgina, osea, antes de haber enviado ninguna informacin al
navegador.
Pero dependiendo de la configuracin de nuestro servidor esto puede funcionar o no.
La mejor manera de saber qu estamos enviando por las cabeceras del http es utilizar un
programa que nos muestre las cabeceras que se generan tanto en el cliente como en el servidor.
Existen varios programas que nos podran servir, pero nosotros vamos a recomendar aqu una
extensin de Firefox que hemos comentado ya en otro artculo: Ver cabeceras HTTP con
LiveHttpHeaders.
Veremos que en algunas ocasiones enviando esta cabecera el navegador recibe un cdigo de error
como este:
HTTP/1.x 404 OK
Eso es algo que tenemos que evitar, porque es ambiguo. La cabecera deseable sera:
HTTP/1.x 404 Not Found
Pues bien, cuando la cabecera que generamos es HTTP/1.x 404 OK tenemos que hacer lo siguiente
para conseguir el deseado HTTP/1.x 404 Not Found.
<?
header("HTTP/1.0 404 Not Found");
header("Status: 404 Not Found");
?>
Primero le indicamos la cabecera del http como 404 y luego lanzamos otra cabecera indicando que
el estatus que tiene que enviar es "Not Found". Esto debera funcionar en todos los casos. Es
posible que con una sola de las dos cabeceras enviadas nos enve ya el error 404 Not Found,
depende de la configuracin de nuestro servidor que necesitemos una u otra. Pero si indicamos las
dos en las pruebas que he hecho con varios servidores siempre he recibido el cdigo de error
correcto.
Insisto en que lo bueno es que veamos qu cabeceras del HTTP estamos enviando con un
producto como LiveHttpHeaders . As podremos estar seguros de qu cabeceras tenemos que
enviar y qu cdigo PHP es el correcto en nuestro caso.
Porque en algunos servidores PHP si enviamos slo esta cabecera:
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
<?
header("Status: 404 Not Found");
?>
Nos enva al navegador el cdigo:
HTTP/1.x 200 OK
Por ejemplo, en este caso es todava peor, porque nosotros habamos querido enviar un error 404
y en realidad lo que ha llegado al navegador es un 200 OK que quiere decir pgina encontrada y
correcta.
En definitiva, cabe estudiar detalladamente este asunto para asegurarnos que estamos enviando
la cabecera correcta y el error 404 es claro.
www.desarrolloweb.com
API de bit.ly
El API de bit.ly permite obtener URLs cortas directamente desde cualquier otro sistema
informtico, sin tener que entrar en el sitio de bit.ly, as como obtener informacin de URLs que se
hayan acortado utilizando este servicio web.
El API que nos ocupa es lo que se denomina un REST API y permite el acceso a recursos del servicio
web de bit.ly, a travs de URLs en las que enviamos informacin sobre la accin que queremos
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
realizar. Devuelve un texto que est en formato JSON y opcionalmente en XML, que contiene el
resultado de la ejecucin del comando enviado en la URL.
Por ejemplo, imaginemos que tenemos una URL larga y deseamos obtener la URL corta
correspondiente. Entonces tendremos que componer una llamada al API de bit.ly con los datos de
esa URL larga y la operacin que queremos realizar con ella (acortarla en este caso). La llamada al
API es una URL que tendr una forma parecida a esta:
http://api.bit.ly/shorten?version=2.0.1&longUrl=http://desarrolloweb.com&login=usuario&apiKey
=R_000000000
Como se puede ver, en esta URL estamos enviando varios datos que conforman la consulta al API.
Hay uno que resulta claro, "longUrl", en el que enviamos la la URL que deseamos acortar. En la
URL se envan otros datos como "version", con la versin del API que estamos utilizando y un par
de datos importantes, tpicos en el trabajo con APIs como el usuario y la llave, que vamos a
explicar a continuacin.
www.desarrolloweb.com
Esperamos que esta introduccin al API de bit.ly haya resultado interesante, pero seguramente te
interese saber algo ms sobre sus posibles funcionalidades o cmo utilizarla desde lenguajes de
programacin como PHP. As pues, te indicamos que todas las informaciones adicionales las
podrs encontrar en el Manual del API de bit.ly.
/shorten
Este comando sirve para recortar una URL larga y obtener una URL ms corta, proporcionada por
bit.ly, que redireccionar a la URL original.
Ejemplo de consulta:
http://api.bit.ly/shorten?version=2.0.1&longUrl=http://desarrolloweb.com&login=tuusuario&apiK
ey=R_000000000000000
Nota: Quizs sobra decir, pues ya se coment en el anterior artculo, que vosotros tenis que
sustituir el nombre de usuario, enviado en el parmetro "login" y la llave del API, enviado en el
parmetro apiKey, por los vuestros que habris obtenido al registraros en bit.ly.
Respuesta para la anterior consulta:
{
"errorCode": 0,
"errorMessage": "",
"results": {
"http://desarrolloweb.com": {
"hash": "tTVQF",
"shortCNAMEUrl": "http://bit.ly/c1SivH",
"shortKeywordUrl": "",
"shortUrl": "http://bit.ly/c1SivH",
"userHash": "c1SivH"
}
},
"statusCode": "OK"
}
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
/expand
Este comando sirve para obtener la URL larga correspondiente a una URL corta de bit.ly. Es decir,
hace el paso contrario de acortar la URL, teniendo la direccin corta, conseguimos averiguar la
larga. Un detalle importante es que, para invocar expand, tenemos dos opciones, una es enviar la
URL corta (como vemos en el ejemplo siguiente) y la otra es enviar el dato " hash" de esa URL, que
podemos ver entre los datos que se obtuvieron al hacer el comando shorten.
Ejemplo de invocacin:
http://api.bit.ly/expand?version=2.0.1&shortUrl=http://bit.ly/c1SivH&login=tuusuario&apiKey=R_
000000000000000
Resultado obtenido para esta consulta:
{
"errorCode": 0,
"errorMessage": "",
"results": {
"c1SivH": {
"longUrl": "http://desarrolloweb.com/"
}
},
"statusCode": "OK"
}
/info
A partir de una URL corta o un Hash, obtenemos informacin variada sobre ese item, como puede
ser la URL larga a la que corresponde, su ttulo, keywors, descripcin o los usuarios que estn
relacionados a esa entrada.
Ejemplo de invocacin: (en el que esta vez enviamos un Hash)
http://api.bit.ly/info?version=2.0.1&hash=tTVQF&login=tuusuario&apiKey=R_000000000000000
La consulta devuelve el siguiente cdigo JSON:
{
"errorCode": 0,
"errorMessage": "",
"results": {
"tTVQF": {
"calais": {},
"calaisId": "",
"calaisResolutions": {},
"contentLegth": 77862,
"contentLength": "",
"contentType": "text/html",
"exif": {},
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
"fileExtension": "",
"globalHash": "tTVQF",
"hash": "tTVQF",
"htmlMetaDescription": "Todo lo que pueden necesitar los programadores y diseu00f1adores
web para aprender o profundizar en el desarrollo de webs..."
"htmlMetaKeywords": [ "recursos para pu00e1ginas web", "manuales de html css",
"promociu00f3n de pu00e1ginas web", ... ],
"htmlTitle": "Desarrollo Web, Tu mejor ayuda para aprender a hacer webs.",
"id3": {},
"indexed": 1253659877,
"keyword": "",
"keywords": [],
"longUrl": "http://desarrolloweb.com/",
"metacarta": [],
"mirrorUrl": "",
"robotsAllowed": true,
"shortenedByUser": "bitly",
"surbl": 0,
"thumbnail": {},
"urlFetched": "http://desarrolloweb.com/",
"userHash": "",
"users": [],
"version": 1.0
}
},
"statusCode": "OK" }
/stats
Una interesante opcin que nos ofrece el servicio web de bit-ly, que consiste en una serie de datos
estadsticos sobre una URL corta, o Hash, como los accesos que ha tenido, la procedencia de los
mismos, etc.
Ejemplo de URL para hacer una consulta sobre datos estadsticos de una URL corta.
http://api.bit.ly/stats?version=2.0.1&shortUrl=bit.ly/dmsnKV&login=tuusuario&apiKey=R_000000
000000000
{
"errorCode": 0,
"errorMessage": "",
"results": {
"clicks": 315,
"hash": "dmsnKV",
"referrers": {
"": { "direct": 174 },
"hootsuite.com": { "/dashboard": 3 },
"iconfactory.com": { "/twitterrific": 2 },
"partners.bit.ly": { "/td": 44 },
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
"search.twitter.com": { "/search": 2 },
"seesmic.com": { "/web/index.html": 4 },
"twitoaster.com": { "/": 2 },
"twitter.com": { "/": 63,
"/ChicadeSeda/tesorodelsaber": 1,
"/Kika381": 1,
"/tuusuario": 3,
"/elgusar": 1,
"/favorites": 1,
"/home": 2,
"/jordisalvia": 1,
"/profesor4": 7,
"/profesor4/favorites": 1
},
"www.twitscoop.com": { "/": 1 },
"www.twittergadget.com": { "/gadget.asp": 1 },
"www.yoono.com": { "": 1 }
}
}, "statusCode": "OK"
}
/errors
Una lista de los cdigos de error con sus descripciones que se pueden producir al acceder al API.
Esta lista de cdigos de error nos servir para poder entender mejor qu es lo que pueda estar
pasando cuando el API no responda como podramos esperar.
Consulta para ver los errores:
http://api.bit.ly/errors?version=2.0.1&login=tuusuario&apiKey=R_000000000000000
El resultado de los errores es demasiado largo para publicarlo aqu, pero podramos verlo
simplemente si accedemos a la URL anterior con nuestros datos de acceso al API.
Este artculo informativo sobre las capacidades del API de bit.ly acaba por aqu, dado que ya
hemos enumerado y explicado todas las posibilidades que existen en la versin actual, en el
momento de escribir este texto, que es la 2.0.1.
En el prximo artculo vamos a mostrar ya cmo utilizar el API para consumir informacin del
mismo desde pginas PHP, un paso que seguramente querrs conocer si ests leyendo estas
lneas.
www.desarrolloweb.com
As que ahora vamos a comenzar a hacer cosas ms prcticas y divertidas. En este caso se trata de
hacer un script PHP que se encargue de conectarse con el API, para enviar una URL larga y obtener
una corta. Como veremos en este artculo, se trata de una tarea bastante sencilla, aunque
requiere de varios pasos, que listamos a continuacin.
Componer una URL para la consulta en el API de bit.ly
Acceder a esa URL por medio de PHP y recibir la informacin en formato JSON
Convertir el JSON resultante en un array asociativo de PHP
Acceder a los datos que necesitemos, es decir a la URL corta generada por bit.ly
Nota: La mayora de las acciones que vamos a realizar las hemos trabajado anteriormente en
distintos artculos de DesarrolloWeb.com, como podran ser Lectura de texto de una URL o
Consumo de JSON desde PHP.
El cdigo del ejemplo bsico de uso del API de bit.ly desde PHP que hemos creado es el siguiente:
//unas variables de configuracin
$servicio_web = "http://api.bit.ly/";
$version_API = "version=2.0.1";
$usuario = "login=usuario"; //sustituye por tu usuario del API
$llave = "apiKey=R_000000"; //sustituye por tu clave del API
//la URL que quiero acortar
$URL_larga = "http://www.desarrolloweb.com/manuales/";
//codifico en formato de URL la URL larga
$query_URL = "&longUrl=" . urlencode("http://www.desarrolloweb.com/manuales/");
//genero la URL para consultar en el API de bit.ly
$URL_consulta_API = $servicio_web . "shorten?" . $version_API . "&" . $query_URL . "&" . $usuario
"&" . $llave;
//leo lo que me devuelve el API al hacer esa consulta, que estar en formato JSON
$respuesta_API = file_get_contents($URL_consulta_API);
//ahora tengo que consumir ese JSON para convertirlo en una estructura de datos accesible desde
PHP
$respuesta_API = json_decode($respuesta_API, true);
//el true anterior hace que json_decode me devuelva sea un array asociativo.
//ahora podramos mostar el contenido completo de la respuesta.
echo "<pre>";
var_dump($respuesta_API);
echo "</pre>";
//compruebo si hubo algn problema
if($respuesta_API["errorMessage"]==""){
//Todo bien, pues no hay errores
//muestro la URL corta generada por el API
echo $respuesta_API["results"][$URL_larga]["shortUrl"];
}else{
echo "Hubo un error";
}
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
Con esto tenemos listo un ejemplo de uso del API, que esperamos se haya podido entender a
travs de los comentarios. Recuerda sustituir por tus propios datos, tanto el usuario y clave del API
como la URL que quieras acortar con bit.ly.
Como se ha podido comprobar, la tarea no es nada complicada, aunque todava puede ser ms
fcil, como veremos en el siguiente artculo, en el que explicaremos y ofreceremos ejemplos sobre
una clase PHP, de programacin orientada a objetos, que existe para acceder al API de bit.ly de
una manera ms cmoda.
permite incorporar a nuestras pginas web las funcionalidades para acortar direcciones de ese
popular servicio web. Hasta el momento, en el Manual del API de bit.ly, hemos comentando la
lista de posibles acciones a realizar y cmo acortar una direccin larga con PHP con un script
sencillo.
Ahora vamos a mostrar cmo realizar una clase, de programacin orientada a objetos en PHP 5,
que resuma las tareas de trabajo con el API de bit.ly y nos permita realizar las acciones tpicas por
medio de mtodos de un objeto. Este ejemplo viene bien para aprender programacin orientada a
objetos con PHP, aparte de servir como prctica sobre el API de este acortador de direcciones.
7.4.1.
Funcionalidades de la clase
La clase PHP que vamos a construir implementa las funcionalidades ms importantes que
podemos necesitar realizar con el API de bit.ly, como acortar una URL larga o expandir una URL
corta previamente generada por bit.ly. Estoy seguro que se podran implementar otros mtodos
tambin tiles sobre el API, pero de momento no queremos complicar demasiado las cosas.
La lista de los mtodos que vamos a tener se puede ver a continuacin.
Constructor:
Sirve para crear un objeto de la clase, para lo que necesitamos indicar nuestro nombre de usuario
de bit.ly y la llave del API, que obtenemos al registrarnos en el servicio web.
acorta_URL:
Este mtodo recibe una URL larga e intenta acortarla con bit.ly. Si no se pudo por cualquier razn
devuelve false y en caso que la URL se acorte con xito, devuelve una cadena con la URL corta.
expande_URL:
Este mtodo sirve para obtener la URL larga a partir de una acortada con bit.ly. Es decir, recibe una
cadena con una URL corta de bit.ly y devuelve la URL original que hay detrs de una URL generada
por este servicio web. Si no se pudo expandir la URL corta, devuelve false.
Estos son los tres mtodos pblicos que tendremos por ahora, aunque dentro de la clase tenemos
otro mtodo privado, que hemos utilizado durante el desarrollo.
www.desarrolloweb.com
muestra_respuesta:
Un mtodo privado que simplemente muestra el contenido completo que devuelve el API de bit.ly
al hacer una consulta. Simplemente imprime en la pgina la respuesta generada en el acceso al
API.
Nota: Recordemos que los elementos privados slo se pueden acceder desde mtodos que hay en
la propia clase, es decir, slo los podemos invocar desde el cdigo de la propia clase. Los elementos
pblicos, por su parte, se pueden acceder a partir de los objetos. En la prctica, si no somos los
desarrolladores de esa clase, slo podremos acceder a los mtodos pblicos
7.4.2.
Ahora podemos ver el cdigo de nuestra clase para el trabajo con bit.ly desde PHP.
class bitly_PHP{
private $usuario;
private $llave;
private $version_API = "version=2.0.1";
private $servicio_web = "http://api.bit.ly/";
function __construct($login, $APIkey){
$this->usuario = "login=" . $login;
$this->llave = "apiKey=" . $APIkey;
}
private function muestra_respuesta($respuesta_API){
echo "<pre>";
var_dump($respuesta_API);
echo "</pre>";
}
public function acorta_URL($URL_larga){
$query_URL = "&longUrl=" . urlencode($URL_larga);
$URL_consulta_API = $this->servicio_web . "shorten?" . $this->version_API . "&" .
$query_URL .
"&" . $this->usuario . "&" . $this->llave;
$respuesta_API = json_decode(file_get_contents($URL_consulta_API), true);
//muestro la resupuesta
//$this->muestra_respuesta($respuesta_API);
if($respuesta_API["errorMessage"]==""){
//Todo bien, pues no hay errores
return $respuesta_API["results"][$URL_larga]["shortUrl"];
}
return false;
}
public function expande_URL($URL_corta){
$query_URL = "&shortUrl=" . urlencode($URL_corta);
$solo_codigo_bitly = substr(strstr($URL_corta, "bit.ly/"),7);
$URL_consulta_API = $this->servicio_web . "expand?" . $this->version_API . $query_URL .
"&" .
$this->usuario . "&" . $this->llave;
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com
7.4.3.
Para acabar, podemos ver cmo utilizar la clase creada anteriormente para acortar una URL y
luego mostrarla de nuevo pero expandida.
//definimos la URL con la que quiero trabajar
$url trabajar = "http://www.desarrolloweb.com/articulos/crear-rss-php-mysql.html";
//construyo el objeto de la clase bitly PHP
$obj_bitly = new bitly_PHP("usuario", "R_00000000000000000000000");
//obtengo la URL corta a partir de la URL original, con el mtodo acorta URL() $url corta = $obj
bitly->acorta URL($url trabajar);
//compruebo que esa URL corta no es false (osea, que no hubo error)
if ($url_corta){
//muestro la URL corta
echo '<p>La URL, una vez acortada es ' . $url corta . '</p>';
echo '<p><a href="' . $url_corta . '">' . $url_corta . '</a></p>';
//pruebo ahora a expandir esa URL
//para ello invoco el mtodo expande URL()
$url larga = $obj bitly->expande URL($url corta);
//compruebo que la URL no sea false
if ($url_larga){
//muestro la URL expandida
echo '<p>La URL, una vez expandida es ' . $url larga . '</p>';
}else{
Manual de PHP 5: http: //www.desarrolloweb.com /manuales/58/
Los manuales de DesarrolloWeb.com tienen el copyright de sus autores. No reproducir sin autorizacin.
www.desarrolloweb.com