Diogo Besson :: tecnologia

Capturando múltiplos registros em formulário para alteração

Capturando múltiplos registros em formulário para alteração

Capturando múltiplos registros em formulário para alteração sem ajax, usando HTML puro, PHP e Mysql. E agora?

Ok… Sem usar Ajax… Qual a melhor forma de fazer isso?

Não estou bem certo se existem outras alternativas, mas sempre usei matrizes para fazer esta tarefa e a situação é bem simples:

Você quer recuperar muitos registros de um banco de dados e postar para alteração entregando os valores novos ao engine de Update.

Você pode optar por fazer uma busca que trás um resultado múltiplo linkado na tela e o envia ao formulário, identificando-o por um código qualquer via GET ou também listar todos os registros encontrados em um formulário e mandá-los diretamente ao engine, que tratará das alterações agrupando-os pelo índice de um array.

Vou tratar aqui desta segunda opção, que creio ser a que o pessoal ainda tem mais dúvidas e acaba mostrando-se uma das mais eficientes.

Primeiramente, conecte ao seu servidor de banco de dados, no meu caso, Mysql; Crie um novo schema; Crie a tabela abaixo:

CREATE TABLE `beer`.`cerveja` (

`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,

`nome` VARCHAR(255) NOT NULL,

`garota` VARCHAR(255) NOT NULL,

PRIMARY KEY (`id`)

)

ENGINE = InnoDB;

Esta tabela é parte de um sistema de cadastro de garotas propaganda para marcas de cerveja, mas o estudo do caso, não vem ao caso agora…

O que importa é que a tabela cerveja do schema beer comporta o campo id, que identifica o registro; inclui o campo nome, que identifica a cerveja; e também o campo garota, que aponta uma garota propaganda para a marca de ceveja registrada.

Vamos agora popular a tabela

INSERT INTO cerveja (nome, garota)

VALUES (‘Kaiser‘, ‘Flávia Kannebley‘),

(‘Brahma Fresh‘, ‘Rosiane Pinheiro‘),

(‘Antarctica‘, ‘Karina Bacchi‘),

(‘Antartica’, ‘Juliana Paes‘),

(‘Tabajara‘, ‘Alessandra Negrini‘),

(‘Tabajara‘, ‘Maria Luiza Mendonça‘);

 

Beleza. Já temos 6 registros pra bagunçar, agora vamos ao PHP:

Existe uma extensão de objeto de database chamada PDO que está disponível a partir do PHP 5. Vamos tentar usá-la aqui pra deixar a brincadeira ainda mais interessante. Quanto à instalação e outros detalhes mais fundos, vou deixar pro meu colega Aderbal Nunes explicar. Ele escreveu um tutorial para iniciantes sobre PHP PDO na Revista PHP no dia 29/05/2007.

http://www.revistaphp.com.br/artigo.php?id=128

Lembrando que você também pode sempre consultar a belíssima documentação do PHP diretamente na web. Documentação do PHP PDO.

http://www.php.net/pdo

Primeiro passo é instanciar um objeto PDO. Para garantir que tudo fique normatizado, usaremos a técnica do “surround with try/catch” para capturar as possíveis exceções de PDO que podem ser lançadas.

No meu caso, que estou usando um servidor local de testes, fica assim:

try{

$pdo = new PDO(“mysql:host=localhost;dbname=beer”, “usuario”, “senha”);

} catch (PDOException $e) {

echo $e->getMessage();

}

O segundo passo é realizar uma busca simples no banco de dados por todos os registros da tabela “cerveja”. Usando o pdo criado acima, ficará assim:

try {

$sql01 = $pdo->prepare(“SELECT id, nome, garota FROM cerveja ;”);

$sql01->execute();

} catch (PDOException $e4) {

echo $e4->getMessage();

}

Agora que a conexão do banco foi feita e a consulta também, vamos listar tudo dentro de um formulário para que os registros possam ser alterados e enviados via POST.

<form action=”” method=”post”>

<table cellspacing=”3″>

<tr style=”font-weight: bold;”>

<td scope=”col”>Id</td>

<td scope=”col”>Nome da Cerveja</td>

<td scope=”col”>Garota Propaganda</td>

</tr>

<?php

while($ponteiro = $sql01->fetch(PDO::FETCH_OBJ)){

?>

<tr>

<td><input id=”id” value=”<?php echo $ponteiro->id; ?>”><?php echo $ponteiro->id; ?></td>

<td> <input type=”text” value=”<?php echo $ponteiro->nome; ?>” size=”50″ maxlength=”254″></td>

<td><input type=”text” value=”<?php echo $ponteiro->garota; ?>” size=”50″ maxlength=”254″></td>

</tr>

<?php

}

?>

<tr><td colspan=”3″><input name=”Salvar” value=”Salvar”></td></tr>

</table>

</form>

Muita atenção às seguintes linhas:

1-) <form action=”” method=”post”>

Action está vazio pois o formulário irá postar todas as variáveis pra dentro dele mesmo.

2-)    while($ponteiro = $sql01->fetch(PDO::FETCH_OBJ))

Enquanto o ponteiro puder mover-se para a próxima linha dentro da consulta sql01 feita acima, armazena o resultado da linha inteira em um objeto instanciado pelo ponteiro em questão. Isso serve para facilitar a recuperação dos resultados mais adiante.

3-) name=”id[]” / name=”nome[]” / name=”garota[]”

Aqui está o grande truque! Os valores postados são armazenados em arrays com índice numérico e enviados “empacotados” para a recuperação. No primeiro caso, por exemplo, você terá id[0] = 1; nome[0] = Kaiser, garota[0]= Flávia Kannebley, ou seja, o registro zero retornado assim estará devidamente identificado sem muitos problemas.

4-) value=”<?php echo $ponteiro->nome; ?>” e etc… diz respeito a isso também. O objeto ponteiro tem um atributo público chamado “nome” que recupera o valor do nome consultado no banco. No caso do registro zero retornado, ele irá ecoar “Kaiser” na tela.

Montado o formulário, é hora da lógica do update.

Primeira coisa que podemos fazer: testar a árvore das variáveis enviadas.

Logo abaixo do primeiro bloco try {} catch {} que armazena nossa PDO, insira o código abaixo:

if($_POST){

echo “<pre>”;

echo htmlspecialchars(var_dump($_POST));

echo “</pre>”;

echo “<hr>”;

}

Esse código verifica se há alguma variável postada. Caso afirmativo, ecoa na tela um VAR_DUMP dessa variável, escapando os caracteres especiais de HTML e estruturando-os com uma tag de preformatting (<pre>).

Se aparecerem os registros bonitinhos no browser é sinal de que está tudo preparado para a lógica. Apague ou /**comente*/ o código acima, pois ele não será mais utilizado.

A lógica estruturada que vamos usar será essa aqui:

// verifica se a ação do formulário enviado é SALVAR

if($_POST[“Salvar”]==”Salvar”) {

// caso afirmativo, prepara um statement sql com variaveis bind

$sql02 = $pdo->prepare(“UPDATE cerveja SET nome = ? , garota = ? WHERE id = ? LIMIT 1;”);

// calcula a soma do numero de registros postados

$numero_de_registros = count($_POST[“id”]);

// tenta iniciar uma transaction com possiveis exceções sendo lançadas

try {

$pdo->beginTransaction();

} catch (PDOException $e1) {

echo $e1->getMessage();

}

// para cada registro postado, define o valor e armazena o mesmo em variáveis locais

for($x=0 ; $x<$numero_de_registros ; $x++) {

$id = $_POST[“id”][$x];

$nome = $_POST[“nome”][$x];

$garota = $_POST[“garota”][$x];

// tenta rechear as variaveis bind com os respectivos valores recuperados do formulario

// atente ao fato da necessidade de especificar a tipagem de cada valor, coisa normalmente estranha ao php

// PARAM_STR é String

// PARAM_INT é Integer

try {

$sql02->bindValue(1, $nome, PDO::PARAM_STR);

$sql02->bindValue(2, $garota, PDO::PARAM_STR);

$sql02->bindValue(3, $id, PDO::PARAM_INT);

$sql02->execute();

// o execute() executa acima o statement MAS NÃO FAZ COMMIT

// caso haja algum problema, ecoa a exceção

} catch (PDOException $e2) {

echo $e2->getMessage();

}

}

// tenta fazer o Commit! Agora sim…

try {

$pdo->commit();

} catch(PDOException $e3) {

// caso a base esteja travada para alteração, espera e tenta de novo, como vc pode ler abaixo:

if(stripos($e3->getMessage(), ‘DATABASE IS LOCKED’) !== false) {

usleep(250000); //espera 0.25 segundos e tenta de novo

$pdo->commit();

} else {

// caso contrário, desfaz as alterações (rollback) e lança uma exceção

$pdo->rollBack();

throw $e3;

}

}

}

No teste, consegui conectar com o banco e fazer quaisquer alterações perfeitamente, tendo o formulário sempre atualizado com os novos valores salvos. Conferindo o Mysql Administrator você também pode ver que o banco é atualizado através desse formulário. E tudo isso em apenas uma página.

Palmas para o empacotamento em array[] e também para o PDO que funciona de forma bacana integrando a programação estruturada com a orientação a objetos.

Se você quiser, por boa prática, pode usar um $pdo = null para fechar a conexão, mas é desnecessário, visto que nesse caso específico ela é encerrada automaticamente no término da execução do script. Você também pode usar conexões persistentes, mas isso já é uma OUTRA história…

Um abraço ao visitante.

Diogo Besson

PS: Caso queira baixar o codigo fonte desse negócio, clique aqui.

6 Comments

  1. Edison

    Olá amigo

    vc me ajudou um monte.

    Agora, não querendo ser chato, será que poderia complementar o código com a reordenação dos registros?

    Deixe eu explicar:

    Temos:
    1 – Kaiser – Flávia Kannebley;
    2 – Brahma Fresh – Rosiane Pinheiro;
    3 – Antarctica – Karina Bacchi;
    4 – Antartica – Juliana Paes;
    5 – Tabajara – Alessandra Negrini;
    6 – Tabajara – Maria Luiza Mendonça;

    Eu gostaria de mudar a ordem das garotas, alterando um ou refazendo toda a ordem dos registros:

    assim (digamos que adicione o campo ‘ordem’):

    1 – Kaiser – Flávia Kannebley – 3;
    2 – Brahma Fresh – Rosiane Pinheiro – 5;
    3 – Antarctica – Karina Bacchi – 8;
    4 – Antartica – Juliana Paes – 9;
    5 – Tabajara – Alessandra Negrini – 17;
    6 – Tabajara – Maria Luiza Mendonça – 22;

    como está, está em ordem crescente pelo campo ordem
    mas, se eu clicar num botão reordenar, ele fizesse a alteração automática a partir de 1, e no caso iria até 6,
    e, se por exemplo quisesse que a Alessandra Negrini ficasse na segunda posição e a Juliana Paes logo após ela, alteraria os números para 2 para a Alessandra Negrini, e 3 para a Juliana Paes. Aí o sistema entenderia que o restante ficaria na mesma ordem, alocando as garotas selecionadas na posição que eu escolhi.
    Outra situação seria, por exemplo se eu quisesse colocar em ordem inversa a partir da segunda: escreveria nos campos sequencialmente: 1, 6, 5, 4, 3 e 2.

    Aí mais uma coisa: e se colocasse flechas para cima e para baixo nos registros, de forma que pudesse classificar individualmente cada uma
    para cima ou para baixo…

    Um exemplo claro do que eu preciso, é o Backend do Joomla, onde eu classifico o conteudo de acordo com a colocação que fiz acima

  2. diogobesson

    Bom… Pelo que eu entendi, você está querendo fazer uma coisa que não tem a ver com a captura dos múltiplos registros e também está querendo fazer uma coisa que não tem a ver com a alteração em massa, certo?

    Tem mais a ver com a ordenação dos registros. A ordenação dos dados.

    Pelo exemplo: id[0] = 1; nome[0] = Kaiser, garota[0]= Flávia Kannebley, ordem[0] = 3, certo?

    E se você conseguisse colocar o valor de ordem[] como índice desse array obtido?

    Ficaria assim:
    id[3] = 1; nome[3] = Kaiser; garota[3] = Flávia Kannebley
    id[5] = 2; nome[5] = Brahma Fresh; garota[5] = Rosiane Pinheiro

    Ou melhor ainda

    novaOrdem[3] = array(id => “1”, nome => “Kaiser”, garota => “Flávia Kannebley”);
    novaOrdem[5] = array(id => “2”, nome => “Brahma Fresh”, garota => “Rosiane Pinheiro”);

    qualquer coisa diferente disso fica um pouco mais complicada, por aí você terá que fornecer seu próprio comparador de ordenação. No Java isso é comum, mas no PHP são poucos os que se atrevem a fazer isso com frequência.

    Eu sugiro uma consulta à função uksort() de ordenação de arrays. Vai te dar uma luz maior.

    o link é:
    http://br.php.net/manual/pt_BR/function.uksort.php

    um abraço,

    Diogo Besson
    .

  3. diogobesson

    Ah! já ia me esquecendo!!!

    A partir do PHP4, temos multisort

    veja a função array_multisort() aqui: http://br.php.net/manual/pt_BR/function.array-multisort.php

    abraço!

  4. Pingback: Top 5 « Diogo Besson :: web tecno log

  5. Pingback: PHP - extensão mysql está obsoleta - Diogo Besson :: Web Tecno Log

  6. Pingback: PHP - extensão mysql está obsoleta :: Diogo Besson Web

Leave a Comment

O seu endereço de e-mail não será publicado.