Archivo de la etiqueta: PHP Tips

Acceder a datos JSON con jQuery – jQuery Tips

Una de las maneras para rellenar un formulario dinámicamente en base a una petición AJAX es por medio de JSON.

Supongamos el siguiente escenario. Tenemos un formulario que se tiene que autorellenar en base a una petición AJAX, por ejemplo, le pasamos el código de una persona y nos tiene que mostrar los datos.


// Fichero datos.php

$datos = array(

1 => array('nombre' => 'Yo', 'apellidos' => 'mismo'),

2 => array('nombre' => 'Tu', 'apellidos' => 'aquel'),

);

$codigo = filter_input(INPUT_POST, 'codigo', FILTER_SANITIZE_NUMBER_INT);

foreach ($datos as &$dato) {
 $dato = utf8_encode($dato);
 }
 echo json_encode($datos[$codigo]);


<!-- Fichero formulario.html -->

<form id='formulario'>
 <input type='text' id='codigo'>
 <button type='button' id='buscar'>Buscar Registro</button>
 <input type='text' id='nombre'>
 <input type='text' id='apellidos'>
</form>
<script>
$('#buscar').click(function(){
 $.post('datos.php', {codigo:$('#codigo').val()}, function(data){
 data = JSON.parse(data);
 $('#nombre').val(data.nombre);
 $('#apellidos').val(data.apellidos);
 });
 return false;
});
</script>

En este ejemplo los datos están almacenados dentro de un array, lo normal es que fueran resultado de una consulta SQL.

En el formulario pongo, por ejemplo, el 1 para obtener los datos, estos se mandan vía post al fichero de datos, antes de devolverlos los codifico con utf8_encode para que no de ningún error, luego les damos formato con json_encode, y una vez que lo recibimos los tenemos que tratar con JSON.parse para poder acceder a ellos como si fueran un objeto.

Problemas con cliente SOAP – PHP Tips

En uno de los proyectos en los cuales estoy trabajando ahora mismo, necesitaba la implementación de un entorno cliente – servidor SOAP. El servidor, vamos a decir que debido a motivos de ecosistema, lo implemente con Delphi, y el cliente con PHP.

Bien, una vez el entorno implementado, y después de hacer las pruebas pertinentes entre el cliente y servidor, los que yo denomino test de «hola mundo», me puse a implementar los servicios que necesitaba, y aquí comenzaron los problemas.

Aparentemente estaba todo bien, pero el servidor me devolvia este error:

Uncaught SoapFault exception: [Client] Function function_nameis not a valid method for this service

Pues bien todo el problema venia que el cliente tenia almacenado en cache los servicios anteriores, y no los nuevos. Podemos solucionar este error de varias maneras. Una seria deshabilitando la cache wsdl en tiempo de ejecución, asi prevenimos que si implementamos servicios nuevos, el cliente no lo reconozca. Que decir que esta opción esta bien en desarrollo, ya que una vez que este todo establecido definitivamente lo podemos deshabilitar.

ini_set("soap.wsdl_cache_enabled", "0");

Otra manera de  hacerlo seria, si usamos la clase SoapClient para crear el cliente SOAP, es pasándolo como parámetro en la creación del objeto

$clienteSoap = new SoapClient('http://misitio.com?wsdl', array('cache_wsdl' => WSDL_CACHE_NONE));

Configuración SOAP en tiempo de ejecución
Clase SoapClient

Averiguar el genero de un nombre con PHP – PHP Tips

El otro día tuve un pequeño problema, tenia que diseñar un formulario, en el cual se recogen los datos desde una base de datos de nombres para luego procesarlos en otro sitio, bien pues cuando obtenía los datos quería que me apareciera el tratamiento (Don o Doña) de la persona que estaba seleccionando y esto quería hacerlo automáticamente.  Una de las primeras cosas que hago cuando me suceden estos dilemas es ponerme a programarlo por mi cuenta, gran fallo, ya que una de las cosas que tenemos que pensar es que esto es una situación habitual y seguramente hay alguna función que nos permita hacerlo de una manera sencilla.

Antes de ponerme a pensar que existiera esa función intente crear una función para solucionar este problema de una manera sencilla. En principio todos los nombres que tengo en la base de datos están en castellano,  entonces pense, a ver la inmensa mayoría de los nombres de chica finalizan con ‘a’, pues bien voy a crear una función para obtener el ultimo carácter del nombre y si es ‘a’ es una chica, si no es un chico. Esta no es una buena solución, aunque tengo que decir que en la mayoría de los casos acierta, pero tenemos excepciones, por ejemplo, en el caso de las chicas (Rocio, Isabel,..) y en el caso de los chicos (Borja). Podríamos optar por agregar una array de excepciones, y cada vez que nos ocurriera una ‘mala coincidencia’ agregar esa excepción. Esta función quedaria de esta manera.

function detectaGenero($nombre) {
    $genero = "Chico";
    $excepcionesChico = array('Borja',);
    $excepcionesChica = array('Rocio','Isabel');
    $letra = substr($nombre, -1);
    if (($letra == 'a' || in_array($nombre, $excepcionesChica)) && !in_array($nombre, $excepcionesChico)) {
        $genero = "Chica";
    }
    return $genero;
}

Si esta función la ponemos a comparar nombres en otro idioma no nos serviria de nada, y luego seria tambien un inconveniente tener que estar cada vez que encontráramos una excepción agregarla al array.

La buena noticia es que existe una extensión PECL Gender, que una vez instalada en nuestro servidor nos permite llamar a la clase Gender y poder conocer el genero de ese nombre. El inconveniente, que es una extensión PECL y si nuestra aplicación web, esta en un hosting en el cual no podemos agregar este tipo de extensiones no nos sirve de nada, a no ser que el proveedor quiera instalarla.

Esta extensión es un port del programa gender.c escrito originalmente por Joerg Michael. Su base de datos de nombres contiene mas de 40000 nombres de 54 países.
La función anterior usando Gender quedaria así:

function detectaGenero($nombre) {
    $genero = "Chico";
    $gender = new Gender;
    $result = $gender->get($nombre);
    if ($result === Gender::IS_FEMALE OR $result === Gender::IS_MOSTLY_FEMALE) {
        $genero = "Chica";
    }
    return $genero;
}

Como podemos ver es mas sencilla que la anterior, mas fiable, y no tenemos que estar agregando excepciones, y pensar en los nombres en otros idiomas.
PHP: Gender – Manual

Capitalizando utf-8 – PHP Tips

Una de las cosas con las que nos tenemos que pelear muchas veces es el tema de la codificación de caracteres, generalmente esto lo solucionamos con el utf8_encode o el utf8_decode, pero en algún caso puede suceder que nos sirva pero que nos salgan resultados no deseados. Pongamos el caso siguiente, tenemos en la base de datos el nombre y apellidos de un cliente y lo tenemos en mayúsculas, y queremos recuperar ese dato para mostrarlo y lo queremos mostrar capitalizado, para realizar esto haríamos lo siguiente:


$string = "RUBÉN YAGÜE ESPAÑA";

$string = ucwords(strtolower(utf8_encode($string)));

echo $string; // Mostraria RubÈn YagÜe EspaÑa

Seguramente si nos vemos en este escenario lo mas rápido seria optar por mostrarlo todo en mayúsculas y ya, pero existe una manera de hacerlo bien.

Buscando por las funciones de PHP he encontrado las funciones mb_* las cuales nos van a ayudar a conseguir nuestro objetivo.

A continuación pongo la función que me he creado para realizar esto

function capitalize($string)
{
    if (mb_detect_encoding($string) === 'UTF-8') {
        $string = mb_convert_case(utf8_encode($string), MB_CASE_TITLE, 'UTF-8');
    } else {
        $string = mb_convert_case($string, MB_CASE_TITLE, 'UTF-8');
    }
    return $string;
}

Esta función me detecta si la codificación de la cadena es UTF-8, si lo es utilizando la función
mb_conver_case y codificando la cadena con utf8_encode nos creara la cadena final capitalizada
correctamente.

Diferencias entre las comillas dobles y las simples en PHP – PHP Tips

Los que nos dedicamos a programar tenemos mas o menos claro cuando usar las comillas dobles o las simples a la hora de establecer el valor de las variables,  e intentamos mantener una uniformidad en nuestra programación, yo por ejemplo use comillas simples o dobles siempre pongo las variables concatenadas y nunca las pongo dentro de las comillas. Bien, para los que se pregunten cual es la diferencia fundamental entre las dobles y las simples la respuesta es que cuando se usan comillas simples las variables no se sustituye el valor de la variable por su valor, en cambio con las comillas dobles si se sustituye, es decir:


$saludo = 'Hola Mundo';

echo 'Y digo al mundo $saludo'; //Muestra: Y digo al mundo $saludo

echo &quot;Y digo al mundo $saludo&quot;; // Muestra: Y digo al mundo Hola Mundo

Tambien tenemos que tener cuidado si en nuestra cadena ponemos caracteres especiales como el fin de párrafo o salto de linea, ya que con las comillas simples se representaran literalmente y con las comillas dobles se generaran.


$linea = 'Hola soy la primera linea\r\nHola soy la segunda'; //No realizara el saldo de linea

$linea = &quot;Hola soy la primera linea\r\nHola soy la segunda&quot;; //Realizara el salto de linea

LOAD DATA INFILE desde un terminal remoto – MySQL Tips

Siguiendo con las entradas relacionadas con mis notas mentales, hoy me he vuelto a cruzar con una situación que se me plantea de vez en cuando y siempre tengo que tirar de la documentación.

El escenario es el siguiente, tengo un programa en php que se ejecuta en terminal que me realiza una consulta e extracción de datos de una base de datos paradox que esta en un servidor, si he dicho paradox, y me genera un fichero csv el cual a continuación por medio de una consulta de load data infile se me vuelca a una base de datos mysql que tengo en otro servidor. Resulta que la consulta load data infile no he conseguido que se me ejecute, en cuando lo solucione publicare la solución así que lo que hago es una vez terminado el proceso de volcado me conecto al servidor vía terminal y ejecuto la consulta load data infile desde la terminal. Si esto lo hago de esta manera y no ejecutando la consulta directamente es debido a lo lento que funciona el paradox. El proceso de volcado de los datos de paradox al fichero oscila entre los 8-10 minutos, realizando la operación directa el proceso duraba entre 45 minutos a 1 hora.

Primero me conecto al servidor remoto mysql con un usuario y contraseña que tenga permisos para acceso remoto, añadiendo al final la opción –local-infile=1 para poder subir ficheros


#mysql -u [usuario] -p -h [host remoto] --local-infile=1

A continuación ejecuto la consulta para que me vuelque el fichero


LOAD DATA LOCAL INFILE [fichero] REPLACE INTO TABLE [db.table]     CHARACTER SET [tipo caracteres]    FIELDS TERMINATED BY  [terminación campos]     ([columna1], [columna2], ..);

En [fichero] ponemos entre comillas la ruta completa del fichero en nuestro ordenador,  en [db.table] el nombre de la base de datos y la tabla en la que vamos a volcar los datos, en tipo carácter ponemos entre comillas el tipo de codificación p.e cp1250, utf8, en [terminación campos] como están delimitados los campos, p.e ; y finalmente entre paréntesis las columnas del la tabla.

Una vez ejecutado puedo decir que en mi caso se volcaron 42673 registros en 0.53 segundos, esta misma operación la he realizado generando un fichero sql para la inserción de los datos y el tiempo era infinitamente superior a este.

 

Servidor PHP integrado en PHP 5.4

Una de las nuevas utilidades con las que cuenta el PHP 5.4 es la del servidor integrado, para lanzarlo es tan sencillo como abrir la terminal, situarnos en el directorio raíz de nuestra aplicación y ejecutar lo siguiente:

php -S localhost:8000

En este ejemplo he usado el puerto 8000 pero si este lo tenemos ocupado podemos probar con otro que tengamos libre. Este servidor esta pensado solo para desarrollo y no para producción.
+ Info

Nombres cortos de variables en bucles – PHP Tips

La inmensa mayoría de programadores, entre los cuales me incluyo, a la hora de escribir un bucle for lo hacemos usando la variable i, y nos quedaría de la siguiente manera:

for ($i = 0; $i <= 10; $i++) {
 // TODO Procesos a ejecutar
}

Este código esta claro y es muy fácil de interpretar.

Imaginemos ahora que tenemos un array llamado $ligas en el cual se almacenan las ligas de fútbol, cada clave de este array apunta a otra array con los equipos de esa liga, y cada clave numérica de este array apunta a un array donde aparecen los nombres de los jugadores.

for ($i = 0; $i < count($ligas); $i++) {
    for ($j = 0; $j <= count($ligas[$i]); $j++) {
        for ($k = 0; $k <= count($ligas[$i][$j]); $k++) {
            echo $ligas[$i][$j][$k];
        }
    }
}

Si realizamos el diseño de nuestros bucles de esta manera seguramente, si queremos compartir este código con alguien le resultara un poco difícil de entender, y cuando digo alguien también nos incluyo a nosotros mismos dentro de un tiempo cuando revisemos el código. Quizá si realizáramos este código de esta manera seria un poco mas claro

for ($liga = 0; $liga < count($ligas); $liga++) {
    for ($equipo = 0; $equipo < count($ligas[$liga]); $equipo++) {
        for ($jugador = 0; $jugador < count($ligas[$liga][$equipo]); $jugador++) {
            echo $ligas[$liga][$equipo][$jugador];
        }
    }
}

Ahora queda mas claro que es lo que se muestra en este bucle.

Conocer el sistema operativo donde se ejecuta nuestro PHP – PHP Tips

A veces podemos vernos en la necesidad de conocer que sistema operativo, o versión de este es en el que se esta ejecutando nuestro codigo PHP, por ejemplo si necesitamos establecer la configuración de las locales.

Tenemos dos opciones para conocerlo, la primera es por medio de la constante PHP_OS, y otra es con la función php_uname(). La primera solo nos va a devolver el sistema operativo, p.e Linux, FreeBSD, WINNT, … en cambio con la funcion nos devolvera una información mas completa. Por ejemplo

 

echo php_uname();
echo PHP_OS;

/* Algunas posibles:
Linux localhost 3.2.0-27-generic #43-Ubuntu SMP Fri Jul 6 14:46:35 UTC 2012 i686
Linux

FreeBSD localhost 3.2-RELEASE #15: Mon Dec 17 08:46:02 GMT 2001
FreeBSD

Windows NT XN1 5.1 build 2600
WINNT
*/

 

La funcion php_uname(), puede aceptar varios parametros, mode para poder especificar que tipo de salida queremos. Estos parametros son:

  • ‘a’: Es la opción por defecto. Contiene todos los modos de la secuencia «s n r v m».
  • ‘s’: Nombre del sistema operativo. eg. FreeBSD.
  • ‘n’: Nombre del host. eg. localhost.example.com.
  • ‘r’: Nombre de la distribucion. eg. 5.1.2-RELEASE.
  • ‘v’: Informacion de la version. Varia mucho dependiendo de los sistemas operativos.
  • ‘m’: Tipo de maquina. eg. i386.

 

echo php_uname();
// Linux pajaroto.ensenalia.com 3.2.0-27-generic #43-Ubuntu SMP Fri Jul 6 14:46:35 UTC 2012 i686
echo php_uname('s');
// Linux
echo php_uname('n');
// Localhost
echo php_uname('r');
//3.2.0-27-generic
echo php_uname('v');
// #43-Ubuntu SMP Fri Jul 6 14:46:35 UTC 2012
echo php_uname('m');
// i686

+ Info http://es.php.net/manual/en/function.php-uname.php

Fechas PHP a MySQL y vuelta – MySQL Tips

PHP Programming languageUna de las cosas con las que toca lidiar practicamente siempre que trabajamos con fechas contra una base de datos MySQL es que la base va MySQLa almacenar las fechas de la manera ISO «año-mes-dia» y nosotros a la hora de trabajar trabajos con el formato Europeo, ya sea «dia-mes-año» o «dia/mes/año».

Durante muchos años trabajaba con la tecnica de la función bidireccional, es decir, me creaba una función la cual cuando le llegaba la fecha la convertia en un sentido u otro.

function cambiaFormatoFecha($fechaOriginal)
{
 //Dividimos la fecha de la hora si existe
 $partesStamp = explode(" ", $fechaOriginal);
 // La primera parte es la fecha, la segunda la hora
 $partesFecha = explode ( "-", $partesStamp[0] );
 // La fecha final
 return $partesFecha[2] ."-".$partesFecha[1]."-".$partesFecha[0];
}

MySQL guarda las fechas separadas por guiones, así que si nosotros definimos el formato de fecha separado con guiones, pues eso que tenemos ganado y esta función nos convierte tanto nuestras fechas cuando las introducimos como las fechas que devuelve el MySQL.

Trabajar con esto puede parecer que es una gran ventaja, pero la verdad que a nivel de rendimiento no lo es ya que supone ejecutar la función cada vez que aparezca un registro de fecha.

Una solución bastante mas eficiente es la de procesar las fechas en la consulta. Para eso utilizaremos las funciones incorporadas de MySQL DATE_FORMAT y STR_TO_DATE.

Si queremos unos registros de una determinada fecha podemos hacer:


SELECT * FROM `tabla` WHERE fecha LIKE STR_TO_DATE('mifecha','%d-%m-%Y);

En esta consulta mifecha esta en el formato dia-mes-año

Si queremos ver las fechas en el formato dia-mes-año


SELECT DATE_FORMAT(fecha,'%d-%m-%Y) FROM `tabla`;

Para mas información

STR_TO_DATE http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_str-to-date

DATE_FORMAT http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_date-format