Archivo para ‘Programación de páginas Web’ Categoria

Mejorando el COUNT(*) de MySQL para las paginaciones

25 de Septiembre de 2009

Generalmente cuando paginamos resultados bajo PHP / MySQL, primero generamos la consulta a la BBDD con el Where y unos “LIMIT” para mostrar solo el “rango” de registros que nos interesa para la página solicitada.

Justo después de esta tipica consulta viene el COUNT (*) pero sin apliar LIMITS ni nada  para saber cuantos registros tenemos en total en la BBDD y “pintar” el sistema de paginación, es decir, la navegación de las páginas.

Pues bien, MySQL tiene un par de funciones que básicamente hacen una especie de COUNT(*) pero mucho más veloz y que vale la pena aplicar en esta situación:

  • SQL_CALC_FOUND_ROWS: calcula el número de resultados de una consulta sin LIMIT.
  • FOUND_ROWS: obtiene el resultado del último SQL_CALC_FOUND_ROWS ejecutados.

Por ejemplo, vamos a obtener de la tabla noticias,  los 5 registros de la página 2 con el sistema sin count (*):

$sql = "select SQL_CALC_FOUND_ROW id, titulo, contenido from noticias where publicado = 1 LIMIT 5,5";
 
$sqlCount = "select FOUND_ROWS() as total ";

El sistema no te libra de ejecutar 2 consultas SQL contra la BBDD pero sí que este par de funciones tienen un menor impacto sobre el sistema haciendo mucho más rápida la consulta de obtener el número de registros.

NOTA: En nuestro php.ini el valor mysql.trace_mode debe estar en Off.

jQuery Visualize

10 de Julio de 2009

jQuery Visualize, es un plugin de jQuery que nos permite generar gráficas dinámicas usando <canvas /> para alogar los gráficos.

Lo curioso de este plugin es que carga los datos desde tablas <html>y el resultado no puede ser más accesible, ya que en caso de que el usuario no tenga el Javascript activo, este podrá ver la tabla con los datos, posibilitando así su comprensión.

Y lo “malo”… tu navegador debe ser HTML5 compatible, de lo contrario no podrás ver funcionar este plugin.

Fuente: anieto2k

Baja los scripts al final del fichero

3 de Julio de 2009

Según cuenta anieto2k una de las tecnicas más usadas para reducir el tiempo de carga de una página es la de bajar el Javasciprt al final de fichero HTML, concretamente antes del tag </body>.

¡Podemos reducir un 47% el tiempo de carga de la página!

Antes:

Después:

Fuente: anieto2k

Generar gráficas con Javascript

26 de Junio de 2009

anieto2k ha publicado un buen listado de librerías Javascript para generar nuestras gráficas más elegantes para nuestros proyectos:

  1. Flot [jQuery]
  2. fgCharting [jQuery]
  3. jQuery Sparklines [jQuery]
  4. jqPlot [jQuery]
  5. TufteGraph [jQuery]
  6. jQuery Google Charting [jQuery]
  7. ProtoChart [Prototype]
  8. JSXGraph [Prototype o jQuery]
  9. Protovis [Native JS]
  10. PlotKit [Nativa JS]

Fuente: anieto2k

7 reglas para realizar Javascript de calidad

19 de Junio de 2009
  • No hagas suposiciones: no pienses que el usuario tendrá el javascript activado o que usará un navegador adecuado.
  • Usa IDs y relaciones entre elementos: para no depender de un HTML mal estructurado y que el javascript sea imposible de realizar, utiliza IDs para acceder a los elementos con los que se quiere tratar y busca elementos que faciliten acceder a otros elementos.
  • Utiliza estilos: en vez de modificar los estilos de los elementos HTML mediante Javascript, usa clases CSS que modifiquen los estilos, y mediante Javascript se le puede añadir la clase a un elemento superior.
  • Comprende el navegador y a los usuarios: debes pensar cómo funciona un navegador, no sobre saturar su comportamiento (abuso de drag&drop, eventos, …). Además debes pensar qué espera el usuario que haga el navegador, y respetarlo.
  • Comprende los eventos: los eventos no solo corresponden a un objeto, sino a los elementros hijo que contiene. Así se pueden realizar eventos sobr un único elemento y no tener que modificar los demás.
  • Respeta el código de otros: seguro que a parte de tu código existe algún otro que has añadido, por lo que deberás programar teniendo en cuenta que hay que evitar conflicto entre funciones.
  • Después de ti vendrá otro: es muy frecuente que alguien acabe modificando tu código, ten un poco de consideración por los demás y escribe código legible y comprensible.

Fuente: The seven rules of unobstrusive JavaScript

Usar los nuevos controles de los mapas de Google Maps

29 de Mayo de 2009

Si usas Google Maps como proveedor de los mapas para tus aplicaciones web, seguramente hayas observado que lo que te explican en la documentación de la API y en general, casi todos los sitios dónde te explican como empezar (incluido aquí en A2Blog), los controles de los mapas se inicializan así:

var mapControl = new GMapTypeControl();
 map.addControl(mapControl);
 map.addControl(new GLargeMapControl());

Con está inicialización obtenemos la versión anterior de los controles de mapa, es decir, algo cómo esto:

Si nos fijamos por ejemplo en maps.google.es, la cosa tiene otra pinta mucho mejor:

¿Cómo conseguir esos controles más vistosos y además no tener que preocuparse por las mejoras que nos puedan ofrecer en el tiempo los chicos de google?

Muy fácil, usemos la propiedad getDefaultUI();

var customUI = map.getDefaultUI();
 // Quitar la vista híbrida -> MapType.G_HYBRID_MAP
 customUI.maptypes.hybrid = false;
 map.setUI(customUI);

Y ya tenemos nuestro mapa con los nuevos controles :)

El código completo de la función de inicializar el mapa es el siguiente:

 function initialize() {
      if (GBrowserIsCompatible()) {
        var map = new GMap2(document.getElementById("map"),
        { size: new GSize(640,320) } );

        map.setCenter(new GLatLng(42.366662,-71.106262), 11);

        var customUI = map.getDefaultUI();
        // Remove MapType.G_HYBRID_MAP
        customUI.maptypes.hybrid = false;
        map.setUI(customUI);

      }
    }

Tiny JS

9 de Abril de 2009

TinyJS es un sitio web donde podemos encontrar gran cantidad de scripts y trozos de código en javascript para nuestros proyectos.

Especialmente podemos encontrar scripts para jQuery, YUI y Moo Tools. Una ventaja muy a tener en cuenta, es que todos los códigos se encuentran documentados, con ejemplos y comprimidos.

Obtener la latitud y longitud de una dirección con Google Maps y C#

20 de Marzo de 2009

Cuando trabajamos con Google Maps usamos las latitudes y longitudes para definir los puntos, el centro del mapa, etc… Si no conocemos esos datos, pero sí la dirección de la ubicación, podemos “geolocalizar“, es decir obtener las coordenadas con el objecto “geocoder“.

Para poder obtener las coordenadas directamente vía C# y no geolocalizar con javascript usaremos el objeto de C# WebRequest y WebResponse para obtener directamente desde Google los datos que necesitamos y poder tratarlos en nuestra aplicación.

La idea es hacer las petiticiones a la URL de geolocalización de Google que es la siguiente: http://maps.google.com/maps/geo?q=Direccion

A esta url, se le deben especificar los siguientes parámetros:

q -> es la dirección que queremos geolocalizar
output -> es como queremos obtener la información del servicio. Puede ser xml, kml, csv o json
key -> nuestra key de la api de google.

En resumidas cuentas, nos queda una URL así, vamos a usar el formato CSV, así que lo especifico ya en el ejemplo:

http://maps.google.com/maps/geo?q=Mataro&output=csv&key=MI-KEY-API

La url anterior debería mostrar en nuestros navegadores algo así:

200,4,41.5375002,2.4452776

Esos son los datos que necesitamos, una tira de valores separados por comas para poder trabajar con ellos.

El primer valor es el código de respuesta de la petición. Existen diferentes códigos en función de si todo ha ido bien, si se ha producido un error o si simplemente, la dirección no se puede encontrar. Aquí hay una tabla que relaciona estos códigos:

  • 200: No se han producido errores, la dirección se analizó correctamente y se devolvió su código geográfico.
  • 400: No se ha podido analizar correctamente la solicitud de ruta
  • 500: No se ha podido procesar correctamente la solicitud de ruta o de códigos geográficos, sin saberse el motivo exacto del fallo.
  • 601: Falta el parámetro HTTP q o no tiene valor alguno. En las solicitudes de códigos geográficos, esto significa que se ha especificado una dirección vacía. En las solicitudes de ruta, esto significa que no se ha especificado ninguna consulta.
  • 602: No se ha encontrado una ubicación geográfica que se corresponda con la dirección especificada. Esto puede deberse a que la dirección sea relativamente nueva o a que no sea correcta.
  • 603: El código geográfico de la dirección indicada o de la ruta para la consulta de ruta proporcionada no puede devolverse por motivos jurídicos o contractuales.
  • 604: El objeto GDirections no pudo calcular la ruta entre los puntos mencionados en la consulta. Esto suele deberse a que no hay ninguna ruta disponible entre los dos puntos o a que no tenemos datos para extraer rutas en la región en cuestión.
  • 610: La clave proporcionada no es válida o no coincide con el dominio para el cual se ha indicado
  • 620: La clave proporcionada ha sobrepasado el límite de solicitudes en un período de 24 horas.

El segundo grupo, es el 4 en el ejemplo, nos indica la precisión del resultado, de nuevo, hay una tabla para relacionar todo esto:

  • 0 Ubicación desconocida.
  • 1 Precisión a nivel de país.
  • 2 Precisión a nivel de región (estado, provincia, prefectura, etc.). 3 Precisión a nivel de subregión (condado, municipalidad, etc.).
  • 4 Precisión a nivel de ciudad o pueblo.
  • 5 Precisión a nivel de código postal.
  • 6 Precisión a nivel de calle.
  • 7 Precisión a nivel de intersección.
  • 8 Precisión a nivel de dirección.

Y por último, los 2 restantes valores, lo que realmente queremos saber, la latitud y la longitud.

Ahora solo nos queda hacer que nuestra aplicación recoja esos valores con un par de funciones simples:

string constructuirGeoURL(string direccion){
	string geoURL = "";

	if(direccion != ""){
		direccion = direccion.Trim();
		direccion = direccion.Replace(" ", "+");

		geoURL = @"http://maps.google.com/maps/geo?
                q=###ADDRESS###&output=###OUTPUT###&key=###KEY###";

		//Sustitución de las variables
		geoURL = geoURL.Replace("###ADDRESS###", direccion);
		geoURL = geoURL.Replace("###OUTPUT###","csv");
		geoURL = geoURL.Replace("###KEY###", ApiGoogle);
	}

return geoURL;
}

Con la función construirGeoURL(), vamos ha obtener la URL que después vamos a usar en la función cargarLatitudLatitud() que nos va a dar la latitud, longitud y el código de respuesta de la petición.

 void cargarLatitudLatitud(string geoURL){
   string csvValues = "";
   string Latitud = "";
   string Longitud = "";
   string Respuesta_geo = "";
	try
	{
	 WebRequest objWebRequest = WebRequest.Create(geoURL);
	 WebResponse objWebResponse = objWebRequest.GetResponse();
	 Stream objWebStream = objWebResponse.GetResponseStream();

         using (StreamReader objStreamReader = new StreamReader(objWebStream))
	 {
	  csvValues = objStreamReader.ReadToEnd();
	 }

	if (csvValues != null)
	{
	 string[] geoValues = csvValues.Split(new char[] { ',' });
	 if (geoValues.Length > 0)
	  {
	   Respuesta_geo = geoValues[0].ToString();
	   Latitud = geoValues[2].ToString();
	   Longitud = geoValues[3].ToString();
	  }
	}

        }
	catch (Exception exp){
	 Response.Write(exp.Message);
	}
}

Para poder usar la función cargarLatitudLatitud(), hay que importar los espacios de nombres siguientes:

<%@ import Namespace="System.Net" %>
<%@ import Namespace="System.IO" %>

Como podéis ver, el uso del objecto WebRequest y WebResponse es sencillo y nos permite trabajar con el servicio de Google Maps para geolocalizar directamente desde nuestras aplicaciones C#.

¿Se os ocurre alguna forma de aprovechar otra característica de Google Maps sobre C#?

Carga Google Analytics y Google Maps asincronamente

13 de Marzo de 2009

Seguramente tanto Google Analytics cómo Google Maps sean usadas por muchas de las aplicaciones Web de hoy en día.

Precisamente estas dos aplicaciones pueden provocar, en muchas situaciones, retrasos en los tiempos de carga o lo que es peor, que no se cargue el contenido de forma correcta.

Google Analytics

Analytics es el gestor de estadísticas gratuito de Google, es usado por muchísimos sitios Web y quizás debido a eso, se suele producir un retraso en la carga de la página, para evitar este retraso simplemente hay que dejarle la carga al evento onload del navegador. Con jQuery esto se traduce así:

  $(document).ready(function(){
      $.getScript('http://www.google-analytics.com/ga.js',function(){
         if (typeof(_gat) == 'object'){
            var pageTracker = _gat._getTracker('UA-XXXXXXX-Y');
            pageTracker._initData();
            pageTracker._trackPageview();
         }
      });
   });

Pero si no estamos usando jQuery podemos usar la función como addLoadEvent() que nos permite añadir funcionalidades al evento onload con compatibilidad en todos los navegadores, sería algo así:

addLoadEvent(function(){
 // Insertamos el Código que Google Analytics
 var analyticsCode = 'UA-XXXXXXX-Y';
 var s = document.createElement("script");
 s.type = "text/javascript";
 s.src = "http://www.google-analytics.com/ga.js";
 s.onload = s.onreadystatechange = function() {
	if (typeof _gat  == 'object'){
            var pageTracker = _gat._getTracker(analyticsCode);
            pageTracker._initData();
            pageTracker._trackPageView();
         }
 }
 document.getElementsByTagName("head")[0].appendChild(s);
});

En ambos casos se debe reemplazar (UA-XXXXXXX-Y) por el código que Google Analytics nos asigna.

Google Maps

La mayor y posiblemente mejor aplicación de mapas de Internet y de dónde la gran mayoría de sitios Web obtienen la información sobre mapas, es sin duda la que más problemas produce. Las largas esperas producen, por ejemplo, en Internet Explorer 6 que el tiempo de carga de las imágenes nos desesperen antes de poder visualizarlas….

Para solucionar el problema basándonos en una solución sobre jQuery podemos usar:

function cargarMapa(){
   if (GBrowserIsCompatible()) {
      var map = new GMap2(document.getElementById("MAPA"));
      map.setCenter(new GLatLng(39.578678,2.646021), 16);
   }
};
$(document).ready(function(){
   var api='AQUI TU GOOGLE MAPS API KEY';
   $.getScript('http://maps.google.com/maps?file=api
&amp;v=2.x&amp;key='+api+'&amp;async=2&amp;callback=cargarMapa');
});

Si se prefiere, también podemos usar el ya conocido addLoadEvent()

addLoadEvent(function(){
	var api='AQUI TU GOOGLE MAPS API KEY';
	function cargarMapa(){
	   if (GBrowserIsCompatible()) {
	      var map = new GMap2(document.getElementById("MAPA"));
	      map.setCenter(new GLatLng(39.578678,2.646021), 16);
	   }
	};
	var s = document.createElement("script");
	s.type = "text/javascript";
	s.src = 'http://maps.google.com/maps?file=api
        &amp;v=2.x&amp;key='+api+'&amp;async=2&amp;callback=cargarMapa';

         document.getElementsByTagName("head")[0].appendChild(s);
})

Fuente: anieto2k

¿Habéis tenido problemas antes con los tiempos de carga usando estos servicios de Google en vuestras aplicaciones Web?

Uso de cursores en Transact SQL

6 de Febrero de 2009

En T-SQL (Transact SQL) podemos definir una variable que nos permite recorrer un conjunto de resultados obtenidos a través de una SELECT fila a fila, ha esta variable se le denomina Cursor

Cuando trabajemos con cursores debemos seguir los siguientes pasos:

  • Declarar el cursor, utilizando DECLARE
  • Abrir el cursor, utilizando OPEN
  • Leer los datos del cursor, utilizando FETCHINTO
  • Cerrar el cursor, utilizando CLOSE
  • Liberar el cursor, utilizando DEALLOCATE

Ejemplo de cursor T-SQL– Declaración del cursor

DECLARE <nombre_cursor> CURSOR
FOR
<sentencia_sql>
-- apertura del cursor
OPEN <nombre_cursor>
-- Lectura de la primera fila del cursor
FETCH <nombre_cursor> INTO <lista_variables>
WHILE (@@FETCH_STATUS = 0)
BEGIN
    -- Lectura de la siguiente fila de un cursor
    FETCH <nombre_cursor> INTO <lista_variables>
    ...
END -- Fin del bucle WHILE
-- Cierra el cursor
CLOSE <nombre_cursor>
-- Libera los recursos del cursor
DEALLOCATE <nombre_cursor>

Usos de un cursor

Utilizar un cursor es muy práctico ya que nos permite por ejemplo, trabajar con los datos de una fila, operar sobre esos datos y por ejemplo, actualizar el registro, con el resultado de las operaciones. Para dar un mejor ejemplo, para realizar una actualización de unos registros que deben tomar el valor calculado en función de otros datos del mismo registro.

DECLARE @fechaInicio varchar(30),  /*Declaramos variables*/
	@fechaFin varchar(30),
	@idFactura int,
	@fechaCalculos datetime
SET @fechaInicio = '1/1/2005'; /*Seteamos variables*/
SET @fechaFin = '1/1/2006';
DECLARE miCursor CURSOR
FOR
/*Especificamos la select*/
select id,fecha as fechaCalculos from FACTURAS_CLIENTES
where fecha >= CONVERT(DATETIME,@fechaInicio,103)
AND fecha <= CONVERT(DATETIME,@fechaFin,103)
OPEN miCursor  /*Abrimos el cursor*/
	FETCH miCursor INTO @idFactura, @fechaCalculos 

/*Asignamos cada columna de la SELECT
a una variable definida arriba*/
WHILE(@@FETCH_STATUS = 0)
BEGIN
  SET @fechaCalculos = @fechaCalculos + 10 -- OPERACION
 -- Mostramos el resultado
 PRINT 'FECHA CALCULOS:'+ CAST(@fechaCalculos  as varchar)
/*Importante volver a hacer el FETCH*/
FETCH miCursor INTO @idFactura, @fechaCalculos  

END
CLOSE miCursor
DEALLOCATE miCursor

Conclusión

Aunque en un principio parezca algo difícil de entender es sencillo si se sigue correctamente la estructura del cursor. Así además evitamos fallos en la sintaxis.

Usar un cursor nos puede simplificar mucho la tarea de programar un script en otro lenguaje de programación para acabar haciendo lo mismo que con un cursor programador directamente sobre T-SQL, que además se ejecutará más rápido.