lunes, 16 de septiembre de 2013

Interfaz de usuario Android: Layouts básicos 2

AbsoluteLayout

Este contenedor posiciona los elementos de forma absoluta. Lo que quiere decir que  indicaremos la posición (x,y) de las vistas que insertemos dentro de este. Esto hace que sea más complicado de mantener y menos flexible que los demás tipos de contenedores. Por eso ha quedado obsoleto y no se recomienda su uso.

TableLayout

Este contenedor permite dividir el espacio disponible en forma de tabla, definiendo las columnas  y especificando el lugar donde se posicionarán sus vistas hijas en la tabla. Al igual que pasa con muchas de los atributos vistos, la definición de la tabla se asemeja a como la definiríamos en HTML. Pero a diferencia de como se define una tabla en HTML, ahora solo crearemos filas (elemento TableRow) y cada vista que coloquemos en ellas se corresponderá con una columna. Evidentemente en cada fila podremos insertar las vistas que queramos, independientemente de que en otra fila hayamos insertado más o menos. Por lo tanto para saber el total de columnas que tiene  el contenedor miraremos la fila que tiene más columnas.

Interfaz de usuario Android: Layouts básicos 1

LinearLayout

Contenedor que posiciona sus vistas (Views) una detrás de otra. Configurable para que  esta colocación sea horizontal (uno detrás de otro) o vertical (uno debajo de otro). Por lo tanto su atributo más importante es: android:orientation:”horizontal|vertical”.  Las vistas empezarán a colocarse en la esquina superior izquierda de la pantalla. Actualmente es uno de los contenedores más utilizados.

Hay 3 atributos muy importantes que tendrán las vistas que se encuentren dentro de un contenedor de tipo LinearLayout y que nos ayudarán a su colocación (de las vistas):
A) Los atributos android:layout_width y android:layout_height explicados en un tutorial anterior.
B) El atributo android:layout_weight (valor por defecto 0) indica que proporción del espacio restante en el contenedor será adjudicado a una vista. Por lo tanto permite dar a las vistas de un LinearLayot unas dimensiones proporcionales entre ellas. Esto quiere decir que si al atributo android:layout_weight de una vista le asignamos el valor “1” y al mismo atributo de otra vista le asignamos “2”, esta última ocupará el doble del espacio libre que la primera.
Hay que tener en cuenta que el resultado de modificar este atributo depende del valor del atributo del contenedor  android:orientation. Ya que si el valor es “vertical” las vistas crecerán en altura para adquirir el espacio extra proporcional. Sin embargo si el valor de la orientación del contenedor es “horizontal”, las vistas crecerán en anchura.

domingo, 15 de septiembre de 2013

El archivo AndroidManifest.xml

En el tutorial anterior la estructura de directorios que tiene un proyecto Android. Y comentamos la importancia de dichos directorios y de los archivos que incluyen. Vamos a presentar el archivo más importante de cada proyecto y que deberá de estar presente en la raíz del proyecto: AndroidManifest.xml.
Dicho archivo es generado automáticamente y modificable gráficamente o  programando. Y por lo tanto es importante conocerlo. Ya que el archivo presenta información esencial sobre la aplicación al sistema operativo Android. Información necesaria para que pueda ejecutar la aplicación.

Principales tareas que realiza AndroidManifest.xml:

- Utiliza el nombre de paquete Java como identificador único de la aplicación.
- Describe los componentes de la aplicación: Actividades, servicios, proveedores de contenido... Para ello utiliza el nombre de las clases que implementan cada uno de estos componentes y publica sus capacidades. Esto permite al sistema operativo conocer que componentes tiene y bajo que condiciones pueden ser lanzados.
- Especifica que permisos tiene la aplicación para acceder a partes protegidas del API que proporciona el sistema Android.
- Declara la mínima versión del sistema operativo en el que funcionará la aplicación.
- Indica las librerías que utiliza el proyecto y por lo tanto tienen que ser empaquetadas al crear la aplicación.
- Permite declarar  una clase 'Instrumentation' que sirve para monitorizar la interacción de la aplicación con el sistema. Esta declaración solo estará presente mientras se desarrolla y prueba la aplicación. Ya que será borrada antes de que la aplicación se vaya a publicar.

miércoles, 11 de septiembre de 2013

Estructura de un proyecto Android

Cuando creamos un nuevo proyecto para Android, ya sea desde eclipse o desde el nuevo Android Studio, se nos crearán una serie de directorios necesarios para posteriormente generar/compilar la aplicación.Vamos a repasar brevemente esa estructura de directorios y nos centraremos en uno de los directorios más importantes a la hora de crear una aplicación: el directorio de recursos.
Estructura de un proyecto Android

Conceptos básicos de Android

Hay 4 bloques/componentes que debemos conocer y que pueden estar presentes, a la vez, en una aplicación Android:

1. Actividad

Cada actividad esta implementada como una simple clase Java que extiende (hereda) de la clase Activity de Android. Una actividad se encargará de mostrar una interfaz de usuario o pantalla gráfica, compuesta de vistas (cada unos de los elementos de la pantalla), y de tratar los eventos sobre estas vistas. Por cada pantalla que necesite una aplicación definiremos una actividad. Por ejemplo una actividad para listar contactos, otra para ver el detalle del contacto elegido y otra para enviar mensajes.
Cuando volvemos atrás en la aplicación, la interfaz es pausada y puesta en una pila. Con lo estamos devolviendo el control a la actividad que controlaba la anterior interfaz. Por lo tanto podemos definir las actividades como los controladores en la arquitectura MVC que utiliza Android.
En el fichero AndroidManifest.xml deberemos especificar todas las actividades de la aplicación, y cual va a ser la que se iniciará con la aplicación.

martes, 10 de septiembre de 2013

Interfaz de usuario Android: Conceptos

Introducción

En el patrón  MVC definiremos, a groso modo, la vista como la visualización del modelo. Más específicamente, la vista es la porción de una aplicación responsable del renderizado  de los elementos visuales y de enviar la interacción del usuario con dicho elementos a otro componente de la arquitectura. La vista es también llamada coloquialmente como interfaz de usuario. Y como Android sigue este patrón, en el que se pretende separar los datos de la lógica, lo correcto es utilizar el mecanismo que proporciona Android para definir la interfaz de usuario: ficheros de diseño basados en XML.
Cada uno de estos ficheros se crearán en el directorio res/layout/ de nuestro proyecto. Y cada uno de ellos se corresponderá con una 'pantalla' gráfica de la aplicación.
Todos los elementos gráficos que se renderizarán en una 'pantalla' son subclases de una clase llamada View, por lo tanto, a partir de ahora a dichos elementos gráficos (campos de texto, botones, imágenes) que formarán la interfaz de usuario les llamaremos vistas.

jueves, 5 de septiembre de 2013

Lista de tareas simple con Symfony 2: Parte 5

Continuación de la página Insertar Tarea

1. Validación del formulario

La validación del formulario se realiza en la entidad asociada, Tarea en nuestro caso, ya que será la que recibirá directamente los datos del formulario y será la que valide sus restricciones.

 /*src/Tarea/ListadoBundle/Entity/Tarea.php*/  
 ….  
  public static function loadValidatorMetadata(ClassMetadata $metadata) {  
     $metadata->addPropertyConstraint('descripcion', new Assert\NotBlank(array(  
       'message' => 'This value should not be blank.'  
     )));  
     $metadata->addPropertyConstraint('descripcion', new Assert\MinLength(12,array(  
       'message' => 'This value is too short. It should have {{ limit }} character or more.'  
     )));  
     $metadata->addPropertyConstraint('fechaRealizar', new Assert\Date(array(  
       'message' => 'This value is not a valid date.'  
     )));  
   }  

En está función estática se añadirán las restricciones sobre cada campo del formulario y sus mensajes de error. Está función será la encargada de comprobar si son válidos los datos enviados junto al formulario y será llamada desde el controlador. Dicho controlador la llamará internamente mediante $form->isValid(). Por lo tanto una vez se envíe el formulario se validará (validación en el servidor).

Lista de tareas simple con Symfony 2: Parte 4

Página Insertar Tarea

Primero de todo vamos a crear una nueva entrada en la configuración de enrutamiento:

 #src/Tarea/ListadoBundle/resources/config/routing.yml  
 ...  
 insertar:  
   pattern: /insertar  
   defaults: { _controller: TareaListadoBundle:Tarea:create }  
   requirements:  { _method: "GET|POST" }  

Podemos ver que la acción se llamará cuando la url del navegador se corresponda con localhost/../insertar y que vamos a usar el mismo controlador (TareaController) pero esta vez llamando al método create.
Es importante especificar que la página podrá ser llamada mediante GET para acceder al formulario y mediante POST, cuando el formulario envíe datos al servidor. Por lo tanto hay que especificar ambos métodos en los requisitos.

A continuación vamos a crear el formulario de inserción de una tarea. Symfony 2 viene incluye un componente para formularios muy potente que facilita la tediosa tarea de tratar con formularios. Y recuerda que, como ocurre con todos los componentes de Symfony2, lo puedes utilizar fuera de Symfony2 en tus propios proyectos.

miércoles, 4 de septiembre de 2013

Lista de tareas simple con Symfony 2: Parte 3

Vista de la página principal

Podríamos recurrir a un método muy común utilizado con PHP  que consiste en  incluir un 'header' y un 'footer' en cada una de las plantillas con las partes que se repiten en todas las páginas/vistas. Sin embargo es recomendado utilizar el motor de plantillas Twig que incorpora Symfony2. Y aprovechar la posibilidad que proporciona de heredar plantillas.

Vamos a ver una breve introducción a algunos conceptos Twig:

A) Sintaxis en TWIG:

- {{.....}} es utilizado para imprimir una variable o expresión en la plantilla.
- {%....%} es utilizado para controlar la lógica de la plantilla. Por lo tanto dentro insertaremos las condiciones y o los bucles for, foreach...
- {#...#} es utilizado para insertar comentarios. Equivalente al comentario multilinea de /**/ de PHP.

Lista de tareas simple con Symfony 2: Parte 2

Vamos a continuar con la creación de la página principal de nuestra lista de tareas.

Controlador de la página principal

Después de definir la entidad, crear su tabla correspondiente en la base de  datos y de añadir algunos datos de prueba, ya podemos implementar nuestro controlador. Para ello vamos a asociar la ruta de la que será nuestra página principal, con el controlador que se va a encargar de tratar con el modelo y renderizar la vista. Por lo que vamos a modificar el fichero ListaCompraBundle/Resources/config/routing.yml .

Por norma, el nombre de un controlador (clase) llevará el sufijo Controller  y nombre de la acción (método de la clase) llevará el sufijo Action.

El controlador encargado de tratar el patrón de ruta '/' va a ser ListadoController.php y  el método, que invocará el controlador, encargado de ejecutar la acción va a ser indexAction. Además le indicaremos que el acceso a dicha ruta se realizará mediante peticiones GET.

 #src/Tarea/ListadoBundle/Resources/config/routing.yml  
 homepage:  
   pattern: /  
   defaults: { _controller: TareaListadoBundle:Tarea:index }  
   requirements:  { _method: "GET" }  

martes, 3 de septiembre de 2013

Lista de tareas simple con Symfony 2: Parte 1

En el tutorial anterior vimos una breve introducción a la estructura de un proyecto Symfony 2. En este y en la siguiente serie de tutoriales vamos a construir una simple lista de tareas con Symfony 2. Iremos explicando paso a paso la creación de una aplicación simple. Y los componentes que la forman.

A la hora de desarrollar una aplicación debemos de tener claro las acciones que va a realizar la misma y mediante que URL's vamos a invocarlas. Ejemplo de URL's que podremos hacer en nuestra aplicación.

URL                                        Action
-------------------------------------------------------------
/                                              Listar tareas (página principal)
/insertar                                   Insertar una tarea
/eliminar/x                                Eliminar la tarea x
/editar/x                                   Editar la tarea x

Creación de la página principal

Configurar la base de datos

Antes de comenzar realmente, tendrás que configurar tu información de conexión a la base de datos. Por convención, esta información se suele configurar en el archivo app/config/parameters.yml aunque también puedes cambiarla desde el navegador entrando en http://localhost/.../web/app_dev.php (esta es la ruta completa si no has configurado el host virtual para el DocumentRoot) y entrando en el apartado configure.

El resultado es un fichero similar a este:

 parameters:  
   database_driver: pdo_mysql  
   database_host: 127.0.0.1  
   database_port: null  
   database_name: tareas  
   database_user: root  
   database_password: tu_password 
   mailer_transport: smtp  
   mailer_host: 127.0.0.1  
   mailer_user: null  
   mailer_password: null  
   locale: en  
   secret: e6ea6da2ce387ebafd55fe3296eeb3a4  
   database_path: null  

lunes, 2 de septiembre de 2013

Introducción a Symfony 2

Symfony y Bundles

Un Bundle es un directorio con una estructura bien definida donde colocaremos los elementos de la arquitectura MVC de un proyecto Symfony 2. Podemos comparar a nivel de concepto los bundles con los plugins de Joomla (por ejemplo).
La primera idea que debe quedar clara, expresada de manera simplista, es que “todo es un bundle” en Symfony2. Por tanto, si queremos desarrollar una aplicación necesitaremos, por lo menos, tener un bundle para alojar el código de la misma. Gracias a este concepto, la distribución de nuestra aplicación o la utilización de funcionalidades de aplicaciones de terceros es muy sencilla.

Nota: También hay que tener en cuenta que la creación de un Bundle significa la creación de un espacio de nombres (enlace a tut. espacio de nombres). Que tendremos que tener en cuenta a la hora de ir creando la aplicación.

domingo, 1 de septiembre de 2013

Symfony 2: Instalación y configuración

Antes de ver los distintos métodos de instalación y actualización, tenemos una lista de requisitos que debemos de cumplir para llevar a cabo dicha tarea.

Requisitos obligatorios:
- PHP debe ser una versión mínima de PHP 5.3.3
- Servidor web (como apache)
- Es necesario habilitar JSON
- Es necesario tener habilitado el ctype
- PHP.ini debe tener configurado el valor date.timezone

Si deseas utilizar Doctrine, necesitarás tener instalado PDO. Además, es necesario tener instalado el controlador de PDO para el servidor de base de datos que desees utilizar.

domingo, 25 de agosto de 2013

Ejemplo PHP de servicio RESTful - Parte 2

En el anterior tutorial creamos un sencillo servicio RESTful. Ahora vamos a ver como interactuar con él.
Para hacer peticiones al servicio RESTFul vamos a utilizar la herramineta cURL desde el interprete de comandos y la librería libcurl para utilizar la misma herramienta desde PHP.

Peticiones desde el interprete de comandos

1. Petición para recibir listado de usuarios:

  curl http://localhost/login_restful/usuarios  

Resultado:

  {"estado":"correcto","usuarios":[{"id":"5","nombre":"modificado","email":"prueba4@ejemplo.com"},{"id":"7","nombre":"modificado2","email":"prueba6@ejemplo.com"},{"id":"10","nombre":"pepe","email":"prueba@e.com"}]}  

2. Petición para crear un nuevo usuario:

 curl -d "nombre=otroUsuario&email=prueba@ejemplo.com&pwd=1234" http://localhost/login_restful/crearUsuario  

Resultado:

  {"estado":"correcto","msg":"usuario creado correctamente","usuario":{"id":"11","nombre":"otroUsuario","email":"prueba@ejemplo.com"}}  

Ejemplo PHP de servicio RESTful - Parte 1

Vamos a crear un sencillo servicio RESTful  orientado a objetos, con el que podremos realizar las siguientes peticiones, utilizando para ello URL's amigables:
- Pedir una lista de usuarios mediante una petición GET.  URL de la petición:  http://localhost/login_restful/usuarios
- Crear un nuevo usuario mediante una petición POST en la que aportaremos los datos del usuario. El sistema asignará el identificador del recurso. URL de la petición: http://localhost/login_restful/crearUsuario
- Solicitar autenticación de un usuario mediante una petición POST y los datos necesarios para la autenticación. URL de la petición: http://localhost/login_restful/login
- Actualizar un usuario mediante una petición PUT a un determinado identificador de recurso. URL de la petición: http://localhost/login_restful/actualizarNombre/1
- Eliminar un usuario mediante una petición DELETE. URL de la petición:  http://localhost/login_restful/borrarUsuario/1

Por cada petición vamos a recibir un objeto JSON ya sea informando de un error o dando información de que la petición se ha resuelto correctamente.

jueves, 22 de agosto de 2013

PHP y cURL (libcurl)

En el tutorial anterior, se explicó el funcionamiento de la herramienta cURL para utilizarla en el interprete de comandos. Ahora vamos a ver como podemos utilizar esa misma herramienta en nuestros scripts PHP.
Para ello utilizaremos la librería de PHP libcurl. Si en nuestra configuración de PHP no la tenemos activa, simplemente modificaremos php.ini y evidentemente reiniciaremos el servidor Apache. Si por el contrario no la tenemos instalada (se puede comprobar con la función phpinfo() en un script), seguiremos las siguientes instrucciones:

 sudo apt-get install php5-curl  
 sudo service apache2 restart //tras cualquier cambio en PHP o mysql es necesario reiniciar el servidor  

Ahora centrémonos en como utilizar la librería en PHP.

Herramienta cURL en el interprete de comandos

cURL es una herramienta muy útil para hacer peticiones HTTP/S, que es multiplataforma y que nos permite utilizar varios protocolos dichas peticiones. Por lo tanto se convierte en una herramienta importantísima a la hora de realizar peticiones a un recurso de un servicio RESTful. Recuerda que un recurso puede ser un fichero XML, JSON o XHTML.
Es posible utilizarla bajo el interprete de comandos (terminal) y mediante PHP gracias a la librería libcurl. En este tutorial vamos a centrarnos en el uso en el interprete de comandos.

Instalación en Ubuntu

Lo normal es que la herramienta cURL para utilizarse en el interprete de comandos ya venga instalada en versión de sistema operativo. Pero si no es el caso, su instalación en Ubuntu es muy sencilla:

 sudo apt-get install curl  

miércoles, 21 de agosto de 2013

Introducción servicios RESTful

Los servicios web son un conjunto de aplicaciones o de tecnologías con capacidad para interoperar en la Web. Estas aplicaciones o tecnologías intercambian datos entre sí con el objetivo de ofrecer unos servicios. Los proveedores ofrecen sus servicios como procedimientos remotos y los usuarios solicitan un servicio llamando a estos procedimientos a través de la Web. Ya que un servicio web esta identificado por un URI.

Estos servicios proporcionan mecanismos de comunicación estándares entre diferentes aplicaciones, que interactúan entre sí para presentar información dinámica al usuario. Para proporcionar interoperabilidad y extensibilidad entre estas aplicaciones, y que al mismo tiempo sea posible su combinación para realizar operaciones complejas, es necesaria una arquitectura de referencia estándar.

Diagrama ejemplo de un servicio Rest

Excepciones en PHP

Una excepción es un objeto derivado de la clase Exception de PHP que se encarga de mantener e informar de cualquier error producido. Por lo tanto su uso principal es para detener la ejecución del programa, notificar de errores y ayudar a depurar información.
Una excepción se creará ante una situación anómala en la ejecución del programa que provoca que este no pueda continuar con normalidad.
La clase Excepción recibe en su constructor dos argumentos opcionales: mensaje y código de error a mostrar. Algunos de los métodos más importantes de la clase Excepcion y que debemos de conocer son los siguientes:
- getMessage(): Devuelve la cadena de error que le llega al constructor de la clase Excepción.
- getCodeError(): Devuelve el entero que representa el código de error que llega al constructor de la clase Exception.
- getFile(): Devuelve el fichero donde se ha producido la excepción.
- getLine(): Devuelve la linea donde se produjo la excepción.
- getTrace(): Devuelve un array multidimensional con información del fichero y linea donde se produce la excepción, además de la función/método donde se produce la misma y los argumentos de entrada.
- getTraceAsString(): Devuelve la información de la función anterior pero en formato de cadena.

martes, 20 de agosto de 2013

PHP orientado a objetos - Clases y métodos Final

Gracias a la herencia, los métodos definidos en una clase base estarán disponibles en las clases que hereden de esta. Siempre y cuando tengan una visibilidad permisiva. O lo que es lo mismo, que su visibilidad no sea privada. Sin embargo hay ocasiones en las que queramos que las clases hijas puedan utilizar los métodos heredados pero no puedan modificarlos o 'sobreescribirlos'. Para ello antepondremos la palabra reservada final a la definición del método en la clase base (la que va a ser heredada). Se antepondrá a otros modificadores.

 class Usuario{  
   protected $nombre;  
   function getNombre(){  
     return $this->nombre;  
   }  
   final function setNombre($name){  
     $this->nombre = $name;  
   }  
 }  
 class Editor extends Usuario{  
   function setNombre($name){  
     echo "intento de modificar método padre";  
   }  
 }  

Si ejecutamos esto obtendremos el siguiente error: Fatal error: Cannot override final method Usuario::setNombre() in ... Con lo que protegemos al método setNombre() de que sea modificado por una clase heredera.

Espacio de nombres (namespaces) en PHP

En un proyecto grande, el número de clases aumenta con facilidad. Y según se van definiendo más clases, y sobre todo si hay diferentes programadores en el desarrollo, es mas probable que se produzcan colisiones entre nombres de dichas clases o funciones. Hasta PHP 5.3 una solución empleada en muchos proyectos era utilizar nombres de clases muy largos para evitar conflictos. Con la llegada de los espacios de nombres, en PHP 5.3, podemos agrupar clases y funciones en contenedores con identificadores. De forma que no haya conflictos con clases y funciones que se llamen igual en los diferentes contenedores (espacios de nombres).

Definir un espacio de nombres

Si no se indica lo contrario, todas las clases y funciones serán definidas en un entorno global. Con la posibilidad de que haya las colisiones de nombres comentadas anteriormente. Así que vamos a empezar a definir un espacio de nombres. Para definir uno, simplemente tenemos que utilizar la palabra reservada namespace seguida del nombre identificador del espacio de nombres. Además la definición de un espacio de nombres es lo primero que tiene que aparecer en el script. Posteriormente ya se pueden hacer los 'includes' necesarios.

sábado, 17 de agosto de 2013

PHP orientado a objetos - Función mágica de autocarga (__autoload)

En la parte1 y parte 2 del tutorial de métodos mágicos vimos métodos que se pueden definir en una clase y que serán llamados por PHP automáticamente dependiendo de la situación. Ahora vamos a ver una función mágica que se va a encargar de la autocarga de clases: __autoload().

La forma clásica de trabajar con programación orientada a objetos es la de definir una clase en cada script y hacer una inclusión de la misma en los scripts que necesiten hacer uso de ella. Pero si tenemos decenas de clases y tenemos que incluirlas múltiples de veces puede ser muy tedioso. Por eso en PHP 5 aparece la función mágica __autoload(). Que será llamada en el momento que se intente utilizar una clase o interfaz que todavía no ha sido definida mediante ninguna inclusión. Y mediante la definición de su lógica intentar incluirla. De esta forma se puede evitar que los desarrolladores tengan que definir una larga lista de 'includes' al principio de los scripts. Ya que estamos haciendo una carga dinámica.

PHP orientado a objetos - Métodos mágicos - Parte 2

En la primera parte del tutorial presentamos los método mágicos __clone(), __set, __get, __toString , __call y __callStatic. Pero aún faltan varios método que vamos a ver a continuación.

__isset y __unset

Si están definidos estos método mágicos son llamados automáticamente cuando se utilizan las funciones isset() y unset() sobre un atributo no definido o inaccesible en el objeto. Recordemos que isset() sirve para comprobar la existencia de una variable y unset() sirve para destruir una variable. Pero para que la comprobación se realice sobre atributos de un objeto tendremos que definir los método mágicos.

El método mágico __isset() recibe un argumento – nombre del atributo a comprobar si existe o no.
El método mágico __unset() recibe un argumento – nombre del atributo que queremos  destruir.

 class Objeto {  
   protected $id;  
   protected $nombre;  
   protected $email;  
   function __construct($id, $nombre, $email) {  
     $this->id = $id;  
     $this->nombre = $nombre;  
     $this->email = $email;  
   }  
   function __isset($atributo) {  
     return isset($this->$atributo);  
   }  
   function __unset($atributo) {  
     if(isset($this->$atributo))  
       unset($this->$atributo);  
   }  
 }  
 $obj2 = new Objeto(1, "objeto1", "prueba1@ejemplo.com");  
 echo isset($obj2->nombre);  

Funciones anónimas en PHP (closures)

En 5.3 aparece un nuevo tipo de concepto: la función anónima o cláusula (closure). Conocida de los programadores de javascript. Una cláusula  es una función que se ejecuta en su propio contexto. Lo que significa que el contexto en el que la función es definido permanecerá hasta el cierre de la misma. Con lo que podemos declarar una función sin nombre y la podremos almacenar en una variable. Y para llamar a la cláusula llamaremos a la variable seguida de los paréntesis de apertura y cierra.
La sintaxis para definir un 'closure' es muy simple:

 function(){  
   //implementacion  
 }  

Hay que tener en cuenta 3 cuestiones de las funciones anónimas y las variables:

lunes, 12 de agosto de 2013

PHP orientado a objetos - Métodos mágicos - Parte 1

En PHP las clases tiene reservadas ciertos nombres de métodos que llevan como prefijo distintivo una doble barra baja. El programador será el encargado de escribir el comportamiento de estos métodos. Pero la caracteristica más importante es que estos métodos nunca serán llamados directamente por el programador. PHP, si están definidos, se encarga de llamarlos en el momento adecuado. Y es por eso que reciben el nombre de método mágicos.
Dos de estos métodos mágicos, __construct y __destruct(), ya los vimos en un tutorial anterior. Por lo tanto vamos a centrarnos en otros métodos nuevos.

__clone()

En PHP 4 se podía copiar un objeto simplemente asignándolo de una variable a otra. Y de esta forma se podía modificar la copia sin que ello afectara al original.

 $objecto1->nombre = "nombre 1";  
 $objecto2 = $objecto1;  
 $objecto2->nombre = "nombre 2";  
 echo $objecto1->nombre; // nombre 1"  

jueves, 8 de agosto de 2013

PHP orientado a objetos - Herencia múltiple

PHP al igual que Java u Objectice-C no soporta herencia múltiple. Ello se debe a que si se heredasen dos clases que contengan métodos con el mismo nombre no sabría que clase debería de tener preferencia.

Pero si estamos ante una situación en la que necesitamos herencia múltiple no está todo perdido.  Ya que existen dos métodos para conseguir simular este tipo de herencia. Aunque el segundo de ellos solo está disponible a partir de PHP 5.4.

Uso de interfaces para simular la herencia múltiple

Como comentamos en el tutorial sobre las interfaces, una clase que implementa una interfaz tiene disponible todos los métodos definidos. Además de estar obligada a implementarlos. Por lo que si una clase implementa una interfaz significa que puede hacer todo lo que la interfaz quiere que haga.

martes, 6 de agosto de 2013

PHP orientado a objetos - Clases abstractas e interfaces

Clase abstractas

La llegada de las interfaces fue uno de los grandes cambios de PHP5. Ya que con ella PHP daba un paso más hacia la programación orientada a objetos completa.
Una clase abstracta es una clase que no se puede instanciar (provocaría error) y por lo tanto no se puede crear un objeto a partir de ella. Su intención es definir una estructura (plantilla), que puede estar parcialmente implementada, para cualquier clase que quiera extenderla. Puede implementear ciertas funcionalidades y dejar que sus herederas terminen de implementearla.
Para crear una clase abstracta debemos usar la palabra clave abstract:

 abstract class Ejemplo{  
 }  

Una clase abstracta debe contener como mínimo un método abstracto. Los métodos abstractos no tienen implementación, sino que definen una funcionalidad que será implementada obligatoriamente en las clases herederas.

 abstract class Animal {   
  function presentacion() {   
   $sonido = $this->sonido();     
   return strtoupper($sonido);   
  }   
  abstract function sonido();     
 }   

lunes, 5 de agosto de 2013

PHP orientado a objetos - Elementos estáticos

Métodos y atributos estáticos

La palabra reservada static, en PHP y cualquier otro lenguaje de programación, es una declaración que se les da a miembros y/o métodos de una clase. Un miembro o método de una clase declarado como static va a poder ser accedido sin necesidad de hacer una instancia del objecto en una variable. Por lo que va a ser accedido a través de la clase y no a través de un objeto.
La palabra clave static se debe de colocar después de la definición de visibilidad (si no existe la visibilidad es pública) y antes del nombre del atributo o método.

Un método estático es lo más parecido a una función de un lenguaje estructurado. Solo que se encapsula dentro de una clase. Y el hecho de estar en un ámbito de clase y no de objeto tiene dos características:

domingo, 4 de agosto de 2013

PHP orientado a objetos - Herencia

Introducción

A grandes rasgos, el termino herencia significa que una o varias clases pueden derivar de una clase base o 'padre'. Una clase que hereda de otra se llama subclase. Esta hereda todas los atributos y métodos de la clase 'padre'. Y además añade sus propias características (atributos y métodos). Por eso se suele decir que una subclase extiende a la clase base.
El concepto de herencia es el mismo que en el mundo real: hijos heredan características de los padres. Por lo que una subclase tendrá a su disposición todas los atributos y métodos de la clase base. Pero esta última (clase base) no podrá utilizar ninguna de las características que extiendan las clases herederas.
Podríamos concluir la introducción con lo dicho en los anteriores párrafos respecto al total acceso a las características de la clase base por parte de las subclases. Pero estaríamos equivocados. Ya que no hemos tenido en cuenta el concepto de visibilidad explicado en el anterior tutorial. Ya que como explicamos, los lenguajes de programación orientados a objetos permiten indicar que atributos y métodos son internos de la clase base y cuáles son accesibles desde fuera de la clase. Y eso quiere decir que la clase heredera solo podrá tener acceso a los atributos y métodos que se hayan especificado con una visibilidad pública (public) o protegida (protected). Los miembros privados  no serán accesibles directamente. Por lo que nuevamente estamos ante el concepto de encapsulación ya que  la clase hija no puede acceder a todas la implementación interna de la clase padre. Solamente puede acceder a ciertos atributos y métodos que la clase padre permita.

miércoles, 31 de julio de 2013

PHP orientado a objetos - Introducción

Definición de clase

Una clase se podría definir como una plantilla de código para generar objetos.

En PHP una clase la definiremos con la palabra clave class seguida del nombre que queramos que tenga dicha clase. El nombre puede ser cualquier combinación de letras, guiones 'bajos' y números. Pero no puede empezar por un número. Ni el nombre puede ser igual al de alguna palabra reservada de PHP. Finalmente una par de llaves limitarán el contenido de la clase.

 class Producto{  
   //contenido de la clase  
 }  

Un objeto se compone  de datos que han sido estructurados de acuerdo con la plantilla definida en una clase. Por lo tanto un objeto es una instancia (representación) o un tipo definido por una clase.
Entonces vamos a ver como generar una instancia de una clase. Para ello utilizaremos el operador new de la siguiente forma:

 p1 = new Producto();  
 p2 = new Producto();  
 p3 = new Producto();  

Como vemos podemos generar tantas instancias (objetos) como queramos de un mismo tipo (clase).

lunes, 29 de julio de 2013

Patrón PHP POST/Redirect/GET

Todas las aplicaciones web tienen dos objetivos básicos:
- Poder obtener información enviada por el usuario desde un navegador.
- Mostrar resultados obtenidos por el procesado de la información anterior.
Esto se consigue mediante los métodos HTTP POST y GET.
En anteriores tutoriales  ya describimos las peculiaridades de utilizar cada método (POST/GET) para el traslado de información en la comunicación cliente-servidor. Y concluimos que para el envío de información importante desde el navegador al servidor era necesario utilizar el método POST. Debido a que los datos no viajaban en la URL, sino que lo hacían junto con las cabeceras.
Además también comentamos que los datos enviados mediante POST son almacenados en la memoria caché de los navegadores. Y aunque a priori este hecho no pueda parecer problemático, vamos a presentar un problema por el cual se puede ocurrir un doble envío de datos.

Para evitar tener que solicitar varias veces los mismos recursos (datos o imágenes) el navegador almacena en el disco duro dichos recursos. De esta forma, si alguien entra  en una página web, el navegador intentará cargar recursos que tenga almacenados. Ya que si no es la primera vez que se visita la página, el navegador habrá guardado recursos en caché.

lunes, 22 de julio de 2013

Seguridad PHP - Cross Site Request Forgery (CSRF)

Los ataques XSS se centraban en explotar la confianza de un usuario en un sitio web, ya que confiaba en la seguridad del servidor para que los atacantes no pudieran apoderarse de información de los usuarios, mediante la inserción de código 'malicioso'.
Pues existen otro tipo de ataques cuya idea es parecida. Este tipo de ataques ocurren cuando un sitio web permite que un usuario autenticado realice acciones sin verificar si realmente es él quien las está realizando. El ataque CSRF puede hacer que el navegador de la víctima envíe una petición HTTP 'fraudulenta'.  Y la aplicación (servidor) vulnerable piensa que es una petición de la víctima. Esto permitiría al atacante forzar al navegador de la víctima a hacer peticiones que la aplicación vulnerable pensaría que son peticiones legítimas.

sábado, 20 de julio de 2013

Seguridad PHP - Robo de sesiones

Introducción

Antes de nada conviene recordar el funcionamiento de las sesiones y las cookies de sesión explicados en anteriores tutoriales.
PHP tiene soporte nativo para trabajar con sesiones. Cada sesión viene identificada  un id aleatorio (32 caracters hexadecimales), que se crea la inicializar dicha sesión con la función session_start(), y que se almacena en una variable llamada PHPSESSID. Este id es esencial ya que cuando creamos una sesión, se crea un array superglobal que almacenará la información de la sesión. Y éste se almacena en el servidor, en un archivo temporal cuyo nombre está formado por 'sess' + dicho ID de sesión (depende de la configuración de php.ini).
Ahora necesitamos que el cliente tenga una forma de hacer peticiones al servidor y que
este sepa que se está comunicando en un contexto de sesión determinado. O dicho de otra forma el servidor tiene que saber que las peticiones del cliente pertenecen a la sesión.

Esquema intercambio cliente-servidor de cookie de sesión

En una comunicación bidireccional hay dos posibilidades para la comunicación de identificador de sesión:

viernes, 19 de julio de 2013

Seguridad PHP - Cross Site Scripting (XSS)

Mientras que un ataque 'SQL injection' pretendía insertar código 'malicioso' en las consultas SQL de una base de datos, XSS pretende que la aplicación web ejecute código JavaScript o similar. Es una vulnerabilidad que aprovecha la falta de mecanismos de filtrado y validación en los campos de entrada. Permitiendo así el envío de scripts completos (como Visual Basic Scripts o JavaScripts) con secuencias de comandos maliciosos que podrían impactar directamente en el sitio web o en el equipo de un usuario. Este código malicioso intenta aprovecharse de la confianza de un usuario en un sitio web, para engañarlo en la realización de alguna acción o forzarlo a enviar algún tipo de información a otro sitio que no es de confianza.

Por lo tanto, la diferencia en la ideología del ataque es que con 'SQL injection' se pretende aprovecharse de la poca seguridad del servidor para obtener acceso o alterar recursos del mismo mediante inserción de código SQL en el mismo. Mientras que con XSS se pretende introducir código JavaScript con el  propósito de que dicho código  al ser ejecutado por un cliente confiado lleve a cabo una acción maliciosa. Por ejemplo, un atacante colocar un enlace en un foro que al ser pinchado revele la información de identificación del usuario y la envíe a una dirección.

jueves, 18 de julio de 2013

Seguridad PHP - SQL injection

Las aplicaciones web permiten que a través de datos introducidos por los usuarios se realicen consultas y operaciones sobre las bases de datos que integran.
Al intento de  insertar o inyectar código dentro del código SQL para alterar el funcionamiento normal y hacer que se ejecute el código 'malicioso' dentro del sistema se le llama 'inyección de sql' o 'sql injection' (en ingles).
La solución para no permitir la inyección de este código es el correcto tratamiento de los datos que llegan a la aplicación de manera externa. Ya que como hemos dicho anteriormente, nunca hay que fiarse de lo que va hará o no un usuario.

Ejemplos de ataques

A) Acceso de administrador

- La siguiente consulta podría ser una consulta real para averiguar la existencia del usuario introducido en el formulario:

 $usuario = $_POST['usuario'];  
 $pass = $_POST['password'];  
 SELECT * FROM usuarios WHERE usuario = '$usuario' AND password = '$pass';  

Supongamos que dichas variables provienen de los inputs usuario y password del formulario de login y que existe un usuario llamado admin. Que pasaría si el usuario introdujese la cadena admin como login y  'or '1'='1 en la contraseña. Pues que la consulta se evaluaría de la siguiente manera:

 SELECT * FROM usuarios WHERE usuario = 'admin' AND password = '' OR '1'='1';  

Pues sí, podríamos ganarnos el pase como admin!!!. Evidentemente pueden haber variantes en el ataque ya que a parte de que admin puede no existir, puede que en la consulta las variables no estén entre comillas.

Seguridad PHP - Validación y filtrado 2

FILTER_CALLBACK


Como habréis visto en el anterior tutorial la cantidad de filtros es bastante decente pero evidentemente no cubre todas las necesidades que puede tener un desarrollador a la hora de filtrara datos. Por lo tanto tenemos que recurrir a funciones creadas por nosotros o a un tipo de filtro especial con llamada a funciones.

El tipo de filtro FILTER_CALLBACK nos permite hacer lo que nos indica su nombre. Llamar a una función nuestra para utilizarla como filtro o como función de filtrado. Y la única opción que permite es el nombre de la función que queremos aplicar.

Vamos a ver un sencillo ejemplo:

 function convertirEspacio($cadena) {  
      return str_replace(" ", "_", $cadena);  
 }  
 $string = "Esto es un ejemplo";  
 echo filter_var($string, FILTER_CALLBACK, array("options"=>"convertirEspacio"));  

Seguridad PHP - Validación y filtrado 1

La primera regla cuando tratamos con datos, ya sean provenientes de peticiones POST o GET, es que nunca nos podemos fiar de lo que pueda o no haber enviado el usuario. Por lo tanto debemos que validar cualquier dato ya que solo podemos permitir la entrada esperada. Y por supuesto no confiar únicamente en la posible validación en el lado cliente del sistema.

PHP nos presenta un conjunto de funciones que nos permitirán la validación y saneamiento de datos de una forma sencilla. La funcion filter_var (PHP >=5.2) nos permite filtrar una variable según el filtro especificado.

La sintaxis de la función es simple:

 mixed filter_var ( mixed $AFiltrar , int $tipo_filtro , mixed $opciones_filtro [opcional] );  

La salida será los datos filtrados o false en caso de fallo. Importante es el último parámetro  en el que podemos añadir opciones, en formato array asociativo o banderas. Existen diferentes formas de especificar tanto opciones como banderas:

Seguridad PHP - register_globals

El primer paso antes de validar cualquier datos de entrada, es comprobar que la directiva register_globals este desactivada. Desde PHP 5.3 fue declarada obsoleta y a partir de la versión 5.4 fue eliminada. Pero hay que tener cuidado si se usa una versión de PHP anterior. Por lo que  podemos usar la función phpinfo() para que nos diga si esta a activada o no.

El tener activa esta directiva ocasiona problemas graves de seguridad. Cuando register_globals está definida a “On” dentro del php.ini, se permitiría que un usuario cualquiera pudiera inicializar una variable remotamente. Y esto es un peligro en combinación con  de la naturaleza de PHP que no obliga a inicializar las variables.

Seguridad PHP - Autenticación HTTP vs PHP (formularios)

Aunque puedan haber ventajas con el uso de autenticación HTTP, sus desventajas hacen que en la mayoría de los caso se opte por una identificación basada en formularios. En vez de confiar en la identificación a nivel de protocolo. Aquí tenemos algunos inconvenientes:

- La nula posibilidad de 'customizar' que proporciona las ventanas emergentes de identificación HTTP. Las ventanas donde se introducen los datos en este tipo de identificación no permiten modificar su estilo. Lo que hace que tengan un estilo completamente diferente al del resto de la aplicación. Y eso quita atractivo a la aplicación/página web.

- En la autenticación HTTP la información de identificación es recordada hasta que se cierra el navegador. Si no se cierra el navegador seguirá recordando tus datos por lo que no los pedirá. Ya que no proporciona un método sencillo para que el usuario finalice la sesión. Por lo que hay que utilizar algún que otro 'truco'.
La consecuencia de esto es que si otra persona intenta entrar en el sitio web podrá entrar haciéndose pasar por ti, ya que no se le solicitaría ningún tipo de credenciales.

miércoles, 17 de julio de 2013

Seguridad PHP - Autenticación HTTP digest

Si la autenticación HTTP básica anterior no se combina con HTTPS, estamos trasmitiendo la información codificada en base-64. Pero no encriptada o usando algoritmos 'hash'. Lo que es muy fácil de decodificar y es prácticamente como si la enviásemos en texto plano.
Por eso el mecanismo que se presenta a continuación, mejora al anterior, transmitiendo la contraseña como un valor resultante de un algoritmo 'hash'. Lo que lo hace algo más seguro. O por lo menos era más seguro hace unos años. Ya que el algoritmo usado es MD5.  Y es bien sabido, que este algoritmo es vulnerable (por fuerza bruta) desde hace tiempo.
El propósito del esquema de autenticación HTTP digest es permitir que los usuarios prueben que ellos conocen una contraseña pero sin revelar dicha contraseña. Al contrarío que la identificación HTTP básica, en esta se crea un hash de diferentes datos usando la contraseña. El hash implica la creación de una cadena basada en datos que tanto el usuario (y por lo tanto el cliente) y el servidor conocen. Pero en definitiva, se envía el hash y no la contraseña. Lo que en caso que alguien consiga interceptar la conexión y suplantar al usuario, no disponga de la contraseña. Que normalmente es requerida para cambios de configuraciones en lo sitios web.

Seguridad PHP - Autenticación HTTP básica

La autenticación básica HTTP es un sencillo mecanismo con el que un servidor puede solicitar información de autenticación (un ID de usuario y contraseña) de un cliente. El cliente pasa la información de autenticación al servidor en una cabecera de autorización. Dicha información se encuentra codificada en base-64. Dada su poca seguridad, es útil para sistemas con un número muy limitado de usuarios y donde la protección no es muy importante. Por ejemplo para sistemas donde solo se quiere evitar usuarios anónimos para acceder al algún recurso.

Proceso:

1. El navegador (cliente) iniciará la comunicación realizando la petición al servidor. Y enviará las siguientes cabeceras (similar) al servidor:

 GET /download/report.doc HTTP/1.1   
 Accept: application/msword, */*   
 Accept-Language: en-ES  
 Accept-Encoding: gzip, deflate   
 User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)   
 Host: ejemplo.com  
 Connection: Keep-Alive  

martes, 16 de julio de 2013

PDO - Parte 2

Otras funciones útiles de PDO 

Existen tres funciones importantes para obtener información de la consulta ejecutada sin tener que recorrer los resultados:

A) Obtener el id de la última fila o secuencia insertada en la base de datos.

 public string PDO::lastInsertId ([ string $name = NULL ] )  

El parámetro $name opcional, sirve para indicar el nombre de columna. Como PDO depende de los drivers para cada gestor de base de datos soportado, en alguno de estos quizás sea necesario especificar el nombre de columna que almacena los identificadores. Como ocurre en PostgreSQL.

 $conn = new PDO('mysql:dbname=test;host=127.0.0.1', 'user', 'password');  
 $stmt = $conn->prepare('INSERT INTO test (name) VALUES (:name)');  
 $stmt->execute([':name' => 'foo']);  
 var_dump($conn->lastInsertId());  

Recuerda que la función es de la clase PDO y no de PDOStatement.

PDO - Parte 1

La extensión PDO nos facilitará mucho la vida a la hora de trabajar con bases de datos, ya que nos permite abstraernos del tipo de gestor de base de datos que estemos utilizando. Esto quiere decir que sin el uso de PDP, si por ejemplo decides migrar tu aplicación de MySQL a PostgreSQL tendrías que cambiar todos los métodos del conector de MySQL por los métodos de PostgreSQL. Con PDO bastaría con que se cambie únicamente la creación del objeto PDO, donde se especifica el tipo de base de datos a conectar, y el resto de la aplicación seguiría funcionando igual. Por lo esta abstracción del acceso de datos convierte a esta extensión en un elemento muy importante para la portabilidad de la aplicación/web.
PDO además te permitirá usar consultas preparadas. Y como vimos en el caso de la extensión MySQLi nos proporciona una herramienta muy importante en seguridad y rendimiento.
- Se encargan de 'desinfectar' los datos automáticamente.
- La separación de lógica y datos hace que la consulta sea analizada/preparada una única vez y se pueda ejecutar múltiples veces con los mismos datos o similares. Evitando cada vez el ciclo de análisis, compilación y optimización que ocurriría en cada consulta no preparada.
- Al igual que Mysqli, proporciona el uso de transacciones.

miércoles, 10 de julio de 2013

Cookies en PHP

Básicamente una cookie es un fichero de texto almacenado en el navegador de un cliente por orden de un sitio web. En estos ficheros, de tamaño máx. 4 KB se almacena información útil para el servidor como podría ser información del último acceso o información para la personalización de la web de un usuario concreto. Una cookie solo puede ser leída por el sitio web (dominio) que la creó.
Hay un limite de cookies que el navegador puede almacenar:
- 20 cookies para un servidor o dominio
- 300 cookies en total.
Ya que estas se almacenan en el disco duro del usuario, hay que tener cuidado con la posibilidad de que dicho usuario desactive su uso. En dicho caso no se almacenarán. Por lo que hay que tener previsto otro tipo de almacenamiento si la persistencia de información en cookies es indispensable para el sitio web.

Una cookie se envía junto a las demás cabeceras HTTP. Por lo tanto se exige lo mismo que exigíamos cuando queríamos enviar dichas cabeceras. Que no haya ninguna salida (elemento html, espacio en blanco o salida del script) anterior al envío. http://programandolo.blogspot.com.es/2013/07/redireccionamiento-php.html

domingo, 7 de julio de 2013

Sesiones en PHP

PHP en cada petición ejecuta el script correspondiente de principio a final. Y hay ocasiones en que sin necesitar la persistencia de datos que ofrece una base de datos, necesitamos almacenar de alguna forma ciertos datos mientras el usuario este utilizando la aplicación/web.
Y al igual que los arrays superglobales asociativos $_GET  y  $_POST existe otro  de especial importancia para dicho almacenamiento de datos: $_SESSION.  Cada vez que un usuario entre en el sitio web, podremos iniciar una sesión con un identificador exclusivo para dicho usuario y se podrán almacenar datos por medio del array $_SESSION hasta que decidamos finalizar una sesión. Dicho ciclo de inicio y fin suele coincidir con login y desconexión del sistema por parte de un usuario.
Internamente, el servidor, almacena los datos del array superglobal de la sesión en un archivo temporal cuyo nombre está formado por 'sess' + dicho ID de sesión (depende de la configuración de php.ini).

Uso de sesiones

1. Inicializando

 session_start();  

Con esta función no solo iniciaremos una nueva sesión particular en el servidor, sino que reanudaremos una posible sesión existente. Ya que al haber iniciado una sesión nueva, el identificador único que se crea es pasado por medio de una cookie al cliente. De esta manera el servidor sabrá si existe una sesión que tiene que recuperar o no. Dicha cookie por defecto se llamará PHPSESSID aunque podremos modificar el nombre en el el archivo php.ini (etc/php5/apach2/php.ini).

miércoles, 3 de julio de 2013

Redireccionamiento en PHP

En PHP existe una función llamada header() que se encarga de especificar una cabecera HTTP.
Dicha función debe de ser llamada antes de mostrar nada por pantalla. De otra manera se producirá un error.
Cada vez que enviamos una salida desde el servidor al cliente (o viceversa) dicha información será enviada junto a un conjunto de cabeceras HTTP. PHP enviará cabeceras aunque no las especifiquemos. Estas cabeceras serán por defecto si no se han sobreecrito con header(). Por lo tanto si existe alguna salida anterior a la llamada de header(), ya se habrá procesado el envió de cabeceras. Y se producirá el error: "headers already sent".

 void header ( string $string [, bool $replace = true [, int $http_response_code ]] )  

- El primer parámetro es la cabecera que indicará la acción a realizar. Las tres cabeceras más habituales, en header() son:
  • "Location ...". Es el uso más típico de header(). Con  este encabezado redirigimos a la dirección especificada y enviará un código 302 (redirect) de estado. Por lo tanto enviará las cabeceras especificas hasta el momento y procederá a realizar una redirección. Podemos introducir una ruta relativa al servidor o una absoluta. 
 header("Content-Type: application/json;charset=utf-8");    
 header("Location: info.php");  
  • "HTTP/...". Especificaremos una cabecera que especificará un código de respuesta HTTP de la respuesta al navegador. 
 header("HTTP/1.1 200 OK");   
  • "Content-Type ..." Con esta cabecera especificaremos el formato de la salida que mostrará el navegador del cliente.
  header("Content-Type: application/json;charset=utf-8");   

martes, 2 de julio de 2013

Formularios y PHP

Cuando un usuario rellena un formulario HTML y presiona el botón (input) de tipo 'submit' toda la información que este haya introducido en los distintos controles será enviado a la dirección (script) y mediante el método indicado.
Ciclo de envío de formulario a un servidor PHP

El método utilizado para el envío de los datos al servidor, indicará como viajan los datos hacia él.

A) GET

- Todos los nombres de los campos y valores viajan por la URL (query strings).
- Como son mostrados por la URL el navegador los almacena en su historial. Lo que no es muy conveniente para el caso de información sensible y más si ese ordenador puede ser usado por más personas. Además que el usuario despistado puede compartir datos al compartir la URL.
- Debido a esta hay una restricción de longitud de los datos. La longitud máxima de la URL es de 2048 caracteres.
- Los datos enviados al servidor, al viajar por la URL, pueden quedar almacenados en los ficheros de 'logs' del mismo.
- Solo se permite enviar datos ASCII.
- Resultados de operaciones GET pueden ser cacheadas. Lo que quiere decir que múltiples llamadas a un servicio pueden resultar una única petición.
- Tipo de codificación (enctype): application/x-www-form-urlencoded. Es el tipo por defecto, además del único, por lo que no es necesario indicarlo.

lunes, 1 de julio de 2013

Extensión MySQLi - Parte 4: Transacciones

Las transacciones con la extensión MySqli son un mecanismo que nos asegura que todas y cada de las consultas que las forman van a ser ejecutadas. En el caso de que falle alguna declaración, la transacción no se llevará a cabo.

Pero tenemos que tener cuidado con el tipo de tabla o tablas sobre las que vamos a realizar la transacción. Como sabemos los tipos más comunes de motores de almacenamiento de tablas en MySQL son MyISAM y InnoDB. Siendo el primero el que se utiliza por defecto si no se dice nada y que excluye la seguridad proporcionada por la integridad referencial. Sin embargo con este tipo no se permiten transacciones. Así que transacciones solo se pueden llevar a cabo sobre tablas InnoDB.

Fases de las transacciones

1. Iniciar transacción - Autocommit

Por defecto, MySQL se ejecuta en modo autocommit. Tener activo el modo de ejecución automática (autocommit) significa que cada consulta se tratará como una transacción individual.  Lo que  conlleva a  que tan pronto como se ejecuta una sentencia se modifica una tabla de MySQL. Haciendo imposible la vuelta atrás (modificación permanente). Pero gracias a InnoDB y a las transacción, las consultas se puede revertir (roll back). Y para ello tenemos que desactivar el citado modo de ejecución automática. Lo que iniciará la transacción.

domingo, 30 de junio de 2013

Extensión MySQLi - Parte 3: Consultas preparadas y escapado

Las consultas que se realizan a la base de datos, en un sistema real, contendrán datos aportados por el usuario. Estos datos habrán sido enviados al servidor ya se mediante peticiones POST o peticiones GET.
La recuperación de estos datos es muy sencilla. Para ello solo tendremos que acceder al array superglobal asociativo correspondiente. Buscaremos en el array $_POST o $_GET dependiendo de como el servidor espere la recepción de información.

Para la comprobación de la existencia de una variable o elemento de array existe una función muy útil llamada isset()

 if (isset($_POST['userName'],$_POST['password'])) {  
   $user = $_POST['userName'];  
   $pass = $_POST['password'];  
   ...  
 }  

Ahora podríamos utilizar estos datos para crear una consulta:

  if (isset($_POST['userName'],$_POST['password'])) {   
   $user = $_POST['userName'];   
   $pass = sha1($_POST['password']);   
   //podriamos comprobar si los campos estan vacios para mostrar error al usuario  
   ...  
   $resultado = $mysqli->query("SELECT idUsuario FROM usuario WHERE nomUsuario='$user' AND  password='$pass'";  
   ...  
  }   

Una regla importante en el desarrollo de aplicaciones web es que nunca hay que fiarse de lo que va a introducir el usuario y siempre hay que adelantarse a posibles datos de carácter malicioso.

Extensión MySQLi - Parte 2: Consultas de selección

En la anterior parte del tutorial hemos hablado de las consultas que no devuelven resultado almacenado en la base de datos; osea las consultas de creación, borrado, inserción y actualización. Pero además de estas, tenemos otro tipo de consultas muy importantes y son las encargadas de mostrar los datos almacenados en la base de datos.

Consultas que devuelven resultado

Este tipo de consultas ejecutarán una sentencia de tipo "SELECT" sobre la base de datos devolviendo un conjunto de resultados en caso de que la consulta sea correcta y haya resultados que mostrar. Y false en caso de error en dicha consulta.

A) Interfaz orientada a objetos

 $sql = "SELECT cliente.id as id, cliente.nombre as nombre, cliente.cantidad as cant, producto.nombre as producto FROM cliente LEFT JOIN producto ON cliente.id=producto.id";  
 $resultado = $mysqli->query($sql);  
 if($mysqli->errno) die($mysqli->error);  

Perfecto, ahora ya hemos ejecutado una consulta que nos va a devolver datos de la base de datos. Los resultados de la ejecución de dicha consulta los tenemos en $resultado. Así que veamos los tres métodos más comunes de mostrar los datos.

Extensión MySQLi - Parte 1: Consultas de modificación

Hasta la versión 5.5 de PHP se podían usar tres extensiones para interactuar con mysql. La extensión MySQL, la extensión MySQLi y PDO. Sin embargo la primera de ella ha quedado obsoleta y ya no se debe de usar (PHP >=5.5). De hecho si la usamos se generará error de tipo E_DEPRECATED.

Las principales ventajas que proporciona MySQLi respecto el uso de la extensión MySQL son:

- Interfaz orientada a objetos. Aunque también podemos usar la interfaz procedimental.
- Soporte para declaraciones preparadas 
- Posibilidad de usar transacciones.

Errores 

Antes de pasar a interactuar con MySQL, hay que comentar ciertas funciones que nos proporcionaran información de los errores que se pueden producir en las diferentes etapas de dicha interacción.

La extensión MySQLi nos proporciona procedimientos y propiedades de objeto que nos informa del último error producido en la base de datos. El uso de cada uno depende de si se está usando la interfaz orientada a objetos o la interfaz procedimental.

Reglas de reescritura - Parte 3: Ejemplos completos

Vamos a ver varios ejemplos que combinan las distintas directivas vistas:

- Ejemplo 1: Permitir el acceso al area de administración solo desde la red local.

 RewriteEngine On  
 RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.[0-9]+$  
 RewriteRule /admin - [F]  

De esta manera si la dirección que hace la petición al servidor, no coincide con el patrón, y la URI a la que intentamos acceder es /admin (área de administración) no redireccionaremos y mostraremos la página de error 403 (acceso prohibido).

- Ejemplo 2: Mostrar una página distinta dependiendo del navegador que estemos usando para realizar las peticiones al servidor.

 RewriteEngine On  
 RewriteCond %{HTTP_USER_AGENT} ^Mozilla  
 RewriteRule ^/$ /index.max.html [L]  
 RewriteCond %{HTTP_USER_AGENT} ^Lynx  
 RewriteRule ^/$ /index.min.html [L]  
 RewriteRule ^/$ /index.html [L]  

Reglas de reescritura - Parte 2: Directivas

RewriteEngine

Lo primero que tenemos que hacer para empezar a escribir reglas de reescritura es indicar a Apache que vamos a utilizar el módulo mod_rewrite . Y para ello utilizaremos la siguiente directiva en el archivo .htaccess

 RewriteEngine on   

Para desactivarlo, y así el servidor ignore el resto de la configuración, sólo tendríamos que poner

  RewriteEngine off  

RewriteBase 

Esta directiva se utiliza para indicar la URL base para la reescritura.

 RewriteBase /    

Esta directiva no es obligatoria pero si que es útil. Por defecto la ruta al contenido que usamos para la reescritura es relativa al directorio raíz  del host (por ejemplo public_html/). Por lo que con esta directiva podemos especificar el directorio (ruta) base para las reglas.

Reglas de reescritura - Parte 1: Introducción

Vamos a ver a lo largo del tutorial como podemos realizar numerosas acciones y tareas gracias a las reglas de reescritura. Sin embargo tres de los mayores propósitos son:
  • Ocultar la funcionalidad de PHP y por lo tanto exponer menos las partes internas del sitio. 
  • Restringir el acceso.
  • Crear URLs limpias y legibles que son más fáciles de recordar. Y ayudar de esta manera a los motores de búsqueda. 
Considerando estos dos ejemplos

http://ejemplo.com/index.php?product_id=7
http://ejemplo.com/7/

Podemos ver como la segunda URL es más fácil de entender, ya que es más amigable tanto para el usuario como para los motores de búsqueda. Además en esta segunda URL se ha escondido que el sitio web utiliza PHP. Lo que no nos va a proporcionar ningún tipo de seguridad pero deja menos pistas.