Variables, referencias, estructuras de control, objetos y patrones de diseño
- Características de PHP
- 1.- Manejo de variables en PHP
- 2.- Referencias.
- 3.- Estructuras de control y funciones
- 4.- Objetos
- 5.- Patrones de diseño en PHP
Características de PHP
PHP es un lenguaje interpretado, creado en el año 1995 por Rasmus Lerdorf. Su sintaxis y propiedades derivan principalmente de C, Java y Perl.
En su uso más común de lenguaje interpretado de servidor, PHP puede ser utilizado como módulo en los servidores más famosos (APACHE, IIS) o como CGI, tal como se funcionaría un script Perl.
PHP, en estos momentos, ha dejado de ser sólo una herramienta para la creación de páginas web dinámicas, para convertirse en un lenguaje de programación de uso general. Se puede usar PHP como línea de comandos, siendo una herramienta sencilla y poderosa y también se pueden generar aplicaciones de escritorio, a través de PHP-GTK, aunque todavía falta un mayor desarrollo de esta forma de trabajo.
La versión estable más reciente es la 4.3.4, mientras que en desarrollo se encuentra la versión 5,aún en estado de beta.
La versión actual estable de PHP, la 4, se caracteriza por su velocidad, independencia de procesos (thread-safe), extensibilidad (a través de módulos escritos en C), soporte mejorado para programación dirigida a objetos y compatibilidad con PHP 3.
Entre las fortalezas de PHP para el desarrollo de aplicaciones web se encuentran:
- Portabilidad: PHP se encuentra disponible en todas las plataformas importantes y las alteraciones necesarias para portar el código de una plataforma a otra son mínimas, sino innecesarias
- Soporte para base de datos: PHP cuenta con soporte nativo o basado en extensiones para las bases de datos más usadas en la actualidad (MySQL, PostgretSQL, Oracle, MSSQL,etc) ,tanto como soporte ODBC, que le permite su conexión a bases no consideradas.
- Excelente documentación: para conocer y manejar de manera adecuada un lenguaje es importante tener una buena documentación. PHP tiene uno de los mejores manuales existentes para un lenguaje, el cual se ve complementando por los comentarios de usuarios, que enriquecen con ejemplos prácticos el uso de determinadas características o funciones del lenguaje
- Flexibilidad en el desarrollo: PHP, al igual que Perl, permite la definición de variables en tiempo de ejecución, e incluso permite la generación de código en tiempo real. No se requiere una IDE específica para trabajar con scripts PHP, y el proceso de depuración se puede realizar directamente en la pantalla del browser, o través de diversas herramientas gratuitas.
1.- Manejo de variables en PHP
PHP maneja diversos tipos de variables: booleanas, enteros, números de punto flotante, cadenas, arrays y objetos. Se incluyen también las variables especiales recurso y NULL. El tipo de variable generalmente no es definido explicitamente por el programador, sino que PHP lo decide en tiempo de ejecución
- Si se desea saber de que tipo es una variable, se puede utilizar
gettype(). - Para determinar si una variable es de un determinado tipo, se debe utilizar el grupo de funciones is_XXX, en el cual XXX corresponde al tipo de función. Por ejemplo,
is_null-is_bool-is_int. - Para cambiar el tipo de una variable, se utiliza el nombre del tipo encerrado entre paréntesis antes de la variable. Por ejemplo
(int)$variable
1.1.- BOOL
Las variables booleanas son aquellas que pueden tomar el valor true o false.
Los siguientes valores son considerados false:
- El valor
false - El entero 0 y el flotante 0.0
- La cadena "" o "0"
- Un array sin elementos
- Un objeto sin miembros
- El valor
NULL
Resultan de interés especial la conversión de las cadenas y los arrays.
Es muy común la verificación de entradas significativas en la cadena, por ejemplo en la validación de cuestionarios o en consultas a base de datos. Para evitar inconvenientes, sugiero el uso de:
if (strlen(trim($var)))
Ya que permite discriminar aquellas cadenas que incluyen solo espacios en blanco (en sentido genérico) y aquellas que pueden contener el valor '0'.
En el caso de los arrays, la verificación de una cadena vacía es especialmente relevante antes de un ciclo foreach, ya que permite la utilización de la fórmula
- if ($var) {
- foreach($var as $item) {
- // codigo
- }
- }
la cual impide la generación de un error si $var resulta ser de otro tipo.
1.2.- NULL
Si se requiere el valor de una variable no definida anteriormente, su tipo es NULL, y su valor es NULL (con mayúsculas).
En el caso de los formularios, una cadena vacía y 0 se convierten en false, por lo que la mejor manera de detectar si una variable no existe en el formulario (por ejemplo, si lo generamos automáticamente), es a través de is_null.
1.3.- ARRAYS
La generación de un array se puede realizar a través del constructo de lenguaje array(), o de forma directa. Para cada valor del array existe una clave que lo identifica, que puede ser un índice (a la C), o una cadena (método asociativo).
Los elementos del array pueden ser agregados con clave o sin ella.
Tenemos entonces:
$a=array(); // Por instrucción $b[1]="hola"; // de forma directa, con índice numérico
$b["hola"]=1; // de forma asociativa.
$b[]="chao"; // sin clave explícita. Toma valor
Si una variable ha sido definida y se utiliza como array, el valor antiguo será eliminado, EXCEPTO SI ES UN STRING.
El uso de los paréntesis en un string, de forma similar a C, nos permite acceder a un caracter específico. Entonces, lo siguiente
$b="string";
$b["hola"]="chao"
No producirá una transformación de $b a array, sino que hará que $b sea "ctring". ¿Por que? Primero, "hola" hace cast a integer, transformándose en 0, haciendo que la expresión se transforme en $b[0]="chao";
Con los resultados previsibles.
1.4.- Alcance (scope) de las variables
Las variables en php pueden ser de tres tipos: globales, locales a la función y locales a una instancia de objeto.
Cualquier variable que se defina fuera de una función o clase, es una variable global.
Toda variable que se defina dentro de una función, es local a ella y no afecta a otra variable global del mismo nombre. Lo mismo ocurre con las variables de clase.
Ahora bien, para hacer referencia a una variable global dentro de una función, es necesario usar, al inicio de ésta la sentencia 'global', seguida por las variables globales entre comas.
global $variable_global_1, $variable_global_2
También se puede hacer referencia a una variable global , utilizando el array superglobal $GLOBALS.
$GLOBALS["variable_global_1"];
1.5.- Variables superglobales
Desde PHP 4.1, existe un conjunto de variables denominadas Superglobales, arrays que contienen información relevante sobre el servidor, el ambiente de ejecución y el ingreso de los usuarios. La gran ventaja de estas variables que son registradas automáticamente en todas las funciones, por lo están disponibles en cualquier alcance. Esto es muy útil, ya que como desde PHP 4.2 la variable de inicialización register_global se encuentra en off, ya no se registran de modo automático como variables globales las variables de formularios, cookies ni variables de sesión.
Por ejemplo, para utilizar el array POST antes de PHP 4, había que utilizar
global $HTTP_POST_VARS;
if ($HTTP_POST_VARS["mi_ingreso"]==1) { ...
Ahora, basta sólo con
if ($_POST["mi_ingreso"]==1) { ...
Las variables superglobales son:
- $GLOBALS : Contiene una referencia a cada variable que se encuentra en el espacio global.
- $_SERVER: Variables del servidor y relacionadas.
- $_POST: Contiene todos los campos de formularios enviados por el método POST.
- $_GET: Contiene todos los campos de formularios enviados por el método GET.
- $_COOKIE: Variables proveidas por los cookies de las páginas.
- $_FILES: Variables proveidas por upload de archivos vía POST.
- $_ENV: Variables del entorno de ejecución.
- $_REQUEST: Total de variables proveidas por los métodos POST, GET, COOKIE y HEAD.
2.- Referencias.
Las referencias constituyen una poderosa herramienta de PHP, muchas veces incomprendidas.
Las referencias permiten acceder desde distintos nombres a un mismo valor. No son punteros, sino alias dentro de la tabla de símbolos.
Por ejemplo:
$a=5;
$b=&$a;
$b=10;
echo $a; // 1
2.1.- Usos de las referencias
2.1.1.- Funciones
El uso más obvio de las referencias es el paso de valores por referencia, no por valor. Por ejemplo
- $a=5;
- function sumar_1(&$a) {
- $a++;
- }
- sumar_1($a);
- echo $a; // 6
Otro uso no tan obvio es el retorno de referencia. Esto es especialmente útil para devolver un valor determinado de un array o un objeto.
function &encontrar_valor(&$a,$i) {
return $a[$i];
}
$a=array(1=>"bueno",2=>"malo",3=>"No tengo
idea");
$b=&encontrar_valor($a,1);
$b="muy bueno";
echo $a[1]; // muy bueno
2.2.2.- Manejo de arrays complejos
Un caso típico que todos hemos tenido que enfrentar es el de manejar variables como
$a[1]["objeto"]->var["array_1"][1]=50;
$a[1]["objeto"]->var["array_1"][2]=60
Esto se puede solucinar con el uso de referencias, similar a lo que hace con 'with' en JS o VB
$rRef=&$a[1]["objeto"]->var["array_1];
$rRef[1]=50;
$rRef[2]=60
2.3.- Consideraciones sobre las referencias
Las referencias no son transitivas. Por ejemplo
$a=5;
$c=10;
$b=&$a;
$b=&$c;
$b=20; // $a=5, $b=$c=20
Si se hace unset sobre una referencia, el valor no se destruye para el resto de las variables. Se debe pensar en el unlink de unix.
$a=5;
$b=&$a;
unset($a); // $b sigue siendo
3.- Estructuras de control y funciones
3.1.- Estructuras de control básicas.
IF
if (<cond>) {<inst>}
elseif (<cond>) {<inst>}
else {<inst>
Alternativa:
if (<cond>) :
<inst>
elseif (<cond>) :
<inst>
else : <inst>
endif
WHILE
while (<cond>) {
<inst>
DO ... WHILE
do {
<inst>
} while (<cond>)
FOR
for (<init>; <cond>; <post-cond>) {
FOREACH
// para valores:
foreach ($aArray as $sValor) {
<inst> }
// para claves y valores:
foreach ($aArray as $sClave=>$sValor) { <inst>
SWITCH
switch ($valor) {
case '<valor>':
break;
case '<valor>':
case '<valor>':
break;
default:
break;
CONTINUE y BREAK.
- continue: omite la ejecución del resto de las instrucciones del bucle y sigue con la siguiente iteración
- break: rompe la ejecución del bucle. Se puede indicar opcionalmente un número para indicar cuantos niveles debe saltar
$sMiValor="Juan Pérez"; $bLoEncontre=false;
foreach ($aEmpresas as $aEmpresa) {
if ($aEmpresa["privada"]) { continue;}
foreach($aEmpresa as $sEmpleado) {
if ($sEmpleado==$sMiValor) {
$bLoEncontre=true; break 2; }
}
} if ($bLoEncontre) {
echo "lo encontre";
} else {
echo "no lo encontré";
}
3.2.- Funciones nativas y de usuario
3.2.1.- Sintaxis de variables y alcance
Las funciones en php siguen la siguiente sintaxis
function nombre_funcion (<args>) {
<inst>
return $valor;
Toda función es accesible, antes o después de su definición explícita, excepto:
- cuando se define condicionalmente
if ($valor) {
function existe() {}
}
- cuando se encuentra dentro de otra función
function padre() {
function hijo() {
}
}
// aqui no puedo llamar a hijo
padre();
// ahora si puedo llamar a hijo
hijo();
3.2.2.- Argumentos
* Para pasar un argumento por referencia, se utiliza
function sumar_1(&$a) {
if (is_numeric($a)) {
$a++;
}
}
sumar_1($a)
* Se pueden utilizar valores por defecto para los argumentos
function correcta($a,$b=false) {}
function erronea($a=false,$b) {}
function erronea_2($a,&$b=false) {
* Se puede entregar una lista de argumentos variables, utilizando las funciones func_num_args(), func_get_arg() y func_get_args()
function funcion_con_argumentos_variables() {
if (func_num_args()<2) {
return "Error";
} else {
$aArgs=func_get_args();
foreach($aArgs as $sClave=>$sValor) {
<...>
}
}
4.- Objetos
PHP, a pesar de ser un lenguaje de programación predominante estructurado, permite la utilización de objetos, los cuales presentan las siguientes características:
- Creación de objetos a través de esquema clase - instancia
- Poliformismo a través de sobrecarga de funciones. No se pueden sobrecargar operadores.
- Herencia simple, no múltiple.
- Todos los métodos y propiedades son públicos. Por convención, se utiliza _ antes del nombre de un método o variable para indicar que es privado.
- No existen formas intrínsecas del lenguaje para indicar que una clase o método es abstracto, o para requerir una implementación específica
4.1.- Creación de objetos
- Los objetos se crean a través de la i
nstrucción class. - Las propiedades se definen con
var(sólo se pueden inicializar con valores estáticos) - Los métodos se definen con
function. - Se puede hacer referencia al mismo objeto a través de la variable
$this - Al crear un objeto, se inicializa la función con el mismo nombre de la clase (constructor)
class pagina {
var $nombre;
var $doctype;
function pagina($nombre) {
$this->nombre=$nombre;
}
function cambiarDoctype($doctype) {
$this->nombre=$doctype;
}
}
$miPagina=new pagina("fea");
$miPagina->cambiarDoctype("strict");
Es importante considerar que el objeto devuelto por new es una copia, no una referencia. Por lo tanto, si se asignan una referencia del objeto a una variable global, se deberá usar lo siguiente:
$ref=array();
class a {
var $objeto;
var $nombre="hola";
function a() {
global $ref;
$ref[]=&$this;
}
}
$aa=&new a();
$bb= new a();
$aa->nombre="chao";
$bb->nombre="chao";
print_r($ref); // mostrara chao y hola, respectivament
Si se requiere verificar que los patrones de inicialización del objeto sean correctos, es mejor utilizar un patrón Factory, que devuelva el objeto por referencia si se valida, false o un objeto de error si no.
4.2.- Clase derivada
Para crear una clase derivada se ocupa extends.
Para sobrecargar una función, basta con crear una nueva con el mismo nombre. Si se desea acceder a la función de la clase padre, se puede utilizar parent::funcion()
El constructor de la clase padre es llamado si no se define uno nuevo. Si se define constructor, no se llama al constructor de la clase padre. Para suplir esto, se puede hacer lo siguiente:
class padre
{
function padre() {
...codigo...
$this->init();
}
function init() {
}
}
class hijo
{
function init() {
...codigo...
}
}
También se puede llamar a parent::<nombre_clase_padre> desde el contructor de la clase hijo
4.3.- Llamada estática a métodos
Una útil característica de PHP es la capacidad de llamar de forma estática a las funciones de una clase. Esto quiere decir que no es necesario intanciarla para ocupar sus funcionalidades. Se utiliza la sintaxis clase::funcion. Es útil para llamar a funciones que devuelven objetos(Factory) y crear namespaces, a la C++
class mensaje
{
function escribir($sTexto) {
echo $sTexto;
}
}
mensaje::escribir("hola")
4.4.- Serialización de objetos
Si se desea grabar en un archivo o en la base de datos el contenido de una instancia, esta se puede serializar.
$sSerial = serialize($miPagina);
$query = "INSERT INTO mis_paginas SET id=1,pagina='$miPagina'"
Para recuperar una clase serializada, es necesario que ya esté definida (se serializan solamente los valores, no los métodos).
$oSerial=unserialize($miPagina)
4.5.- Como simular funciones abstractas
La forma más sencilla de simular funciones abstractas es generando un error si son accesadas desde la clase padre
class abstracto
{
function funcion_abstracta
{
trigger_error("abstracto::funcion_abstracta : se debe sobrecargar esta
función", E_USER_ERROR);
}
}
4.6.- Como simular interface
Se puede crear un objeto interface, que verifique que otra clase contenga los métodos y propiedades requeridos.
include("PEAR.php");
class Interface
{
var $aMetodos = array();
var $aPropiedades = array();
var $sModoError = "PEAR_Error";
var $aErrores = array();
function Interface($aMetodos, $aPropiedades) {
$this->aMetodos = $aMetodos;
$this->aPropiedades = $aPropiedades;
}
function verificarClase($sClase) {
$aClassVars = array_keys(get_class_vars($sClase));
$aClassMethods = get_class_methods($sClase);
foreach($this->aMetodos as $sMetodo) {
if (!in_array($sMetodo, $aClassMethods)) {
$this->agregarError("No existe el método '$sMetodo' para la clase
'$sClase'");
}
}
foreach($this->aPropiedades as $sPropiedad) {
if (!in_array($sPropiedad, $aClassVars)) {
$this->agregarError("No existe la propiedad '$sPropiedad' para la clase
'$sClase'");
}
}
if ($this->aErrores) {
if ($this->sModoError == "PEAR_Error") {
return PEAR::raiseError(implode("\n", $this->aErrores));
} elseif ($this->sModoError == "PHP_Error") {
trigger_error(implode("\n", $this->aErrores), E_USER_ERROR);
}
} else {
return true;
}
}
function agregarError($sTexto) {
$this->aErrores[] = $sTexto;
}
}
$aMetodos = array("get", "set");
$aPropiedades = array("nombre");
$oInterface = new Interface($aMetodos, $aPropiedades);
$mRes = $oInterface->verificarClase("Interface");
print_r($mRes->getMessage());
5.- Patrones de diseño en PHP
5.1.- Que son los patrones de diseño
Los patrones son formas de describir buenos diseños y prácticas, que permiten describir una experiencia de programación de tal manera que otros la puedan reutilizaar.
El propósito de los patrones es crear un cuerpo de conocimientos que ayuden a los diseñadores de software a resolver problemas recurrentes. Los patrones ayudan a crear un lenguaje común para comunicar descubrimientos y experiencias acerca de los problemas y sus soluciones.
5.2.- Patrones en PHP
Si bien el desarrollo de pequeñas aplicaciones en PHP hace en muchas ocasiones innecesario el uso de patrones, por lo evidente de las soluciones, al adentrarnos en problemas de mediana y gran envergadura nos encontramos muchas veces con problemas en apariencia difíciles, que nos obligan a modificar el código en reiteradas ocasiones. Un adecuado conocimiento de algunos patrones nos permiten diseñar de manera más apropiada nuestras aplicaciones, previniendo problemas a posteriori.
5.3.- Ejemplos de patrones
5.3.1.- Factory
Problema: se debe generar un objeto de acuerdo a una entrada específica definida en tiempo de ejecución.
Ejemplo: Crear un generador de thumbnails que sea fácilmente extensible a diversos tipos de archivos
Solución: se crea una clase (o función), que devuelve otra clase de acuerdo al contexto.
Código:
- Con switch
class generadorImagenes
{
function &Factory($tipo, $archivo) {
switch($tipo) {
case 'gif':
return &new ImagenesGif($archivo);
break;
case 'jpg':
return &new ImagenesJpg($archivo);
break;
default:
return false;
break;
}
}
}
$miObjeto=&generadorImagenes($sTipo,$sArchivo)
5.3.2.- Singleton
Problema: Se requiere crear y acceder a una sola instancia de un objeto.
Solución: Se genera una función o clase (patrón Factory) que genera una instancia de un objeto. Si detecta que este ya existe, retorna esa instancia.
Ejemplo: Crear una sola conexión a la base de datos, accesible desde cualquier parte del script.
class conexionDb
{
} // metodo con global
function &getDb() {
if (!isset($GLOBALS["CONEXION_DB"])) {
$GLOBALS["CONEXION_DB"] = &new conexionDb();
}
return $GLOBALS["CONEXION_DB"];
}
// con static function &getDb() {
static $db = false;
if (!$db) {
$db = &new conexionDb();
}
return $db;
}
5.3.3.- Estrategia
Problema: Se tiene multitud de problemas cuya solución abstraca es la misma, pero que requieren algoritmos específicos.
Ejemplo: se desea validar un formulario. Las acciones requeridas son comunes a cualquier tipo de campo (verificar que no esté vacios si es un campo requerido, que no contengan datos erróneos, filtrar los contenidos para que sean procesables, etc.), pero la acción específica varía de acuerdo al tipo de campo.
Solución: Crear una clase padre, que contenga las funciones más importantes, y derivar de ella subclases que contengan la implementación específica de acuerdo al tipo particular de problema. Para obtener la clase correspondiente, se utiliza un patrón Factory.
class procesadorCamposForma
{
function &Factory($tipo) {
$sClass = "procesadorCamposForma".$tipo;
if (class_exists($sClass)) {
$oTemp = &new $sClass();
return $oTemp;
} else {
return false;
}
}
function procesadorCamposForma() {
}
function esRequerido() {
}
function estaVacio() {
}
function filtrar() {
}
}
class procesadorCamposFormaText extends procesadorCamposForma
{
function esRequerido() {
}
function estaVacio() {
}
function filtrar() {
}
}
5.3.4.- Façade
Problema: Se tiene multitud de objetos, que deben actuar coordinadamente para realizar determinadas actividades
Ejemplo: Se deben crear formularios que reflejen el estado actual de la base de datos. La información recibida debe ingresar nuevamente a la base de datos.
Resolución: Se crea un objeto que controle a los otros objetos, ocultando al programador la complejidad de la tarea.
class conexionBaseDeDatos
{
}
class creadorFormularios
{
}
class procesadorFormularios
{
}
class formulariosTablas
{
var $oDb;
var $oCf;
var $oPf;
function formulariosTablas(&$oConexionDB) {
$this->oDb = &$oConexionDB;
$this->oCf = &new creadorFormularios();
$this->oPf = &new procesadorFormularios();
}
function generarFormulario($sTabla) {
$aTablaEstructura = $this->oDb->getEstructuraTabla($sTabla);
$aDatos = $this->oDb->getDatosTablas($sTabla, $aTablaEstructura["cols"]);
return $this->oCf->crearFormulario($aTablaEstructura["cols"], $aDatos);
}
}
5.3.5.- Cadena de responsabilidad
Problema: Se deben realizar un conjunto de acuerdo a una determina petición, pero sin acoplar de modo fijo la petición a un objeto.
Ejemplo: Se deben realizar múltiples operaciones sobre un item, cada una de las cuales puede modificar lo que recibe la siguiente, ser necesarias y/o excluyentes entre sí.
Solución: Se encadenan los objetos receptores, de tal manera que la petición pase de unos a otros hasta que alguno lo procese. Se establece una superclase manejadora abstracta, de las cuales deriven otras clases que contengan las implementaciones concretas (patrón Estrategia).
class Comando {
function getDatos($aDatos) {
}
function verificar($aOpciones) {
}
function procesarDatos() {
}
}
class ComandoAgregar extends Comando {
}
class ComandoModificar extends Comando {
}
class ComandoQuitar extends Comando {
}
$aOperaciones = array("agregar", "quitar", "modificar");
$aDatos = $conexionDb->getDatos($_GET["tabla"]);
foreach($aOperaciones as $sOperacion) {
if (in_array($sOperacion, $_GET["operacion_seleccionada"])) {
$oComando = Comando::Factory($sOperacion);
$oComando->getDatos($aDatos);
$oComando->verificar($_GET["opciones"]);
$aDatos = $oComando->procesarDatos();
}
}
| Adjunto | Tamaño |
|---|---|
| php_dia_1.ppt | 54 KB |
- 6851 lecturas

El cambio de backend de un sitio no concluye con el paso de toda la información pertinente. Queda un aspecto muy importante que cuidar: los links.
Sí, señores. No hay nada peor para las visitas que ir a su querido feed de noticias y encontrars
Acerca de los frameworks...
Hola, llevo un tiempo con PHP, te recomiendo un libro para completar este artículo, su título es CorePHP programming de Leon Atkinson ,editorial Prentice Hall. He leido muchos de sus capítulos y la verdad es que te aclaran un montón cosas que no imaginabas sobre este lenguaje. Algunas de ellas las he puesto en práctica en un framework que estoy desarrollando en el blog de zenphp, desde hace más tiempo he publicado algunos artículos de mis experiencias en granadaphp.agenciaq4.com, una comunidad de este lenguaje, espero que esta información llegue a quien le hace falta.
Saludos.
Enviar un comentario nuevo