<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sortea2 &#187; Tutoriales</title>
	<atom:link href="http://www.sortea2.com/blog/category/tutoriales/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sortea2.com/blog</link>
	<description>El blog de la herramienta de sortear</description>
	<lastBuildDate>Sat, 17 Jul 2010 17:48:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Montar SVN en tu proyecto web</title>
		<link>http://www.sortea2.com/blog/2010/07/montar-svn-en-tu-proyecto-web/</link>
		<comments>http://www.sortea2.com/blog/2010/07/montar-svn-en-tu-proyecto-web/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 13:21:24 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Tutoriales]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=639</guid>
		<description><![CDATA[Subversion (SVN) es, junto a GIT el líder en control de versiones de software libre. Subversion es una mejora del antiguo sistema llamado CVS que tenía sus limitaciones; aunque aún se sigue utilizando en multitud de proyectos creo que es mucha mejor opción Subversion.

En esta entrada no voy a hablaros de montar un servidor SVN, [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://subversion.tigris.org/'>Subversion (SVN)</a> es, junto a <a href='http://git-scm.com/'>GIT</a> el líder en <strong>control de versiones de software libre</strong>. Subversion es una mejora del antiguo sistema llamado CVS que tenía sus limitaciones; aunque aún se sigue utilizando en multitud de proyectos creo que es mucha mejor opción Subversion.</p>
<p><img alt="Subversion logo" src="http://subversion.tigris.org/images/subversion_logo_hor-468x64.png" title="Subversion" class="alignnone" width="468" height="64" /></p>
<p>En esta entrada no voy a hablaros de montar un servidor SVN, principalmente porque es una tarea compleja que está destinada más bien a administradores de sistemas. Os voy a hablar de <strong>como configurar vuestro proyecto </strong>para beneficiarse del funcionamiento de un servidor existente. Si lo que necesitas es crear tú mismo un servidor para estos fines, te recomendaría mejor <a href="http://www.amazon.co.uk/Version-Control-Subversion-Ben-Collins-Sussman/dp/0596004486">el libro de O&#8217;Reilly de SVN</a>.</p>
<p>Para proyectos en los que trabaje más de una persona creo que es una herramienta que una vez se conoce es poco menos que imprescindible. Incluso si trabajamos solos puede servirnos de gran ayuda para no perder ninguno de los cambios que hagamos y poder tener un histórico permanente del proceso de desarrollo.</p>
<p>Antes de adentrarme a explicar la configuración, diré básicamente en qué puede ayudarnos este sistema:</p>
<ul>
<li>Cada cambio que se envíe al servidor será guardado sin sobreescritura. Si nos <em>cargamos</em> sin querer un archivo podremos echar mano del SVN para recuperarlo.</li>
<li>Posibilidad de mezclar dos archivos para ver las diferencias respecto a versiones. Podemos ver, por ejemplo, los cambios que hizo algún compañero en cada línea para comprender como han cambiado las cosas.</li>
<li>Se añade un comentario a cada subida de archivos al servidor que hagamos. Esto ayuda a saber para qué se tocó ese fichero.</li>
<li>Todos los cambios de los demás se podrán descargar de una vez, solamente aquellos archivos que tengan cambios. A veces, sobre todo en proyectos de programación web, se tocan archivos diversos de carpetas diferentes y en vez de tener que explorar y mirar las fechas de modificación, con SVN hacer un par de clics hará que ya lo tengamos todo más reciente.</li>
<li>Control del trabajo de cada uno. Para empresas puede ser muy útil para saber quienes hacen tal cosa. Conocer los porcentajes de código que escribe cada empleado, etc.</li>
<li>En caso de tratarse de un proyecto de software libre tener un control de versiones <strong>es imprescindible</strong>, puesto que necesitamos un lugar en el que la gente que quiera aportar cosas al proyecto pueda conectarse. De cualquier otra manera sería un caos.</li>
</ul>
<p>Hasta aquí la enumeración de algunas de las ventajas, estoy seguro que me he saltado decenas de ellas.</p>
<p><strong>Conseguir servidor:</strong></p>
<p>Bueno, pues lo primero que necesitamos para empezar es un hosting de Subversion. Hostings hay muchos, aunque la mayoría son de pago y hay que saber encontrar el óptimo. Si tu proyecto es <strong>de software libre</strong> no debes preocuparte lo más mínimo de tener que pagar ni nada, puesto que para apoyar el Software Libre hay hostings gratuitos con capacidades ilimitadas para sus usuarios.</p>
<p>Una comparativa genial de los distintos hostings de Subversion que hay se puede encontrar en <a href="http://www.svnhostingcomparison.com/">http://www.svnhostingcomparison.com/</a></p>
<p>Para software libre está claro que las dos opciones idóneas deben ser <a href='http://code.google.com/hosting/'>Google Code</a> y <a href='http://sourceforge.net/'>SourceForge.net</a>. Hay más que ofrecen capacidades ilimitadas, pero creo que esos están por delante.</p>
<p>Si nuestro proyecto es de <strong>software propietario</strong> entonces tendremos que ajustarnos un poco más, tendremos que escoger entre <strong>pagar para tener algo holgado</strong> o encontrar un hosting que permita privacidad en los proyectos y una cantidad de almacenamiento y usuarios aceptable.</p>
<p>Sin duda alguna, la mejor opción gratuita para software propietario es <a href='http://www.assembla.com/'><strong>Assembla</strong></a>. Brinda de manera gratuita 2GB de almacenamiento, un <strong>número ilimitado de programadores</strong> e incluso <a href="http://es.wikipedia.org/wiki/Transport_Layer_Security">SSL</a>; sin contar que la velocidad de subida y bajada es super apropiada.</p>
<p>Hay más opciones, aunque la siguiente mejor ofrece 1/4 del almacenamiento que da Assembla, por lo que no merecen la pena. Si queremos pagar ya solo depende de lo que necesitemos y lo que podamos pagar, hay un punto en el que compensa tener un servidor dedicado tanto propio como alquilado para que se encargue únicamente del control de versiones.</p>
<p><strong>Montar servidor:</strong></p>
<p>Para <strong>montar el servidor</strong> habrá que seguir los pasos por los que nos guíe el sitio web del servicio web escogido hasta que finalmente obtendremos una dirección URL tal que así:</p>
<pre>https://subversion.assembla.com/svn/sortea2</pre>
<p>Hay que tenerla muy en cuenta puesto que a esta URL es a la que nos conectaremos. El <strong>usuario y la contraseña</strong> para conectarse será exactamente el mismo que el que tuvimos que usar para loguearnos en la página web.</p>
<p><strong>Programa cliente:</strong></p>
<p>A continuación tendremos que usar <strong>nuestro programa de lado del cliente para conectarnos</strong>; esto es, un programa en nuestro ordenador al que le daremos URL, password y usuario y estaremos conectados.</p>
<p>Para Windows el que se utiliza casi siempre es el <a href='http://tortoisesvn.net/'><strong>Tortoise SVN</strong></a>, que es un cliente de escritorio de software libre también con una interfaz inmejorable. Una vez lo tengamos instalado este programa lo que hace es añadir unas opciones a los menús contextuales del explorador de Windows relativas a repositorios SVN.</p>
<p><strong>Una nota importante</strong> a tener en cuenta para pasos posteriores es que si utilizamos Dreamweaver nos interesará <strong>descargar la versión de 32 bits de Tortoise</strong> si luego queremos conectar ambos sistemas. Se puede tener instalada la versión de 32 y de 64 bits al mismo tiempo de cualquier manera, pero conviene tenerlo en cuenta.</p>
<p><strong>Conectarse al repositorio</strong>:</p>
<p>La primera vez que queramos establecer conexión tendremos que dar click derecho sobre la carpeta y seleccionar <strong>SVN Checkout&#8230;</strong>, en el cuadro que nos saldrá pegaremos la URL del repositorio que nos proporcionó el sistema de hosting y a continuación se nos pedirá un par de usuario/contraseña. Si le damos a &#8220;recordar&#8221; no volverá a preguntar ni pedir autorización.</p>
<p><img src="http://www.sortea2.com/blog/wp-content/images/subversion_tortoise_checkout.jpg" alt="Ejemplo de Checkout con Tortoise" title="subversion_tortoise_checkout" width="468" height="363" class="alignnone size-full wp-image-649" /></p>
<p>Una vez aquí, si todo ha ido correctamente lo que tendremos que hacer es <strong>subir los archivos al repositorio</strong>. Para ello haremos click derecho sobre la carpeta y le daremos a &#8220;SVN Commit&#8221;. De ahí seleccionaremos archivos que no estén versionados (&#8220;show unversioned files&#8221;), seleccionaremos los que queramos y se subirán uno a uno al hosting de SVN.</p>
<p>Si por el contrario nuestro hosting ya estaba montado anteriormente y lo que queremos es descargar las cosas para tener las copias en local, en vez de &#8220;Commit&#8221; seleccionaremos &#8220;SVN Update&#8221; y nos descargaremos todo lo que no tengamos descargado.</p>
<p><strong>Integrar con Dreamweaver:</strong></p>
<p>Si utilizas Adobe Dreamweaver como entorno de desarrollo quizás lo que más te interese es tener las posibilidades de envío y recepción de archivos en la misma ventana del programa en vez de estar intercambiando con el explorador de windows para hacer las operaciones.</p>
<p>Dreamweaver desde la versión CS4 <strong>incluía un cliente de SVN integrado</strong>, el problema viene de que si tenemos un repositorio creado con Tortoise y luego los usamos con el cliente ese de DW no nos servirá, porque tiene una incompatibilidad documentada que Adobe contempla en su sitio web ofreciendonos un parche. Dicho parche está escrito en Python, por lo que si no tenemos instalado Python (90% de los mortales) no funcionará, además hay que tener en cuenta que la versión de Python <strong>deberá ser la de 32 bits</strong>, porque si no tampoco se iba a poder instalar el parche, debido a que DW dirá que no encuentra una instalación de Python válida.</p>
<p>En definitiva, es mejor olvidarse de todos estos escollos y simplemente usar una extensión para Dreamweaver llamada <a href='http://sourceforge.net/projects/subweaver/'><strong>SubWeaver</strong></a> que actúa como <strong>intermediario entre Dreameaver y Tortoise</strong>. Ya es cuestión de usar los menús contextuales que nos brinda la extensión y estaremos 100% integrados con Tortoise desde Dreamweaver.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2010/07/montar-svn-en-tu-proyecto-web/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 consejos para optimizar MySQL</title>
		<link>http://www.sortea2.com/blog/2010/06/10-consejos-optimizar-mysql/</link>
		<comments>http://www.sortea2.com/blog/2010/06/10-consejos-optimizar-mysql/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 18:04:16 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[consejos]]></category>
		<category><![CDATA[guía]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[rendimiento]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=619</guid>
		<description><![CDATA[En un proyecto web medianamente ambicioso llega siempre el momento en que la parte &#8220;sagrada&#8221; de la aplicación es la Base de Datos. El problema reside cuando las tablas de nuestra Base de Datos empiezan a tener más de 10.000 registros. A partir de ese momento debemos pensar de diferente manera: los accesos deben optimizarse, [...]]]></description>
			<content:encoded><![CDATA[<p>En un proyecto web medianamente ambicioso llega siempre el momento en que la parte &#8220;sagrada&#8221; de la aplicación es <strong>la Base de Datos</strong>. El problema reside cuando las tablas de nuestra Base de Datos empiezan a tener más de 10.000 registros. A partir de ese momento debemos pensar de diferente manera: los accesos deben optimizarse, el sistema de búsqueda ya es demasiado lento y a veces llega incluso al límite de tiempo de ejecución, ya no se puede hacer un ALTER TABLE sin tener que tener la tabla bloqueada unos segundos, etc. Cuando nos empezamos a encontrar con estos problemas es cuando no hemos hecho una predicción suficientemente buena y debemos actuar rápidamente para remediarlo.</p>
<p>Optimizar MySQL es una tarea que debemos tener en mente desde el minuto cero al empezar a programar. A continuación os mostraré 10 consejos que pueden acelerar los accesos a vuestras tablas:</p>
<ol>
<li>
<h3>Usa índices:</h3>
<p>Seguramente lo hayas oído cientos de veces, pero al utilizar inteligentemente índices los accesos se hacen de una manera directa. Los campos que solamos incluir dentro del &#8220;<code>WHERE</code>&#8221; de las consultas debería tratarse de estar indexadas.</p>
<p>Los accesos vía <code>PRIMARY KEY</code> son, con diferencia los más veloces. Si sabemos que un determinado registro no va a poderse repetir, debemos incluirle un índice <code>UNIQUE</code> y si vamos a realizar búsquedas sobre un campo de fecha por ejemplo, le podemos añadir un <code>INDEX</code> simple.</p>
<p>Hay que tener en cuenta que los índices son acumulativos y se tienen en cuenta de izquierda a derecha en la definición de la estructura de la tabla. Esto quiere decir que las búsquedas estarán optimizadas en ese orden. El primer campo indexado será el primer criterio en velocidad.</p>
</li>
<li>
<h3>Utilización de campos binarios</h3>
<p>Los tipos de dato binario son <code>BINARY, VARBINARY y BLOB</code> que van en consonancia con <code>CHAR, VARCHAR y TEXT</code>. Si el texto que vas a almacenar no va a tener una codificación como UTF-8 es mucho más conveniente utilizar campos binarios, puesto que ocupan mucho menos espacio y las comparaciones se hacen <strong>como datos numéricos</strong> internamente.</p>
<p>Por ejemplo, campos que guarden cadenas codificadas como MD5, campos de <em>permalink</em>, nombres de usuario que sepamos que no permiten caracteres extraños, etc. pueden ser puestos como binarios y los accesos y el tamaño de la tabla será muy inferior.</p>
</li>
<li>
<h3>Utiliza UNSIGNED</h3>
<p>Si sabes que en ese campo solamente irán números positivos, utiliza UNSIGNED. Esto aumenta al doble la capacidad máxima de los campos sin alterar el número de bytes necesarios para almacenar cada dato. Por ejemplo, todos los campos que utilicen un <code>AUTO_INCREMENT</code> deben utilizarlo, puesto que de la otra manera tendremos un rango enorme de números que jamás utilizaremos.</p>
</li>
<li>
<h3>Guarda información redundante</h3>
<p>Si tienes una entidad fuerte con entidades débiles, guarda toda la información que puedas en la entidad padre sobre las entidades débiles, esto es: total de datos de cada una, máximos, mínimos y media (si se utilizarían para algo), último dato introducido, etc. Cada vez que se realice una modificación en las entidades débiles habrá que actualizar a la padre, pero si normalmente nuestra aplicación recibe más consultas que actualizaciones esto supondrá una ventaja en el rendimiento.</p>
</li>
<li>
<h3>No uses tipos de datos gigantes</h3>
<p>Me atrevería a decir que el 99% de las personas jamás necesitarán un campo <code>LONGTEXT</code> a no ser que se trate de un gestor de contenidos o algo por el estilo; incluso habrá muy pocas que necesiten un campo <code>BIGINT</code> para uso normal. Un BIGINT ocupa cada número 8 bytes y puede almacenar un número de un 9 seguido de <strong>18 ceros</strong> (aproximadamente). El campo LONGTEXT almacena hasta 4 billones y pico de caracteres, que pueden ser mucho más de 50 páginas de Word por ejemplo.</p>
<p>Los tipos de dato exageradamente grandes ocupan por cada unidad más tamaño y rara vez se utilizan por completo. Es por eso que es más recomendable usar medidas más comedidas de datos.</p>
</li>
<li>
<h3>Trata de usar los simplificadores del lenguaje</h3>
<p>MySQL proporciona algunas maneras que ayudan a hacer las consultas más cortas y más fáciles de entender. Estos métodos no solo nos ayudan a nosotros, sino que internamente son mucho más eficientes. Por ejemplo, usar la expresion <code>" WHERE sorteo = 1 OR sorteo = 2 OR sorteo = 5"</code> es mucho menos eficiente que la siguiente: <code>" WHERE sorteo IN(1,2,5)"</code>.</p>
<p>Algunas de estas expresiones pueden ser BETWEEN, IN, LEAST, GREATEST o INTERVAL.</p>
</li>
<li>
<h3>Intenta unificar consultas</h3>
<p>Intenta siempre hacer una consulta cuando normalmente lo harías con varias. INSERT puede insertar varios registros al mismo tiempo si se separan los &#8220;VALUES&#8221; por paréntesis y comas, por ejemplo: <code>INSERT INTO sorteo VALUES (1,23),(4,5,6),(7,8,9)</code>.</p>
<p>DELETE múltiples se pueden construir en vez de en bucle insertando los valores a borrar dentro de un <code>IN()</code> de MySQL.</p>
</li>
<li>
<h3>Evita operaciones matemáticas</h3>
<p>No es buena idea hacer cálculos complejos en una SELECT. Siempre que sea posible hay que traer los datos al lenguaje que utilices (PHP por ejemplo) y hacer estos cálculos. Por ejemplo, realizar redondeos, medias, divisiones y demás puede resultar problemático y hay que tener siempre en mente que <strong>cuanto menos trabajo haga la Base de Datos, más eficiente será</strong>.</p>
</li>
<li>
<h3>Utiliza <a href="http://dev.mysql.com/doc/refman/5.0/es/myisam-storage-engine.html">MyISAM </a>si es posible</h3>
<p>Un denominador común en las aplicaciones web es que casi siempre se hacen más selects que inserts/updates/deletes. Si este es nuestro caso, podemos renunciar a las posibilidades relacionales que permite <a href="http://dev.mysql.com/doc/refman/5.0/en/innodb.html">InnoDB </a>para tener un gestor más rápido en las consultas.</p>
</li>
<li>
<h3>Emplea frecuentemente el LIMIT</h3>
<p>Esto es a la vez un consejo de rendimiento y de seguridad. Si estamos seguros de que vamos a borrar <strong>un registro</strong> de la tabla, entonces podemos añadirle un <code>LIMIT 1</code> al final y así nos aseguraremos que no se borrará en ninguno de los casos nada fuera de control. Esto es aplicable también para SELECTs y UPDATEs.</p>
<p>Cada vez que tengas claro con cuantos registros estás trabajando, utilízalo.</p>
</li>
</ol>
<p>En definitiva todos los puntos se refieren a que hay que tener control total de los datos que tenemos almacenados, siempre teniendo en cuenta las limitaciones y tratando de mantener una integridad de los datos.</p>
<p>Fuentes: <a href='http://www.amazon.co.uk/MySQL-Certification-Study-Guide-authoritative/dp/0672328127'>MySQL Certification Study Guide</a>, <a href='http://www.amazon.co.uk/Building-Scalable-Web-Sites-Henderson/dp/0596102356/'>Building Scalabe Web Sites (The Flickr way)</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2010/06/10-consejos-optimizar-mysql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bases legales de un sorteo. Cómo deben ser</title>
		<link>http://www.sortea2.com/blog/2009/03/bases-legales-de-un-sorteo-como-deben-ser/</link>
		<comments>http://www.sortea2.com/blog/2009/03/bases-legales-de-un-sorteo-como-deben-ser/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 18:17:00 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Sorteos]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[explicaciones]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=349</guid>
		<description><![CDATA[En este artículo trataremos de explicaros cómo debe ser el documento con las bases legales de un sorteo, para ello utilizaremos un ejemplo práctico en un sorteo ficticio:

Sortea2.com S.A.
La empresa Sortea2.com, con domicilio en C/Inexistente sin nº en Madrid, España organiza una acción promocional con el sistema de sorteo aleatorio dirigida a personas residentes en [...]]]></description>
			<content:encoded><![CDATA[<p>En este artículo trataremos de explicaros cómo debe ser el documento con las bases legales de un sorteo, para ello utilizaremos un ejemplo práctico en un <strong>sorteo ficticio</strong>:</p>
<hr/>
<h4>Sortea2.com S.A.</h4>
<p>La empresa Sortea2.com, con domicilio en C/Inexistente sin nº en Madrid, España organiza una acción promocional con el sistema de sorteo aleatorio dirigida a personas residentes en territorio español, mayores de edad.</p>
<h4>Objetivo</h4>
<p>Sortea2.com organiza este sorteo con el objetivo de incentivar a los usuarios a registrarse en la web de la empresa.</p>
<h4>Periodo de la promoción</h4>
<p>Esta acción promocional estará activa para los usuarios que se registren en nuestra web entre los días 24 de marzo y 31 de abril de 2009. El sorteo se realizará ante notario el 4 de mayo de 2009.</p>
<h4>Mecánica y modo de participación</h4>
<p>Para participar es necesario efectuar el registro en sortea2, desde la siguiente dirección: http://www.sortea2.com/registro</p>
<p>Será imprescindible rellenar todos los campos correctamente para conseguir participar. Sortea2.com se reserva el derecho a rechazar algún registro de motu propio y sin previo aviso por parecerle defectuoso. Solo se permitirá un registro por persona.</p>
<p>Entre todos los usuarios que se registren durante el periodo de la promoción se realizará el sorteo de un iPod Touch de 2Gb el día 4 de mayo de 2009 ante notario. El notario extraerá de la lista de participantes a un (1) ganador y a tres (3) suplentes.</p>
<p>En caso de que no se pueda contactar con el ganador, que rechace el premio o que en un periodo de 15 días después de comunicarle que ha resultado ganador no responda, se procederá a contactar con el segundo suplente.</p>
<h4>Premios</h4>
<p>El premio consiste en un iPod Touch de 2Gb valorado en 00,00€.</p>
<h4>Comunicación al ganador</h4>
<p>En un periodo máximo de una semana después del sorteo, se contactará con el ganador mediante correo electrónico. En caso de que no responda, se contactará con el primer suplente.</p>
<h4>Cancelación del sorteo</h4>
<p>El sorteo solo no se podrá cancelar, una vez iniciado el periodo de la promoción, ya se debe continuar.</p>
<h4>Disponibilidad del premio</h4>
<p>En caso de que el premio no se pueda entregar exactamente el mismo modelo, se procederá a regalar un premio de el mismo valor o superior. No se permitirá canjear el premio por dinero en metálico.</p>
<h4>Publicidad</h4>
<p>Sortea2.com se reserva el derecho a publicar el nombre de usuario del ganador con fines promocionales.</p>
<h4>Aceptación de las bases</h4>
<p>El mero hecho de participar en el sorteo implica que el usuario acepta totalmente las condiciones de estas bases legales.</p>
<p><em>En Madrid, a 24 de marzo de 2009</em></p>
<hr/>
Insisto en que este sorteo <strong>no existe</strong>, es simplemente un ejemplo. Lo importante es ver que nada de eso debe faltar en unas bases legales, puede tener más términos, pero esos <strong>son los imprescindibles</strong>.</p>
<p>Para cualquier duda, no dudeis en insertar algún comentario y os responderemos a cualquier cuestión.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2009/03/bases-legales-de-un-sorteo-como-deben-ser/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Como hacer sorteos anonimos</title>
		<link>http://www.sortea2.com/blog/2009/03/como-hacer-sorteos-anonimos/</link>
		<comments>http://www.sortea2.com/blog/2009/03/como-hacer-sorteos-anonimos/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 15:56:52 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Promoción]]></category>
		<category><![CDATA[Tutoriales]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=323</guid>
		<description><![CDATA[Es normal que en algunos casos uno quiera realizar un sorteo y que sólo se entere quien se tiene que enterar de que este se ha realizado. Uno no desea darle publicidad o transparencia. Simplemente quiere dar unos ganadores.
Para un sorteo así, la herramienta ideal es la página de sorteos simples. Se introduce la lista [...]]]></description>
			<content:encoded><![CDATA[<p>Es normal que en algunos casos uno quiera realizar un sorteo y que sólo se entere quien se tiene que enterar de que este se ha realizado. Uno no desea darle publicidad o transparencia. Simplemente quiere dar unos ganadores.</p>
<p>Para un sorteo así, la herramienta ideal es la página de <a href="http://www.sortea2.com/sorteos"><strong>sorteos simples</strong></a>. Se introduce la lista de nombres y se pulsa sortear. Con el resultado que obtengamos copiamos los nombres o imprimimos la pantalla y podemos felicitar a los vencedores.</p>
<div id="attachment_324" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.sortea2.com/blog/wp-content/images/sorteo-simple-ejemplo.png"><img src="http://www.sortea2.com/blog/wp-content/images/sorteo-simple-ejemplo-300x147.png" alt="Sorteo simple de ejemplo" title="Sorteo simple de ejemplo" width="300" height="147" class="size-medium wp-image-324" /></a><p class="wp-caption-text">Sorteo simple de ejemplo</p></div>
<p>Nadie verá quiénes eran los participantes ni siquiera quienes fueron los vencedores. Esta información no se almacenará en ninguna parte, con lo que el autor del sorteo puede hacer con ella lo que quiera sin preocuparse de que miradas indiscretas se enteren de que él ha sorteado algo.</p>
<p>Si se desea realizar un sorteo más completo, y sobre todo aprovechar la posibilidad de programar un sorteo para que se realice a una fecha y hora determinadas (lo cual es especialmente útil para tareas rutinarias, pues se pueden programar numerosos sorteos y esperar a que se vayan publicando los resultados cuando llegue esa fecha), se puede usar la herramienta de <a href="http://www.sortea2.com/sorteos-avanzados"><strong>sorteos avanzados</strong></a>.</p>
<p>Sin embargo habrá quienes no quieran ver su nombre en las páginas web, quienes no quieran que se sepa que ha participado en un sorteo que no ganó. Si se quiere aprovechar la enorme utilidad de los sorteos avanzados manteniendo la privacidad, lo ideal es hacerlo <strong>usando alias o nicknames</strong>.</p>
<p>Por ejemplo supongamos que queremos sortear algo comprometido, digamos un jamón entre los clientes de un sex shop. Podemos usar la primera opción, de sorteos sencillos, porque nadie verá los nombres que se introduzcan. Pero también podemos hacerlo programando el sorteo, diciendo &#8220;el lunes 3 de agosto a las 21:00 horas se realizará el sorteo&#8221;. En este sorteo, en lugar de introducir los nombres de los concursantes, que tratamos de mantener en el anonimato, utilizamos por ejemplo una tabla de números:</p>
<p>Celestino Corbacho  &#8211;> 100<br />
Cristina Garmendia   &#8211;> 200<br />
Miguel Sebastián   &#8211;> 300<br />
Beatriz Corredor &#8211;> 400<br />
Bibiana Aído &#8211;> 500</p>
<div id="attachment_325" class="wp-caption alignnone" style="width: 310px"><a href="http://www.sortea2.com/blog/wp-content/images/sorteo-avanzado-ejemplo.png"><img src="http://www.sortea2.com/blog/wp-content/images/sorteo-avanzado-ejemplo-300x219.png" alt="sorteo-avanzado-ejemplo" title="sorteo-avanzado-ejemplo" width="300" height="219" class="size-medium wp-image-325" /></a><p class="wp-caption-text">sorteo-avanzado-ejemplo</p></div>
<p>A los participantes les decimos con qué número participan, y le podemos quizás dar una papeleta donde se indique esto.</p>
<p>Y luego simplemente programamos el sorteo, con total anonimato, usando los números o el alias, en lugar de sus nombres.</p>
<p><a href="http://www.sortea2.com/blog/wp-content/images/sorteo-avanzado-ejemplo2.png"><img src="http://www.sortea2.com/blog/wp-content/images/sorteo-avanzado-ejemplo2-300x200.png" alt="" title="sorteo-avanzado-ejemplo2" width="300" height="200" class="alignnone size-medium wp-image-326" /></a></p>
<p>Así, si algún curioso lo consulta (en la <a href="http://www.sortea2.com/versorteo/260">dirección del sorteo</a>), no sabrá nada de los clientes de esta tienda, mientras que cualquiera de los participantes podrá saber si ha sido premiado o no, al mismo tiempo sabrá que el sorteo ha sido real y no que le han dado el premio al cuñado del dueño del sex-shop. </p>
<p>Usando sortea2 se consigue transparencia y además con toda la privacidad que uno quiera mantener.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2009/03/como-hacer-sorteos-anonimos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo se hizo el posicionamiento en buscadores en Sortea2</title>
		<link>http://www.sortea2.com/blog/2009/02/como-se-hizo-el-posicionamiento-en-buscadores-en-sortea2/</link>
		<comments>http://www.sortea2.com/blog/2009/02/como-se-hizo-el-posicionamiento-en-buscadores-en-sortea2/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 18:39:13 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[seo]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=294</guid>
		<description><![CDATA[Una de las cosas más importantes en la creación de una web es la parte del posicionamiento en buscadores, no en vano, al menos el 80% de las visitas serán procedentes de Google y el número de visitas dependerá de dónde nos encontremos en los resultados de las búsquedas.

En este artículo trataré de explicaros las [...]]]></description>
			<content:encoded><![CDATA[<p>Una de las cosas más importantes en la creación de una web es la parte del <strong>posicionamiento en buscadores</strong>, no en vano, al menos el 80% de las visitas serán procedentes de Google y el número de visitas dependerá de dónde nos encontremos en los resultados de las búsquedas.</p>
<p><a href='http://www.google.es/search?q=viajes' target='_blank'><img src='http://www.sortea2.com/blog/wp-content/uploads/posicionamiento-google.jpg' alt='Conseguir los primeros resultados atrae muchas visitas' title='Conseguir los primeros resultados atrae muchas visitas' /></a></p>
<p>En este artículo trataré de explicaros las técnicas que hemos utilizado para tratar de facilitarle el trabajo a Google:</p>
<h3>Estructura</h3>
<p><span class='header'>Crea un código simple y legible</span><br />
No es para nada recomendable el uso de multitud de tablas anidadas unas en otras ni la utilización de <strong>marcos</strong> o cosas por el estilo. Evita siempre complicar las cosas e intenta que todo el código esté bien estructurado.</p>
<p><span class='header'>Relaciona unas páginas con otras</span><br />
Trata de enlazar páginas relacionadas entre sí, porque eso es algo favorable de cara a Google. Intenta crear secciones tales como <strong>&#8220;Temas relacionados&#8221;</strong> dentro de una página o cosas por el estilo.</p>
<p><span class='header'>Enlaza a fuentes que amplien información</span><br />
Siempre que sea posible, enlaza a fuentes originales o a páginas que aclaren un determinado tema. Un ejemplo corriente puede ser el enlazar a algún artículo de la wikipedia que explique algún término que utilicemos.</p>
<h3>Uso correcto de etiquetas HTML</h3>
<p><span class='header'>Usa la etiqueta apropiada en el lugar apropiado</span><br />
Un ejemplo habitual puede ser el uso de las etiquetas <code>strong </code>en vez de <code>b</code> y las etiquetas <code>em </code>en vez de <code>i</code>. Estas etiquetas cumplen una de las funciones iniciales del HTML: <strong>ser descriptivas</strong>, mientras que cualquier elemento de una web puede estar en negrita (gracias a CSS), es necesario que se pueda especificar explícitamente que esa zona está resaltada por algo, no que están en negrita por ser una especie de encabezado ni nada. En resumen, intentar <strong>usar todas las etiquetas html posibles</strong>, cada una en su sitio; si hay que usar un h3 en vez de un span, mejor que mejor.</p>
<p><span class='header'>Usar tablas lo menos posible</span><br />
Las tablas son un lío para Google, usarlas solamente en el caso de que sean imprescindibles.</p>
<h3>Contenido</h3>
<p><span class='header'>Haz a las imágenes descriptivas</span><br />
Las imágenes son <strong>muy buenas para el posicionamiento</strong>, pero si están bien usadas. Hay que tratar de ponerles un nombre descriptivo al archivo, incluirle un atributo <code>alt</code> y escribirles algo en el atributo <code>title</code>. Hay que tener en cuenta que el Googlebot tan solo podrá leer los textos y las etiquetas, no lo que ponga en la imagen.</p>
<p><span class='header'>Añade etiquetas meta</span><br />
Una de las mejores maneras de posicionar la web es añadiendole meta-tags descriptivas. Estas etiquetas se añaden dentro del <code>head</code> y las hay de dos tipos:</p>
<p>Etiqueta descripción:</p>
<p><code>&lt;meta name='description' content='Sortea2, la herramienta para sortear. Realice sorteos entre todos los participantes que desee, puede guardarlos, programarlos, comentar los sorteos, votarlos y mucho más.'/&gt;</code></p>
<p>Hay que escribir una descripción buena. Ojo con repetir mucho alguna palabra que eso no le gusta nada a Google.</p>
<p>Etiqueta tags:</p>
<p><code>&lt;meta name='keywords' content='viaje,Estados Unidos,star wars,nocilla,marzo 2009,  sorteos, sortear, to raffle, rifas, raffles, lotería, programar, participantes'/&gt;</code></p>
<p>Aquí debes escribir algunas palabras que estén relacionadas con una página en particular o de toda la página. Si la web es dinámica (como Sortea2), es altamente recomendable crear etiquetas variables. Por ejemplo, en las <a href="http://www.sortea2.com/">páginas de sorteos</a>, una parte de las keywords de esta etiqueta meta son las propias tags del sorteo.</p>
<p><span class='header'>Crea contenido propio</span><br />
Hay que tener en cuenta que si <strong>copias y pegas</strong> texto de otras webs, evidentemente la web que creó ese contenido antes es la que va a estar delante en las búsquedas, así que es mejor ni intentarlo. Hay que <strong>crear contenido escrito por uno mismo</strong>, y en caso de tener que copiar un fragmento de texto, indicar la fuente original.</p>
<h3>Consideraciones de compatibilidad</h3>
<p><span class='header'>Tratar de pasar el W3C Validator</span><br />
Una medida genial para posicionarse es hacer una web accesible a todos los navegadores. En Sortea2 ya escribimos un artículo sobre <a href="http://www.sortea2.com/blog/2009/01/como-pasar-el-w3c-validator-y-no-morir-en-el-intento/">como pasar el W3C Validator</a>.</p>
<h3>Conseguir links externos</h3>
<p><span class='header'>Conseguir links externos mejora el pagerank</span><br />
El <a href="http://es.wikipedia.org/wiki/Pagerank" target="_blank">pagerank</a> es una de las medidas que utiliza Google para determinar los resultados. Este número depende del número de links que tenga nuestra página de otras páginas.</p>
<p>Esta parte es la que más ayuda en el posicionamiento en buscadores, pero también <strong>es la que menos depende de uno mismo</strong>. Podemos tratar de colocar algunos links a nuestras páginas en algunos sitios, aunque en esta parte lo único que se debería hacer es <strong>crear contenido de calidad</strong> que haga que la gente te enlace por sí misma.</p>
<p>El principal rival que tenemos en este tema es el <code>no follow</code> dentro del atributo <code>rel </code>de los links. Esto lo que hace es decirle a los buscadores que ese link no lo tengan en cuenta a la hora de valorar esa web enlazada. Se suele utilizar en los comentarios de los blogs para que la gente no haga spam.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2009/02/como-se-hizo-el-posicionamiento-en-buscadores-en-sortea2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pasar el W3C Validator</title>
		<link>http://www.sortea2.com/blog/2009/01/pasar_el_w3c_validator/</link>
		<comments>http://www.sortea2.com/blog/2009/01/pasar_el_w3c_validator/#comments</comments>
		<pubDate>Fri, 30 Jan 2009 16:13:02 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[sortea2]]></category>
		<category><![CDATA[w3c validator]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=288</guid>
		<description><![CDATA[El servicio w3c validator tiene la utilidad de testear una web para encontrar las partes en las que esta puede ser incompatible con los estándares, las partes con errores y los posibles conflictos que se pueden dar.

Este servicio puede validar HTML indicando la URL de la web, subiendo un archivo .html o escribiendo el HTML [...]]]></description>
			<content:encoded><![CDATA[<p>El servicio <a href="http://validator.w3.org/">w3c validator</a> tiene la utilidad de testear una web para encontrar las partes en las que esta puede ser <strong>incompatible con los estándares</strong>, las partes con <strong>errores y los posibles conflictos </strong>que se pueden dar.</p>
<p><img src='http://www.sortea2.com/blog/wp-content/uploads/w3c.jpg' alt='El W3C validator sirve para validar el código HTML' title='El W3C validator sirve para validar el código HTML' /></p>
<p>Este servicio puede validar HTML indicando la URL de la web, subiendo un archivo .html o escribiendo el HTML directamente.</p>
<p>Pasar correctamente estas validaciones y por consiguiente conseguir el logo de &#8220;W3C validator&#8221; es <strong>bastante complicado</strong>, sobre todo en el caso de intentar pasar este test una vez finalizada la parte de desarrollo en la página web; a nosotros nos sucedió ese problema: tratamos de solucionar la mayor parte de problemas de compatibilidad posibles, pero no fue posible en todos los casos.</p>
<p>A priori puede parecer que, mientras la página funcione y se vea más o menos bien en la mayoría de los navegadores, es suficiente; pero no deberíamos conformarnos con esto porque el principal motivo para esforzarse en este tema es que <strong>Google indexa mejor</strong> páginas que sean <em>W3C compatible</em>, esto es debido a que para el robot de Google le es <strong>más fácil leer nuestra web</strong>, por lo que obtendríamos mejores resultados en las búsquedas de Google.</p>
<p>A continuación voy a detallarle las cosas que <strong>suelen dar errores </strong>y que hay que tratar de evitar porque dan problemas con el validador de W3C:</p>
<p><br/><br />
<span class='header'>Dejarse etiquetas sin cerrar: </span><br />
Esto puede parecer obvio, pero no lo es tanto. A veces se nos puede olvidar cerrar un div, es normal, y este validador nos lo indicará.<br />
Pero hay casos en los que hay que cerrar las etiquetas aunque no haga falta, por ejemplo, en el caso de utilizar XHTML, las etiquetas <code>img </code>deben terminar con /&gt;, las etiquetas <code>meta </code>, <code>link</code>, <code>input</code>, etc. necesitan ser cerradas de manera explícita.<br />
Otro caso es el de las etiquetas que aparentemente no es necesario cerrar, sino que el navegador sobreentiende que ya han finalizado. Este es el caso, por ejemplo de las etiquetas &lt;option&gt; y &lt;li&gt; no son imprescindibles de cerrar, porque cuando empieza la siguiente etiqueta de este tipo ya se sobreentiende que se han cerrado. Esta práctica no cumple con los estándares, por lo que deberíamos evitarla.</p>
<p><br/><br />
<span class='header'>Uso excesivo de tablas</span><br />
Este es un problema dificil de diagnosticar, puesto que el validador nos mostrará un <strong>montón de errores </strong>cuando una página tiene muchas tablas. Para que las tablas sean compatibles, tienen que estar compuestas de la siguiente manera: <code>&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;</code>, en caso de que el tbody se nos olvide o algo, ya nos dará error.<br />
El consejo sería evitar el uso de las tablas, aunque, como a veces es inevitable, se pueden o bien ignorar los errores, o tratar de usar todas las etiquetas necesarias.</p>
<p><br/><br />
<span class='header'>Elementos que están donde no deben</span><br />
Este problema es típico cuando se define unos estilos dentro del body o cuando se tratan de usar etiquetas meta dentro del body. También da error en caso de introducir una etiqueta que dibuje algo en la pantalla dentro del head.<br />
Estos errores son habitualmente fáciles de solucionar, aunque hay veces que hay problemas inevitables. Se trata de situar cada elemento en su sitio y ya está; si nos es imprescindible que un elemento esté fuera del sitio, tampoco nos tenemos que obsesionar.</p>
<p><br/><br />
<span class='header'>Atributos que una etiqueta no tiene</span><br />
Este tipo de errores se suele dar en páginas en las que se aplica Javascript, como nos es necesario acceder a los elementos de la página a través de atributos id, name, class, etc., a veces podemos tener el caso de que nos hagan falta más atributos o algo así.<br />
Un caso puede ser tener un elemento <code>&lt;td&gt;</code> en el que hemos aplicado un atributo id para ponerle estilo CSS, si este id se repite (más adelante veremos que esto también da problemas), entonces tenemos que tener otro atributo que se refiera a este elemento td. Una posible solución es usar un <strong>atributo name</strong>, esta práctica no es muy recomendable, puesto que da errores de compatibilidad; siempre hay que tratar de usar un atributo <strong>id y que sea único</strong>.<br />
El atributo <code>name </code>se debería utilizar <strong>solo para formularios </strong>y para anclas.</p>
<p><br/><br />
<span class='header'>Problemas con IDs</span><br />
Un ID es un identificador <strong>único</strong>, por lo tanto, se debe utilizar tan solo para una etiqueta hml. En caso de usarlo para aplicar un estilo CSS, se debe tener en cuenta que si ese estilo solo se va a usar en una etiqueta de la misma página, entonces si se puede usar un ID; en caso de tener que reutilizar el mismo estilo varias veces en el mismo documento, entonces hay que usar una <strong>class</strong>.<br />
Los IDs no pueden <strong>empezar por un número</strong> sino que deben empezar por una letra o un guión bajo o similar. Esto puede suponer un problema cuando, para aplicar Javascript nos es necesario aplicar un ID a un elemento que sea su número identificador; por ejemplo, en la pantalla de <a href="http://www.sortea2.com/publicos">lista de sorteos </a> cada sorteo tiene en el botón de borrar sorteo asignado un id que es el número de sorteo. En nuestro caso nos es imprescindible, puesto que así se facilitan mucho las operaciones internas; podríamos haber evitado esta práctica, aunque no lo hemos visto necesario.<br />
En resumen, que se evite empezar por un número, aunque tampoco tiene que ser algo que complique mucho la programación interna en Javascript o PHP.</p>
<p><br/><br />
<span class='header'>Resumen</span><br />
Concluyendo, hay que tratar de pasar el W3C validator aunque tampoco debe ser una obsesión que haga que pongamos todos nuestros recursos en pasar con éxito. Es más <strong>importante saber como evitar los errores </strong>que saber cómo arreglarlos; esto es debido a que a veces es tan avanzada la programación interna, que es muy complicado modificarla a posteriori para que se tomen en cuenta los cambios.</p>
<p>En <a href="http://www.sortea2.com">sortea2 </a>hemos tratado de pasar el W3C validator, aunque en la mayoría de las páginas no nos ha sido posible. Lo importante es saber qué técnicas evitar a la hora de programar y es por eso por lo que os escribo este artículo.</p>
<p><br/><br/><br />
<em>¿crees que faltan errores de compatibilidad comunes? comunícanoslo a través de los comentarios.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2009/01/pasar_el_w3c_validator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Evitar problemas cuando Javascript no está habilitado en el navegador</title>
		<link>http://www.sortea2.com/blog/2009/01/evitar-problemas-cuando-javascript-no-esta-habilitado-en-el-navegador/</link>
		<comments>http://www.sortea2.com/blog/2009/01/evitar-problemas-cuando-javascript-no-esta-habilitado-en-el-navegador/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 09:01:51 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[habilitado]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[truco]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=280</guid>
		<description><![CDATA[Cuando una página de nuestra web necesita obligatoriamente tener javascript habilitado en el navegador para poder mostrarse correctamente, pero no queremos que los usuarios que no lo tengan habilitado accedan automáticamente a otra página para que pueda llevar a cabo la tarea que quería utilizar, tenemos que idear un método que detecte si javascript está [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando una página de nuestra web necesita obligatoriamente <strong>tener javascript habilitado </strong>en el navegador para poder mostrarse correctamente, pero no queremos que los usuarios que no lo tengan habilitado accedan automáticamente a otra página para que pueda llevar a cabo la tarea que quería utilizar, tenemos que idear un método que detecte si javascript está habilitado y, en caso negativo, redireccionar a otra página.</p>
<p>Este problema lo tuvimos en la pantalla de <a href="http://sortea2.com/sorteos">sorteos simples</a>, queríamos que los usuarios sin javascript pudieran explotar todas las posibilidades de nuestro sistema para sortear. Para ello, creamos una página alternativa a esta, la de <a href="http://www.sortea2.com/sorteosnoscript">sorteos simples sin javascript</a>. Como vemos, visualmente es practicamente idéntica, pero a la hora de darle al botón de ¡sortear! el resultado necesita que la página se actualice.</p>
<p>Bien, ya teníamos las dos páginas, pero ¿cómo hacer que la gente que no tenga javascript sepa facilmente que hay otra página que hace exactamente lo mismo  y que sí le funciona?. La solución que pensamos que era la más fácil era usando la clásica etiqueta de <strong><code>&lt;noscript&gt;&lt;/noscript&gt;</code></strong>. Esta etiqueta lo que hace es ejecutar lo que haya dentro en el caso de no tener javascript. Entonces lo que había que hacer era que lo que hubiera dentro fuera una instrucción que redireccionara la página a otra.</p>
<p>La instrucción es una etiqueta meta, la siguiente:</p>
<div id='codigo'>
&lt;NOSCRIPT&gt;<br />
&lt;META HTTP-EQUIV=&#8217;Refresh&#8217; CONTENT=&#8217;0;URL=$parametro&#8217;&gt;<br />&lt;/NOSCRIPT&gt;
</div>
<p>Más tarde veremos por qué en el atributo URL ponemos una variable de javascript, pero si unicamente necesitas redireccionar una página, puedes poner directamente la página a la que quieres que se redireccione.</p>
<p>Con este código ya podría funcionar todo correctamente, aunque nosotros tuvimos que ir más allá, porque hicimos una función que, entre otras cosas, miraba que página quería ser redireccionada y la redireccionaba donde debía.</p>
<p>Un fragmento de la función sería este:</p>
<div id="codigo"> $paginanojs = array(1 =&gt; “sorteos-simples”, 2 =&gt; “sorteos”, 3 =&gt; “registro”, 4 =&gt; “login”);</p>
<p> for ($i = 1 ; $i &lt;= count($paginanojs)  ; $i++)<br /> {<br /> <span class="indented">if ($noscript == $paginanojs[$i])</span><br /> <span class="indented">{</span><br /> <span class="indented">if ($noscript == &quot;sorteos-simples&quot;)</span><br /> <span class="indented"><span class="indented">$parametro = &quot;../sorteosnoscript&quot;;</span></span><br /> <span class="indented">elseif ($noscript == &quot;sorteos&quot;)</span><br /> <span class="indented"><span class="indented">$parametro = &quot;../nojs?pag=sorteos_av&quot;;</span></span><br /> <span class="indented">else</span><br /> <span class="indented"><span class="indented">$parametro = &quot;../nojs?pag=&quot;.$paginanojs[$i];</span></span></p>
<p> <span class="indented">echo</span>&quot;&lt;NOSCRIPT&gt;&quot;.<br /> &quot;&lt;META HTTP-EQUIV=&#8217;Refresh&#8217; CONTENT=&#8217;0;URL=$parametro&#8217;&gt;&quot;.<br /> &quot;&lt;/NOSCRIPT&gt;;</span><br /> <br/> <span class="indented">$noscript = 0;<br/></span> <span class="indented"> break;</span><br /> <span class="indented">}</span><br /> } </div>
<p>A esta función se la llama con el parámetro <strong>$noscript</strong>, y ya hace lo que predeterminadamente hemos programado.</p>
<p>En nuestro caso, necesitábamos que las páginas de <a href="http://sortea2.com/registro">registro</a>, de <a href="http://sortea2.com/login">login </a>y de <a href="http://sortea2.com/sorteos-avanzados">sorteos avanzados </a>fueran a una página auxiliar, porque no habíamos creado ninguna página que hiciera su misma función pero sin javascript, en estas páginas lo que se hace es informar al usuario de que no puede utilizar esas funciones. Puede que en el futuro habilitemos estas páginas para este tipo de usuarios.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2009/01/evitar-problemas-cuando-javascript-no-esta-habilitado-en-el-navegador/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problemas CSS en Internet Explorer</title>
		<link>http://www.sortea2.com/blog/2008/12/problemas-css-en-internet-explorer/</link>
		<comments>http://www.sortea2.com/blog/2008/12/problemas-css-en-internet-explorer/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 12:30:02 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Tutoriales]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=182</guid>
		<description><![CDATA[Problemas de CSS en Internet Explorer   
Internet Explorer tiene una manera de entender CSS muy  “peculiar” que  hace que todos los  diseñadores web tengan que dedicar gran parte de su tiempo en hacer que su  proyecto funcione particularmente en Internet Explorer. Esto es una gran  pérdida de tiempo y [...]]]></description>
			<content:encoded><![CDATA[<p><span class="header">Problemas de CSS en Internet Explorer</span> <br/> <br /> 
<p>Internet Explorer tiene una manera de entender CSS muy  “peculiar” que  hace que todos los  diseñadores web tengan que dedicar gran parte de su tiempo en hacer que su  proyecto funcione particularmente en Internet Explorer. Esto es una gran  pérdida de tiempo y puede que de dinero, pero que no hay más remedio que  afrontar, por esto:</p>
<p> <a href="http://www.thecounter.com/stats/2008/December/browser.php"><img src="http://www.sortea2.com/blog/wp-content/uploads/estadisticas_navegadores.jpg" alt="estadisticas_navegadores.jpg" width="497" height="146" border="0" /></a></p>
<p> Hay que preocuparse por el volumen de visitas que van a  llegar al website por parte de Internet Explorer, porque es tal que no se puede  despreciar.</p>
<p> <span class="header">Caso particular</span> </p>
<p> Particularmente, en Sortea2, nuestra <a href="http://www.sortea2.com">página de sorteos</a>, también tuvimos que lidiar con estos problemas,  tuvimos que tomar medidas porque la página, que se visualizaba correctamente en  <a href="http://www.mozilla-europe.org/es/firefox/">firefox</a>, <a href="http://www.opera.com/">opera</a>, etc., era impresentable en <a href="http://www.microsoft.com/spain/windows/ie/default.mspx">Explorer</a>, las cosas normalmente se  montaban unas encima de otras y tal.<span class="header"></p>
<p> <span class="header">Qué cosas dan problemas</span> </p>
<p> Tras haber terminado el diseño de Sortea2, he llegado a la conclusión de que  estas cosas son las que dan problemas:</p>
<ol>
<li>Listas.</li>
<li>Márgenes negativos para posicionar.</li>
<li>Posicionamiento normal.</li>
<li>Desbordamiento de divs.</li>
<li>Imágenes de fondo.</li>
</ol>
<p>1.  Las listas es lo  que habitualmente más problemas da, cuando quieres formatearlas con padding y  margin suelen tratar las cosas de diferente manera que los navegadores  normales. Por ejemplo, no puedes variar el valor de margin-left en las listas  para que estén alineadas a la izquierda con tan solo poner: “margin-left:0px;”.<br /> También suelen dar problemas las listas que se colocan a lo ancho (float:left;),  hay que ir probando con qué valores funcionan bien. Por ejemplo, en nuestro  menú horizontal, el valor float:left; había que ponerlo en #menu_horizontal li  a {} para que funcionase, mientras que en otros lugares se podía colocar  directamente en #menu_horizontal li {}.</p>
<p> 2. Los márgenes negativos no sé exactamente por qué dan  tantos problemas. A veces funcionan, otras veces no, y otras veces hay que  poner valores distintos a lo habitual para que se coloque en el lugar que se  desea. El mejor ejemplo es en la parte de arriba de sortea2, en la que se ve  una diferencia de colocación entre cualquier navegador y Internet Explorer,  esto es debido a que a veces los márgenes negativos no funcionaban y tuvimos  que intentar colocar las cosas con otros valores.</p>
<p> 3. El posicionamiento normal, con “position:relative y  absolute” no suele dar muchos quebraderos de cabeza, simplemente algunas veces  hay que cambiar los valores un poco para que las cosas cuadren.</p>
<p> 4. El desbordamiento de divs tiene su “particularidades” en  Internet Explorer cuando se quiere hacer “overflow”. Normalmente al desbordarlo  suele tener después un tamaño extraño que cuesta colocar. Esto nos pasó con el  div #resultado, que se despliega en la <a href="http://www.sortea2.com/sorteos">pantalla de sorteos simples</a> al hacer un  sorteo, en firefox funciona perfectamente, pero en internet explorer se ve como  se contrae un poco cuando la lista de ganadores es demasiado grande y hace que  salga el scroll en el div.</p>
<p> 5. Las imágenes de fondo se suelen colocar correctamente y  tal, el problema es el orden en que se cargan. Por ejemplo, al principio, en  las pestañas que se utilizan cuando se utiliza el buscador o en la pantalla de  Mis Sorteos, utilizábamos un hover que consistía en otra imagen, Bien, pues  firefox y opera cargaban esa imagen antes de que terminara de cargar la página,  por lo que el efecto se hacía correctamente; el problema lo daba Internet  Explorer, porque se cargaba la imagen en el momento en que se hacía el hover,  con lo que había que esperar un tiempo para ver el efecto. Fue tan desastroso  el resultado que optamos por subrayar esos links al pasar por encima y listo,  de camino lo dejamos igual para ambos navegadores.</p>
<p> <span class="header">Soluciones</span> </p>
<p> La solución por la que optamos nosotros fue:
<ul>
<li>Una hoja de estilos común, en la que las  propiedades que funcionasen en ambas estuvieran recogidas.</li>
<li>Una hoja de estilos para Internet Explorer, con  todas las correcciones posibles para que se mostrase bien la página.</li>
<li>Una hoja de estilos para los demás navegadores.  Para evitar que unas propiedades se pisaran a otras, optamos por poner en una  hoja de estilos independiente todas las propiedades que daban problemas en  Explorer, pero con los valores que serían normales.</li>
</ul>
<p>Ahora bien, ¿cómo sabemos qué navegador está mostrando la  página y por lo tanto qué hoja de estilo abrir?<br /> Bien, nuestra página está hecha con PHP, por lo que os voy a  mostrar un método para hacerlo con este lenguaje (también se podría hacer con  javascript).</p>
<p> <span class="header">Abrir una hoja u otra dependiendo del navegador</span> </p>
<p> Bien, PHP recibe por parte del navegador una serie de <strong>variables de servidor</strong> (idioma, <strong>navegador, </strong>versión de este último, etc.), pues tenemos que recoger lo que diga la  variable que dice qué navegador está mostrando la página:</p>
<p> $idnavegador = $_SERVER['HTTP_USER_AGENT'];</p>
<p> Esto es lo que obtendríamos de firefox:<br /> <em>Mozilla/5.0 (Windows;  U; Windows NT 5.1; es-ES; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5</em></p>
<p> Y esto es lo que nos devuelve Internet Explorer:<br /> <em>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT  5.1; SV1; InfoPath.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR  3.0.04506.30)</em></p>
<p> Debe haber alguna manera universal que distinga ambos  códigos, porque Internet Explorer da problemas igualmente en su versión 6 como  en su versión 7. <br /> Bueno, pues vamos a buscar las diferencias entre ambas  cadenas para ver qué podemos sacar que nos diga que estamos en Explorer.</p>
<p> En <em>Mozilla/X.0 </em>no  se puede sacar mucho, la verdad, porque es casi idéntico y con PHP no se podría  hacer un cálculo. Pero si nos metemos dentro del paréntesis  empezamos a ver cosas interesantes, y ya si  nos metemos en ver que hay después del punto y coma, ya lo tenemos.</p>
<p> Uno nos devuelve una U y otro nos dice MSIE X.XX, ahí está  la diferencia; pero queremos detectar cualquier explorer, no una versión  determinada; bien, pues recoges la palabra MSIE y listo, con un parseo veremos  que se puede hacer fácilmente:<br /> 
<div id="codigo"> $puntocoma = <span class="literales">&quot;;&quot;</span>;<br />       <br /> $total_length = <span class="funciones_php">strlen</span>($idnavegador);<br /> $puntocoma1 = <span class="funciones_php">strpos</span>($idnavegador, $puntocoma);<br /> $navegador = <span class="funciones_php">substr</span>($idnavegador, ($puntocoma1 + <span class="numero">2</span>), ($total_length &#8211;  $puntocoma1));<br /> $navegador = <span class="funciones_php">substr</span>($navegador, <span class="numero">0</span>, <span class="numero">5</span>);</div>
<p> Es cierto que puede ser un poco lioso, pero es simple: se  busca el punto y coma, se coge lo que hay después de él, y luego se cogen 5  caracteres (con 4 recuerdo que dio problemas una vez) de lo que se haya sacado.  Con esto ya tenemos esto: “MSIE “, ¡era lo que queríamos!, bueno, pues ahora  con un if abrimos una hoja u otra y ya está todo listo.<br /> 
<div id="codigo"> <span class="verde">if</span>  ($navegador == &quot;MSIE &quot;)<br /> <span class="indented"><span class="funciones_php">echo</span> <span class="literales">&quot;\t&lt;link  href=&#8217;../css/ie-hacks.css&#8217; rel=&#8217;stylesheet&#8217; type=&#8217;text/css&#8217;&gt;\n&quot;</span>;</span><br /> <span class="verde">else</span><br /> <span class="indented"><span class="funciones_php">echo</span> <span class="literales">&quot;\t&lt;link  href=\&quot;../css/normal.css\&quot; rel=\&quot;stylesheet\&quot;  type=\&quot;text/css\&quot; /&gt;\n&quot;</span>;</span> </div>
<p>Ya está, ahora ponemos las propiedades que dan problemas en  ie-hacks y ya solo se verán en ese navegador.</p>
<p> <span class="header">Conclusión<br /> </span><br /> Internet Explorer es un navegador problemático y tenemos que poner nuestros  medios para hacer que esos problemas desaparezcan porque tiene una cuota de  mercado espectacular y merece la pena dedicarle tiempo.<br /> Puede que nuestro método de obtención del navegador no sea  precisamente la mejor y la más simple, pero lo cierto es que funciona y que  jamás ha dado ningún problema. </p>
</p>
<p><span class="header">Consejo final</span> </p>
<p> Como consejo final te diré que cada vez que hagas algún cambio relativamente  importante en tu web, si no eres un asiduo a Internet Explorer, que la pruebes ahí  antes de seguir con otra cosa, porque luego volver atrás para resolver  problemas antiguos es muy molesto.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2008/12/problemas-css-en-internet-explorer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jquery. Plugin útiles y otros no tanto.</title>
		<link>http://www.sortea2.com/blog/2008/12/jquery-plugin-utiles-y-otros-no-tanto/</link>
		<comments>http://www.sortea2.com/blog/2008/12/jquery-plugin-utiles-y-otros-no-tanto/#comments</comments>
		<pubDate>Sat, 13 Dec 2008 12:22:08 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Jquery]]></category>
		<category><![CDATA[Tutoriales]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=113</guid>
		<description><![CDATA[La página de Sortea2 abunda en el uso de Javascript mediante librerías de Jquery. Quizás a veces los efectos sean hasta molestos (lo sentimos) pero no se puede decir que la página es estática.
Cuando se utiliza Jquery una de las mayores ventajas que se esgrimen es la existencia de innumerables plugins, a cual más útil. [...]]]></description>
			<content:encoded><![CDATA[<p>La página de Sortea2 abunda en el uso de Javascript mediante librerías de Jquery. Quizás a veces los efectos sean hasta molestos (lo sentimos) pero no se puede decir que la página es estática.</p>
<p>Cuando se utiliza Jquery una de las mayores ventajas que se esgrimen es la existencia de innumerables plugins, a cual más útil. Y es verdad. Pero también es complicado adaptarse a cada uno de ellos. Cada programador tiene sus manías, sus ideas propias, su forma de hacer las cosas diferente. El uso de plugins tomados cada uno de un sitio, creados por programadores diferentes, da una absoluta falta de homogeneidad en el código.</p>
<p>Si uno se acostumbra a copiar trozos de código de aquí y de allí, es un <a href="http://en.wikipedia.org/wiki/Script_kiddie"><em>script kiddie</em></a>, un niñato que no sabe programar, sólo mal reutilizar.</p>
<p>Pero ante la ingente cantidad de herramientas tecnológicas, cada una con sus peculiaridades, se debe elegir entre eso o luchar vanamente por tratar de conocer un lenguaje para que pocos días después surja uno nuevo y también imprescindible. Por eso creo que es justificable el <em>copypasteo </em>de código ajeno, aunque a veces obtengamos resultados poco coherentes. Pero operativos.</p>
<p>Siempre luchando por entender las peculiaridades de cada uno de los plugins, a veces uno se frustra al ver que no hay forma de hacer funcionar uno en particular. Esto no se suele comentar mucho, porque se mira la página del desarrollador, con la demo operativa, se da plamas, se guarda el link y luego cae en el más oscuro de los olvidos, sin pensar la utilidad de aquello.</p>
<p>Por eso si vas a desarrollar un plugin para Jquery, te recomendaría en que emplearas el máximo tiempo posible en tener una demo que funcione, con diseño excelente. Que luego el plugin sea operativo o no, es lo de menos porque no se va a usar tanto como parece.</p>
<p>En fin, que paso a detallar los plugins que hemos usado en <a href="http://www.sortea2.com/">Sortea2.com</a>, y cuales no y por qué. No trata de ser una lista de &#8220;mejores plugins&#8221;, sino simplemente de plugins que han funcionado.</p>
<p><span class="header">1. Calendario.</span></p>
<p>Hemos empleado <a href="http://www.kelvinluck.com/assets/jquery/datePicker/v2/demo/">el plugin datePicker</a>.<br />
Su funcionamiento no es muy complejo de configurar y el resultado es sencillo, admitiendo días y fechas en castellano.<br />
Lo tenemos en la ventana de sorteos programados, para ver la fecha en que se programa un sorteo.</p>
<p><a href="http://www.sortea2.com/sorteos-avanzados"><img class="aligncenter size-full wp-image-114" title="jquery-datepicker" src="http://www.sortea2.com/blog/wp-content/images/jquery-datepicker.png" alt="" width="486" height="272" /></a></p>
<p>Por contra, aunque existen varios plugins para seleccionar la hora que nos podían haber servido en esa misma página, tras probar con varios siempre obtuvimos resultados poco satisfactorios. No dudo que el plugin funcione, pero para nuestro caso no servía. Y no pedíamos nada especial, simplemente un selector de fechas.</p>
<p>Tanto <a href="http://labs.perifer.se/timedatepicker/">este TimePicker</a>, com este <a href="http://www.oakcitygraphics.com/jquery/clockpick/trunk/ClockPick.cfm">otro timepicker</a> llegaron a funcionar, pero la hora no había forma de ajustarla al control indicado, siempre aparecía en la parte de abajo de la página. También existe un <a href="http://haineault.com/media/jquery/ui-timepickr/page/">tercer plugin</a> para seleccionar horas, pero ya es suficiente por el momento.</p>
<p>Seguramente la causa no era otra que algún tag de html mal cerrado por nuestra parte, o una mala configuración de las propiedades. El caso es que tras mucho tiempo perdido, decidimos descartarlo definitivamente.</p>
<p>Preparar un selector de horas y minutos es trivial, ni siquiera hace falta javascript, por lo que al final tomamos ese camino, con el resultado que podéis ver en la página de sorteos avanzados.</p>
<p><a href="http://www.sortea2.com/sorteos-avanzados"><img src="http://www.sortea2.com/blog/wp-content/images/jquery-timepicker.png" alt="" title="jquery-timepicker" width="360" height="364" class="aligncenter size-full wp-image-117" /></a></p>
<p>Quizás falte coherencia en el diseño entre la selección de fecha y hora. Es algo que podemos mejorar con el tiempo.</p>
<p><span class="header">2. Cookie.</span></p>
<p>El que hayamos usado un <a href="http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/">plugin para manejar las cookies</a> lo veo más como un error y un síntoma de la paranoia que hay en torno al uso de los plugins. Hasta para la tarea más sencilla se buscan utilidades hechas por otros. Creo que si hubiéramos usado javascript puro y duro, habríamos necesitado menos código que con este plugin. Pero al menos permite el uso sencillo de cookies.</p>
<p>En la aplicación tenemos dos cookies, una para <a href="http://www.sortea2.com/blog/?p=66">controlar el idioma con el que se accede a la página</a> y otra para gestionar las identidades de los usuarios.</p>
<p>El plugin al que me refiero <a href="http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/">es este</a>.</p>
<p><span class="header">3. Subida de ficheros mediante Ajax.</span></p>
<p>Una de las peores ideas que tuvimos al desarrollar la página fue permitir el subir un listado de nombres cargándolo desde un fichero. Es una de estas funcionalidades que consumen mucho tiempo de desarrollo y que luego nadie usa. O peor aún, nadie usa para bien porque son una puerta abierta a las vulnerabilidades.</p>
<p>Al final la hicimos. También en la ventana de sorteos avanzados, se puede cargar una lista de nombres de un fichero, idealmente un .txt en que cada nombre ocupa una línea.</p>
<p><a href="http://www.sortea2.com/sorteos-avanzados"><img src="http://www.sortea2.com/blog/wp-content/images/jquery-fileupload.png" alt="" title="jquery-fileupload" width="312" height="221" class="alignnone size-full wp-image-120" /></a></p>
<p>De nuevo aquí tiramos de un plugin que permite hacer una subida de fichero en forma totalmente asíncrona, sin tener que recargar la página y sin causar problemas.</p>
<p>Este es el <a href="http://www.phpletter.com/Our-Projects/AjaxFileUpload/">plugin para subir ficheros</a> con Jquery. Causó numerosos problemas conseguir adaptarlo al funcionamiento de la página, en gran parte porque fue una de las primeras tareas desempeñadas, cuando aún estábamos iniciándonos con el Jquery.</p>
<p>La idea inicial y algo que llegamos a hacer era mostrar la lista de nombres en un espacio dentro de la ventana, para que el usuario pueda ver quiénes participarán en el sorteo. Pero con el tiempo se nos fue acabando el sitio en la ventana y ya era todo muy complicado. Costó quitar una funcionalidad que ya estaba hecha, pero era necesaria una mayor simplicidad.</p>
<p><span class="header">4. Livequery.</span></p>
<p><a href="http://brandonaaron.net/docs/livequery/">Livequery </a>es posiblemente <strong>el plugin más útil</strong> de todos los que hemos empleado.</p>
<p>Nuestro problema es que cuando creábamos controles dinámicamente (como las listas de nombres y la de premios, que se amplian conforme el usuario va añadiendo más) era complicado hacer que estos controles heredaran los eventos de los controles iniciales en la página.</p>
<p>La tarea de añadir un <em>listener </em>a los eventos para nuevos controles era un motivo de quebraderos de cabeza. Y sin embargo con usar livequery esto se solucionó automáticamente.</p>
<p>Además fue el plugin más sencillo de implementar, pues es casi trivial. ¡Estamos enamorados de Livequery!</p>
<p><span class="header">5. Dynacloud.</span></p>
<p>También tenemos una nube de etiquetas, como toda aplicación que quiera parecer 2.0. Y para ello lo primero era buscar el plugin correspondiente. En este caso, <a href="http://johannburkard.de/blog/programming/javascript/dynacloud-a-dynamic-javascript-tag-keyword-cloud-with-jquery.html">Dynacloud</a>, para hacer una nube de tags.</p>
<p>Pues bien, no conseguimos hacerlo funcionar en la forma en que nos hubiera gustado. De nuevo mil historias, y cuando lográbamos que apareciera algo, estaba fuera de formato o al final de la página. Hicimos la funcionalidad desde cero, no es nada difícil.</p>
<p><a href="http://www.sortea2.com"><img src="http://www.sortea2.com/blog/wp-content/images/jquery-tagcloud.png" alt="" title="jquery-tagcloud" width="292" height="433" class="aligncenter size-full wp-image-121" /></a></p>
<p><span class="header">6. Sugerir tag.</span></p>
<p>Finalmente, un <a href="http://remysharp.com/2007/12/28/jquery-tag-suggestion/">plugin para sugerir un tag</a> cuando estás escribiendo un nuevo sorteo. Como se hace en <a href="http://delicious.com">delicious</a>, cuando introduces las primeras letras realiza una consulta y obtiene tags similares ya empleados para crear mayor uniformidad en la información.</p>
<p>No sin algo de sufrimiento, también se pudo poner en marcha con un resultado que consideramos muy bueno.</p>
<p><a href="http://www.sortea2.com/blog/wp-content/images/jquery-tag-suggest.png"><img src="http://www.sortea2.com/blog/wp-content/images/jquery-tag-suggest-300x98.png" alt="" title="jquery-tag-suggest" width="300" height="98" class="alignnone size-medium wp-image-122" /></a></p>
<p>Como se hacen consultas continuas al servidor, para cada uno de los caracteres, en orden a aliviar la carga sobre la base de datos, optamos por cargar todos los tags en un fichero. De esta forma, no se realiza ninguna consulta a base de datos, simplemente se abre el fichero, se vuelca directamente sobre un array y se buscan las coincidencias.</p>
<p>Este fichero de tags se va actualizando cada cierto tiempo mediante una tarea y santas pascuas. Nos libramos de tener que estar machacando la base de datos realizando consultas poco eficientes (el &#8220;like&#8221; en SQL no es lo más rápido y directo que digamos).</p>
<p>Como resumen, espero que esta entrada le sirva a alguien de ayuda para ver cómo los plugins te solucionan problemas y ahorran tiempo, pero a veces pierdes mucho tiempo sin poder hacerlos funcionar y otras es más eficaz codificar uno mismo la tarea que necesita.<br />
También puedes ver plugins que a lo mejor no son muy espectaculares, pero son operativos y necesarios para el funcionamiento de una página.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2008/12/jquery-plugin-utiles-y-otros-no-tanto/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Zonas horarias y PHP</title>
		<link>http://www.sortea2.com/blog/2008/11/zonas-horarias-y-php/</link>
		<comments>http://www.sortea2.com/blog/2008/11/zonas-horarias-y-php/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 19:49:55 +0000</pubDate>
		<dc:creator>bernabe</dc:creator>
				<category><![CDATA[Tutoriales]]></category>

		<guid isPermaLink="false">http://www.sortea2.com/blog/?p=86</guid>
		<description><![CDATA[Introducción. Métodos sencillos que no funcionan
Cuando escribimos nuestra página de sorteos consideramos que sería útil que los usuarios pudieran realizar un sorteo a una fecha y hora determinadas. Por si desean darle un poco de emoción o dar claridad a un sorteo. No es lo mismo que tú publiques unos resultados sino que digas &#8220;en [...]]]></description>
			<content:encoded><![CDATA[<p><span class="header">Introducción. Métodos sencillos que no funcionan</span></p>
<p>Cuando escribimos <a href="http://www.sortea2.com/sorteos-avanzados">nuestra página de sorteos</a> consideramos que sería útil que los usuarios pudieran realizar un sorteo a una fecha y hora determinadas. Por si desean darle un poco de emoción o dar claridad a un sorteo. No es lo mismo que tú publiques unos resultados sino que digas &#8220;en esta página ofrecerán los resultados&#8221;. Es una forma de mostrar que no influyes en el resultado.</p>
<p>Al querer realizar los sorteos a una hora concreta detectamos que era problemática la situación de cara a los usuarios que no usasen la misma zona horaria que nosotros (que es la de España). Una solución sería dar todas las fechas con nuestro horario. Es exigir a los clientes que se adapten a nuestras condiciones. Aunque hay muchos que optan por ella, me parece inadmisible.</p>
<p>Nuestra primera idea fue la de mostrar un desplegable con zonas horarias, mediante una función sencilla:<br />
Se muestra una zona horaria e internamente se guarda un valor numérico: el número de horas de diferencia respecto de la hora de Madrid.</p>
<p>Lisboa(-1)<br />
Madrid(0)<br />
Canarias(-1)<br />
Nueva York(-6)<br />
México DF (-7)</p>
<p>Esta aproximación es una de las más frecuentes. Es sencilla y fácil de tratar. Cuando un usuario de México solicita que su sorteo sea a las 13:00 horas, convertimos el horario al de España (sumamos 7 horas) y lo guardamos (20:00 horas). Luego cuando ese usuario decida consultar el sorteo, volvemos a realizar la conversión inversa, restando siete horas.</p>
<p>Sin embargo la vida no es tan fácil. Quizás el mayor de los problemas es la maligna <strong>DST </strong>(<em>Daylight Saving Time</em>, Horario de verano en castellano).</p>
<p>Porque cuando nos acercamos a estos días en que se suma o resta una hora, los resultados pueden ser impredecibles.</p>
<p>a) Hay países que no cambian nunca de horario (sabia decisión). Entonces respecto a ellos habrá veces que España tenga X horas de diferencia y el resto del año X +1 horas.</p>
<p>b) Hay países que cambian de horario en fechas diferentes, como sucede con Estados Unidos. No se puede ignorar a Estados Unidos, que tiene más usuarios de castellano que la propia España.<br />
Estados Unidos es aún más complejo por cuanto las elecciones presidenciales pueden cambiar la fecha en que se realice el cambio de hora. Además, tiene potestad para realizar cambios en el día seleccionado para la modificación horaria, sabemos cuando cambiarán el año que viene, pero dentro de tres años puede cambiar de sistema (ya lo han hecho varias veces). Vamos, que es todo un caso a tratar por separado.</p>
<p>c) Hay países que incluso cambian la regla. Muchos países decidieron dejar de cambiar de hora hace algún tiempo. De cara al futuro no es problemático pero si queremos hacer una correcta conversión de fechas, su situación debe ser tenida en cuenta.</p>
<p>d) Hay países que no tienen zonas horarias exactas. Ya sea porque tengan diferencias de cuarto de hora respecto de una zona (como Nepal, +5:45) o Venezuela (-4:30). Además, el caso de Venezuela, en que dicho cambio de zona horaria es muy actual, es problemático para fechas del pasado reciente.</p>
<p>Por todas estas razones, <strong>el método de sumar o restar horas, sencillamente no sirve</strong>.</p>
<p><span class="header"><br />
Zonas horarias y PHP</span></p>
<p>Para nuestro caso, al estar desarrollada la página con PHP, tras buscar soluciones posibles por Internet, sin mucho éxito y tratando de hacer alguna cosa bien, optamos por mirar algunas funciones propias de PHP.</p>
<p>Las <a href="http://es.php.net/manual/en/ref.datetime.php">funciones propias de PHP para zonas horarias</a> en la versión actual (4.4) son las siguientes:</p>
<ul> # timezone_abbreviations_list<br />
# timezone_identifiers_list<br />
# timezone_name_from_abbr<br />
# timezone_name_get<br />
# timezone_offset_get<br />
# timezone_open<br />
# timezone_transitions_get</ul>
<p>No creemos que sea necesario dar una enumeración de las mismas, máxime cuando se puede consultar la completa documentación online. Lo importante es saber que la forma en que PHP guarda las zonas horarias. Aunque hay posibles conversiones de texto (siempre más fáciles si el texto está en inglés), lo suyo es usar los pares Continente/País que presenta PHP en su <a href="http://es.php.net/timezones">lista de zonas horarias soportadas</a>.</p>
<p>Por ejemplo:</p>
<ul> Europe/Madrid<br />
America/Mexico_City<br />
America/Buenos_Aires<br />
Atlantic/Canary</ul>
<p>La lista de zonas horarias admitidas es extensísima. En muchos casos estas zonas horarias son idénticas, como sucede con Madrid, Berlín o París. De ahí que no tenga mucho sentido mostrar desplegables casi infinitos en sus posibilidades (sólo <a href="http://es.php.net/manual/en/timezones.antarctica.php">para la Antártida</a> PHP soporta ¡Ocho zonas horarias!).</p>
<p>Se realiza una selección de países y ciudades representativas. Lo ideal es mostrar junto a dicha ciudad la zona horaria correspondiente para que así un usuario de un lugar recóndito pueda localizar la zona que mejor se adapte a su ubicación:</p>
<ul> Buenos Aires (GMT -3)</p>
<p>La Paz (GMT -4)<br />
Caracas (GMT -4.5)<br />
Montreal (GMT -5)</ul>
<div id="attachment_104" class="wp-caption aligncenter" style="width: 409px"><a href="http://www.sortea2.com/sorteos-avanzados"><img class="size-full wp-image-104" title="zonas-horarias-php" src="http://www.sortea2.com/blog/wp-content/images/zonas-horarias-php.jpg" alt="Desplegable zonas horarias" width="399" height="510" /></a><p class="wp-caption-text">Desplegable zonas horarias</p></div>
<p>Por lo tanto, trabajamos con tres valores:</p>
<p>a) El <strong>código</strong> de zona horaria de PHP: America/Buenos_Aires<br />
b) La <strong>descripción</strong> para seres humanos de dicha zona: Buenos Aires<br />
c) Un <strong>indicativo</strong> para usuarios que no encajen exactamente con dicho país: GMT -3</p>
<p>Esto ya sugiere que crear una tabla donde se guarde la información de las zonas horarias puede ser de gran ayuda.</p>
<p>Si te interesa la que usamos en nuestra página, <a href="http://www.sortea2.com/blog/wp-content/images/timezone-tabla-php.txt">puedes descargártela de aquí, </a>en formato de creación para MySQL (fácilmente adaptable a otras bases de datos).</p>
<p><span class="header"><br />
Zonas horarias. ¿Qué convertimos?</span></p>
<p>Antes de continuar una buena tarea sobre la que meditar es cómo vamos a guardar las fechas y horas en nuestra base de datos. Si nos centramos en la ciudad en que vivimos, nos podemos encontrar con que el servidor que alberga nuestra página esté ubicado en otra zona horaria. Cierto es que a veces podemos manipular esta hora, pero en hostings compartidos, a veces esto no es posible.</p>
<p>Así, uno puede encontrase con que:</p>
<p>a) Su zona horaria es de Madrid, España.<br />
b) Quiere guardar una fecha y hora de Canarias, España.<br />
c) El servidor está situado en Los Ángeles, Estados Unidos.</p>
<p>Con lo cual los problemas están casi garantizados.</p>
<p>Tampoco hay que volverse loco ante las diferencias de fechas. Salvo que tengas una situación tan especial como la nuestra, en que necesitamos programar tareas futuras, quizás puedas sobrevivir sin problemas y sin saber nada de todo esto. Pero el conocimiento siempre es útil.</p>
<p>En las tablas de datos es común guardar un registro con la fecha y hora de la última modificación. ¿Debemos convertir esa fecha y hora?</p>
<p>Pues salvo que sean tareas críticas, probablemente no. Las fechas de creación de registro bien se pueden quedar en el horario que tenga el servidor. Sólo aquellas que requieran de ser mostradas en pantalla pueden y deben ser tratadas con mayor consideración. En el caso de sortea2.com, las horas a las que se programan los sorteos. Para ellas no sólo se guardará la fecha y hora, sino también la zona horaria en que se realizaron.</p>
<p>Por lo tanto, por sentido común, no es muy lógico guardarlas en una horario tan poco estándar como el de Madrid. Hay dos opciones principales:</p>
<ul> Guardar la hora y decir &#8220;son las 14:30 con el horario de Buenos Aires&#8221;.<br />
Convertirla al estandar GMT (Hora de Greenwich, Inglaterra) e indicar la zona horaria deseada. &#8220;son las 16:30, zona horaria preferida Buenos Aires&#8221;.</ul>
<p>Esta segunda opción nos parece mejor porque permite en un momento dado comparar fechas de inmediato. Del otro modo casi siempre habrá que hacer una conversión antes de poder continuar.</p>
<p>Como <strong>resumen</strong>: se guardan las horas en estandar GMT, sólo en los casos en que no sean necesarias manipulaciones posteriores.</p>
<p><span class="header"><br />
Zonas horarias y PHP. Las transiciones.</span></p>
<p>Tras planear el desarrollo de la página, sólo queda un problema: cómo convertir entre dos zonas horarias dadas. No sé cómo lo habrán desarrollado en otros lenguajes de programación, pero en PHP el método es realmente <strong>ingenioso y complicado</strong>.</p>
<p>Vaya por delante que en internet hay numerosas clases realizadas por otros que explican cómo realizar estos cambios. Hay incluso clases hechas en PEAR que se supone son totalmente estándar. Tras la nefasta experiencia de usar una de ellas y descubrir que estaba mal (no distinguía los cambios de hora), decidí seguir el camino difícil y propio.</p>
<p>Siempre es más fácil usar algo ya hecho y que funcione. Y uno puede vivir dignamente sin conocer las transiciones de PHP.</p>
<p>Pero si quieres continuar, las transiciones son un array de fechas correspondiente a cada una de las zonas horarias. Es un array monstruoso en que se muestran los días del año en que se produce un cambio de hora para dicha zona horaria. Por ejemplo, para la zona horaria Europe/Madrid dice:</p>
<p>( [0] =&gt; Array ( [ts] =&gt; -1661734800 [time] =&gt; 1917-05-05T23:00:00+0000 [offset] =&gt; 3600 [isdst] =&gt; 1 [abbr] =&gt; WEST )</p>
<p>Que traducido al cristiano es algo así como:</p>
<ul>
<li>A la fecha y hora UNIX (segundos desde el 1 de enero de 1970) (correspondiente a GMT, hora estandar de Greenwich) es la de -1661734800).</li>
<li>Que se corresponde con la fecha y hora &#8220;en inglés&#8221; de 1917-05-05 23:00:00+0000.</li>
<li>Se produjo un cambio de hora que deja a la hora de Madrid respecto de la de GMT en 3600 segundos (una hora más).</li>
<li>Dejando la zona horaria en GMT+1.</li>
<li>Quedando en la zona horaria la WEST.</li>
</ul>
<p>El listado de transiciones de la zona horaria de Madrid nos avisa de cada cambio de hora que se ha producido en la historia, desde el verano de 1917 hasta el año 2037. Si se necesita tratar fechas anteriores o posteriores, aparte de considerar la opción del suicidio, habría que tirar de enciclopedias y realizar un tedioso trabajo manual.</p>
<p>Este extensísimo array <strong>es la pieza fundamental para realizar conversiones entre zonas horarias en PHP.</strong></p>
<p>Veamos por ahora cómo obtener el fichero de transiciones para una zona horaria:</p>
<p>$timezone = &#8220;Europe/Madrid&#8221;;<br />
$timezoneinfo = new DateTimeZone($timezone);<br />
$arraytime = $timezoneinfo-&gt;getTransitions();</p>
<p>En la <strong>primera línea</strong> definimos la zona horaria a tratar, según las zonas horarias que PHP entiende.</p>
<p>En la <strong>segunda</strong> creamos un objeto de tipo zona horaria, relativo a dicha zona inicial.</p>
<p>En la <strong>tercera</strong> obtenemos las transiciones: cuándo se produjeron los cambios de hora respecto de GMT para esa zona horaria.</p>
<p>Es curioso ver el fichero de transiciones. Ahora solemos cambiar de hora los sábados de 2:00 am a 3:00 am, pero en 1917 decidieron hacerlo a las 0:00 horas. Se nota que se trasnochaba menos por aquel entonces. Durante la II Guerra Mundial hubo cambios de hora a las 11:00 de la noche. Luego se volvió a las 12:00 y en los ochenta se pasó a hacerlo a la 1:00 am.</p>
<p>Como podemos ver, y evitemos dispersarnos, los cambios de hora son una verdadera pesadilla en lo que al <strong>horario de verano</strong> se refiere.</p>
<p>Con el array de transiciones ya es más o menos fácil. Si tenemos una fecha en formato GMT, junto con una zona horaria deseada y deseamos convertirla a la hora propiamente dicha, basta con:</p>
<p>Tomamos la hora en GMT y recorremos el array de transiciones, hasta que encontramos una hora superior a la nuestra.<br />
Por ejemplo, si tenemos las 20:00 del 15 de Enero de 2012, y el horario deseado es el de Madrid, vemos que el último cambio de horas se produce el 30 de octubre del 2011. Y que entonces España tendrá una hora más que la hora GMT. Esto sucederá así hasta el 25 de Marzo del 2012, por lo que efectivamente, si queremos convertir esa hora en GMT a hora de Madrid, debemos sumarle una hora (3600 segundos) más.</p>
<p>[110] =&gt; Array ( [ts] =&gt; 1319936400 [time] =&gt; 2011-10-30T01:00:00+0000 [offset] =&gt; 3600 [isdst] =&gt; [abbr] =&gt; CET )<br />
[111] =&gt; Array ( [ts] =&gt; 1332637200 [time] =&gt; 2012-03-25T01:00:00+0000 [offset] =&gt; 7200 [isdst] =&gt; 1 [abbr] =&gt; CEST )</p>
<p>Este proceso es mucho más delicado si la hora está en el mismo borde del cambio de hora. Por ejemplo, si queremos convertir las 01:00 horas del 25 de marzo de 2012, de horario GMT al horario de Madrid.</p>
<p>Para afinar completamente la regla es la siguiente:</p>
<ul>
<li>Partimos de una hora.</li>
<li>Recorremos las transiciones hasta pasarnos de dicha hora.</li>
<li>Miramos el registro anterior. Obtenemos la diferencia de segundos.</li>
<li>Se la sumamos a la hora que teníamos. Si nos hemos pasado de la siguiente transición, tomamos esa siguiente, sino (lo habitual) nos quedamos con la que teníamos.</li>
</ul>
<p>La verdad es que esto se entiende mejor con el código que escrito con palabras:</p>
<div id="codigo">$timezoneinfo = <span class="verde">new</span> <span class="funciones_php">DateTimeZone</span>($timezone);<br />
$arraytime = $timezoneinfo<span class="funciones_php">-&gt;</span>getTransitions();</p>
<p>$i = <span class="punto">-</span><span class="numero">1</span>;</p>
<p><span class="verde">foreach</span> ($arraytime <span class="verde">as</span> $transicion)<br />
{<br />
<span class="indented">$i <span class="punto">++</span>;</span><br />
<span class="indented"><span class="verde">if</span> ($transicion[ts] + $arraytime[$i][offset] &gt;= $gmttime)</span><br />
<span class="indented">{</span><br />
<span class="indented">$indice = $i -<span class="numero">1</span>;</span><br />
<span class="indented"><span class="verde">break</span>;</span><br />
<span class="indented">}</span><br />
}<br />
$newtime = $gmttime <span class="punto">+</span> $arraytime[$indice][offset];</div>
<p>Nos recorremos el array de transiciones. Cuando la transición + las horas de diferencia sean mayores que nuestra fecha de partida, quiere decir que hemos llegado y es el momento de tomar ese valor, sumarlo a la fecha que teníamos y voilá, ya hemos convertido la fecha.</p>
<p><span class="header">Zonas horarias y PHP. Funciones de conversión.</span></p>
<p>Básicamente ya hemos expuesto todo el proceso. Lo único necesario son dos funciones: una que parta de una zona horaria y una hora expresada en dicha zona horaria y la transforme en GMT y otra que partiendo de una hora en GMT y una zona horaria, realice la transformación inversa.</p>
<p>Pueden servir las dos siguientes funciones:</p>
<div id="codigo"><span class="funciones_php">function</span> of_gmttolocaltime ($gmttime, $timezone)<br />
{<br />
$timezoneinfo = <span class="verde">new</span> <span class="funciones_php">DateTimeZone</span>($timezone);<br />
$arraytime = $timezoneinfo<span class="funciones_php">-&gt;</span>getTransitions();</p>
<p>$i = <span class="punto">-</span><span class="numero">1</span>;</p>
<p><span class="verde">foreach</span> ($arraytime <span class="verde">as</span> $transicion)<br />
{<br />
<span class="indented">$i <span class="punto">++</span>;</span><br />
<span class="indented"><span class="verde">if</span> ($transicion[ts] + $arraytime[$i][offset] &gt;= $gmttime)</span><br />
<span class="indented">{</span><br />
<span class="indented"><span class="indented">$indice = $i -<span class="numero">1</span>;</span></span><br />
<span class="indented"><span class="indented"><span class="verde">break</span>;</span></span><br />
<span class="indented">}</span><br />
}<br />
$newtime = $gmttime <span class="punto">+</span> $arraytime[$indice][offset];<br />
<span class="verde">return</span> $newtime;<br />
}</div>
<div id="codigo"><span class="comentario">/**<br />
* Entrada. Una hora en formato UNIX de una zona horaria, y el nombre de la zona horaria.<br />
* Salida. La hora convertida a GMT.<br />
*/</span><br />
<span class="funciones_php">function</span> of_localtimetogmt ($localtime, $timezone)<br />
{<br />
$timezoneinfo = <span class="verde">new</span> DateTimeZone($timezone);<br />
$arraytime = $timezoneinfo-&gt;getTransitions();</p>
<p>$i = -<span class="numero">1</span>;</p>
<p><span class="verde">foreach</span> ($arraytime <span class="verde">as</span> $transicion)<br />
{<br />
<span class="indented">$i <span class="punto">++</span>;</span><br />
<span class="indented"><span class="verde">if</span> ($transicion[ts] &#8211; $arraytime[$i][offset]&gt;= $localtime)</span><br />
<span class="indented">{</span><br />
<span class="indented">$indice = $i -<span class="numero">1</span>;</span><br />
<span class="indented"><span class="verde">break</span>;</span><br />
<span class="indented">}</span><br />
}<br />
$newtime = $localtime &#8211; $arraytime[$indice][offset];<br />
<span class="verde">return</span> $newtime;<br />
}</div>
<p>Las horas siempre se expresan en horario UNIX. ¡Bastante quebradero de cabeza dan las zonas horarias para sufrir aún más con los formatos locales de fecha y hora!</p>
<p>Creo que ha quedado todo bien expresado pero si tienes alguna duda o aclaración déjala en los comentarios. Las correcciones también son bienvenidas.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sortea2.com/blog/2008/11/zonas-horarias-y-php/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
	</channel>
</rss>
