Documentos de Académico
Documentos de Profesional
Documentos de Cultura
1.1 Constructores
Siempre construye
En PHP5, una clase puede tener un slo constructor. Si se ha declarado un mtodo __construct y un mtodo del mismo nombre que la clase (un constructor en PHP4), se ignora este ltimo como constructor. Una funcin constructora siempre construye y devuelve un objeto implcitamente. El mtodo no debe devolver ningn valor, y en caso de hacerlo se ignora y se devuelve un nuevo objeto.
class foo { function __construct() { echo "construido en PHP5 como "; return 5; } function foo() { echo "construido como en PHP4 como "; } } $bar = new foo(); echo " ", get_class($bar);
Construido en PHP5 como foo Observa que el constructor empleado es el mtodo __construct, y que el valor devuelto, el nmero 5, se ignora completamente. Ten en cuenta, este comportamiento a la hora de implementar algunos patrones como singleton, factora, etc.
1.2 Destructores
Destruir un objeto
En PHP se puede destruir un objeto y cualquier variable usando la funcionunset(variable). Si queremos que al destruir un objeto se realicen ciertas operaciones especiales,como por ejemplo cerrar una conexin abierta, debemos implementar en la clase el mtodo __destruct.
El mtodo _destruct no puede recibir argumentos
He sido construido y destruido..y la vida sigue Observa que dentro de la funcin foo se construye el objeto. Al terminar la funcin, PHP5 recoge la basura: destruye el objeto ya que se trata de una variable local que dejar de existir al terminar la funcin), y sigue con la ejecucin del script.
echo " referencia=", $referencia->nombre; echo " asignado=" , $asignado->nombre; echo " clon=" , $clon->nombre;
original=B referencia=B asignado=B clon=A En este ejemplo, creamos a partir de un original tres objetos. Fjate que al cambiar el original, el objeto creado por asignacin y por referencia quedan modificados; el clon, no.
1.4 Operador ::
Propiedades de clase
En PHP 5, el operador :: se aplica para hacer referencia a una propiedad o mtodo de una clase.
El operador -> requiere de un objeto (prefijo $) y :: de una clase (sin prefijo). class Animal { .. } // Animal es una clase no un objeto. Animal::sonido() // contador es una propiedad esttica. Animal::$contador ;
Cuando referenciamos propiedades de clase estas tienen que ser estticas. Si invocamos un mtodo, no existe el objeto $this.
class Animal { static private $contador=0; public $sonido; function __construct ( $sonido) { self::$contador++; $this->sonido= $sonido; } function sonido(){ if (isset( $this ) ){ echo $this->sonido, " ", $this->sonido, " "; } else { echo "tenemos " . self::$contador . " animales ". "pero no se que ruido hacen."; } } } $miPerro = new Animal("guau");
$miGato
= new Animal("miau");
miau miau guau guau tenemos 2 animales pero no se que ruido hacen. Para que el mtodo sonido funcione hemos tenido que hacer un test ( $this) ) para comprobar que tenemos un objeto.
isset (
class Animal { static private $animalesCreados = 0; public $nombre; function __construct ( $nombre) { self::$animalesCreados++; $this->nombre = $nombre; } function contador(){ return self::$animalesCreados; } } $miPerro = new Animal("perro"); $miGato = new Animal("gato"); echo "Total animales creados: " .Animal::contador();
Total animales creados: 2 La propiedad $animalesCreados es comn para todos los objetos creados. Para consultar dicha propiedad podemos hacer: $miGato->contador() , $miPerro>contador() o utilizar la referencia a la clase Animal::contador()que no requiere ningun objeto para invocar el mtodo.
Definir constantes
Una clase puede tener sus propias constantes, que sern accesibles como propiedades de un objeto, o la forma mas recomendable usando el operador :: aplicado a la clase. Las propiedades constantes no se preceden con $ Para definir una propiedad constante basta con anteponer la palabra declaracin de la misma.
class miTrigometria { const public PI = '3.14'; function getPI() { return self::PI; // ejemplo de uso con self } } $oTrigo = new miTrigometria(); echo miTrigometria::PI," ", $oTrigo->PI;
const
a la
3.14 3.14
} class Bombero extends Persona { function sirena(){ echo " piu..piu..piuo"; } function habilidades(){ echo " comer, beber, dormir, .ah, y apagar fuegos"; } } $irene= new Bombero("irene"); $irene->existe(); $irene->sirena(); $irene->habilidades();
Ahora tenemos un objeto bombero, que puede hacer todo lo que hacen los objetos personas (andar) pero tiene funciones propias (sirena) y adems tiene su propia versin de otras funciones (habilidades).
/* nota: no se considera adecuado implementar un mtodo en un clase abstracta. */ echo "algo "; } } class Perro extends Animal { function sonido(){ echo "guau guau "; } function tiraLeUnHueso(){ echo "ahi va ese huesito"; } } class Gato extends Animal { function sonido(){ echo "miau miau "; } function queHaceTodoEldia(){ echo "dormir "; } } $miPerro = new Perro(); $miGato = new Gato(); // $miAnimal = new Animal(); no permitido $miPerro->sonido(); $miPerro->queHaceTodoElDia(); $miPerro->tiraLeUnHueso(); echo "<br>"; $miGato->sonido(); $miGato->queHaceTodoElDia();
guau guau algo ahi va ese huesito miau miau dormir Observa, el comportamiento de los mtodos. En la clase Perro se ha aadido un mtodo nuevo, implementado un mtodo abstracto, y otro ha quedado tal cual. En Gato, se han implementado los dos mtodos abstractos.
1.9 Interface
Declarar una interface
Una interface es una declaracin que dice que mtodos debera tener una clase. Las interface no son clases, y las clases no se extienden sino que se implementan.
interface Animal { function sonido(); function queHaceTodoElDia(); }
Si incluimos una propiedad o el cuerpo de un mtodo se produce un error. Para implementar una interface hacemos:
class Perro implements Animal { ...
Tenemos que implementar todos los mtodos de la interface. Si olvidamos uno, se genera un error. Podemos aadir propiedades y nuevos mtodos. Observa el ejemplo completo
interface Animal { function sonido(); function queHaceTodoElDia(); } class Perro implements Animal { function sonido(){ echo "guau guau "; } function tiraLeUnHueso(){ echo "ahi va ese huesito "; } function queHaceTodoEldia(){ echo "jugar "; } } class Gato implements Animal { function sonido(){ echo "miau miau "; } function queHaceTodoEldia(){ echo "dormir "; } } $miPerro = new Perro(); $miGato = new Gato(); $miPerro->sonido(); $miPerro->queHaceTodoElDia(); $miPerro->tiraLeUnHueso(); echo "<br>"; $miGato->sonido(); $miGato->queHaceTodoElDia();
__call
__clone (mtodo)
Cuando se clona un objeto se realiza un copiado de memoria. Eso no asegura que el objeto resultante funcione correctamente si se trata de un objeto que requiera un conexin o realizar alguna inicializacin por ejemplo o hace uso de variables de sesin.
__autoload (funcin)
Si defines una funcin __autoload esta funcin sera invocada por PHP5 cada vez que se encuentra con una clase cuya definicin no ha sido cargada. Este sencillo mecanismo evita el uso constante de include.
__set y __get
En PHP, los objetos tienen propiedades dinmicas. Si asigno un valor a una propiedad no existente, esta se crea para mi objeto. Implictamente, cada objeto tiene un mtodo para asignar una propiedad, y otra para consultar: se trata de obj->propiedad = algo, y obj->propiedad. Podemos ver estas dos construcciones del lenguaje como si fueran dos mtodos. Con el mtodo __set crearemos nuestra propia funcin para asignar propiedades a los objetos, y con __get para consultarlos.
1.12 Serialize
Serializar un objeto
En PHP serialize una variable significa codificar la variable como un cadena de carcteres. El proceso de volver a crear la variable a partir de la cadena codificada se llama unserialize.
Estos procesos se aplican por ejemplo: al guardar un objeto en un fichero (serialize) o recuperar un objeto previamente guardado (unserialize) al enviar un objeto va http en una aplicacin AJAX, o al recibir un objeto previamente serializado
2 | PATRONES SIMPLES
An tenemos un problema a resolver: impedir que se pueda clonar el objeto Singleton. Tendremos que implementar el mtodo clone, para lanzar un error en caso de clonar.
public function __clone() { trigger_error('Clone no esta permitido.', E_USER_ERROR); }
} // No permitimos la clonacion public function __clone() { trigger_error('Clone no esta permitido.', E_USER_ERROR); } // creamos el mtodo singleton public static function singleton() { if (!isset(self::$instance)) { // con este pequeo truco nuestro cdigo // funciona en cualquier clase. $c = __CLASS__; self::$instance = new $c; } return self::$instance; } // Example method public function foo() echo 'foo!'; } } $nuevo = ejemplo::singleton(); {
Coche En el ejemplo, se declara el constructor como privado ya que no queremos instancias de vehculo.
Factora abstracta
Se pueden crear factoras abstractas. La idea es la siguiente: tengo que construir un programa con ventanas y controles para distintas plataformas: Linux, Mac y Windows. El problema es que en cada una de ellas las funciones para gestioanr ventanas y controles se llaman de manera distinta. Puedo crear una factoria abstracta, llamada factoriaVentanas, que se encargar de llamar a la funciones adecuadas para cada plataforma.
// entorVentanas es una factoria abstracta. if ( $entorno=="MAC") { $ventana = new entornoVentanas("mac"); } else { $ventana = new entornoVentanas("linux"); } // ahora me da igual estar en un entorno mac o // linux. La programacion es la misma. $ventana->abrirVentana(); $ventana->anadirControl();
Aqui tienes otro ejemplo. Hemos desarrollado un juego de marcianos y le hemos hecho separando la lgica del juego (calcular donde va mi nave, por donde aparecen los marcianos) de la presentacin. As podemos jugar al mismo juego en 2D y 3D, o hacer algo mucho mas til: probar el juego con distintos motores 3D.
class marciano3D { function mostrar(){ echo "soy un marciano en 3D "; } } class marciano2D { function mostrar(){ echo "soy un marciano en 2D "; } } class nave3D { function mostrar(){ echo "soy una nave en 3D "; } } class nave2D {
function mostrar(){ echo "soy un mave en 2D "; } } class factoria{ private $marciano, $nave; function __construct( $claseMarciano, $claseNave ){ $this->marciano= $claseMarciano; $this->nave = $claseNave; } function crear( $que ){ switch ( $que){ case "marciano": return new $this->marciano; case "nave" : return new $this->nave; } } } $juego2D= new factoria("marciano2D", "nave2D"); $juego3D= new factoria("marciano3D", "nave3D"); $marcianoA = $juego2D->crear("marciano"); $marcianoA->mostrar(); $marcianoB = $juego3D->crear("marciano"); $marcianoB->mostrar();
Observa que al crear cada factora indicamos que clases debe usar.
function setMasa($masa) { $this->masa = $masa; } function setSalsa($salsa) { $this->salsa = $salsa; } function setRelleno($relleno){ $this->relleno = $relleno; } function servir(){ echo "<p>Pizza de masa {$this->masa}, "; echo "salsa {$this->salsa} y con "; echo "{$this->relleno} de relleno</p>"; } } /** los especialistas abastractos. */ abstract class PizzaBuilder { protected $pizza; function getPizza() { return $this->pizza; } function crearNuevaPizza() { $this->pizza = new Pizza(); } /* cada especialista debe implementar estos mtodos */ abstract function buildMasa(); abstract function buildSalsa(); abstract function buildRelleno(); } /** un especialista para pizzas hawaianas */ class HawaiPizzaBuilder extends PizzaBuilder { function buildMasa() { $this->pizza->setMasa("suave"); } function buildSalsa() { $this->pizza->setSalsa("dulce"); } function buildRelleno() { $this->pizza>setRelleno("chorizo+alcachofas"); } } /** otro especialista para pizzas picantes */ class PicantePizzaBuilder extends PizzaBuilder { function buildMasa() { $this->pizza->setMasa("cocida"); } function buildSalsa() { $this->pizza->setSalsa("picante"); } function buildRelleno() { $this->pizza>setRelleno("pimienta+salchichn"); } } /** La cocina como personaje Director */ class Cocina { private $pizzaBuilder; function setPizzaBuilder($pb) { $this->pizzaBuilder = $pb; } function getPizza() { return $this->pizzaBuilder>getPizza(); } function construirPizza() { $this->pizzaBuilder->crearNuevaPizza(); $this->pizzaBuilder->buildMasa(); $this->pizzaBuilder->buildSalsa(); $this->pizzaBuilder->buildRelleno(); }
} /** Ponemos en marcha la cocina */ $cocina = new Cocina(); $hawai_pizzabuilder = new HawaiPizzaBuilder(); $picante_pizzabuilder = new PicantePizzaBuilder(); /** Un cliente pidiendo una pizza. */ $cocina->setPizzaBuilder( $hawai_pizzabuilder ); $cocina->construirPizza(); $cocina->getPizza()->servir(); /** Otro cliente pidiendo una pizza. */ $cocina->setPizzaBuilder( $picante_pizzabuilder ); $cocina->construirPizza(); $cocina->getPizza()->servir();
Pizza de masa suave, salsa dulce y con chorizo+alcachofas de relleno Pizza de masa cocida, salsa picante y con pimienta+salchichn de relleno
// La clase encargada de generar objetos a partir de los prototipos class FactoriaPrototipo { private $mapaObjetos; function __construct() { $this->mapaObjetos["productoTipo1"] = $this->mapaObjetos["productoTipo2"] = } new UnProducto(1); new UnProducto(2);
function create($nombre) { return ( isset($this->mapaObjetos[$nombre]) ? clone $this>mapaObjetos[$nombre] : Null); } } // Test de unidad $factoria = new FactoriaPrototipo(); $producto = $factoria->create("productoTipo1"); $producto->show(); $producto2 = $factoria->create("productoTipo2"); $producto2->show();
echo( "'$args' added to user list\n" ); } } $ul = new UserList(); $ul->addObserver( new UserListLogger() ); $ul->addCustomer( "Jack" ); $ul->addCustomer( " y otro mas" );
'Jack' added to user list ' y otro mas' added to user list
3 | PEAR
Instalacin
PEAR se puede instalar con la mayora de distribuciones Linux. Funciona como una especie de "apt-get": incluso necesitas permisos de root para algunas operaciones. Para instalar un determinado paquete, o listar los paquetes instalados tendremos que hacer:
pear install Numbers_roman pear list
Los paquetes se instalarn en un directorio local, que en Ubuntu es usr/share/php. Adems, se prepara el entorno de PHP para incluir el este directorio dentro del PATH de los include. Si podemos instalar PEAR en el servidor, podemos optar por un mtodo mas rudimentario: copiar los paquetes a nuestro servidor web, en una carpeta llamado include/pear y cargar los paquetes manualmente.
Soporte de PHP
Desde la versin 4, PHP soporta nativamente la funcin gettext y las funciones auxiliares para establecer el locale, dominios, etctera.
La funcin gettext queda reemplazada por una serie de funciones que suelen ser:
_e() para traducir y echar el valor. (doble barra baja) __ () solo para traducir. t() para traducir.
Wordpress utiliza dos sistemas: 1. gettext oficial de PHP (funcion _) 2. un sistema propio ( funcin _e y __ )
Algunos programas, por ejemplo Drupal, utilizan ficheros .po sin pasarlos a .mo, otros requieren las compilacin, Wordpress, etctera.
Algunos enlaces