Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Wesley David

Completa classe CRUD com validação de dados

Recommended Posts

Sempre que necessito venho no iMasters para tirar dúvidas e como sempre tive ótimos resultados nas minhas dúvidas, hoje venho para deixar minha pequena contribuição.

 

Segue abaixo uma classe CRUD que desenvolvi a algum tempo, esta classe sempre me atendeu bem, ela já realiza as validações das informações para evitar sql Injection.

 

Eu ainda não encontrei bugs ou falhas, se vocês encontrarem alguma entrem em contato para realizar correções.

 

Se tiverem dúvidas da utilização estou a disposição :)

 

<?php



/*

* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

* /\/\/\ CRIADO POR: WESLEY DAVID SANTOS        /\/\/\/\/\

* /\/\/\ CONTATO: wesleydavidsantos@gmail.com   /\/\/\/\/\

* /\/\/\ DATA CRIAÇÃO 03/07/2011                /\/\/\/\/\

* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

* 

* CLASSE DE MANIPULAÇÃO DE DADOS COM PDO

* AÇÕES: SELECT , INSERT , UPDATE , DELETE

* 

* VARIÁVEIS 

*      $_db => Armazena a conexão com o banco de dados

*      $_table => Armazena o nome da tabela que será usada, deverá ser configurada em cada classe

*      $_separator => Armazena a string utilizada para separar as posições de campo, valor, tipo, relação referentes ao parametros

* 

* MÉTODOS

*      __construct => Assim que instanciado a classe é realizada a conexão com o banco de dados

*      setBindValue => Função utilizada para validar o tipo de dado informado e setar cada valor em seu determinado lugar

*      prepareWhere => Função utilizada para gerar a parte WHERE da sql

*      prepareValues => Função utilizada para atribuir os valores aos campos correspondentes

*      read => Função utilizada para executar a instrução SELECT no banco de dados

*      readManual => Função utilizada para executar qualquer tipo de instrução sql, deverá ser enviada a sql e os prarametros que serão utilizados para executar a sql

*      insert => Função utilizada para inserir novos dados no banco

*      delete => Função utilizada para deletar dados do banco

*      update => Função utilizada para alteração dos dados do banco

*      lastInsertId => Função utilizada para retornar o id da ultima ação realizada

* 

* 

* EXEMPLOS

*  // $_separator é uma variável publica que determina o que será usado para separar os valores, CAMPOS, VALOR, TIPO, RELAÇÃO .
   // Neste Script utilizo as letras >< como default para separação dos valores, ela pode ser alterada a qualquer momento.  

*  $_separator = '><';   

*

*  USO DO MÉTODO INSERT

*      $obj = new ModelPDO();

*      $obj->_table = "usuario"; // Tabela a ser utilizada

*      $dados = array('nomeUsuario><wesley><str', 'login><david><str', 'senha><wds><str', 'idade><26><int'); // Dados a serem inseridos

*      $obj->insert($dados); // Insere os novos dados

* 

*  USO DO MÉTODO UPDATE

*      $obj = new ModelPDO();

*      $obj->_table = "usuario"; // Tabela a ser utilizada

*      $dados = array('nomeUsuario><wesley david><str', 'login><david_wesley><str', 'senha><wds123><str', 'idade><27><int'); // Dados a serem alterados

*      $where = array('idUsuario><=><6><int'); // Qual posição do banca a ser alterado

*      $obj->update($dados, $where); // Alteração dos dados

* 

*  USO DO MÉTODO DELETE

*      $obj = new ModelPDO();

*      $obj->_table = "usuario"; // Tabela a ser utilizada

*      $where = array('idUsuario><=><6><int'); // Campo a ser deletado

*      $obj->delete($where); // Deleta o campo

* 

*  USO DO MÉTODO READ

*      $obj = new ModelPDO();

*      $obj->_table = "usuario"; // Tabela a ser utilizada

*      $where = array('nomeUsuario><LIKE><%wesley%><str><&&', 'idade><=><26><int'); // Campo a ser pesquisado

*      $limit = 2;

*      $obj->read($where, $limit); // Executa o Select 

* 

*  USO DO MÉTODO READMANUAL

*      $obj = new ModelPDO();

*      $obj->_table = "usuario"; // Tabela a ser utilizada

*      $sql = "Select idUsuario From usuario"; // Sql criada manualmente

*      $where = array('nomeUsuario><LIKE><%wesley%><str><&&', 'idade><=><26><int'); // Dados a serem comparados

*      $limit = 2; // Quantidade para retorno

*      $obj->readManual($sql, $where, $limit); // Executa a SQL 

* 

* 

*  OBS: 

*      O uso da cláusula WHERE deve seguir o formato:

*      $WHERE é um array que deve ter o seguinte formato => nome_campo_bd><comando_condição><valor><tipo_campo><relacionamento(default, significa o relacionamento entre as outras comparações do where)     

*      Mais exemplos de uso dentro a função prepareWhere

* 

*      O formato para INSERT ou UPDATE deve seguir o formato => 

                                                           $dados['nome_campo><valor_campo><tipo'] 
                                                           $dados['nome_campo1><valor_campo1><tipo1']
                                                           OU
                                                           $dados = array('nome_campo><valor_campo><tipo', 'nome_campo1><valor_campo1><tipo1'); 

* 

*      O exemplos acima foram utilizados métodos public, alterei os mesmos para protected para que a classe seja usada como extends o que oferece mais segurança

* 

*/



/* DADOS DE CONFIGURAÇÃO DO BANCO DE DADOS */
define('HOST', 'localhost');
define('DB_NAME', 'NOME_BANCO_DE_DADOS');
define('USER', 'NOME_USUARIO');
define('PASS', 'SENHA_USUARIO');
define('DSN', 'mysql:host='.HOST.';dbname='.DB_NAME);


class Model {



   /* VARIÁVEL DE CONEXÃO COM O CAMPO */

   private $_db;



   /* VARIÁVEL COM O NOME DA TABELA A SER ACESSADA */

   public $_table;



   /* VARIÁVEL UTILIZADA PARA APRESENTAR A STRING QUE SERÁ UTILIZADA PARA SEPARAR OS CAMPOS, VALOR, TIPO, RELAÇÃO  */

   public $_separator = '><';



   function  __construct() {

       /* QUANDO A CLASSE É INSTÂNCIADA É CRIADA UMA CONEXÃO COM O BANCO DE DADOS */



       try{



           $this->_db = new PDO(DSN, USER, PASS);

           $this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);





       }catch(PDOException $e){

           echo htmlentities('Erro na conexão com o banco de dados. '.$e);

       }



   }



   private function setBindValue( $query, $campo, $valor, $tipo ){

       /* 

        * FUNÇÃO QUE SETA O CAMPO , VALOR E TIPO 

        * ELE É UTILIZADO PARA VALIDAÇÃO DAS INFORMAÇÕES

        * OBS: ESTOU UTILIZANDO OS PRINCIPAIS TIPOS DE CAMPOS, CASO HAJA NECESSIDADE DE OUTROS TIPOS É SÓ INSERIR SEGUINDO O PADRÃO

        */



       /* Força o tipo para maiúsculo */

       $tipo = strtoupper($tipo);



       /* Valida o campo e seta o bindValue do PDO */

       switch ($tipo){



           case 'STR': if(!is_string($valor)) die ("Valor não corresponde com tipo de campo informado. <b>{$campo}</b>");   

                       $query->bindValue(':'.$campo, $valor, PDO::PARAM_STR);

           break;    



           case 'INT': if(!is_numeric($valor)) die ("Valor não corresponde com tipo de campo informado. <b>{$campo}</b>");   

                       $query->bindValue(':'.$campo, $valor, PDO::PARAM_INT); 

           break;    



           case 'BOOL': if(!is_bool($valor)) die ("Valor não corresponde com tipo de campo informado. <b>{$campo}</b>");   

                        $query->bindValue(':'.$campo, $valor, PDO::PARAM_BOOL);

           break;    



           default: echo 'Erro no tipo do campo '.$campo; 

           exit;



       }



       return $query;



   }



   private function prepareWhere( $where=array(), $limit=null, $offsset=null, $orderby=null, $relacionamento=null ){

       /*

        * FUNÇÃO PREPAREWHERE => ELA É RESPONSÁVEL POR REGISTRAR DE FORMA CORRETA OS CAMPOS DE BUSCA DA CONSULTA

        * 

        * $WHERE é um array que deve ter o seguinte formato => nome_campo_bd><comando_condição><valor><tipo_campo><relacionamento(default, significa o relacionamento entre as outras comparações do where)    

        *                                                      EX.: $where = array('id><=><22><int');

        *                                                      EX.: $where = array('id><=><22><int><&&', 'nome><=><wesley><str');

        *                                                      EX.: $where = array('id><=><22><int><||', 'nome><LIKE><%wesley%><str');         

        * 

        */



       /* $sqlWhere => sql criada com os dados do where */

       $sqlWhere = "";



       /* 

        * $arrayValues => recebe um array bidimensional onde a segunda camada armazena os valores do where.

        * Ex.: $arrayValues[] = array('campo'=>nome_campo, 'valor'=>valor, 'tipo'=>tipo_do_campo);         

        */        

       $arrayValues = array();



       /* Recebe um array com os campos a serem válidados */

       foreach ($where as $key => $value){



           /* Separa os campos num novo array */

           $wh = explode($this->_separator, $value);



           /* Verifica se foi retornado um array e se este array possui no mínimo 3 campos que são os obrigatórios */

           if(is_array($wh) && sizeof($wh) >= 4){



               /* É separado os parametros */

               $campo    = $wh[0];

               $condicao = $wh[1];

               $valor    = $wh[2];

               $tipo     = $wh[3];

               $relacao  = isset($wh[4]) ? $wh[4] : '';



               $arrayValues[] = array('campo'=>$campo, 'valor'=>$valor, 'tipo'=>$tipo);



               /* $sqlWhere = nome           =               :nome           && (default)  */

               $sqlWhere .= $campo . ' ' . $condicao . ' :' . $campo . ' ' . $relacao . ' ';    



           }



       }





       /* Função de preparação do where */

       $clausulaWhere = !empty($sqlWhere) ? ' WHERE '.$sqlWhere : ' ';



       /* Trata a claúsula LIMIT */

       $sqlLimit = '';

       if(!empty($limit)){ 

           $sqlLimit = ' LIMIT :limitCondicao '; 

           $arrayValues[] = array('campo'=>'limitCondicao', 'valor'=>$limit, 'tipo'=>'int'); 

       }





       /* Trata a claúsula OFFSET */

       $sqlOffset = '';

       if(!empty($offsset)){

           $sqlOffset = ' OFFSET :offSetCondicao ';

           $arrayValues[] = array('campo'=>'offSetCondicao', 'valor'=>$offsset, 'tipo'=>'int'); 

       }





       /* Trata a claúsula ORDER BY */

       $sqlOrderby = '';

       if(!empty($orderby)){ 

           $sqlOrderby = ' ORDER BY :orderByCondicao';

           $arrayValues[] = array('campo'=>'orderByCondicao', 'valor'=>$orderby, 'tipo'=>'str'); 

       }





       /* SQL WHERE FINAL que foi criada */

       $sql = $clausulaWhere .' '. $sqlOrderby .' '. $sqlLimit .' '. $sqlOffset;





       /* Retorna um array com as variáveis preparadas */

       return array('values'=>$arrayValues, 'where'=>$sql);      



   }



   private function prepareValues($sql, $values){

       /*

        * FUNÇÃO RESPONSÁVEL POR ATRIBUIR OS VALORES AOS SEUS DEVIDOS CAMPOS E EXECUTAR A SQL

        */



       try{



           $query = $this->_db->prepare($sql);



           /* Prepara os valores */

           foreach($values as $key => $value) {



               $query = $this->setBindValue($query, $value['campo'], $value['valor'], $value['tipo']);



           }  



           //echo $query->queryString;



           /*

            * SE DESEJAR VER A SQL USE O COMANDO ABAIXO

            * echo $query->queryString;

            */



           $query->execute();



           return $query;



       }catch(PDOException $e){

           echo $e->getMessage();

       }



   }



   protected function read( $where=array(), $limit=null, $offsset=null, $orderby=null, $relacionamento=null ){



       /*

        * FUNÇÃO READ => FAZ A LEITURA DO BANCO DE DADOS

        * EX.: 

        *      $where = array('nomeCategoria><LIKE><%s%><str');

        *      $limit = 2;

        *      read($where, $limit);

        */



       /* Recebe toda a parte WHERE preparada e os valores a serem adicionados */

       $arrayPrepareWhere = $this->prepareWhere($where, $limit, $offsset, $orderby, $relacionamento);



       /* SQL FINAL que foi criada */

       $sql = 'SELECT * FROM ' . $this->_table .' '. $arrayPrepareWhere['where'];        



       /* RECEBE A QUERY EXECUTADA */

       $query = $this->prepareValues($sql, $arrayPrepareWhere['values']);



       /* TIPO DE RETORNO DE DADOS */

       $query->setFetchMode(PDO::FETCH_ASSOC);



       return $query->fetchAll();

   }



   protected function readManual( $sql, $where=array(), $limit=null, $offsset=null, $orderby=null, $relacionamento=null ){

       /*

        * FUNÇÃO READMANUAL => DEVE SER REPASSADO UMA SQL COMPLETA, MÁS AS CLÁUSULAS DE RELACIONAMENTO DEVEM SER REPASSADAS SEPARADAS PARA VALIDAÇÃO

        * EX.: 

        *      $sql = 'SELECT id, nome FROM usuario';

        *      $where = array('nomeCategoria><LIKE><%s%><str');

        *      $limit = 2;

        *      readManual($sql, $where, $limit);

        */



       /* Recebe toda a parte WHERE preparada e os valores a serem adicionados */

       $arrayPrepareWhere = $this->prepareWhere($where, $limit, $offsset, $orderby, $relacionamento);



       /* SQL FINAL que foi criada */

       $sql .= ' '. $arrayPrepareWhere['where']; 



       /* RECEBE A QUERY EXECUTADA */

       $query = $this->prepareValues($sql, $arrayPrepareWhere['values']);



       /* TIPO DE RETORNO DE DADOS */

       $query->setFetchMode(PDO::FETCH_ASSOC);



       return $query->fetchAll();



   }



   protected function insert( array $dados ){

       /*

        * FUNÇÃO INSERT => RESPONSÁVEL POR  

        * $dados['nome_campo><valor_campo><tipo'];

        */



       $values = array();

       $sqlCampo = $sqlValues = '';



       /* Recebe um array com os campos a serem válidados */

       foreach ($dados as $key => $value){



           /* Separa os campos num novo array */

           $wh = explode($this->_separator, $value);



           /* Verifica se foi retornado um array e se este array possui 3 campos que são os obrigatórios */

           if(is_array($wh) && sizeof($wh) == 3){



               /* É separado os parametros */

               $campo = $wh[0];

               $valor = $wh[1];

               $tipo  = $wh[2];



               $values[] = array('campo'=>$campo, 'valor'=>$valor, 'tipo'=>$tipo);



               $sqlCampo  .= ''.$campo.',';

               $sqlValues .= ':'.$campo.',';



           }



       }



       /* PARA NÃO REALIZAR A VALIDAÇÃO DENTRO DO LOOP AQUI É RETIRADO A ÚLTIMA VIRGULA ADICIONADA */

       $sqlCampo  = substr($sqlCampo, 0, (strlen($sqlCampo)-1));

       $sqlValues = substr($sqlValues, 0, (strlen($sqlValues)-1));



       /* SQL FINAL DO INSERT */

       $sql = "INSERT INTO {$this->_table} ({$sqlCampo}) VALUES ({$sqlValues})";



       $query = $this->prepareValues($sql, $values);



       /* RETORNA O NÚMERO DE COLUNAS AFETADAS */

       return $query->rowCount();



   }

   function insertManual( $sql ){

       return $this->_db->query($sql);

   }    

   protected function delete( $where=array() ){

       /* FUNÇÃO DELETE => DELETA INFORMAÇÕES DO BANCO DE ACORDO COM O ARRAY WHERE  */



       $arrayDelete = $this->prepareWhere($where);



       $sql = "DELETE FROM {$this->_table} ".$arrayDelete['where'];



       $query = $this->prepareValues($sql, $arrayDelete['values']);



       /* RETORNA O NÚMERO DE COLUNAS AFETADAS */

       return $query->rowCount();



   }



   protected function update( array $dados, $where=array() ){



       /*

        * FUNÇÃO UPDATE => RESPONSÁVEL POR ALTERAÇÃO DOS DADOS 

        * $dados['nome_campo><valor_campo><tipo'];

        */



       $values = array();

       $sqlUpdate = '';



       /* Recebe um array com os campos a serem válidados */

       foreach ($dados as $key => $value){



           /* Separa os campos num novo array */

           $wh = explode($this->_separator, $value);



           /* Verifica se foi retornado um array e se este array possui 3 campos que são os obrigatórios */

           if(is_array($wh) && sizeof($wh) == 3){



               /* É separado os parametros */

               $campo = $wh[0];

               $valor = $wh[1];

               $tipo  = $wh[2];



               $values[] = array('campo'=>'UP'.$campo, 'valor'=>$valor, 'tipo'=>$tipo);



               $sqlUpdate  .= ' ' . $campo . '= :UP' . $campo . ',';



           }



       }



       /* PARA NÃO REALIZAR A VALIDAÇÃO DENTRO DO LOOP AQUI É RETIRADO A ÚLTIMA VIRGULA ADICIONADA */

       $sqlUpdate  = substr($sqlUpdate, 0, (strlen($sqlUpdate)-1));



       /* Recebe um array com os campos a serem válidados para where */

       $sqlWhere = '';

       foreach ($where as $key => $value){



           /* Separa os campos num novo array */

           $wh = explode($this->_separator, $value);



           /* Verifica se foi retornado um array e se este array possui no mínimo 3 campos que são os obrigatórios */

           if(is_array($wh) && sizeof($wh) >= 4){



               /* É separado os parametros */

               $campo    = $wh[0];

               $condicao = $wh[1];

               $valor    = $wh[2];

               $tipo     = $wh[3];

               $relacao  = isset($wh[4]) ? $wh[4] : '';



               $values[] = array('campo'=>$campo, 'valor'=>$valor, 'tipo'=>$tipo);



               /* $sqlWhere = nome           =               :nome           && (default)  */

               $sqlWhere .= $campo . ' ' . $condicao . ' :' . $campo . ' ' . $relacao . ' ';    



           }



       }        



       /* Função de preparação do where */

       $clausulaWhere = !empty($sqlWhere) ? ' WHERE '.$sqlWhere : ' ';            



       $sql = "UPDATE {$this->_table} SET {$sqlUpdate} {$clausulaWhere}";



       $query = $this->prepareValues($sql, $values);



       /* RETORNA O NÚMERO DE COLUNAS AFETADAS */

       return $query->rowCount();



   }



   protected function lastInsertId(){

       return $this->_db->lastInsertId();

   }



}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Show de bola, porém postou na categoria errada.

Compartilhar este post


Link para o post
Compartilhar em outros sites

interessante, mas pq nao usou o query object? gostei de ter usado as excecoes, porem algo que voce esqueceu: nem todos os hosts tem habilitado o PDO :thumbsup:

 

detalhe, dentro do query object, você pode usar o composte pattern pra montar o where...

Compartilhar este post


Link para o post
Compartilhar em outros sites

porem algo que voce esqueceu: nem todos os hosts tem habilitado o PDO

 

Bem lembrado, nesse caso, é bom trabalhar com adaptadores, quase a mesma coisa do que o Zend .. daí você teria que separar tudo que é relacionado a execução, do que é relacionado a preparação de query .. dessa forma, poderia ter inúmeros adaptadores, porem fazendo a mesma coisa ..

 

<?php
         /**
          * ...
          */
         interface Adapter { } 

         class MySQLPDOAdapter implements Adapter { } // utiliza a PDO

         class MySQLMySQLiAdapter implements Adapter { }  // utiliza a biblioteca mysqli 

         class MySQLResourceAdapter implements Adapter { } // utiliza funções mysql_

         class MySQL {

                /**
                 * Guarda o adaptador padrão
                 * @var Adapter Object ()
                 */
                private $_adapter ;

                public function setDefaultAdapter ( Adapter $adapter ) {
                       $this->_adapter = $adapter ;
                }

                public function getDefaultAdapter ( ) {
                       return !( $this->_adapter instanceOf Adapter ) ?: $this->_adapter ;
                }

         }

         $Db = new MySQL ( ) ;
         $Db->setDefaultAdapter( new MySQLPDOAdapter ( ) ) ;

         print_r ( $Db ) ;
         print_r ( $Db->getDefaultAdapter() ) ;

 

;)

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.