1. Enorable
  2. Lenguajes De Programación
  3. Php Y Msqli
10
 
07/10/2021 |  vistas:

Paginar datos con Php y Mysqli

Imagen de portadaPhp y Mysqli: En un ejemplo básico vamos a descubrir cómo paginar con Php y Mysqli los datos almacenados en una tabla de nuestra base de datos Mysql.

En esta oportunidad voy a mostrar una alternativa para lograr una paginación de datos haciendo uso una de las tecnologías libres más usadas por los programadores desde hace muchos años ya. Me refiero al lenguaje de programación de Php en conjunto con el motor de base de datos de Mysql y la extensión de Mysqli.

Lo que buscamos con la paginación o segmentación de datos es simplificar la vista de los registros que se le muestran a los usuarios en una página web. Esto nos permite reducir el tiempo de respuesta de nuestro servidor al limitar la cantidad de datos que se quieren consultar, incluso con la implementación de un buen índice de datos. También nos ayuda a evitar una lectura completa de los datos de la tabla.

Puede visualizar una demostración del código para paginar los datos con Php y Mysqli. Al mismo tiempo, les voy a dejar un enlace para contribuciones a todos los que pudieron sacar algún provecho de este trabajo.

Para comprender el código es necesario tomar en cuenta lo siguiente:

  1. Se requieren conocimientos básicos de HTML, Php y Mysql.
  2. Poseer los datos de conexión a la base de datos Mysql donde se va a trabajar.
  3. El usuario de la base de datos debe tener privilegios para crear la tabla "Empleados".

Para este ejemplo vamos a trabajar con una tabla de "Empleados" (`employee_data`), la cual tiene una estructura compuesta de cinco (5) campos: `empd_id`, `empd_names`, `empd_date_of_birth`, `empd_address` y `empd_phone`.
// Estructura de la tabla de "Empleados" (`employee_data`)

CREATE TABLE `employee_data` (
`empd_id` int(11) NOT NULL,
`empd_names` varchar(60) NOT NULL,
`empd_date_of_birth` date NOT NULL,
`empd_address` varchar(100) NOT NULL,
`empd_phone` varchar(15) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
// Establecer la clave principal de la tabla

ALTER TABLE `employee_data`
ADD PRIMARY KEY (`empd_id`);

// Establecer el campo `empd_id` como "auto_increment"

ALTER TABLE `employee_data`
MODIFY `empd_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
// Alimentar la tabla de "Empleados" (`employee_data`) con algunos datos

INSERT INTO `employee_data` (`empd_id`, `empd_names`, `empd_date_of_birth`, `empd_address`, `empd_phone`) VALUES
(1, 'Mark Fields', '1990-07-16', 'Kendall, Florida, EEUU', '5559990123'),
(2, 'Bertha Lopez', '1974-12-03', 'Miami, Florida, EEUU', '+1-5551991-0000'),
(3, 'Gonzales Victor Raul', '1982-09-21', 'Santiago, Chile', '9101920000'),
(4, 'Aura Roos', '1988-11-07', 'Lima, Perú', '999-5555-1234'),
(5, 'Frederick Anthony Erick ', '1971-12-12', 'Toronto, Canada', '999-555-0101'),
(6, 'Fields Mark II', '1992-07-11', 'Boston, EEUU', '+100099988'),
(7, 'Lopez Bertha Ms.', '1985-09-12', 'Orlando, Florida, EEUU', '+1-5551991-0000'),
(8, 'JD Pedroia', '1979-11-02', 'México, Ciudad De México', '9981919191'),
(9, 'Alex Rios', '1988-11-07', 'Bogotá, Colombia', '999-5555-1234'),
(10, 'Victoria Rivas', '1976-01-01', 'Barcelona, España', '555-9980001');
COMMIT;

Ahora que ya tenemos creada nuestra tabla con datos de ejemplos, vamos a programar nuestro pequeño sistema con algunas líneas código que nos permita acceder a la información de los "Empleados".

En particular, para acceder a Mysql desde Php trabajo mejor con la clase Mysqli (que se puede activar como extensión). Por ello he creado una pequeña clase extendida de mysqli para consultar los datos. Veamos de qué se trata.
<?php
/**
* Clase PHP para conexión a la base de datos Mysql
* @resume Clase connDB extendida de la clase mysqli
* @construct $host, $username, $pwd, $db
* @methods sql_query, closeDB
*/

class connDB extends mysqli {

/**
* @construct '__construct'
* El constructor de nuestra clase requiere cuatro parámetros para la conexión a la base de datos
* Estos parámetros son "host", "usuario", "contraseña", "instancia (base datos)"
*/

public function __construct( $host, $username, $pwd, $db ) {
parent::__construct( $host, $username, $pwd, $db );

// Validar que la extensión 'mysqli' esté activa en Php

if ( !function_exists( 'mysqli_init' ) && !extension_loaded( 'mysqli' ) ) {
die( 'Error: No encontramos la extensión `Mysqli`.' );
}

// Comprobar la conexión

if ( $this->connect_errno ) trigger_error( 'Error de Conexión ('.$this->connect_errno.')', E_USER_ERROR );

// Configurar la codificación de los datos a UTF-8 (opcional)

$this->query( "SET NAMES 'utf8'" ); // Puede comentar esta línea si lo desea
}

/**
* @method 'sql_query'
* @param '$sql' este parámetro admite una cadena de datos con la sentencia o consulta sql
* @return retorna un objeto 'mysqli_result' o false si la consulta falló
*/

public function sql_query( $sql ) {
if( !isset( $sql ) OR empty( $sql ) ) return;
if( $query = $this->query( $sql ) ) return $query;
}

/**
* @method 'closeDB'
* @resume cierra la conexión de la base de datos
*/

public function closeDB () {
$this->close();
}

}
?>

¡Muy bien! Ahora que vamos a trabajar a partir de nuestra clase 'connDB' para la demostración, quiero que prueben su funcionamiento consultando todos los registros de la tabla que hemos creado de la siguiente manera:

<?php
// Sentencia o consulta Sql

$sql = "SELECT ed.empd_id AS id,
ed.empd_names AS names,
ed.empd_date_of_birth AS dob,
ed.empd_address AS addr,
ed.empd_phone AS phone
FROM employee_data ed
ORDER BY 1";

// Establecer la conexión con la base de datos

$connDB = new connDB( "localhost", "usuario", "contraseña", "instancia" );

// Ejecutar la consulta

$query = $connDB->sql_query( $sql );

// Leer los datos si '$query' retorna un objeto 'mysqli_result'

if( $query ) {
while( $rq = $query->fetch_array() ) {
echo $rq['id'].";".$rq['names'].";".$rq['dob'].";".$rq['addr'].";".$rq['phone'];
echo "<br />";
}
}
$connDB->closeDB();
?>
// Datos que se deben imprimir

1 1990-07-16 Kendall, Florida, EEUU 5559990123
2 1974-12-03 Miami, Florida, EEUU +1-5551991-0000
3 1982-09-21 Santiago, Chile 9101920000
4 1988-11-07 Lima, Perú 999-5555-1234
5 1971-12-12 Toronto, Canada 999-555-0101
6 1992-07-11 Boston, EEUU +100099988
7 1985-09-12 Orlando, Florida, EEUU +1-5551991-0000
8 1979-11-02 México, Ciudad De México 9981919191
9 1988-11-07 Bogotá, Colombia 999-5555-1234
10 1976-01-01 Barcelona, España 555-9980001

Ya que sabemos que nuestra clase funciona correctamente entonces procedemos a pintar o diseñar con un poco de estilo (CSS) la vista de los datos en nuestra página.

<?php
// Diseñando nuestra página con los datos a consultar

$page = !isset( $_REQUEST['p'] ) ? 1 : $_REQUEST['p'];
$pageGroup = 4;

echo "<br>";
echo "Muestra de la paginación de datos con Php y Mysqli";
echo "<br>";
echo "Está navegando en la página: ".$page."<br /><br />";

$sql = "SELECT ed.empd_id AS id,
ed.empd_names AS names,
ed.empd_date_of_birth AS dob,
ed.empd_address AS addr,
ed.empd_phone AS phone
FROM employee_data ed
ORDER BY 1
LIMIT ".limit( 10, $page, $pageGroup ); // El total de registros de la tabla es 10

$connDB = new connDB( "localhost", "usuario", "contraseña", "instancia" );

$query = $connDB->sql_query( $sql );
$data = '';

if( $query ) {
$data .= '<div style="display:grid;grid-template-columns:10% 30% 10% 30% 20%;width:100%;height:200px;padding:1px;border:1px solid #000;box-sizing: border-box;">';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#eeeffe;word-break:break-word;font-weight:bold;">ID</div>';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#eeeffe;word-break:break-word;font-weight:bold;">NAMES</div>';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#eeeffe;word-break:break-word;font-weight:bold;">DATE OF BIRTH</div>';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#eeeffe;word-break:break-word;font-weight:bold;">ADDRESS</div>';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#eeeffe;word-break:break-word;font-weight:bold;">PHONE</div>';
while( $rq = $query->fetch_array() ) {
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#FBF8F8;word-break:break-word;">' .$rq['id'] .'</div>';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#FBF8F8;word-break:break-word;">' .$rq['names'].'</div>';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#FBF8F8;word-break:break-word;">' .$rq['dob'] .'</div>';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#FBF8F8;word-break:break-word;">' .$rq['addr'] .'</div>';
$data .= '<div style="display:inline-block;margin:1px;padding:5px;background:#FBF8F8;word-break:break-word;">' .$rq['phone'].'</div>';
}
$data .= '</div>';
$data .= '<div style="display:grid;grid-template-columns:25% 25% 25% 25%;width:100%;margin:20px 0;padding:5px;border:1px solid #000;box-sizing:border-box;">';
$data .= '<div></div>';
$data .= '<div style="display:block;margin:auto;">'.prevQuery( 10, $page, $pageGroup ).'</div>';
$data .= '<div style="display:block;margin:auto;">'.nextQuery( 10, $page, $pageGroup ).'</div>';
$data .= '<div></div>';
$data .= '</div>';
$query->close();
echo $data;
}
$connDB->closeDB();
?>

Al revisar el código de arriba he resaltado en negrita algunas líneas que son de especial importancia para el resultado final de nuestro recurso; aún requerimos de las funciones de usuario: 'limit()', 'prevQuery()' y 'nextQuery()', así como poder recuperar el parámetro del número de la página que se debe pasar por la url y es contenido en la variable $page, mientras que definimos el número de registros por página en la variable $pageGroup. Estas nos permiten establecer la paginación o segmentación de la información que tenemos almacenada en la tabla de "Empleados".

<?php
/**
* @funcion limit
* @resume función de usuario que permite establecer un 'LIMIT' en la consulta SQL
* @params $total, $pageNum, $pageGroup
* @return '$limit'
*/

function limit( $total, $pageNum, $pageGroup = 10 ) {
$page = 1;
$p = ( is_numeric( $pageNum ) )
? $pageNum
: $page;
if ( isset( $p ) && ( $p > 0 && $p <= ceil( $total / $pageGroup ) ) ) {
$p = $p;
} else { $p = $page; }
$y = $pageGroup;
$x = ( $p - $page ) * $y;
$limit = $x.",".$y;
return $limit;
}

/**
* @funcion nextQuery
* @resume función de usuario que permite navegar al próximo grupo de datos
* @params $total, $page, $pageGroup, $param1, $param2, $label
* @return '$return' un enlace de hipertexto
*/

function nextQuery( $total, $page, $pageGroup = 10, $param1 = 'ctrl&p=', $param2 = 'ctrl&p=', $label = 'Siguiente' ) {
$np = '';
if ( isset( $page ) && !empty( $page ) && is_numeric( $page ) ) {
$p = $page;
} else { $p = 1; }
$uri = self_request_uri();
if( ( $p + 1 ) <= ceil( $total / $pageGroup ) ) {
$np = $p + 1;
}
$return = '<a style="display:block;width:100%;padding:10px;background-color:#fff;outline:none;text-decoration:none;color:#666;">Fin</a>';
if( preg_match( '/(\?'.$param1.'[^0-9]+)|(\?'.$param1.'[0-9]+)/i', $uri, $coin ) ) {
$link = preg_replace( '/(\?'.$param1.'[^0-9]+)|(\?'.$param1.'[0-9]+)/i', '', $uri ).'?'.$param2.$np;
} else {
$link = '?'.$param2.$np;
}
if( is_numeric( $np ) && isset( $link ) && !empty( $link ) ) {
$return = '<a style="display:block;width:100%;padding:10px;background-color:#eee;outline:none;text-decoration:none;color:#0000ff;" href="'.$link.'">'.$label.'</a>';
}
return $return;
}

/**
* @funcion prevQuery
* @resume función de usuario que permite navegar al anterior grupo de datos
* @params $total, $page, $pageGroup, $param1, $param2, $label
* @return '$return' un enlace de hipertexto
*/

function prevQuery( $total, $page, $pageGroup = 10, $param1 = 'ctrl&p=', $param2 = 'ctrl&p=', $label = 'Anterior' ) {
$np = '';
if ( isset( $page ) && !empty( $page ) && is_numeric( $page ) ) {
$p = $page;
} else { $p = 1; }
$uri = self_request_uri();
if( $p != 1 && $p <= ceil( $total / $pageGroup ) ) {
$np = $p - 1;
}
$return = '<a style="display:block;width:100%;padding:10px;background-color:#fff;outline:none;text-decoration:none;color:#666;">Inicio</a>';
if( preg_match( '/(\?'.$param1.'[^0-9]+)|(\?'.$param1.'[0-9]+)/i', $uri, $coin ) ) {
$link = preg_replace( '/(\?'.$param1.'[^0-9]+)|(\?'.$param1.'[0-9]+)/i', '', $uri ).'?'.$param2.$np;
}
if( is_numeric( $np ) && isset( $link ) && !empty( $link ) ) {
$return = '<a style="display:block;width:100%;padding:10px;background-color:#eee;outline:none;text-decoration:none;color:#0000ff;" href="'.$link.'">'.$label.'</a>';
}
return $return;
}
?>

Como ya lo expliqué en las líneas de código anterior, las funciones 'limit()', 'prevQuery()' y 'nextQuery()' permiten la paginación de los datos. Esto se cumple gracias a que 'limit()' imprime algo como "1,4" o "2,4" o "3,4" y así sucesivamente dependiendo del número de la página a consultar, pero luego nosotros lo concatenamos a la consulta SQL de la siguiente manera: "LIMIT ".limit( 10, $page, $pageGroup );.

Por otro lado, las funciones 'prevQuery()' y 'nextQuery()' nos permite avanzar en la navegación del grupo de datos que se verá en cada página mediante un "enlace de texto" ("Anterior" y "Siguiente").

Ahora bien, hay una utilidad adicional que he creado para manejar correctamente los enlaces de texto de "Anterior" y "Siguiente". Dicha utilidad está representada por dos funciones 'current_uri()' y 'self_request_uri()'. Veamos el código de estas dos funciones.

<?php
/**
* Funciones de utilidad *
*/

function current_uri() {
if ( !empty( $_SERVER['HTTPS'] ) && ( 'on' == $_SERVER['HTTPS'] ) ){
$uri = 'https://';
} else {
$uri = 'http://';
}
return $uri .= ( $_SERVER['SERVER_NAME'] != 'examples.com' )
? '127.0.0.1'
: $_SERVER['SERVER_NAME'];
}

function self_request_uri() {
return current_uri().$_SERVER['REQUEST_URI'];
}
?>

¡Y eso es todo! Espero que este artículo le sea de ayuda para aquellos programadores que están empezando a trabajando con Php y Mysqli o incluso con lenguajes de programación diferentes, ya que se puede adaptar la idea de las funciones para la paginación a su lenguaje preferido y mejorarlo.

Por último les dejo nuevamente una demo del código para que puedan evidenciar la idea.
Consulta Lo+ Top de Lenguajes De Programación