Fala minha gente!
Hoje vou mostrar para vocês como usar a extensão MySQLi (MySQL Improved ou MySQL Melhorado) do MySQL.
Já falei um pouco sobre o MySQLi nesse post, mas foi sobre o método procedural, e hoje vamos falar sobre o método orientado a objetos.
Antes de mais nada: o MySQLi só está presente na versão 4.1.3+ do MySQL e na versão 5 do PHP, se você tem um servidor que não tenha alguma dessas versões, se mate.
E vejam que coisa interessante está escrita na Overview do MySQLi:
Note: If you are using MySQL versions 4.1.3 or later it is strongly recommended that you use this extension.
Que em tradução livre seria:
Nota: Se você está usando a versão 4.1.3 ou superior do MySQL é altamente recomendável que você use essa extensão.
Começando do começo: O velho modo
Acredito que todos vocês já viram uma conexão e consulta MySQL feita da seguinte forma:
<?php
// Conecta ao banco de dados
mysql_connect('127.0.0.1', 'usuario', 'senha');
mysql_select_db('meusite');
// "Hoje" em formato SQL
$data = date('Y-m-d');
// Monta e executa uma consulta SQL
$sql = "SELECT `id`, `titulo`, `link` FROM `noticias` WHERE `ativa` = 1 AND `data` <= '". $data ."'";
$query = mysql_query($sql);
// Para cada resultado encontrado...
while ($noticia = mysql_fetch_assoc($query)) {
// Exibe um link com a notícia
echo '<a href="'. $noticia['link'] .'" title="'. $noticia['titulo'] .'">'. $noticia['titulo'] .'</a>';
echo '<br />';
} // fim while
// Total de notícias
echo '<br />Total de notícias: ' . mysql_num_rows($query);
?>
Não há nada de especial com esse código… Conectamos ao MySQL e depois procuramos todas as notícias ativas e anteriores ao dia de hoje (inclusive)… O código por si só não é feito nem “mal organizado”, mas isso é por que vocês ainda não conhecem o MySQLi!
Orientação a Objetos: a beleza programação
Agora veja o código que faz a mesma coisa que o anterior, só que em sua versão MySQLi orientada a objetos:
<?php
// Conecta ao banco de dados
$mysqli = new mysqli('127.0.0.1', 'usuario', 'senha', 'meusite');
// Verifica se ocorreu algum erro
if (mysqli_connect_errno()) {
die('Não foi possível conectar-se ao banco de dados: ' . mysqli_connect_error());
exit();
}
// "Hoje" em formato SQL
$data = date('Y-m-d');
// Prepara uma consulta SQL
if ($sql = $mysqli->prepare("SELECT `id`, `titulo`, `link` FROM `noticias` WHERE `ativa` = 1 AND `data` <= ?")) {
// Atribui valores às variáveis da consulta
$sql->bind_param('s', $data); // Coloca o valor de $data no lugar da primeira interrogação (?)
// Executa a consulta
$sql->execute();
// Atribui o resultado encontrado a variáveis
$sql->bind_result($id, $titulo, $link);
// Para cada resultado encontrado...
while ($sql->fetch()) {
// Exibe um link com a notícia
echo '<a href="'. $link .'" title="'. $titulo .'">'. $titulo .'</a>';
echo '<br />';
} // fim while
// Total de notícias
echo '<br />Total de notícias: ' . $sql->num_rows;
// Fecha a consulta
$sql->close();
}
// Fecha a conexão com o banco de dados
$mysqli->close();
?>
De primeiro contato sei que muita gente vai achar que o MySQLi é mais complicado, é só ver o número de linhas: quase o dobro.. Mas o MySQLi tem uma vantagem indescutível em cima do MySQL normal: a segurança.
Primeiro nós PREPARAMOS uma consulta com um local para receber um valor variável… É aquela interrogação.
Depois nós dizemos que o local reservado receberá um conteúdo do tipo string (s) com valor $data.. Ou seja, se $data fosse um inteiro ou booleando a consulta daria um erro, ela só aceitará strings, e digo mais: strings que não modifiquem a consulta… se for uma SQL Injection o MySQLi irá escapá-la e ele [o ataque] não funcionará!
Depois é só executar, reservar variáveis para o resultado e usá-las com um fetch() normal..
Vejam um exemplo de consulta com três parâmetros: duas strings e um inteiro:
<?php
// "Hoje" em formato SQL
$data = date('Y-m-d');
// Nome do autor
$autor = 'Thiago Belem';
// Prepara uma consulta SQL
if ($sql = $mysqli->prepare("SELECT `id`, `titulo`, `link` FROM `noticias` WHERE (`data` <= ?) AND (`ativa` = ?) AND (`autor` = ?)")) {
// Atribui valores às variáveis da consulta
$sql->bind_param('sis', $data, 1, $autor);
// Executa a consulta
$sql->execute();
// ... Todo o resto é igual
}
?>
Nessa consulta nós reservamos espaços para três variáveis… Depois nós passamos os seus tipos e valores usando o método bind_param(), o primeiro parâmetro traz os tipos dos valores, no exemplo foi usado “sis” que significa: uma string, um integer (inteiro) e uma string… Depois nós passamos os valores normalmente..
Os tipos de valores aceitos pelo MySQLi são:
- i para integer (inteiro)
- s para string
- d para double (decimal)
- b para blob
Quem quiser saber um pouco mais sobre MySQLi, é só checar a documentação no php.net, e não se esqueça de deixar o seu comentário agradecendo (ou reclamando o.O)!
Espero que tenham gostado!
Você também vai gostar de ler:
- Guia prático de MySQLi no PHP
- Orientação a Objetos – Material Básico
- Contador de visitas usando o MySQL
- Usando Namespaces no PHP
- Como criar um Sistema de Login com Níveis de Permissão
Postado em Artigos, Destaques, MySQL, PHP, Tutoriais
Com as tags Artigo, Ataque, Banco de Dados, Código, Conexão, DIE, Documentação, MySQL, MySQLi, Orientação a Objetos, Parâmetros, PHP, PHP 5, POO, Programação, Scripts, Segurança, Senha, Servidor, SQL, SQL Injection, Strings, Tutorial, Variáveis
Escrito por Thiago Belem
Gostou desse artigo?
Não se esqueça de assinar o RSS e divulgue-o para o mundo:

Thiago blz?
Cara, eu usava essa classe do fabyo
http://forum.imasters.uol.com.br/index.php?/topic/125343-classe-de-conexao-com-mysqli/
Gostei muito da sua, será que teria como adptar?? Tipo da um prepare e um execute ?
[s]
Opa, realmente uma excelente dica!
Como sugestão, você poderia fazer um artigo sobre as Stored Procedures.
Abraço ai pro pessoal de Pará… huahuahauha ^^
Parabéns pelo post. Já tinha lido o anterior e não tinha percebido muito bem as vantagens. Agora sim foi possivel notar como é útil esta extensão. Vlw
tenho umas dúvidas….
você usa um if na hora de preparar a query, então se houver algum erro na preparação, como uma sintaxe errada, a preparação retorna zero e o resto não seria executado?
se ainda seria possível acontecer SQL injection mesmo usando o MySQLi, como funcionaria isso já que você disse que ele bloqueia? como evitar?
uhh…tive um problema recentemente quando coloquei um nome de um campo de uma tabela minha como ‘group’. o problema se resolveu quando eu simplesmente mudei o nome do campo. seria esse um nome proibido ou coisa assim?
acho que é só :p
haha, abusei nas perguntas. mas se puder me ajudar com essas dúvidas eu fico meeega grato (:
@Hugo Leonardo
Exatamente
Com o prepare e os parâmetros (?) na query, quando você passa o parametro para a consulta você diz de que tipo ele é (string, integer e etc.) e o MySQLi cuida de escapar o parâmetro para evitar injection.
GROUP é uma palavra reservada do MySQL, assim como outras palavras como SELECT, UPDATE, DELETE, WHERE, FROM, ORDER e etc… Você pode ver uma lista das palavras reservadas aqui: http://dev.mysql.com/doc/refman/5.1/en/reserved-words.html
Parabéns Thiago. Você poderia me dizer se existe alguma vantagem do mysqli sobre o PDO ?
@Plinio
O MySQLi é só para MySQL já o PDO funciona com SQL Server, Firebird/Interbase, MySQL, Oracle, ODBC, DB2, PostgreSQL e SQLite… Eu pessoalmente prefiro o MySQLi.. Mas isso vai de cada um.
Sempre me perguntei a diferença entre o MySql e o MySqli, mas nunca tinha ido atras saber. Teu artigo esclareceu as idéias. Valeu.
eu prefiro continuar usando o PDO do PHP
Show!
A primeira vez que li pensei que fosse mysql(li) de light.
Agora que vi que é mysql(i) de Improved.
Muito bom o artigo.
Parabéns!
parabéns
Confesso que não entendi muito bem. Especialmente na parte de atribuir a variável.
1º – Por que fazer desse modo? Pq não montar a query diretamente?
Ex: Pq não colocar diretamente a variável $hoje no lugar do 1º ‘?’ ?
$mysqli->prepare("SELECT `id`, `titulo`, `link` FROM `noticias` WHERE (`data` <= ?) AND (`ativa` = ?) AND (`autor` = ?)")2º – O que significa o ’sis’ do código abaixo?
Ex:
$sql->bind_param('sis', $hoje, 1, $autor);@Fillipe
1º – A “graça” do MySQLi está justamente nos prepared statements que é esse formato onde você prepara a query antes e passa os parâmetros depois.
2º – Leia o artigo com mais atenção que explico o por que do “sis”.
Thiago “de Belém”, foi ótimo. auhuahuahaua.
E então você recomenda msm o MySQLi ? Msm usando o ainda tem algum risco de SQL Injection?
Muito legal essa dica Thiago, valew!
@Leandro
Sim, eu recomendo… E sim, ainda há risco de SQL Injection, por isso você deve fazer as coisas com atenção e responsabilidade… Não é uma funcionalidade ou extensão que vai deixar o seu sistema seguro.
Cara enfiei o pé fundo no ADOdb que faz estas 44 linhas em 5 e achei o máximo. Eu acredito que em termos de segurança, satisfaça os requisitos mas fico sempre me perguntando se seria adequado ou se terá suporte no futuro e tal. Na php 5.3 o odbc é nativo certo? será que é uma boa opção tb para o MySQL?
Abrax
@Villas
Eu particularmente prefiro o MySQLi do que o ADOdb.. Isso vai de cada um.
É muito bom rever algumas funcionalidades
Acredito que tenha ocorrido um erro de declaração de variáveis, veja:
$sql->bind_param('sis', $hoje, 1, $autor);No início você fez a seguinte declaração: $data = date(‘Y-m-d’);
Logo o correto seria assim, não?
$sql->bind_param('s', $data);Abraços!
@Leonardo
Muito obrigado pelo toque.. Já fiz a correção.. Isso que dá fazer o tutorial e não rodar antes de publicar.
Sigo seu blog e aprendo muita coisa. Parabéns!
Olá Thiago.. Parabéns pelo post
Morei um tempo em Belém.. agora vejo que tem gente boa nesses lados dai..
Abs
@Carlos
Eu sou Thiago Belem, não Thiago de Belém ou Thiago Belém..
Não nasci, não moro e nunca fui em Belém… Sou carioca xD
Fora o while estar errado no primeiro código, está muito bom o teu texto!
Realmente é um pouco complicado no começo, mais acho que depois de usar umas 3 x já fica sussa
O problema é usar a primeira hdsauihdusai
Linha 15: whlie
[]’s
@Renan
Já fiz a correção… Obrigado pela participação!