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
- Como criar um Sistema de Login com Níveis de Permissão
- Contador de visitas usando o MySQL
- Criando um sistema de login com PHP e MySQL
Postado em Artigos, Destaques, MySQL, PHP, Tutoriais
Com as tags Artigo, Ataque, Banco de Dados, Código, Conexão, Consultas, DIE, Documentação, MySQL, MySQLi, Orientação a Objetos, Parâmetros, PHP, PHP 5, POO, Programação, Scripts, Segurança, Senha, Servidor, Sistema, 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:

Lembrando que funções como bind_param são obsoletas e serão removidas.
Agora é mysqli_stmt_bind_param
André.
E aí Thiago,
Cara, me tira uma dúvida. A extensão antiga retorna um vetor em consultas, isso não é melhor do que criar outras variáveis pra imprimir esses valores? Tem como fazer isso no Mysqli? Não é mais usual, ou eu tô falando besteira?
abraço
Thiago, seria redundante usar o mysql_real_scape_string em conjunto com o mysqli? ou tornaria mais seguro?
e se for redundante, eu perderia alguma coisa se optar por usar mysql_query em conjunto com mysql_real_scape _string (eu acho mais fácil de escrever o código) ou tem mais alguma vantagem que eu estaria perdendo além da proteção contra o SQL Injection?
Obrigado desde já.
@Hugo
Acredito que você não coneguiria usar os dois juntos pois o mysql_real_scape_string() usa a conexão aberta com o mysql_connect(), o que você não terá se usar MySQLi (que abre uma outra conexão).
O MySQLi é mais rápido e mais seguro que o MySQL normal e procedural… Além da segurança existem outros recursos que você pode fazer uso no MySQLi como os stored procedures onde você tem um “padrão” de consulta e você muda apenas as variáveis… É como se, na versão procedural, você fizesse uma função para realizar a consulta X mas recebendo como parâmetros algumas variáveis que serão usadas dentro da consulta.
Até a própria documentação do PHP recomenda que você use o MySQLi se você tiver a opção de usá-lo (leia-se: se ele existir no seu servidor).
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!