segunda-feira, 29 de julho de 2013

Classes em PHP - Melhorando o construtor na Classe Application - ASP Application

É preciso acertar o escopo de variáveis na Classe Application.

Ao contrário do que nossa lógica pensa, o PHP já afirma todas as variáveis das funções como locais. Se o desenvolvedor quiser aproveitar uma variável pública (declarada fora do escopo de qualquer função) ele deve se referir a ela, no início da função desejada, com a diretiva global.

Introduzimos também o método getIp para trazer o IP da requisição.


  class Application {
    public $Noip = '';
    public $rs = '';
    function __construct(){
      global $Noip, $rs;
      $Noip = $_SERVER['REMOTE_ADDR'];
      echo $Noip . "-";
      $rs = "/var/www/chatonline/" . $Noip . ".txt";
      echo $rs . "-";
      }
    public function getIp(  ){
      global $Noip;
      return $Noip;
      }
    public function getVar( $varName ){
      global $rs;
      $conteudo = file_get_contents($rs);
      $arr = unserialize($conteudo);
      return $arr[$varName];
      }
    public function setVar( $varName, $valVar ){
      global $rs;
      $conteudo = file_get_contents($rs);
      $arr = unserialize($conteudo);
      if( file_exists($rs) ){
unlink($rs);
}
      }
    }


sexta-feira, 26 de julho de 2013

Classes em PHP - Introduzindo o construtor na Classe Application

No post anterior apresentamos uma classe em PHP para fazer o papel do objeto Application do ASP.

Agora vamos reproduzí-la aqui com o construtor instanciando a variável que contém o número do IP da máquina cliente:

  class Application {
    public $Noip = '';
    function __construct(){
      $Noip = $_SERVER['REMOTE_ADDR'];
      }
    public function getVar( $varName ){
      $rs = "/var/www/chatonline/" . $Noip . ".txt";
      $conteudo = file_get_contents($rs);
      $arr = unserialize($conteudo);
      return $arr[$varName];
      }
    public function setVar( $varName, $valVar ){
      $rs = "/var/www/chatonline/" . $Noip . ".txt";
      $conteudo = file_get_contents($rs);
      $arr = unserialize($conteudo);
      if( file_exists($rs) ){
unlink($rs);
}
      $arr[$varName] = $valVar;
      $conteudo = serialize($arr);
      file_put_contents($rs, $conteudo);
      return;
      }
    }

Desta forma, o local de obtenção do número IP fica sendo um só, e a classe ganha um construtor.

Objeto Application ASP em PHP - Classe Application

Os desenvolvedores ASP devem morrer de raiva ao migrar para o PHP, no momento em que precisam utilizar um objeto do tipo Application.

Não tem problema algum, e a resolução é muito simples com uma classe muito simples. Aconselhamos a leitura do post anterior sobre "Persistência de Dados em PHP".

A classe

A classe em PHP tem dois métodos, sem muitas preocupações com as regras ortodoxas de instanciação:

  class Application {
    public function getVar( $varName ){
      $Noip = $_SERVER['REMOTE_ADDR'];
      $rs = "/var/www/chatonline/" . $Noip . ".txt";
      $conteudo = file_get_contents($rs);
      $arr = unserialize($conteudo);
      return $arr[$varName];
      }
    public function setVar( $varName, $valVar ){
      $Noip = $_SERVER['REMOTE_ADDR'];
      $rs = "/var/www/chatonline/" . $Noip . ".txt";
      $conteudo = file_get_contents($rs);
      $arr = unserialize($conteudo);
      if( file_exists($rs) ){
unlink($rs);
}
      $arr[$varName] = $valVar;
      $conteudo = serialize($arr);
      file_put_contents($rs, $conteudo);
      return;
      }
    }

Optamos por utilizar o Número IP do cliente como referencia. No entanto, para maior precisão, para um sistema bem concebido, a referência (nome do arquivo) deverá ser o login do usuário. Portanto, o desenvolvedor deverá ter a preocupação de integrar o seu sistema a um módulo de autenticação já existente, ou desenvolver um módulo para este fim.

Ambos os métodos lêem o número de IP da variável de servidor no índice "REMOTE_ADDR". Este número é concatenado à extensão "txt", compondo o nome do arquivo a ser gravado, e que fará o papel de "cookie" de servidor.

Função setVar

Vamos analisar esta função primeiro, pois ela é que produz a sequência de caracteres com o formato que vamos utilizar.

É lido um arquivo que, de forma objetiva, contém um arranjo gravado, com elementos cujo índice é aquilo que corresponde ao nome da variável Application que queremos armazenar. No post anterior sobre "Persistência de Dados em PHP" explicamos a manipulação do arranjo, sua serialização e desserialização.

Através do conhecido comando file_get_contents() trazemos o $conteudo do jeito como foi gravado por operações anteriores que possam ter acontecido. No entanto, este conteúdo está sob a forma de sequência serializada de caracteres, também explicada no post de Persistência de Dados em PHP. É preciso abrir este formato novamente na forma de arranjo tradicional. Tal operação é feita pelo comando unserialize().

Devido à manipulação de permissões, ao ser criado o arquivo no servidor, posteriormente não existe a possibilidade de leitura. Por isto, logo após a coleta do arranjo, o arquivo de apoio é apagado. O item que corresponde ao elemento do arranjo que armazena a variável de Aplicação é alterado por uma operação de arranjo. Todo o arranjo é novamente serializado, e o comando file_put_contents() é executado, finalizando a operação.

Função getVar

É uma função mais simples que putVar, pois apenas extrai o elemento do arranjo necessário, sem precisar apagar o arquivo com toda a sequência de valores, e sem necessidade de substituir o valor anterior.

Uso da Classe

Esta classe deverá ser incluída na script PHP que for utilizá-la através da instrução PHP include:

Depois é só utilizar seus métodos.

Exemplo 1

Leitura de um elemento, cujo índice é "Fnd":

  include "ClassApp.php";
  $app = new Application();
  echo $app->getVar("Fnd");

Exemplo2

Alteração de um elemento, cujo índice é "Fco", e leitura para conferência:

  include "ClassApp.php";
  $app = new Application();
  echo $app->setVar("Fco", "Franciscópolis Urbanus");
  echo $app->getVar("Fco");

Problemas de acento serão resolvidos com o correto uso das tags META.



Persistência de Dados em PHP - Gravação de arquivo em servidor

A linguagem de script ASP fornece a facilidade de persistência de variáveis em uma Sessão de usuário e em toda a aplicação.

O PHP possui a parte de sessão, mas não a de aplicação. Existem alternativas como o módulo Memcache ou Memcached e classes desenvolvidas pela comunidade. Mas como as aplicações são muito diversificadas, e nem sempre você possui um profissional de suporte disposto a instalar complementos, verificar as dependências e realmente configurar o ambiente PHP da forma correta, escrevemos este artigo para que você tenha uma opção de escolha.

Gravação em arquivo

O PHP oferece funções semelhantes às da linguagem C++ para gravação de arquivos sequenciais. No entanto, existem alternativas de mais alto nível como:

file_put_contents - Grava uma sequência de caracteres em arquivo NO SERVIDOR Web;
file_get_contents - Lê uma sequência de caracteres de um arquivo NO SERVIDOR Web;

As sintaxes serão mostradas nos trechos de código abaixo.

Arrays e Serialização

As sequências de caracteres devem ter uma determinada estrutura, para que mais informação possa ser gravada em uma sequência, e para que o tempo de acesso ao disco compense. Não é eficiente guardar uma variável por arquivo no servidor. Vamos optar por gravar um arranjo inteiro, ou um objeto.

Para simular estrutura dentro de uma sequência de caracteres, optamos pela serialização e desserialização de arranjos. Estas operações são feitas pelas funções:

serialize - Serializa, ou seja, cria a estrutura de pares de conteúdos na base chave-conteúdo em uma sequência;
unserialize - Abre a estrutura de pares de conteúdos na base chave-conteúdo;

As sintaxes serão mostradas nos trechos de código abaixo.

Gerando o arranjo indexado

Arranjos indexados por números tem pouca serventia. O ideal é gerar o índice por algum mnemônico, sigla, ou sequência que vai ser muito usada para consulta:

$arr = array();
$arr["Fco"] = "Francisco da Silva";
$arr["Sam"] = "Samuel de Souza";
$arr["Fnd"] = "Fernando Alves de Souza";

A forma de armazenamento na memória é complexa, mas o serialize compõe uma sequência para gravação que é satisfatória:

$conteudo = serialize($arr);

Ao imprimirmos o $conteudo, ele apresenta a seguinte saída:

a:3{s:3:"Fco";s:18:"Francisco da Silva";s:3:"Sam";s:18:"Samuel de Souza";s:3:"Fnd";s:23:"Fernando Alves de Souza"}

O prefixo a:3 informa que o arranjo possui 3 itens.

Cada string é precedida de uma letra "s" (indicando string ou sequência de caracteres alfanuméricos) seguida de ":" (dois pontos), seguida de um número que indica quantos caracteres a string possui. Ao final de cada informação desta, segue-se um ";" (ponto e vírgula). É como uma tabela de campos em banco de dados.

s:3:"Fco" - Tipo string, tamanho 3, conteúdo "Fco"
s:18:"Francisco da Silva" - Tipo string, tamanho 18, conteúdo "Francisco da Silva"

Gravação em arquivo no servidor Web

$rs = "/var/www/chatonline/result.txt";
file_put_contents($rs,$conteudo);

Uma das simplificações interessantes deste comando é que o descritor do arquivo é o próprio path e nome do arquivo a ser gravado, sem as instanciações cansativas de objetos, transformações de descritores e outras futilidades das linguagens a objeto.

Leitura de um elemento

Um outro programa PHP pode fazer a leitura de um dos elementos deste arranjo gravado, da seguinte forma:

$rs = "/var/www/chatonline/result.txt";
$conteudo = file_get_contents($rs);
$arr = unserialize($conteudo);
echo $arr["Sam"];

o resultado apresentado na tela do browser é:

Samuel de Souza

Em um próximo post, vamos criar uma classe para armazenamento de variáveis de uma aplicação de um cliente pelo seu número IP, ou pelo login, conforme o tipo de escopo. Para intranets, o IP basta. Mas para aplicações de Internet, o melhor é utilizar o login único por pessoa.








quarta-feira, 24 de julho de 2013

Stored Procedures em Mysql via PhpMyAdmin

Problema proposto

Temos um sistema bem simples, com apenas duas tabelas e um relacionamento via chave estrangeira, conforme o diagrama:


Layout desejado

O proprietário do sistema deseja o seguinte layout de saída:


Para um município fornecido pelo parâmetro nomemun, serão apresentados somente os vídeos mais recentes (maior data) para cada categoria.

Quando não for dado nenhum município (nomemun vazio), serão apresentados os últimos vídeos por categoria, independente do município.

Relacionamento

Para um relacionamento normal, através da chave estrangeira, faríamos simplesmente:

SELECT v.Id, v.Categoria, v.Titulo, v.Idyoutube, v.Idmun, m.Municipio FROM video AS v, municipio AS m WHERE ( v.Idmun = m.Id )

Neste caso aparecem todos os videos mas sem o agrupamento por Categoria. Vamos resolver o problema utilizando a cláusula GROUP BY:

SELECT v.Id, v.Categoria, v.Titulo, v.Idyoutube, v.Idmun, m.Municipio FROM video AS v, municipio AS m WHERE ( v.Idmun = m.Id ) GROUP BY v.Categoria

Restringindo a apresentação ao último vídeo

Quando lemos "último vídeo", em termos lógicos estamos querendo dizer que o vídeo apresentado corresponde à maior data. Este campo é o útil Dtcad (data de cadastramento do video), portanto a sentença fica da seguinte forma:

SELECT v.Id, v.Categoria, v.Titulo, v.Idyoutube, v.Idmun, m.Municipio FROM video AS v, municipio AS m WHERE ( v.Idmun = m.Id AND v.Dtcad = ( SELECT MAX(DtCad) FROM video AS w WHERE w.Categoria = v.Categoria ) ) GROUP BY v.Categoria

A expressão:

v.Dtcad = ( SELECT MAX(DtCad) FROM video AS WHERE w.Categoria = v.Categoria )

faz com que seja selecionado o registro de video cuja data de cadastramento seja a maior para cada Categoria.

A Stored Procedure no PhpMyAdmin

No PhpMyAdmin, entramos nas Rotinas (Routines em inglês) do banco de dados:


A tela seguinte é:

Por um sério erro de tradução, o link recebeu o texto "Adicionar Indice", mas realmente o certo é "Adicionar Rotina", que fornece a tela a seguir, quando clicado:


A tela acima já mostra tanto o parâmetro de entrada que nós convencionamos (nomemun), do tipo varchar, comprimento 30, quanto o código da Stored Procedure, que pelo espaço insuficiente na janela, reproduzimos abaixo:

if nomemun = '' then
SELECT v.Id, v.Categoria, v.Titulo, v.Idyoutube, v.Idmun, m.Municipio FROM video AS v, municipio AS m WHERE ( v.Idmun = m.Id AND v.Dtcad = ( SELECT MAX(DtCad) FROM video AS WHERE w.Categoria = v.Categoria ) ) GROUP BY v.Categoria
else
SELECT v.Id, v.Categoria, v.Titulo, v.Idyoutube, v.Idmun, m.Municipio FROM video AS v, municipio AS m WHERE ( v.Idmun = m.Id AND m.Municipio = nomemun AND v.Dtcad = ( SELECT MAX(DtCad) FROM video AS WHERE w.Categoria = v.Categoria ) ) GROUP BY v.Categoria
end if
























quarta-feira, 17 de julho de 2013

Script padrão para bancos de dados Mysql em linguagem PHP - XII

A ação Edit

Todos os registros da tabela do banco de dados podem ser alterados. Difícil é trazê-los transformando cada campo para exibição em uma forma editável, invertendo para gravação em certos casos (data e senha). E, posteriormente, é necessária uma nova transformação para gravação.

Código:

 case "edit":
   // Verifica permissão para a operação
   if( $permiteEdit ){
     $operation = $operEdit;
     $description = $descEdit;
     require("libCabecalhoPadrao.php");
     include 'Conexao_banco.php';
     // Obtém um registro
     $result = mysqli_query($conn, "select * from " . $tabela . " WHERE Id = " . $_GET['Id'] );
     if( $row = mysqli_fetch_array($result) ){
     ?>
     <h2 class=tit>EDITAR</h2>
     <h5 class=help>Altere os conteúdos. Os campos de senha precisam da checagem caso sejam 
alterados.</h5>
     <?php
openQuadro();
echo "<form method=post action=?action=editsave&Id=" . $_GET['Id'] . "&estilo=" . 

$_GET['estilo'] . ">";
echo "<table border=0 cellspacing=0>";
// Loop no esquema da estrutura de dados
for($x=0;$x<$NoCampos;$x++){
 $tipo = strtolower($arr[$x][4]);
 $sTipo = "";
 $inp = "<input";
 echo "<tr>";
 echo "<td><label>" . $arr[$x][1] . "</label></td>";
 echo "<td>";
 $valor = $row[$arr[$x][0]];
 // Ajuste do tipo, valor, delimitador e tag do campo
 $pl = new paramLineOut($arr,$x,$valor);
 $inp = $pl->taginput;
 $valor = $pl->valorfinal;
 $sTipo = $pl->tipocampo;
 $deli = $pl->delimitador;
 echo $inp;
 echo " name=" . $arr[$x][0] . " id=" . $arr[$x][0];
 if ( strtolower($inp) == "<select" ) {
     echo ">";
     echo "<option value=" . $row[$arr[$x][0]] . ">" . $row[$arr[$x][0]];
     echo $arr[$x][6];
   } elseif ( strtolower($inp) == "<textarea" ) {
     echo " cols=" . $arr[$x][2] . " rows=" . number_format($arr[$x][3]/$arr[$x][2],0,'.','') 

. ">";
   } elseif ( strtolower($inp) == "<input" ){
     echo " type=" . $sTipo . " size=" . $arr[$x][2] ." maxlength=" . $arr[$x][3] . " value=" 

. $valor . ">";
   }
 if ( $sTipo == "password" ){
   echo "Alterada <input type=checkbox name=ck" . $arr[$x][0] . " id=ck" . $arr[$x][0] . ">";
   }
 if ( $inp == "<textarea" ) {
   echo $row[$arr[$x][0]] . "</textarea>";
   }
 if ( $inp == "<select" ) {
   echo "</select>";
   }
 echo "</td><td>";
 echo "<span class=msg>" . $arr[$x][7] . "</span>";
 echo "</td>";
 echo "</tr>";
 }
echo "<tr><td colspan=3 align=center><input class=post type=submit value=\"" . $btnEdit . 

"\"></td>";
echo "</table>";
echo "</form>";
closeQuadro();

     include 'Conexao_banco_close.php';
     } else {
     echo $msgPermissao;
     }
   break;

Verificação de autorização

// Verifica permissão para a operação
   if( $permiteEdit ){
               .
               .
               .
               } else {
      echo $msgPermissao;
      }
O código desta ação fica condicionado a uma verificação no parâmetro $permiteAdd, declarado no include ExemploDefinicao.inc. Se lá estiver declarado um valor "S" para este parâmetro, o restante da ação será permitido, senão será mostrada a mensagem $msgPermissao, também declarada no include de que falamos aqui.

Cabeçalho da ação

     $operation = $operEdit;
     $description = $descEdit;
     require("libCabecalhoPadrao.php");

Da mesma forma que na ação add, estas linhas de código desenham o cabeçalho da tela de operação de edição (edit).

As variáveis $operation e $description são parâmetros do HTML contido no include libCabecalhoPadrao.php, cujo código repetiremos aqui:
 <div class=h2><div class="btn b1"><?= $titulo ?> - <?= $operation ?></div></div>
  <div class=h3><div class="btn b2"><?= $description ?>&nbsp;[<?= $_SERVER['REMOTE_ADDR'] .'-' . $_SERVER['SERVER_ADDR'] ?>]
  <a class="btn" style="margin-left:50px;" href="?estilo=<?= $_GET['estilo'] ?>"><span class="btn a">TELA INICIAL</span></a>
  </div>
  </div>

O cabeçalho é feito à base de DIVs, pois são os containers mais flexíveis do HTML.

Leitura do registro a ser alterado

A URL (endereço http) formatado quando se clica na operação de edição contém, em um de seus parâmetros, o identificador (id) do registro.. Este precisa ser lido, porque, diferentemente da ação add, os campos do formulário deverão receber os conteúdos atuais do registro a ser editado. Para tal, é preciso providenciar a leitura do registro na tabela do banco de dados.

   include 'Conexao_banco.php';
   // Obtém um registro

   $result = mysqli_query($conn, "select * from " . $tabela . " WHERE Id = " . $_GET['Id'] );

É feita a conexão ao banco de dados utilizando códigos contidos no include "Conexao_banco.php". Em seguida é disparada uma query Select sobre a tabela em questão, procurando o registro cujo Identificador (Id) é o parâmetro Id contido na URL de chamada.

Quadro do formulário de Edição

     if( $row = mysqli_fetch_array($result) ){
     ?>
     <h2 class=tit>EDITAR</h2>
     <h5 class=help>Altere os conteúdos. Os campos de senha precisam da checagem caso sejam alterados.</h5>
     <?php

openQuadro();

O recordset ($result) com o registro (esperamos que seja só um, pois cada registro tem um id diferente do outro) é testado. Se realmente a operação devolver algum registro, a script iniciará o desenho (renderização tecnicamente falando) de um cabeçalho secundário para o formulário de edição.

Este é feito com as tags Header normais. Em seguida é chamada a rotina openQuadro, já descrita anteriormente.

Código Formulário de edição

echo "<form method=post action=?action=editsave&Id=" . $_GET['Id'] . "&estilo=" .  $_GET['estilo'] . ">";
echo "<table border=0 cellspacing=0>";
// Loop no esquema da estrutura de dados
for($x=0;$x<$NoCampos;$x++){
 $tipo = strtolower($arr[$x][4]);
 $sTipo = "";
 $inp = "<input";
 echo "<tr>";
 echo "<td><label>" . $arr[$x][1] . "</label></td>";
 echo "<td>";
 $valor = $row[$arr[$x][0]];
 // Ajuste do tipo, valor, delimitador e tag do campo
 $pl = new paramLineOut($arr,$x,$valor);
 $inp = $pl->taginput;
 $valor = $pl->valorfinal;
 $sTipo = $pl->tipocampo;
 $deli = $pl->delimitador;
 echo $inp;
 echo " name=" . $arr[$x][0] . " id=" . $arr[$x][0];
 if ( strtolower($inp) == "<select" ) {
     echo ">";
     echo "<option value=" . $row[$arr[$x][0]] . ">" . $row[$arr[$x][0]];
     echo $arr[$x][6];
   } elseif ( strtolower($inp) == "<textarea" ) {
     echo " cols=" . $arr[$x][2] . " rows=" . number_format($arr[$x][3]/$arr[$x][2],0,'.','') 

. ">";
   } elseif ( strtolower($inp) == "<input" ){
     echo " type=" . $sTipo . " size=" . $arr[$x][2] ." maxlength=" . $arr[$x][3] . " value=" .  $valor . ">";
   }
 if ( $sTipo == "password" ){
   echo "Alterada <input type=checkbox name=ck" . $arr[$x][0] . " id=ck" . $arr[$x][0] . ">";
   }
 if ( $inp == "<textarea" ) {
   echo $row[$arr[$x][0]] . "</textarea>";
   }
 if ( $inp == "<select" ) {
   echo "</select>";
   }
 echo "</td><td>";
 echo "<span class=msg>" . $arr[$x][7] . "</span>";
 echo "</td>";
 echo "</tr>";
 }
echo "<tr><td colspan=3 align=center><input class=post type=submit value=\"" . $btnEdit . 

"\"></td>";
echo "</table>";
echo "</form>";
closeQuadro();


Início do formulário

echo "<form method=post action=?action=editsave&Id=" . $_GET['Id'] . "&estilo=" . 
$_GET['estilo'] . ">";
echo "<table border=0 cellspacing=0>";

A ação deste formulário direciona a script para a ação editsave, que vai gravar as alterações feitas no registro. E repare que o parâmetro Id tem que ser repassado para esta ação também, pois a identidade do registro não pode ser perdida.

Loop dos campos

// Loop no esquema da estrutura de dados
for($x=0;$x<$NoCampos;$x++){
 $tipo = strtolower($arr[$x][4]);
 $sTipo = "";
 $inp = "<input";
 echo "<tr>";
 echo "<td><label>" . $arr[$x][1] . "</label></td>";
 echo "<td>";

A leitura dos campos (SCHEMA) da tabela é feita de forma parecida com a que foi feita para a ação add. Estabelecemos um loop de 0 até o número de campos ($NoCampos) disponíveis.

Até aqui, é construído o Label do campo para exibição.

Ajustes do campo

Por razões parecidas com as da ação de inclusão, o campo precisa ter seu valor ajustado, e o delimitador regularizado, bem como o tipo de campo registrado. Isto é feito através da classe paramLineOut.

 $valor = $row[$arr[$x][0]];
 // Ajuste do tipo, valor, delimitador e tag do campo
 $pl = new paramLineOut($arr,$x,$valor);
 $inp = $pl->taginput;
 $valor = $pl->valorfinal;
 $sTipo = $pl->tipocampo;
 $deli = $pl->delimitador;

Construção do campo de entrada

 echo $inp;
 echo " name=" . $arr[$x][0] . " id=" . $arr[$x][0];
 if ( strtolower($inp) == "<select" ) {
     echo ">";
     echo "<option value=" . $row[$arr[$x][0]] . ">" . $row[$arr[$x][0]];
     echo $arr[$x][6];
   } elseif ( strtolower($inp) == "<textarea" ) {
     echo " cols=" . $arr[$x][2] . " rows=" . number_format($arr[$x][3]/$arr[$x][2],0,'.','') . ">";
   } elseif ( strtolower($inp) == "<input" ){
     echo " type=" . $sTipo . " size=" . $arr[$x][2] ." maxlength=" . $arr[$x][3] . " value=" . $valor . ">";
   }
 if ( $sTipo == "password" ){
   echo "Alterada <input type=checkbox name=ck" . $arr[$x][0] . " id=ck" . $arr[$x][0] . ">";
   }
 if ( $inp == "<textarea" ) {
   echo $row[$arr[$x][0]] . "</textarea>";
   }
 if ( $inp == "<select" ) {
   echo "</select>";
   }
 echo "</td><td>";

A classe paramLineOut devolveu, pelo seu parâmetro de saída taginput, a tag de HTML correta a ser usada.

Término da exibição do campo

 echo "<span class=msg>" . $arr[$x][7] . "</span>";
 echo "</td>";
 echo "</tr>";
 // Fechamento do loop
                  }

A última informação colocada para cada campo é o sétimo atributo, que contém alguma mensagem de auxílio no preenchimento do campo.

Botão submit

echo "<tr><td colspan=3 align=center><input class=post type=submit value=\"" . $btnEdit . "\"></td>";

Fechamento do formulário, do painel que o contém e do loop de campos

echo "</table>";
echo "</form>";
closeQuadro();
}

Conclusão da ação

     include 'Conexao_banco_close.php';
     } else {
     echo $msgPermissao;
     }
   break;

Fecha-se a conexão com o banco. Se não houver permissão para esta ação na template ExemploDefinicao.inc, é emitida uma mensagem de impossibilidade da ação ser completada.