DB-2-MDB2

Tradução de http://www.phpied.com/db-2-mdb2/

Introdução

Recentemente eu tive de migrar um projeto do PEAR:DB para o PEAR::MDB2 - a nova abstração de banco de dados. Eu fiz algumas anotações sobre as partes de código que eu precisei mudar, e espero que eles possam ser úteis para alguém que esteja fazendo o mesmo. Muito obrigado ao Lukas Smith, o desenvolvedor líder que sempre respondeu muito rápido aos meus relatórios e questionamentos na lista do PEAR.

Uma coisa a ser notada no MDB2 é que ele tenta não fazer qualquer trabalho desnecessário e faz muitas coisas sob demanda. Por exemplo, quando você cria um objeto, isso não significa que uma conexão tenha sido feita. Ela é feita somente quando você faz o primeiro acesso real a um banco de dados, como por exemplo, um SELECT.

Eu assumo que você já tem uma base do PEAR::DB, desde que esse texto ilustra uma comparação entre o DB e o MDB2 , mas mesmo que você não o conheça, espero que esse texto seja uma introdução interessante ao DB e ao MDB2.

Incluindo as bibliotecas

Primeiramente, incluindo as bibliotecas (Eu assumo que você já tem o PEAR na sua máquina).

<?
require_once 'DB.php';
require_once 'MDB2.php'
?>

Uma coisa a ser notada é que a instalação do MDB2 não inclui os drivers MDB2 de banco de dados. Assim, se você vai usar o MySQL, por exemplo, você precisa instalar o wrapper separadamente: pear install MDB2_Driver_mysql em adição a pear install MDB2

DSN

A seguir, a string de conexão. É a mesma para o MDB2 e para o DB.

<?php
$dsn = 'mysql://root@localhost/db2mdb2';
?>

A propósito, tando o MDB2 e o DB aceitam um array com todos os detalhes da conexão.

Criando instâncias

<?php
$db =& DB::connect($dsn);
$mdb2 =& MDB2::factory($dsn)
?>

O MDB2 dispõe também de um método de fábrica para criar uma instância. Nesse momento, a conexão com o banco ainda não é feita. O MDB2 também dispõe de um método singleton() para criar uma instância.

Fetchmode

É o mesmo em ambos, apenas observe o prefixo da constante.

<?
// set fetchmode
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$mdb2->setFetchMode(MDB2_FETCHMODE_ASSOC);
?>

SELECTS simples

Esses são métodos para selecionar uma linha, uma coluna, uma célula e uma porção de registros.o DB usa o prefixo get, e o MDB2 usa query.

<?php
// seleciona alguns rrgistros e os traz em um array
$all = $db->getAll('SELECT * FROM people');
$all = $mdb2->queryAll('SELECT * FROM people');

// seleciona uma célula
$one = $db->getOne('SELECT name FROM people WHERE id = 1');
$one = $mdb2->queryOne('SELECT name FROM people WHERE id = 1');

// uma linha
$row = $db->getRow('SELECT * FROM people WHERE id = 1');
$row = $mdb2->queryRow('SELECT * FROM people WHERE id = 1');

// uma coluna
$col = $db->getCol('SELECT name FROM people');
$col = $mdb2->queryCol('SELECT name FROM people')
?>

Adicionado aspas a valores

No DB, o método sugerido para adicionar aspas é o quoteSmart(). NoMDB2 é o quote() e ele aceita um segundo parâmetro que diz qual o tipo do valor a receber as aspas. Se o segundo parâmetro é omitido, o , MDB2 irá tentar adivinhar o tipo.

$one = $mdb2->queryOne(
         'SELECT name FROM people WHERE id = '
         . $db->quote(1, 'integer')
       )
?>

Tabelas de Sequência

Se você usa tabelas de sequência, ambas as bibliotecas dipões de um método nextId():

<?php
echo $db->nextId('people_db');
echo $mdb2->nextId('people_mdb2');
?>

A única diferença é que quando o DB cria uma tabela sequência(com um campo e um valor), o nome do campo é id, onde o MDB2 irá usar sequence. Se você está movendo um projeto existente para o MDB2 como eu, e já tam as tabelas sequência criadas pelo DB, você tem a opção de renomear essa campo no banco de dados para todas as tabelas sequência, ou você or you can set an MDB2 option and you're good to go.

<?php
$mdb2->setOption('seqcol_name','id');
?>

Auto execute

Digamos que você tenha os dados:

<?php
$data = array('id' => 5, 'name' => 'Cameron');
?>

Para auto-inserir, usando o DB , você faria:

<?php
$db->autoExecute('people', $data, DB_AUTOQUERY_INSERT);
?>

Para o MDB2, a auto execução é provavelmente considerada uma característica usada frequentemente, então não faz parte da instãncia base. Você precisa carregar um módulo adicionar para ter acesso a isso:

<?php
$mdb2->loadModule('Extended');
?>

Agora você pode:

<?php
$mdb2->autoExecute('people', $data, MDB2_AUTOQUERY_INSERT);
?>

O exemplo acima vai funcionar em PHP5 somente. Em PHP4, devido ao suporte limitado a sobrecarga de objetos (Obrigado de novo Lukas por esclarecer isso!), você precisaria fazer:

<?php
$mdb2->extended->autoExecute('people', $data, MDB2_AUTOQUERY_INSERT);
?>

Perceba que a segunda forma irá funcionar em PHP5 também.

Prepared statements

No DB:

<?php
$statement = $db->prepare('INSERT INTO people VALUES (?, ?)');
$data = array(6, 'Chris');
$db->execute($statement, $data);
$db->freePrepared($statement);
?>

No MDB é quase da mesma forma, o que muda é que o statement se torna um objeto e você pode chamar seus métodos para executar e liberar a memória (no lugar dos métodos do MDB2)

<?php
$statement = $mdb2->prepare('INSERT INTO people VALUES (?, ?)');
$data = array(7, 'Dave');
$statement->execute($data);
$statement->free();
?>

Execute multiple

O mesmo se aplica para a execução de uma declaração com diversas linhas de dados em um array. O executeMultiple() está no módulo estendido do MDB2 module, então você irá precisar carregá-lo:

DB:

<?php

$statement = $db->prepare('INSERT INTO people VALUES (?, ?)');
$data = array(
    array(8, 'James'),
    array(9, 'Cliff')
);

$db->executeMultiple($statement, $data);
$db->freePrepared($statement);
?>

MDB2:

<?php
$statement = $mdb2->prepare('INSERT INTO people VALUES (?, ?)');
$data = array(
    array(10, 'Kirk'),
    array(11, 'Lars')
);

$mdb2->loadModule('Extended');
$mdb2->extended->executeMultiple($statement, $data);

$statement->free();
?>

Transações

No DB:

<?php
$db->autoCommit();
$result = $db->query('DELETE people'); // will cause an error

if (PEAR::isError($result)) {
    $db->rollback();     //echo 'rollback';
} else {
    $db->commit();     //echo 'commit';

}
?>

No MDB2 você precisa verificar se transações são suportadas no seu banco de dados. Então, durante a transação. você pode sempre verificar: "Eu estou numa transação?"

<?php
if ($mdb2->supports('transactions')) {
    $mdb2->beginTransaction();

}
$result = $mdb2->query('DELETE people');
if (PEAR::isError($result)) {
    if ($mdb2->in_transaction) {
        $mdb2->rollback();         // echo 'rollback';
    }
} else {
    if ($mdb2->in_transaction) {
        $mdb2->commit();         // echo 'commit';
    }
}
?>

Script exemplo

Você pode baixar um script que tem os exemplos acima e testá-los. Segue também o arquivo sql para recriar o banco de dados:

PHP 4 - A Bíblia PHP-GTK: Criando Aplicações Gráficas com PHP PHP 5: Conceitos, Programação e Integração com Banco de Dados PHP-Nuke: Integração, Administração e Desenvolvimento PHP 5: Guia de Consulta Rápida PHP para Quem Conhece PHP PHP e MySQL: Guia Introdutório PHP com Ajax na WEB 2.0 PHP 5: Programação Poderosa PHP Para Profissionais