Como paginar dados de forma eficiente com PHP e MySQL

Usando parâmetros nomeados do PDO para implementar paginação de dados no MySQL

02/04/2024

Como paginar dados de forma eficiente com PHP e MySQL

Como paginar dados de forma eficiente com PHP e MySQL

Introdução

A paginação de dados é uma técnica essencial para desenvolvedores web, permitindo exibir grandes quantidades de informações em partes gerenciáveis sem sobrecarregar o usuário ou o sistema. Este artigo explora como implementar a paginação eficiente de dados do MySQL usando PHP, demonstrando através de um código de exemplo prático e detalhado.

Código de Exemplo

Este código PHP utiliza PDO para realizar uma paginação eficiente de dados da tabela products em um banco de dados MySQL. A conexão é estabelecida, e a página atual é determinada a partir da entrada do usuário.

A consulta ao banco de dados é paginada, limitando os resultados a um subconjunto específico por página. Os resultados são exibidos em uma tabela HTML, com links para navegar entre as páginas.

// Parâmetros de Conexão
$host = 'seu_host';
$db   = 'seu_banco_de_dados';
$user = 'seu_usuario';
$pass = 'sua_senha';
$charset = 'utf8mb4';

// Opções do PDO
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

// String de Conexão
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

// Determinação da Página Atual
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 10; // Produtos por página
$offset = ($page - 1) * $perPage;

// Consulta Paginada com Bind Direto no Execute
$stmt = $pdo->prepare('SELECT * FROM products ORDER BY price LIMIT :perPage OFFSET :offset');
$stmt->execute([':perPage' => $perPage, ':offset' => $offset]);
$products = $stmt->fetchAll();

// Descobrindo o Número Total de Produtos para Paginação
$totalStmt = $pdo->query('SELECT COUNT(*) FROM products');
$totalRows = $totalStmt->fetchColumn();
$totalPages = ceil($totalRows / $perPage);

// Exibindo os Produtos em uma Tabela
echo "<table border='1'><tr><th>ID</th><th>Nome</th><th>Preço</th></tr>";
foreach ($products as $product) {
    echo "<tr><td>" . $product['id'] . "</td><td>" . $product['name'] . "</td><td>$" . $product['price'] . "</td></tr>";
}
echo "</table>";

// Links de Paginação
echo "<p style='text-align: center;'>";
if ($page > 1) {
    echo '<a href="?page=' . ($page - 1) . '">Página Anterior</a> ';
}
if ($page < $totalPages) {
    echo '<a href="?page=' . ($page + 1) . '">Próxima Página</a>';
}
echo "</p>";

Explicando o Código

Nesta seção, vamos detalhar cada parte do código de exemplo para entender melhor como funciona a paginação de dados do MySQL usando PDO em PHP. O processo inclui conectar ao banco de dados, calcular a paginação e executar a consulta paginada.

Conexão com o Banco de Dados

Para estabelecer uma conexão segura com o banco de dados MySQL, utilizamos a extensão PDO do PHP. Especificamos os detalhes de conexão, como host, nome do banco de dados, usuário e senha, e definimos algumas opções de PDO para garantir uma execução segura e eficiente das consultas, protegendo contra ataques de injeção SQL.

$host = 'seu_host';
$db   = 'seu_banco_de_dados';
$user = 'seu_usuario';
$pass = 'sua_senha';
$charset = 'utf8mb4';

$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

Determinação da Página Atual e Preparação da Consulta Paginada

Após estabelecer a conexão com o banco de dados, o próximo passo é calcular qual página de dados será exibida. Isso é feito verificando o parâmetro 'page' na URL. Com base nesse valor, calculamos o deslocamento necessário para a consulta SQL. Essa abordagem permite buscar do banco de dados apenas os registros necessários para a página atual, otimizando o desempenho e a experiência do usuário.

$page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 10; // Produtos por página
$offset = ($page - 1) * $perPage;

$stmt = $pdo->prepare('SELECT * FROM products ORDER BY price LIMIT :perPage OFFSET :offset');
$stmt->execute([':perPage' => $perPage, ':offset' => $offset]);
$products = $stmt->fetchAll();

Exibição dos Dados e Geração dos Links de Paginação

Com os dados paginados obtidos da consulta ao banco, o próximo passo é exibi-los em uma tabela HTML. Utilizamos um loop para percorrer o array de produtos retornados e montar a tabela com os campos id, name e price. Após exibir os produtos, calculamos e exibimos os links para as páginas anterior e próxima, se aplicável. Isso é feito com base no número total de registros e no número de registros por página, permitindo a navegação entre diferentes conjuntos de dados paginados.


// Exibindo os Produtos em uma Tabela
echo "<table border='1'><tr><th>ID</th><th>Nome</th><th>Preço</th></tr>";
foreach ($products as $product) {
    echo "<tr><td>" . $product['id'] . "</td><td>" . $product['name'] . "</td><td>$" . $product['price'] . "</td></tr>";
}
echo "</table>";

// Links de Paginação
echo "<p style='text-align: center;'>";
if ($page > 1) {
    echo '<a href="?page=' . ($page - 1) . '">Página Anterior</a> ';
}
if ($page < $totalPages) {
    echo '<a href="?page=' . ($page + 1) . '">Próxima Página</a>';
}
echo "</p>";

Observações Importantes

Índice no Campo price: Para garantir uma paginação eficiente, é crucial que a tabela products tenha um índice no campo price. Isso melhora significativamente a performance das consultas ordenadas por preço, especialmente em tabelas com grande volume de dados. Um índice adequado reduz o tempo de busca e ordenação, agilizando o carregamento das páginas.

Uso de Parâmetros Nomeados: A segurança da sua aplicação é fundamental. O uso de parâmetros nomeados em suas consultas SQL, como demonstrado, é uma prática recomendada para prevenir ataques de injeção de SQL. Diferentemente da concatenação direta de strings, os parâmetros nomeados garantem que os valores inseridos sejam tratados adequadamente pelo PDO, evitando que comandos maliciosos sejam executados no banco de dados.

Verificação do Cache de Consultas: É crucial verificar se o seu servidor de banco de dados MySQL tem o recurso de query cache ativado, pois esta configuração pode acelerar significativamente o acesso a dados e a resposta para consultas repetidas. Para clientes hospedados na MCO2, podem ficar tranquilos: todos os nossos servidores de banco de dados estão otimizados para acesso a dados, com o query cache habilitado por padrão, garantindo máxima eficiência e desempenho.

Conclusão

A eficácia da paginação transcende a simples navegação entre registros, impactando diretamente a experiência do usuário e a performance da aplicação. Adotar as melhores práticas desde o início pavimenta o caminho para desenvolver soluções web ágeis e seguras, preparadas para escalar conforme as demandas crescem.

Este artigo nas redes sociais: Twitter/X, LinkedIn, Telegram, Pinterest, Tumblr, Flipboard, Mastodon

Domínios hospedados
Clientes satisfeitos