<?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>Temas Innecesarios &#187; css</title>
	<atom:link href="http://jcesar.artelogico.com/tag/css/feed/" rel="self" type="application/rss+xml" />
	<link>http://jcesar.artelogico.com</link>
	<description>Estará listo en seis meses así tengamos que trabajar en el por un año.</description>
	<lastBuildDate>Thu, 02 Sep 2010 03:03:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Paginación estilo Digg con MySQL y PHP</title>
		<link>http://jcesar.artelogico.com/2009/05/paginacion-estilo-digg-con-mysql-y-php/</link>
		<comments>http://jcesar.artelogico.com/2009/05/paginacion-estilo-digg-con-mysql-y-php/#comments</comments>
		<pubDate>Fri, 22 May 2009 23:45:44 +0000</pubDate>
		<dc:creator>jcarrascal</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://jcesar.artelogico.com/?p=35</guid>
		<description><![CDATA[Cuando se tiene una buena cantidad de resultados es conveniente presentarlos al usuario página por página para facilitar la navegación. Esto es algo que se pregunta a menudo en los foros de PHP &#8220;Tengo una petición que me regresa muchos registros. ¿Cómo separo los resultados en varias páginas?&#8221;. En este tutorial voy a mostrar un [...]]]></description>
			<content:encoded><![CDATA[<p>Cuando se tiene una buena cantidad de resultados es conveniente presentarlos al usuario página por página para facilitar la navegación. Esto es algo que se pregunta a menudo en los foros de PHP <em>&#8220;Tengo una petición que me regresa muchos registros. ¿Cómo separo los resultados en varias páginas?&#8221;</em>.</p>
<p>En este tutorial voy a mostrar un método para dividir los resultados en varias páginas y al final le daremos un estilo similar a Digg. Lo que queremos obtener es un listado de 12 películas por página y en la parte inferior enlaces a páginas similar al que usa <a href="http://digg.com">Digg</a>, que se ven así:</p>
<p><a href="http://jcesar.artelogico.com/wp-content/uploads/2009/05/digg.png" rel="shadowbox[post-35];player=img;"><img src="http://jcesar.artelogico.com/wp-content/uploads/2009/05/digg.png" alt="digg" title="digg" width="520" height="100" class="aligncenter size-full wp-image-37" /></a></p>
<p>Para efectos de demostración voy a utilizar la <a href="http://downloads.mysql.com/docs/sakila-db.zip">base de datos Sakila</a> que es una base de datos de ejemplo desarrollada para MySQL. Específicamente queremos mostrar la información de las películas almacenadas en la tabla film.</p>
<p>A continuación voy a discutir este <a href='http://jcesar.artelogico.com/wp-content/uploads/2009/05/indexphp.txt'>script de ejemplo de paginación estilo Digg con MySQL y PHP</a>. Para probarlo en su equipo deberá tener instalado Sakila. Guárdelo en una carpeta de su servidor web y cambie los datos de la conexión a la base de datos que se encuentran al comienzo:</p>
<pre class="prettyprint">
$hostname    = 'localhost';
$username    = 'root';
$password    = '123456';
$database    = 'sakila';
</pre>
<h4>Las consultas</h4>
<p>Primero necesitamos hacer una consulta para obtener el número de registros en la tabla y lo almacenamos en una variable <code>$filmsCount</code>:</p>
<pre class="prettyprint">
select count(*) filmsCount
	from film
</pre>
<p>Ahora calculamos el número máximo de páginas que podemos mostrar. Para esto utilizamos el número de registros que acabamos de obtener y lo dividimos entre el número de registros por página. Aquí estoy usando la función ceil(), que redondea el numero hacia arriba, porque también tenemos que contar la última página que puede quedar con menos registros que las demás.</p>
<pre class="prettyprint">
$pagesCount = (int)ceil($filmsCount / $rowCount);
</pre>
<p>Ahora averiguamos en qué página estamos. En el URL va a venir un parámetro <code>pageIndex </code>con el índice de la página. Si no está presente suponemos que estamos en la primer página y si sobrepasa la última página suponemos que estamos en la página actual.</p>
<pre class="prettyprint">
$pageIndex = isset($_REQUEST['pageIndex']) ? (int)$_REQUEST['pageIndex'] : 0;
if ($pageIndex >= $pagesCount)
	$pageIndex = $pagesCount - 1;
</pre>
<p>Estamos listos para obtener los registros de la página. El <code>SELECT</code> de MySQL tiene unos parámetros justo para esto. Se pasan con la cláusula <code>LIMIT</code> de esta forma</p>
<pre class="prettyprint">
$offset = $pageIndex * $rowCount;
$sql = "
select *
	from film
	order by title
	limit $offset, $rowCount
";
</pre>
<p><code>$rowCount</code> es el número de registros por página y puede ser el número que usted quiera. En el ejemplo estoy usando 12. Los registros los almaceno como objetos en un arreglo <code>$films</code> y luego recorro el arreglo para mostrar cada registro.</p>
<h4>Los enlaces de las páginas</h4>
<p>Ahora la parte más delicada: Mostrar el listado de páginas con el estilo de Digg. Vamos a crear una lista <code>&lt;UL&gt;</code> donde cada elemento va a ser un enlace a la página correspondiente.</p>
<p>El enlace a la página anterior es el más sencillo. Simplemente, si estamos en una página mayor a la primera mostramos el enlace:</p>
<pre class="prettyprint">
&lt;ul id="pages"&gt;
&lt;?php
// Página anterior.
if ($pageIndex &gt; 0) {
?&gt;
	&lt;li class="page"&gt;&lt;a href="?pageIndex=&lt;?php echo $pageIndex - 1 ?&gt;"&gt;&amp;lquo;&lt;/a&gt;&lt;/li&gt;
&lt;?php } ?&gt;
</pre>
<p>Ahora mostraríamos la página actual rodeada de N páginas adelante y atrás. El número de páginas a mostrar lo guardo en la variable <code>$pagesToShow</code>. Entonces calculamos las páginas que se van a mostrar así:</p>
<pre class="prettyprint">
$start = $pageIndex - $pagesToShow;
if ($start &lt; 0)
	$start = 0;

$end = $pageIndex + $pagesToShow;
if ($end &gt;= $pagesCount)
	$end = $pagesCount - 1;
</pre>
<p><code>$start</code> y <code>$end</code> los usaremos luego en un ciclo; sin embargo, hay que tener en cuenta la primera y segunda página. En Digg siempre se muestran los enlaces de la primera y segunda página. No importa si uno está en la página 500, siempre se muestran. Entonces los mostramos teniendo en cuenta que no se pueden repetir después:</p>
<pre class="prettyprint">
if ($start &gt; 0) {
	for ($i = 0; $i &lt; 2 &amp;&amp; $i &lt; $start; ++$i) {
?&gt;
	&lt;li class="page"&gt;&lt;a href="?pageIndex=&lt;?php echo $i ?&gt;"&gt;&lt;?php echo $i + 1 ?&gt;&lt;/a&gt;&lt;/li&gt;
&lt;?php
	}
}
</pre>
<p>Ahora si podemos mostrar las páginas con toda tranquilidad. Lo único que tenemos que tener en cuenta es que a la página actual no le ponemos enlace:</p>
<pre class="prettyprint">
for ($i = $start; $i &lt;= $end; ++$i) {
	if ($pageIndex == $i) {
?&gt;
	&lt;li class="page current"&gt;&lt;?php echo $i + 1 ?&gt;&lt;/li&gt;
&lt;?php
	} else {
?&gt;
	&lt;li class="page"&gt;&lt;a href="?pageIndex=&lt;?php echo $i ?&gt;"&gt;&lt;?php echo $i + 1 ?&gt;&lt;/a&gt;&lt;/li&gt;
&lt;?php
	}
}
</pre>
<p>Ya vamos terminando&#8230; De forma similar a la primera y segunda página, la penúltima y última siempre se muestran. Pero tenemos que evitar repetirlas así que usamos la función <code>max()</code> para evitarlo:</p>
<pre class="prettyprint">
if ($end &lt; $pagesCount - 1) {
	for ($i = max($pagesCount - 2, $end + 1); $i &lt; $pagesCount; ++$i) {
?&gt;
	&lt;li class="page"&gt;&lt;a href="?pageIndex=&lt;?php echo $i ?&gt;"&gt;&lt;?php echo $i + 1 ?&gt;&lt;/a&gt;&lt;/li&gt;
&lt;?php
	}
}
</pre>
<p>Y para finalizar mostramos el enlace a la página siguiente que es bastante sencillo y cerramos el <code>&lt;UL&gt;</code>:</p>
<pre class="prettyprint">
&lt;?php
// Siguiente página
if ($pageIndex &lt; $pagesCount) {
?&gt;
	&lt;li class="page"&gt;&lt;a href="?pageIndex=&lt;?php echo $pageIndex + 1 ?&gt;"&gt;&amp;gt;&lt;/a&gt;&lt;/li&gt;
&lt;?php } ?&gt;
&lt;/ul&gt;
</pre>
<p>Ahora necesitamos algo de CSS para que se parezca al de Digg. Lo que tenemos que hacer cambiar la lista de dirección vertical a horizontal con un <code>display: inline;</code> para los elementos, agregar los bordes, unos paddings y estamos listos. Este es el código CSS que yo utilicé en el ejemplo:</p>
<pre class="prettyprint">
#pages {
	clear: both;
	text-align: center;
}
#pages li {
	display: inline;
	padding: 3px 6px 4px;
}
#pages li.page {
	border: 1px solid #CCC;
}
#pages li.current {
	background-color: #CCC;
}
</pre>
<p>El resultado final es una página como la de la captura de pantalla en la que podemos ver 12 películas por páginas y usar los enlaces de la parte inferior para navegar por las páginas.</p>
<p><a href="http://jcesar.artelogico.com/wp-content/uploads/2009/05/paginacion-estilo-digg.png" rel="shadowbox[post-35];player=img;"><img src="http://jcesar.artelogico.com/wp-content/uploads/2009/05/paginacion-estilo-digg-300x246.png" alt="paginacion-estilo-digg" title="paginacion-estilo-digg" width="300" height="246" class="aligncenter size-medium wp-image-46" /></a></p>
<p>En una aplicación más grande, la lógica necesaria para mostrar los enlaces de las páginas debería encapsularse en una clase para evitar errores cuando se desee reutilizar en otro listado y el HTML podría guardarse en una plantilla separada. Este ejercicio se lo dejo quienes lean este blog&#8230; si, cualquiera de ustedes tres.</p>
<p><strong>ACTUALIZACIÓN 2009/05/29:</strong> Como correctamente apunta <a href="http://jalcom.blogspot.com/">Jairo</a>, a los enlaces de la paginación hay que agregarle cualquier parámetro que modifique los resultados del <code>SELECT</code>. Por ejemplo, si hay que filtrar los films por el precio deberíamos pasarlo al final del URL así:</p>
<pre class="prettyprint">
&lt;?php
// Siguiente página
if ($pageIndex &lt; $pagesCount) {
?&gt;
	&lt;li class="page"&gt;&lt;a href="?pageIndex=&lt;?php echo $pageIndex + 1,
		'&amp;price=', $price ?&gt;"&gt;&amp;gt;&lt;/a&gt;&lt;/li&gt;
&lt;?php } ?&gt;
&lt;/ul&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jcesar.artelogico.com/2009/05/paginacion-estilo-digg-con-mysql-y-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
