Ir para conteúdo

Arquivado

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

Nerdmonkey

Classe para gerenciar postagens

Recommended Posts

Boa noite!

 

Acabei de criar a classe que faz toda gestão dos dados enviados via $_POST. O tratamento é feito com AJAX e gostaria de saber a opinião de vocês quando a melhorias no código. Eu fazia manualmente um a um e durante algumas semanas fiquei pensando em como automatizar todo esse processo. Ainda estou aprendendo e tenho me esforçado ao máximo pra poder entender todo o conceito do POO. Sei que é muita coisa mas um dia chego lá. Então lá vai

 

 

<?php
/**
 * UpdateData.class [ Helper ]
 * Responsável por verificar os dados enviado via $_POST e inserir ou atualizar essas informações 
 * no banco de dados
 * 
 */
class UpdateData {   
    /** A data e hora atual */
    private $DataCadastro;
    
    /** A tabela que receberá a ação */
    private $Table;
    
    /** Os campos que serão validados e salvos na tabela */
    private $Fields;
    
    /** Os dados que serão utilizados para realizar a ação na tabela */
    private $DataObj;
    
    /** A mensagem de erro */
    private $Errors;
    
    /** A mensagem de sucesso */
    private $Success;
    
    /** Itens para checar se o registro já existe */
    private $Itens;
    
    /** Construct */
    function __construct($Table, array $Fields, $Itens = null) {
        $this->Table = $Table;
        $this->Fields = $Fields;
        $this->Itens = $Itens;
        $this->DataCadastro = date('Y-m-d H:i:s');
        
        // Execute methods
        $this->CheckFields();
        $this->SetAction();
    }
 
    /**
     * <b>CheckFields: </b> Método responsável por verificar se o campo está vazio e retornar a mensagem
     * de erro em formato de json
     * 
     * @return json
     */
    public function CheckFields(){        
        if(is_array($this->Fields)):
            /** Define os dados que serão utilizados para manipular a tabela */
            $this->DataObj = $this->Fields;
        
            /** Trata alguns campos removendo caracteres da máscara jQuery */
            foreach($this->DataObj as $IndiceObj):
                if($IndiceObj=='cnpj' || $IndiceObj=='cpf' || $IndiceObj=='cep' || $IndiceObj=='telefone'):
                    $this->DataObj = str_replace(['_', '-', '.', '/'], '', $this->DataObj);
                endif;
            endforeach;
            
            /** Passwords => For change | Encoding sha1() */
            if(isset($this->Fields['senha']) && !empty($this->Fields['senha'])):
                foreach($this->Fields as $Indice => $Val):
                    if($Indice == 'senha'):
                        $this->Fields['senha'] = sha1($this->Fields['senha']);
                    endif;
                endforeach;
            endif;
            
            /** Passwords => For check if it's correctly */
            if(isset($this->Fields['atual_pass']) && !empty($this->Fields['atual_pass'])):
                foreach($this->Fields as $Indice => $Val):
                    if($Indice == 'atual_pass'):
                        $this->Fields['atual_pass'] = sha1($this->Fields['atual_pass']);
                    endif;
                endforeach;
                
                $ReadPass = new Read;
                $ReadPass->ExeRead('rio_clientes', 'senha,id,email', 'WHERE senha = :senha_atual', "senha_atual={$this->Fields['atual_pass']}");
                
                if(!$ReadPass->getResult() && empty($this->Success)):
                    $this->Errors=['erros' => "A senha atual está incorreta#exibir_erros"];
                    echo json_encode($this->Errors);
                    exit;
                endif;
            endif;          
 
            /** Validação para tela de alteração de dados */
            if($this->CheckAction()==1):
                $this->Errors=['erros' => "Preencha ou o campo com o novo e-mail ou o campo com a nova senha. E informe a senha atual para concluir.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            elseif($this->CheckAction()==2):
                $this->Errors=['erros' => "Tudo certo. Basta informar sua senha atual.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            elseif($this->DataObj['action']!='validate_data_access'):
                /** Faz a validação dos campos */
                foreach($this->Fields as $Indice => $Val):           
                    if($Indice != 'action' && $Indice != 'id' && empty($Val)):
                        $this->Errors=['erros' => "Campo obrigatório#{$Indice}"];
                        echo json_encode($this->Errors);
                        exit;
                    endif;
                 endforeach;
            endif;
        endif;
    }
    
    /** PRIVATES METHODS */
    /**
     * <b>CheckDuplicidade: </b> Método responsável por verificar se o registro já existe na tabela
     * 
     * @return boolean
     */
    private function CheckDuplicidade() {
        if(!empty($this->Itens) && !empty($this->Fields[$this->Itens])):
            $ReadItens = new Read;
            $ReadItens->ExeRead($this->Table, $this->Itens, "WHERE {$this->Itens} = :itens AND id != :id", "itens={$this->Fields[$this->Itens]}&id={$this->Fields['id']}");
 
            if($ReadItens->getResult()):
                return false;
            else:
                return  true;
            endif;
        else:
            return true;
        endif;
    }
    
    /**
     * 
     */
    private function CheckAction() {
         if($this->DataObj['action']=='validate_data_access'):
            if(empty($this->DataObj['email']) && empty($this->DataObj['senha'])):
                return 1;
            elseif(!empty($this->DataObj['email']) && empty($this->DataObj['senha']) && empty($this->DataObj['atual_pass'])):
                return 2;
            elseif(empty($this->DataObj['email']) && !empty($this->DataObj['senha']) && empty($this->DataObj['atual_pass'])):
                return 2;
            endif;
        endif;
    }
    
    /**
     * <b>SetAction: </b> Método privado responsável por realizar a ação na tabela
     * 
     * @return boolean
     */
    private function SetAction() {
         /** Remove alguns índices do array, por padrão todos os campos que não estão na tabela */
        unset($this->DataObj['id']);
        unset($this->DataObj['action']);
        unset($this->DataObj['atual_pass']);
        
        // Elimina o e-mail do update, se ele estiver vazio
        if(empty($this->DataObj['email'])):
            unset($this->DataObj['email']);
        endif;
        
        // Elimina a senha do update, se ela estiver vazia
        if(empty($this->DataObj['senha'])):
            unset($this->DataObj['senha']);
        endif;
        
        // Realiza o insert
        if(!isset($this->Fields['id']) || empty($this->Fields['id'])):
            if($this->CheckDuplicidade()===true):
                $InsertData = new Create;
                $InsertData->ExeCreate($this->Table, $this->DataObj);
 
                 if($InsertData->getResult()):
                    $this->Success=['sucesso' => "Registro inserido com sucesso#sucesso"];
                    echo json_encode($this->Success);
                endif;
            else:
                $this->Errors=['erros' => "Esse registro já existe. Não será possível realizar essa ação com essa informações.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            endif;
        // Realiza o update
        else:
            if($this->CheckDuplicidade()===true):
                
                // Salva a data de alteração da senha
                if(!empty($this->DataObj['senha'])):
                    $this->DataObj['data_alteracao_senha'] = $this->DataCadastro;
                endif;                
                
                // Realiza o update
                $UpdateData = new Update;
                $UpdateData->ExeUpdate($this->Table,$this->DataObj, "WHERE id=:id", "id={$this->Fields['id']}");
 
                // Atualiza a sessão com o novo e-mail
                if(!empty($this->DataObj['email'])):
                    $sessao = new Session;
                    $_SESSION['logado'] = $this->DataObj['email'];
                endif;
        
                // Mensagem de sucesso
                if($UpdateData->getResult()):
                    $this->Success=['sucesso' => "Dados atualizados com sucesso#sucesso"];
                    echo json_encode($this->Success);
                endif;
            else:
                $this->Errors=['erros' => "Esse registro já existe. Não será possível realizar essa ação com essa informações.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            endif;
        endif;
    }
}

 

Usage

 

 

/** Post form */
$Post=filter_input_array(INPUT_POST);
 
/** Define as variáveis utilizadas pela classe */
switch($Post['action']):
    // Meus dados
    case "validate_meus_dados":
        $Table = 'clientes';
        $Iten = ''; // Quando existir, irá verificar se o registro é duplicado ou não
        break;
endswitch;
 
/** Objeto da classe */
$updData=new UpdateData($Table, $Post, $Iten);

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fiz uma atualização

<?php
ini_set('display_errors',0);
ini_set('display_startup_erros',0);

/**
 * UpdateData.class [ Helper ]
 * Responsável por verificar os dados enviado via $_POST e inserir ou atualizar essas informações
 * no banco de dados
 *
 * @copyright (c) 2015, Samuel dos Santos   Programação Criativa
 */
class UpdateData {   
    // A data e hora atual
    private $DataCadastro;
    
    // A tabela que receberá a ação
    private $Table;
    
    // Os campos que serão validados e salvos na tabela
    private $Fields;
    
    // Os dados que serão utilizados para realizar a ação na tabela
    private $DataObj;
    
    // A mensagem de erro
    private $Errors;
    
    // A mensagem de sucesso
    private $Success;
    
    // Itens para checar se o registro já existe
    private $Itens;
    
    // Parsestring para comparação de duplicidade de registros
    private $Parse;
    
    function __construct($Table, array $Fields, $Itens = null) {
        $this->Table = $Table;
        $this->Fields = $Fields;
        $this->Itens = $Itens;
        $this->DataCadastro = date('Y-m-d H:i:s');
        
        // Execute methods
        $this->CheckFields();
        $this->SetAction();
    }

    /** PRIVATES METHODS */
    /**
     * <b>CheckFields: </b> Método responsável por verificar se o campo está vazio e retornar a mensagem
     * de erro em formato de json
     *
     * @return json
     */
    private function CheckFields(){        
        if(is_array($this->Fields)):
            /// Atribui os valores
            $this->DataObj = $this->Fields;
        
            // Trata o modelo para trabalharmos com url's amigáveis
            $this->FriendUrlModelo();
            
            // Trata os campos com máscaras [plugin::jquery]
            $this->TrataMask();

            // Passwords => For change | Encoding sha1()
           $this->EncodingSha1();
            
            // Passwords => For check if it's correctly
            $this->PassAtualCheck();

            // Validação para tela de alteração de dados
            if($this->CheckAction()==1):
                $this->Errors=['erros' => "Preencha ou o campo com o novo e-mail ou o campo com a nova senha. E informe a senha atual para concluir.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            elseif($this->CheckAction()==2):
                $this->Errors=['erros' => "Tudo certo. Basta informar sua senha atual.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            elseif($this->DataObj['action']!='validate_data_access'):
                // Faz a validação dos campos fora da tela de alteração de dados
                foreach($this->Fields as $Indice => $Val):        
                    // Lançamos os campos com exceções, ou seja, com preenchimento opcional
                    if($Indice != 'action' && $Indice != 'id' && empty($Val) && $Indice != 'garantia' && $Indice != 'link' && $Indice != 'id_sub1' && $Indice != 'id_sub2' && $Indice != 'id_sub3'):
                        $this->Errors=['erros' => "Campo obrigatório#{$Indice}"];
                        echo json_encode($this->Errors);
                        exit;
                    endif;
                 endforeach;
            endif;
        endif;
    }

    /**
     * <b>CheckDuplicidade: </b> Método responsável por verificar se o registro já existe na tabela
     *
     * @return boolean
     */
    private function CheckDuplicidade() {
        if(!empty($this->Itens)):
            // Quando o id for nulo atribuimos 0 ao valor
            if(!isset($this->DataObj['id'])):
                $this->DataObj['id'] = 0;
            endif;
            
            // Monta os itens para comparação e o parsestring
            $this->CreateItensParseToCompare();
            
            $ReadItens = new Read;
            $ReadItens->ExeRead($this->Table, '*', "WHERE {$this->Itens} AND id != :id", $this->Parse . "&id={$this->DataObj['id']}");
            
            if($ReadItens->getResult()):
                return false;
            else:
                return  true;
            endif;
        else:
            return true;
        endif;
    }
    
    /**
     * <b>CheckAction: </b> Método exclusivo para a tela de alteração de dados de acesso do cliente
     *
     * @return int
     */
    private function CheckAction() {
         if($this->DataObj['action']=='validate_data_access'):
            if(empty($this->DataObj['email']) && empty($this->DataObj['senha'])):
                return 1;
            elseif(!empty($this->DataObj['email']) && empty($this->DataObj['senha']) && empty($this->DataObj['atual_pass'])):
                return 2;
            elseif(empty($this->DataObj['email']) && !empty($this->DataObj['senha']) && empty($this->DataObj['atual_pass'])):
                return 2;
            endif;
        endif;
    }
    
    /**
     * <b>FriendUrlModelo: </b> Trata o modelo para trabalharmos com url's amigáveis
     *
     * @return array Adiciona o campo modelo_tratado ao índice de $this->DataObj[]
     */
    private function FriendUrlModelo() {
        if(isset($this->DataObj['modelo']) && !empty($this->DataObj['modelo'])):
            $Funcoes=new Valid;
            $this->DataObj['modelo_tratado'] = $Funcoes->retira_acentos(utf8_decode($this->DataObj['modelo']), '-');
        endif;
    }
    
    /**
     * <b>TrataMask: </b> Remove os caracteres atribuídos pela máscara jQuery
     *
     * @return array Retorna os campos preço,cnpj,cpf,cep,telefone tratados
     */
    private function TrataMask() {
        if(isset($this->DataObj['preco']) && !empty($this->DataObj['preco'])):
            $this->DataObj['preco'] = str_replace('.', '', $this->DataObj['preco']);
            $this->DataObj['preco'] = str_replace(',', '.', $this->DataObj['preco']);
        endif;
        
        foreach($this->DataObj as $IndiceObj):
            if($IndiceObj=='cnpj' || $IndiceObj=='cpf' || $IndiceObj=='cep' || $IndiceObj=='telefone'):
                $this->DataObj = str_replace(['_', '-', '.', '/'], '', $this->DataObj);
            endif;
        endforeach;
    }
    
    /**
     * <b>CreateItensParseToCompare: </b> Cria os campos para comparar se o registro está duplicado
     *
     * @return array Retorna os itens a serem comparados e o parseString desses mesmos itens montados prontos
     * para serem utilizados na query
     */
    private function CreateItensParseToCompare() {
        foreach($this->Itens as $Itens => $Val):
            $this->Itens .= $Itens . ' =:' . $Itens . ' AND ';
            $this->Parse .= $Itens . '=' . $Val . '&';
        endforeach;
        
        $this->Itens = substr($this->Itens, 0, strrpos($this->Itens, 'AND'));
        $this->Parse = substr($this->Parse, 0, strrpos($this->Parse, '&'));
        $this->Itens = str_replace('Array', '', $this->Itens);
    }
    
    /**
     * <b></b> Codifica a senha com a sha1
     *
     * @return array Retorna a senha codificada no indíce existente senha
     */
    private function EncodingSha1() {
         if(isset($this->DataObj['senha']) && !empty($this->DataObj['senha'])):
            $this->DataObj['senha'] = sha1($this->DataObj['senha']);
        endif;
    }
    
    /**
     * <b>PassAtualCheck:</b> Checa se a senha atual está correta
     *
     * @return json $erros Caso a senha esteja incorreta
     */
    private function PassAtualCheck() {
        if(isset($this->DataObj['atual_pass']) && !empty($this->DataObj['atual_pass'])):
            $this->DataObj['atual_pass'] = sha1($this->DataObj['atual_pass']);

             $ReadPass = new Read;
             $ReadPass->ExeRead('rio_clientes', 'senha,id,email', 'WHERE senha = :senha_atual', "senha_atual={$this->DataObj['atual_pass']}");

             if(!$ReadPass->getResult() && empty($this->Success)):
                 $this->Errors=['erros' => "A senha atual está incorreta#exibir_erros"];
                 echo json_encode($this->Errors);
                 exit;
             endif;
         endif;          
    }
    
    /**
     * <b>SetAction: </b> Método privado responsável por realizar a ação na tabela
     *
     * @return boolean
     */
    private function SetAction() {
         /** Remove alguns índices do array, por padrão todos os campos que não estão na tabela */
        unset($this->DataObj['id']);
        unset($this->DataObj['action']);
        unset($this->DataObj['atual_pass']);
        
        // Elimina o e-mail do update, se ele estiver vazio
        if(empty($this->DataObj['email'])):
            unset($this->DataObj['email']);
        endif;
        
        // Elimina a senha do update, se ela estiver vazia
        if(empty($this->DataObj['senha'])):
            unset($this->DataObj['senha']);
        endif;
        
        // Realiza o insert
        if(!isset($this->Fields['id']) || empty($this->Fields['id'])):
            if($this->CheckDuplicidade()===true):
                $InsertData = new Create;
                $InsertData->ExeCreate($this->Table, $this->DataObj);

                 if($InsertData->getResult()):
                    $this->Success=['sucesso' => "Registro inserido com sucesso#sucesso"];
                    echo json_encode($this->Success);
                endif;
            else:
                $this->Errors=['erros' => "Esse registro já existe. Não será possível realizar essa ação com essa informações.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            endif;
        // Realiza o update
        else:
            if($this->CheckDuplicidade()===true):
                
                // Salva a data de alteração da senha
                if(!empty($this->DataObj['senha'])):
                    $this->DataObj['data_alteracao_senha'] = $this->DataCadastro;
                endif;                
                
                // Realiza o update
                $UpdateData = new Update;
                $UpdateData->ExeUpdate($this->Table,$this->DataObj, "WHERE id=:id", "id={$this->Fields['id']}");

                // Atualiza a sessão com o novo e-mail
                if(!empty($this->DataObj['email'])):
                    $sessao = new Session;
                    $_SESSION['logado'] = $this->DataObj['email'];
                endif;
        
                // Mensagem de sucesso
                if($UpdateData->getResult()):
                    $this->Success=['sucesso' => "Dados atualizados com sucesso#sucesso"];
                    echo json_encode($this->Success);
                endif;
            else:
                $this->Errors=['erros' => "Esse registro já existe. Não será possível realizar essa ação com essa informações.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            endif;
        endif;
    }
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acredito que o que você tem é um bom ponto de partida para uma boa aprendizagem.

Você colocou uma classe, eu vou colocar dicas para você melhorar sua classe e experiência na POO. Em um primeiro momento, vou questionar sua "codificação". Conforme for o andamento, irei questionar outros detalhes da classe.

Comentários:
- Os comentários estão bons para a leitura, e, em alguns momentos, você utiliza phpDoc. Mas você deveria fazer mais uso dele;

Tais como:

    /**
     * @var \DateTime
     **/
    private $DataCadastro;

Nomemclatura:

Eu vejo dois problemas, ambos são pontos de vista mas vão interferir no seu código

- Utilize o padrão CamelCase:
- UpperCamelCase para nomes de classes, interfaces, traits e namespaces;
- LowerCamelCase para métodos, funções, atributos e variáveis.

- Utilize apenas um idioma.
- A progração por si só é em ingles, logo, utilize tudo em inglês

Veja:

private function FriendUrlModelo() {
private function TrataMask() {
private function CreateItensParseToCompare() {
private function PassAtualCheck() {

Todos os métodos, acima listados, possuem palavras em mais de um idioma. Isso é ruim para a leitura e entendimento do código.

Você usando dois idiomas, eu tenho que adivinhar o significado do nome da classe:

class UpdateData {

Você está atualizando uma data ou dados? Quando eu ler a classe, vou entender o funcionamento da classe e o significado do nome, mas isso por si só é ruim. Eu não deveria conhecer a classe para entender o que a classe se propõe.

Preceitos e conceitos:
- Sempre que houver um erro que altere o fluxo natural, não retorne null, false ou os erros, lance uma exceção;

Veja o phpDoc abaixo:

@return json $erros Caso a senha esteja incorreta

Não retorne o json, lance uma exception e, então, o seu cliente deve tratar a alteração do fluxo de execução. Sua classe não deve ser responsável pelo ouput, ao menos não deveria.

- Em orientação a objetos, utilize objetos:

$this->DataCadastro = date('Y-m-d H:i:s');

Você está usando uma string literal, seria mais interessante um objeto:

$this->DataCadastro = new \DateTime();

Complexidade ciclomática alta:

Eu não realizei os testes, mas sei que a complexidade do seu código é alta, ele possui muitas variações no fluxo de execução. E isso deve ser tratado. Para realizar o tratamento, eu recomendo a leitura sobre Object Calisthenics, isso veio do java mas agregou muito ao PHP, poderá ler nos links abaixo:

 

http://pt.slideshare.net/guilhermeblanco/phpubsp-object-calisthenics-aplicado-ao-php?next_slideshow=1

http://pt.slideshare.net/guilhermeblanco/php-para-adultos-clean-code-e-object-calisthenics

 

Leituras adicionais:

PSRs: Não é obrigatório o uso de tudo que é dito, nem eu mesmo utilizo tudo, mas é importante conhecer, entender e saber aplicar.

 

Uma vez que são regras desenvolvidas pela e para a comunidade PHP.

PSR - 1: http://www.php-fig.org/psr/psr-1/

PSR - 2: http://www.php-fig.org/psr/psr-2/

PSR - 4: http://www.php-fig.org/psr/psr-4/

 

Ferramentas sugeridas (para o linux nesse caso):

PHP Mess Detector: Essa "belezura" lhe mostra várias "bagunças" que podem haver no seu código, além de alta complexidade e alguns detalhes a mais.

 

PHP CodeSniffer: Lhe aponta questões definidas nas PSRs e alguns pontos a mais de codificação. Os mesmos pontos ressaltados pela PSR vale aqui, é bom saber, mas não precisa utilizar tudo a risca.

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Adorei a avaliação Gabriel Heming. Já estou trabalhando nessas melhorias. Agora ficou uma dúvida, que ainda não testei mas, acredito que vai dar bizu. Se ao invés de retornar os erros e sim os Exceptions, que realmente, melhorou muito a legibilidade do código, como faço para jogá-lo para o json.

 

Porque essa validação trabalha em conjunto com o AJAX, certo ?! Eu envio os dados para a classe e, no caso como está acima, ele retorna a mensagem de erro no formato json pra que eu possa exibí-la ao usuário. É possível que eu faça esse tratamento diretamente no catch e retornar o json corretamente ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim, você deve tratar diretamente no try/catch e retornar o json, mas o mais importante é aonde ficará esse try/catch.

 

Quando você desenvolve uma biblioteca, deve separar o que é a biblioteca e quem está usando.

 

Se um dia você quiser usar sua biblioteca para updates síncronos, que seria a requisição normal do servidor, sua biblioteca estaria "amarrada" ao fato de sempre retornar um json, ou executar um exit ou realizar o output (print/echo) de informação.

 

A responsabilidade de saída/output deve ser realizada pelo cliente que está utilizando a biblioteca. Mas cada um com sua responsabilidade, uma model não pode sair printando informação por ai... :lol:

 

Mas caso a Model que esteja utilizando sua biblioteca receba um try/catch, ela pode tomar para si a responsabilidade de tratar a exceção ou repassar o tratamento (reenviando a exception ou criando uma nova exception) para o controller e, então, o controller pode ter a responsabilidade de enviar a informação para o navegador.

 

Aqui fica um pouco contraditório, visto que nenhuma view deveria ser exibida (visto do ponto de vista que é um retorno para o navegador). Entretanto, para a infomação chegar ao navegador, deve ser printado. Nesse caso, eu não vejo problema em possuir na camada de controle um echo json_encode, visto que é um tipo de retorno que é realizado em forma de output.

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Legal Gabriel, o interessante da Orientação a Objetos é que a teoria faz muita diferença na hora do aprendizado. Fiz algumas modificações nos comentários, tentei padronizar com o phpDoc, mas confesso que sou fraco em comentários e tratamento de erros, estou inclusive estudando sobre o assunto pra resolver isso de uma vez =p

 

Eu vou testar agora porque provavelmente travou em alguma coisa, mas já não me importa que funcione e sim que eu saiba o que estou fazendo. Porque se eu sei o que fiz sei identificar o problema :v

 

Mas se quiser me ajudar pode apontar possíveis pontos para melhorá-la ainda mais.

Tentei diminuir a complexidade ciclomática, bem legal os artigos.

 
 <?php
ini_set('display_errors',0);
ini_set('display_startup_erros',0);

/**
 * <b>ChangeMySQLTableRows.class [ Change Rows Table ]: </b>
 * Altera uma ou mais linhas da tabela MySQL definida na variável private $Table
 * Os comandos podem ser tanto
 *
 * @copyright (c) 2015, Samuel dos Santos   Programação Criativa
 */
class ChangeMySQLTableRows {   
    /** @var DateTime Tell him, what time is it ? */
    private $DataCadastro;
    
    /** @var  Table The table where the data are change  */
    private $Table;
    
    /** @array Fields Container for params coming from $_POST form */
    private $Fields;
    
    /** @array DataObj Container for @array Fields */
    private $DataObj;
    
    /** @var Erros The error message */
    private $Errors;
    
    /** @var Success The success message */
    private $Success;
    
    /** @array Itens To check if the record is duplicated before inserting it */
    private $Itens;
    
    /** @var Pase To create a bind values for @var Itens */
    private $Parse;
    
    /**
     * @__contruct Required @var Table what receive changes,
     * @array Fields what it contains all $_POST itens from form,
     * @array Itens Optional if  you want to compare fields existings report it in forma ['item' => $Post['field']]
     *
     */
    function __construct($Table, array $Fields, $Itens = null) {
        $this->Table = $Table;
        $this->Fields = $Fields;
        $this->Itens = $Itens;
        $this->DataCadastro = new \DateTime();
        $this->DataObj = $this->Fields;
        
        // Execute methods
        $this->verifyFields();
        $this->setActions();
    }

    /************************************************************
     * ********************** Private methods **********************/
    /**
     * <b>verifyFields: </b> Verify all fields and all messages
     *
     * @return json
     */
    private function verifyFields(){        
        if(is_array($this->Fields)):
            /** @method friendUrlModelProduct() */
            $this->friendUrlModelProduct();
            
            /** @method RemoveMask() */
            $this->removeMask();

            /** @method encodingSha1() */
           $this->encodingSha1();
            
            /** @method checkPassActual() */
            $this->checkPassActual();

            /** @method setErros() */
            $this->setErros();
        endif;
    }
    
    /**
     * <b>setErros: </b> Set the errors and return from JSON
     *
     * @return Exception
     */
    private function setErros() {
        // Validação para tela de alteração de dados
        if($this->DataObj['action']!='validate_data_access'):
            // Faz a validação dos campos fora da tela de alteração de dados
            foreach($this->Fields as $Indice => $Val):        
                // Lançamos os campos com exceções, ou seja, com preenchimento opcional
                if($Indice != 'action' && $Indice != 'id' && empty($Val) && $Indice != 'garantia' && $Indice != 'link' && $Indice != 'id_sub1' && $Indice != 'id_sub2' && $Indice != 'id_sub3'):
                    $this->Errors=['erros' => "Campo obrigatório#{$Indice}"];
                    echo json_encode($this->Errors);
                    exit;
                endif;
             endforeach;
        endif;
    }

    /**
     * <b>createBindValues: </b> Create bindValues in format :bind | =value to check that the record alread exists in $var Table
     * on this method @checkAlreadyExists
     *
     * @return array Return the bindValues for the query
     */
    private function createBindValues() {
        foreach($this->Itens as $Itens => $Val):
            $this->Itens .= $Itens . ' =:' . $Itens . ' AND ';
            $this->Parse .= $Itens . '=' . $Val . '&';
        endforeach;
        
        $this->Itens = substr($this->Itens, 0, strrpos($this->Itens, 'AND'));
        $this->Parse = substr($this->Parse, 0, strrpos($this->Parse, '&'));
        $this->Itens = str_replace('Array', '', $this->Itens);
    }
    
    /**
     * <b>checkAlreadyExists: </b> Compare the @array Iten[key] whith @var Iten[val]
     * If match it that mean the row already exists in the @var  Table so the method stop and return throw new Exception
     *
     * @return Exception in case of error or booleano
     */
    private function checkAlreadyExists() {
        if(!empty($this->Itens)):

            /** Set id = 0 when this not isset and make the query works correctly */
            if(!isset($this->DataObj['id'])):
                $this->DataObj['id'] = 0;
            endif;
            
            /** @method  createBindValues()*/
            $this->createBindValues();
            
            /** @class composer */
            try {
                $ReadItens = new Read;
                $ReadItens->ExeRead($this->Table, '*', "WHERE {$this->Itens} AND id != :id", $this->Parse . "&id={$this->DataObj['id']}");
                
                if($ReadItens->getResult()):
                    throw new Exception("Esse registro já existe.", E_USER_NOTICE);
                endif;
            } catch (Exception $e) {
                echo $e;
            }
        else:
            return true;
        endif;
    }
    
    /**
     * <b>changeDataUser: </b> Check for content in a input
     * Try if all this is null if not, try if either is empty and return the message error
     *
     * @return Exception
     */
    private function changeDataUser() {
         if($this->DataObj['action']=='validate_data_access'):
            if(empty($this->DataObj['email']) && empty($this->DataObj['senha'])):
                $e = new Exception('Preencha ou o campo com o novo e-mail ou o campo com a nova senha. E informe a senha atual para concluir.', E_USER_NOTICE);
            elseif(!empty($this->DataObj['email']) && empty($this->DataObj['senha']) && empty($this->DataObj['atual_pass'])):
                $e = new Exception('Tudo certo. Basta informar sua senha atual.', E_USER_NOTICE);
            elseif(empty($this->DataObj['email']) && !empty($this->DataObj['senha']) && empty($this->DataObj['atual_pass'])):
                $e = new Exception('Tudo certo. Basta informar sua senha atual.', E_USER_NOTICE);
            endif;
        endif;
    }
    
    /**
     * <b>fFriendUrlModelProduct: </b> Transforms the product model to work with url's friendly
     *
     * @return array Increment the @array DataObj with a new index
     */
    private function friendUrlModelProduct() {
        if(isset($this->DataObj['modelo']) && !empty($this->DataObj['modelo'])):
            $Funcoes=new Valid;
            $this->DataObj['modelo_tratado'] = $Funcoes->retira_acentos(utf8_decode($this->DataObj['modelo']), '-');
        endif;
    }
    
    /**
     * <b>removeMask: </b> Remove the characters aditionais from maks plugin jQuery
     *
     * @return array All set fields without the characters from mask
     */
    private function removeMask() {
        if(isset($this->DataObj['preco']) && !empty($this->DataObj['preco'])):
            $this->DataObj['preco'] = str_replace('.', '', $this->DataObj['preco']);
            $this->DataObj['preco'] = str_replace(',', '.', $this->DataObj['preco']);
        endif;
        
        foreach($this->DataObj as $IndiceObj):
            if($IndiceObj=='cnpj' || $IndiceObj=='cpf' || $IndiceObj=='cep' || $IndiceObj=='telefone'):
                $this->DataObj = str_replace(['_', '-', '.', '/'], '', $this->DataObj);
            endif;
        endforeach;
    }
    
    /**
     * <b>encodingSha1</b> Encoding password fields with sha1
     *
     * @return array Change field passwords value in @array DataObj with value encoding by sha1
     */
    private function encodingSha1() {
         if(isset($this->DataObj['senha']) && !empty($this->DataObj['senha'])):
            $this->DataObj['senha'] = sha1($this->DataObj['senha']);
        endif;
    }
    
    /**
     * <b>checkPassActual:</b> Check if this actual password value is true
     *
     * @return json $erros Caso a senha esteja incorreta
     */
    private function checkPassActual() {
        if(isset($this->DataObj['atual_pass']) && !empty($this->DataObj['atual_pass'])):
            
            /** @return Encoding actual password by sha1 */
            $this->DataObj['atual_pass'] = sha1($this->DataObj['atual_pass']);

            try{
                /** @class composer */
                $ReadPass = new Read;
                $ReadPass->ExeRead('rio_clientes', 'senha,id,email', 'WHERE senha = :senha_atual', "senha_atual={$this->DataObj['atual_pass']}");

                 if(!$ReadPass->getResult() && empty($this->Success)):
                     throw new Exception('A senha atual está incorreta', E_USER_NOTICE);
                 endif;
            } catch (Exception $e) {
                echo $e;
            }  
         endif;          
    }
    
    /**
     * <b>unsetFields: </b> Unset index from @array Dataobj with a specif rules
     *
     * @return array @array DataObj with removeds indexes
     */
    private function unsetFields() {
        /** @return Remove the index from @array DataObj */
        unset($this->DataObj['id']);
        unset($this->DataObj['action']);
        unset($this->DataObj['atual_pass']);
        
        /** @return Remove the index email from @array DataObj if is null */
        if(empty($this->DataObj['email'])):
            unset($this->DataObj['email']);
        endif;
        
        /** @return Remove the index senha from @array DataObj if is null */
        if(empty($this->DataObj['senha'])):
            unset($this->DataObj['senha']);
        endif;
    }
    
    /**
     * <b>setActions: </b> Execute the principals methods
     * Can be a insert or a update in a @var Table
     *
     * @return Exception Container a message success
     */
    private function setActions() {
         /** @method unset unsetFields() Remove indexes from @array DataObj */
        $this->unsetFields();
        /** @method Insert insertNewRow() Insert a new record in a @var Table */
        if(!isset($this->Fields['id']) || empty($this->Fields['id'])):
            $this->insertNewRow();
        /** @method Update updateNewRow() Update a new record in a @var Table */
        else:
            $this->updateNewRow();
        endif;
    }
    
    /**
     * <b>setNotExistsFields: </b> Create a new indexes in a @array DataObj
     *
     * @return array @array DataObj with the new indexes
     */
    private function setNotExistsFields() {
        if(!empty($this->DataObj['senha'])):
            $this->DataObj['data_alteracao_senha'] = $this->DataCadastro;
        endif;     
    }
    
    /**
     * <b>updateSession: </b> Update index session when e-mail is update in a @var Table
     *
     * @return array New email value for currenctly session
     */
    private function updateSession() {
        if(!empty($this->DataObj['email'])):
            /** @class composer */
            $sessao = new Session;
            /** @return array New value for set index $_SESSION */
            $_SESSION['logado'] = $this->DataObj['email'];
        endif;
    }
    
    /**
     * <b>insertNewRow: </b> Insert a new row in a @var Table
     *
     * @return boolean
     */
    private function insertNewRow() {
        if($this->checkAlreadyExists()):
            try {
                $InsertData = new Create;
                $InsertData->ExeCreate($this->Table, $this->DataObj);

                /** @return Exception Message successful */
                 if($InsertData->getResult()):

                endif;
            } catch (Exception $e) {
                /** @return json Message in json format for AJAX */
            }
        endif;
    }
    
    /**
     * <b>updateNewRow: Update a exists row in a @var Table</b>
     *
     *  @return boolean
     */
    private function updateNewRow() {
        if($this->checkAlreadyExists()):
            /** @methos Create setNotExistsFields() Create new indexes in a @array DataObj */
            $this->setNotExistsFields();   
        
            try {
                /** @class composer */
                $UpdateData = new Update;
                $UpdateData->ExeUpdate($this->Table,$this->DataObj, "WHERE id=:id", "id={$this->Fields['id']}");

                /** @method Update updateSession() Update the currenctly session with a new email */
                $this->updateSession();

                /** @return Exception */
                if($UpdateData->getResult()):
                    
                endif;
            } catch (Exception $ex) {
                /** @return  */
            }
        endif;
    }
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

E a maneira correta de se trabalhar com o try catch seria essa

try {
                /** @class composer */
                $ReadItens = new Read;
                $ReadItens->ExeRead($this->Table, '*', "WHERE {$this->Itens} AND id != :id", $this->Parse . "&id={$this->DataObj['id']}");
                
                /** @return Error Not an Excepetion */
                if($ReadItens->getResult()):
                    $this->Errors=['erros' => "Campo Esse registro já existe.#exibir_erros"];
                    echo json_encode($this->Errors);
                endif;
            } catch (Exception $e) {
                /** @return */
            }

Compartilhar este post


Link para o post
Compartilhar em outros sites

Consegui uma semântica melhor porém o exception não é passado

try {
                /** @class composer */
                $UpdateData = new Update;
                $UpdateData->ExeUpdate($this->Table,$this->DataObj, "WHERE id=:id", "id={$this->Fields['id']}");

                /** @method Update updateSession() Update the currenctly session with a new email when it exists */
                $this->updateSession();

                if($UpdateData->getResult()):
                     /** @throws Exception */
                     throw new Exception("Registro atualizado com sucesso.", E_USER_NOTICE);
                endif;
            } catch (Exception $ex) {
                /** @return json Message successful for AJAX interaction  */
                $this->Success=['sucesso' => $e];
                echo json_encode($this->Success);
            }

O jSON retorna

sucesso null

Compartilhar este post


Link para o post
Compartilhar em outros sites

Quando eu faço um

throw new Exception("Registro atualizado com sucesso.", E_USER_NOTICE);
eu estou armazenando o erro para ser tratado no catch na variável, nesse caso, $e ? Ou seja, eu armazeno essa mensagem em $e bem como posso pegar o código do erro, o arquivo , etc ... ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Desculpa se estou postando muito é que estou empolgado com essa bagaça e quero ver ela funcionando. Meu presente de aniversário AUAHAUHAUHUAHUA

 

Essa é a versão que finalizei aqui porque tenho que sair

 

 

<?php
ini_set('display_errors',0);
ini_set('display_startup_erros',0);

/**
 * <b>ChangeMySQLTableRows.class [ Change Rows Table ]: </b>
 * Altera uma ou mais linhas da tabela MySQL definida na variável private $Table
 * Os comandos podem ser tanto
 *
 * @copyright (c) 2015, Samuel dos Santos   Programação Criativa
 */
class ChangeMySQLTableRows {   
    /** @var DateTime Tell him, what time is it ? */
    private $DataCadastro;
    
    /** @var  Table The table where the data are change  */
    private $Table;
    
    /** @array Fields Container for params coming from $_POST form */
    private $Fields;
    
    /** @array DataObj Container for @array Fields */
    private $DataObj;
    
    /** @var Erros The error message */
    private $Errors;
    
    /** @var Success The success message */
    private $Success;
    
    /** @array Itens To check if the record is duplicated before inserting it */
    private $Itens;
    
    /** @var Pase To create a bind values for @var Itens */
    private $Parse;
    
    /**
     * @__contruct Required @var Table what receive changes,
     * @array Fields what it contains all $_POST itens from form,
     * @array Itens Optional if  you want to compare fields existings report it in forma ['item' => $Post['field']]
     *
     */
    function __construct($Table, array $Fields, $Itens = null) {
        $this->Table = $Table;
        $this->Fields = $Fields;
        $this->Itens = $Itens;
        $this->DataCadastro = new \DateTime();
        $this->DataObj = $this->Fields;
        
        /** @method friendUrlModelProduct() */
        $this->friendUrlModelProduct();

        /** @method RemoveMask() */
        $this->removeMask();

        /** @method encodingSha1() */
       $this->encodingSha1();

        /** @method checkPassActual() */
        $this->checkPassActual();

        /** @method setErros() */
        $this->setErros();
        
        /** @method setActions() */
        $this->setActions();
    }

    /************************************************************
     * ********************** Private methods **********************/
    /**    
    /**
     * <b>setErros: </b> Set the errors and return from JSON
     *
     * @return Exception
     */
    private function setErros() {
        // Validação para tela de alteração de dados
        if($this->DataObj['action']!='validate_data_access'):
            // Faz a validação dos campos fora da tela de alteração de dados
            foreach($this->Fields as $Indice => $Val):        
                // Lançamos os campos com exceções, ou seja, com preenchimento opcional
                if($Indice != 'action' && $Indice != 'id' && empty($Val) && $Indice != 'garantia' && $Indice != 'link' && $Indice != 'id_sub1' && $Indice != 'id_sub2' && $Indice != 'id_sub3'):
                    $this->Errors=['erros' => "Campo obrigatório#{$Indice}"];
                    echo json_encode($this->Errors);
                    exit;
                endif;
             endforeach;
        endif;
    }

    /**
     * <b>createBindValues: </b> Create bindValues in format :bind | =value to check that the record alread exists in $var Table
     * on this method @checkAlreadyExists
     *
     * @return array Return the bindValues for the query
     */
    private function createBindValues() {
        foreach($this->Itens as $Itens => $Val):
            $this->Itens .= $Itens . ' =:' . $Itens . ' AND ';
            $this->Parse .= $Itens . '=' . $Val . '&';
        endforeach;
        
        $this->Itens = substr($this->Itens, 0, strrpos($this->Itens, 'AND'));
        $this->Parse = substr($this->Parse, 0, strrpos($this->Parse, '&'));
        $this->Itens = str_replace('Array', '', $this->Itens);
    }
    
    /**
     * <b>checkAlreadyExists: </b> Compare the @array Iten[key] whith @var Iten[val]
     * If match it that mean the row already exists in the @var  Table so the method stop and return throw new Exception
     *
     * @return Exception in case of error or booleano
     */
    private function checkAlreadyExists() {
        if(!empty($this->Itens)):

            /** Set id = 0 when this not isset and make the query works correctly */
            if(!isset($this->DataObj['id'])):
                $this->DataObj['id'] = 0;
            endif;
            
            /** @method  createBindValues()*/
            $this->createBindValues();
            
            try {
                /** @class composer */
                $ReadItens = new Read;
                $ReadItens->ExeRead($this->Table, '*', "WHERE {$this->Itens} AND id != :id", $this->Parse . "&id={$this->DataObj['id']}");
                
                if($ReadItens->getResult()):
                    /** @throws Exception */
                    throw new Exception("Esse registro já existe.", E_USER_NOTICE);
                endif;
            } catch (Exception $e) {
                /** @return json Message successful for AJAX interaction  */
                $this->Errors=['erros' => "Esse registro já existe.#exibir_erros"];
                echo json_encode($this->Errors);
            }
        else:
            return true;
        endif;
    }
    
    /**
     * <b>changeDataUser: </b> Check for content in a input
     * Try if all this is null if not, try if either is empty and return the message error
     *
     * @return Exception
     */
    private function changeDataUser() {
         if($this->DataObj['action']=='validate_data_access'):
            if(empty($this->DataObj['email']) && empty($this->DataObj['senha'])):
                $this->Errors=['erros' => "Preencha ou o campo com o novo e-mail ou o campo com a nova senha. E informe a senha atual para concluir.#exibir_erros"];
                echo json_encode($this->Errors);
            elseif(!empty($this->DataObj['email']) && empty($this->DataObj['senha']) && empty($this->DataObj['atual_pass'])):
                $this->Errors=['erros' => "Tudo certo. Basta informar sua senha atual.#exibir_erros"];
                echo json_encode($this->Errors);
            elseif(empty($this->DataObj['email']) && !empty($this->DataObj['senha']) && empty($this->DataObj['atual_pass'])):
                $this->Errors=['erros' => "Tudo certo. Basta informar sua senha atual.#exibir_erros"];
                echo json_encode($this->Errors);
            endif;
        endif;
    }
    
    /**
     * <b>fFriendUrlModelProduct: </b> Transforms the product model to work with url's friendly
     *
     * @return array Increment the @array DataObj with a new index
     */
    private function friendUrlModelProduct() {
        if(isset($this->DataObj['modelo']) && !empty($this->DataObj['modelo'])):
            $Funcoes=new Valid;
            $this->DataObj['modelo_tratado'] = $Funcoes->retira_acentos(utf8_decode($this->DataObj['modelo']), '-');
        endif;
    }
    
    /**
     * <b>removeMask: </b> Remove the characters aditionais from maks plugin jQuery
     *
     * @return array All set fields without the characters from mask
     */
    private function removeMask() {
        if(isset($this->DataObj['preco']) && !empty($this->DataObj['preco'])):
            $this->DataObj['preco'] = str_replace('.', '', $this->DataObj['preco']);
            $this->DataObj['preco'] = str_replace(',', '.', $this->DataObj['preco']);
        endif;
        
        foreach($this->DataObj as $IndiceObj):
            if($IndiceObj=='cnpj' || $IndiceObj=='cpf' || $IndiceObj=='cep' || $IndiceObj=='telefone'):
                $this->DataObj = str_replace(['_', '-', '.', '/'], '', $this->DataObj);
            endif;
        endforeach;
    }
    
    /**
     * <b>encodingSha1</b> Encoding password fields with sha1
     *
     * @return array Change field passwords value in @array DataObj with value encoding by sha1
     */
    private function encodingSha1() {
         if(isset($this->DataObj['senha']) && !empty($this->DataObj['senha'])):
            $this->DataObj['senha'] = sha1($this->DataObj['senha']);
        endif;
    }
    
    /**
     * <b>checkPassActual:</b> Check if this actual password value is true
     *
     * @return json $erros Caso a senha esteja incorreta
     */
    private function checkPassActual() {
        if(isset($this->DataObj['atual_pass']) && !empty($this->DataObj['atual_pass'])):
            
            /** @return Encoding actual password by sha1 */
            $this->DataObj['atual_pass'] = sha1($this->DataObj['atual_pass']);

            try{
                /** @class composer */
                $ReadPass = new Read;
                $ReadPass->ExeRead('rio_clientes', 'senha,id,email', 'WHERE senha = :senha_atual', "senha_atual={$this->DataObj['atual_pass']}");

                 if(!$ReadPass->getResult() && empty($this->Success)):
                    /** @throws Exception */
                     throw new Exception("A senha atual está incorreta.", E_USER_NOTICE);
                 endif;
            } catch (Exception $e) {
                /** @return json Message successful for AJAX interaction  */
                $this->Errors=['erros' => "A senha atual está incorreta.#exibir_erros"];
                echo json_encode($this->Errors);
            }  
         endif;          
    }
    
    /**
     * <b>unsetFields: </b> Unset index from @array Dataobj with a specif rules
     *
     * @return array @array DataObj with removeds indexes
     */
    private function unsetFields() {
        /** @return Remove the index from @array DataObj */
        unset($this->DataObj['id']);
        unset($this->DataObj['action']);
        unset($this->DataObj['atual_pass']);
        
        /** @return Remove the index email from @array DataObj if is null */
        if(empty($this->DataObj['email'])):
            unset($this->DataObj['email']);
        endif;
        
        /** @return Remove the index senha from @array DataObj if is null */
        if(empty($this->DataObj['senha'])):
            unset($this->DataObj['senha']);
        endif;
    }
    
    /**
     * <b>setActions: </b> Execute the principals methods
     * Can be a insert or a update in a @var Table
     *
     * @return Exception Container a message success
     */
    private function setActions() {
         /** @method unset unsetFields() Remove indexes from @array DataObj */
        $this->unsetFields();
        /** @method Insert insertNewRow() Insert a new record in a @var Table */
        if(!isset($this->Fields['id']) || empty($this->Fields['id'])):
            $this->insertNewRow();
        /** @method Update updateNewRow() Update a new record in a @var Table */
        else:
            $this->updateNewRow();
        endif;
    }
    
    /**
     * <b>setNotExistsFields: </b> Create a new indexes in a @array DataObj
     *
     * @return array @array DataObj with the new indexes
     */
    private function setNotExistsFields() {
        if(!empty($this->DataObj['senha'])):
            $this->DataObj['data_alteracao_senha'] = $this->DataCadastro;
        endif;     
    }
    
    /**
     * <b>updateSession: </b> Update index session when e-mail is update in a @var Table
     *
     * @return array New email value for currenctly session
     */
    private function updateSession() {
        if(!empty($this->DataObj['email'])):
            /** @class composer */
            $sessao = new Session;
            /** @return array New value for set index $_SESSION */
            $_SESSION['logado'] = $this->DataObj['email'];
        endif;
    }
    
    /**
     * <b>insertNewRow: </b> Insert a new row in a @var Table
     *
     * @return boolean
     */
    private function insertNewRow() {
        if($this->checkAlreadyExists()==true):
            try {
                $InsertData = new Create;
                $InsertData->ExeCreate($this->Table, $this->DataObj);

                /** @return Exception Message successful */
                 if($InsertData->getResult()):
                     /** @throws Exception */
                     throw new Exception("Registro inserido com sucesso.", E_USER_NOTICE);
                endif;
            } catch (Exception $e) {
                /** @return json Message successful for AJAX interaction  */
                $this->Success=['sucesso' => 'Registro inserido com sucesso.'];
                echo json_encode($this->Success);
            }
        endif;
    }
    
    /**
     * <b>updateNewRow: Update a exists row in a @var Table</b>
     *
     *  @return boolean
     */
    private function updateNewRow() {
        if($this->checkAlreadyExists()==true):
            /** @methos Create setNotExistsFields() Create new indexes in a @array DataObj */
            $this->setNotExistsFields();   
        
            try {
                /** @class composer */
                $UpdateData = new Update;
                $UpdateData->ExeUpdate($this->Table,$this->DataObj, "WHERE id=:id", "id={$this->Fields['id']}");

                /** @method Update updateSession() Update the currenctly session with a new email when it exists */
                $this->updateSession();

                if($UpdateData->getResult()):
                     /** @throws Exception */
                     throw new Exception("Registro atualizado com sucesso.", E_USER_NOTICE);
                endif;
            } catch (Exception $e) {
                /** @return json Message successful for AJAX interaction  */
                $this->Success=['sucesso' => 'Registro atualizado com sucesso.'];
                echo json_encode($this->Success);
            }
        endif;
    }
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

É importante se impolgar, pois, apesar de exigir muito trabalho, é bem satisfatório. Vamos aos trabalhos iniciais.

Documentation phpDoc
O phpDoc, além de documentar o código, supre alguns pontos que o PHP deixa de lado. Um deles é a tipagem de dados e retorno.

Comentários do phpDoc sempre devem estar em blocos de comentários (DocBLock). Então comentários de uma linha não são válidos. Como o comentário abaixo.

/** @var DateTime Tell him, what time is it ? */
private $DataCadastro;

o phpDocumentor se baseia, principalmente, em annotations dentro dos DocBlocks, toda a lista de annotations disponíveis você pode visualizar no link acima da documentação do phpDoc.

Falando sobre a @var, após a annotation, deve vir o tipo da variável e, de forma opcional, sua descrição. Nesta parte abaixo, está incorreta:

/** @array Fields Container for params coming from $_POST form */
private $Fields;

O correto deveria ser:

/**
 * @var array Fields Container for params coming from $_POST form 
 */
private $Fields;

Outro ponto interessante, é que você pode identificar o tipo que será utilizado dentro do array, tal como um array de strings:

/**
 * @var string[]
 */

Um array de vários tipos:

/**
 * @var mixed[]
 */

Um vetor (array de multipla dimensão):

/**
 * @var array[]
 */

E, também, um conjunto de valores:

/**
 * @var string|null
 */

Nesse último exemplo, é explícito que o valor só pode ser entre string ou null.

Outra parte dos comentários, é sua utilidade. Comentários devem complementar a leitura do código, e não repeti-la. Em todas as linhas, abaixo copiadas, você está sendo redundante, comentando o que o próprio código já está me dizendo.

/** @method friendUrlModelProduct() */
$this->friendUrlModelProduct();

/** @method RemoveMask() */
$this->removeMask();

/** @method encodingSha1() */
$this->encodingSha1();

/** @method checkPassActual() */
$this->checkPassActual();

/** @method setErros() */
$this->setErros();

/** @method setActions() */
$this->setActions();

Outros pontos de comentários redundantes:

/************************************************************
     * ********************** Private methods **********************/
/** @throws Exception */

O @throws deve ser utilizado, mas não aonde ele está e sim na assinatura do método:

/**
 * <b>insertNewRow: </b> Insert a new row in a @var Table
 *
 * @return boolean
 * @throws \Exception If cannot insert a new row
 */
private function insertNewRow() {

Seguindo o mesmo padrão, o tipo da exception lançada e, opcionalmente, a sua descrição.

Codificação:

Colocar as propriedades em lowerCamelCase e, de preferência, em inglês. Anteriormente eu não comentei, mas não é uma necessidade ser em inglês, mas é importante seguir um padrão e, já que a linguagem de programação é em inglês, facilita bastante tudo ser em inglês:

/** 
 * @var DateTime 
 */
private $dateInsert;

/** 
 * @var string  
 */
private $table;

/** 
 * @var string[]
 */ 
private $fieldList;

É uma convenção, ajuda bastante na leitura.

Outro ponto, não anteriormente comentado, não abrevie nada. O código em si deve dizer o que ele se propõe. Logo, não é bom ver nada disso aqui:

private $DataObj;

São apenas algumas "letrinhas" a mais e que, para a compreensão, fazem uma enorme diferença:

private $dataObject;

Por enquanto é o que eu pude escrever com o tempo disponível que eu possuo. Assim que tiver mais tempo, passarei mais detalhes.

Como sugestão, leia e aplique os links abaixo (são os mais importantes nesse momento):
http://pt.slideshare.net/guilhermeblanco/phpubsp-object-calisthenics-aplicado-ao-php?next_slideshow=1
http://pt.slideshare.net/guilhermeblanco/php-para-adultos-clean-code-e-object-calisthenics

PSR - 1: http://www.php-fig.org/psr/psr-1/

PSR - 2: http://www.php-fig.org/psr/psr-2/

Compartilhar este post


Link para o post
Compartilhar em outros sites

Suas dicas são boas Gabriel. Sei que não consegui eliminar todas as falhas, porque realmente li todas as referência que você me passou, mas, está funcionando agora perfeitamente e atende como eu esperava. Aliás, está orientado a objetos e tudo que eu fazia manualmente e "proceduralmente" não é mais necessário. Viva o/

 

Se quiser avaliar novamente ignorando alguns poucos métodos que fogem da regra de manter apenas um nível de indentação e um ou outro que utilizam o else e o elseif, fique a vontade. Suas críticas são muito construtivas e ajudaram a melhorar meu código então, quanto mais melhor =)

<?php
/**
 * <b>ChangeMySQLTableRows.class [ Change Rows Table ]: </b>
 * Altera uma ou mais linhas da tabela MySQL definida na variável private $Table
 * Os comandos podem ser tanto
 *
 * @copyright (c) 2015, Samuel dos Santos   Programação Criativa
 */
class ChangeMySQLTableRows {   
    /**
     * @var \DateTime $actualData Tell him, what time is it ?
     */
    private $actualData;
    
    /**
     * @var  string $table The table will receive changes
     */
    private $table;
    
    /**
     * @var array $fields It contains the data coming from form
     */
    private $fields;
    
    /**
     * @var mixed[] $dataObject It contains the same values in the @table
     * but it is usage for eliminate indexes before insert or update any data
     */
    private $dataObject;
    
    /**
     * @var string | null $errors It contains the message error, when exist
     */
    private $errors;
    
    /**
     * @var string | null $success It contains the message success, when exist
     */
    private $success;
    
    /**
     * @var mixed[] $itens Stores  the values to compare if the record
     * already exists in the @table
     */
    private $itens;
    
    /**
     * @var string $parse Stores the bind values for compare in query
     * when we need to check if the record already exists in the @table
     */
    private $parse;
    
    /**
     * This contructor require an @var string $table, an @var array $fields and optional @var mixed[] $itens
     * for initializate the class correctly and work well. And finaly this call the principal methods for work with it
     */
    function __construct($table, array $fields, $itens = null) {
        $this->table = $table;
        $this->fields = $fields;
        $this->itens = $itens;
        $this->actualData = new DateTime();
        $this->dataObject = $this->fields;

        /**
         * Call the methods in order of execute
         */
        $this->changeDataUser();
        $this->friendUrlModelProduct();
        $this->removeMask();
        $this->encodingSha1();
        $this->checkPassActual();
        $this->checkAlreadyExists();
        $this->setErros();
        $this->setActions();
    }

    /**
     * <b>setErros: </b> Set the errors and return if from AJAX
     * This return will be focus the fiel id pass in second param object
     * This work well like this:
     * we explode this json and stores it in an new array where index[0] contains the message
     * and index[1] contains the field what we are focus and change a background
     *
     * @return \Exception Return this error in json format
     */
    private function setErros() {
        if($this->dataObject['action']!='validate_data_access'):
            foreach($this->fields as $Indice => $Val):        
                if($Indice != 'action' && $Indice != 'id' && empty($Val) && $Indice != 'garantia' && $Indice != 'link' && $Indice != 'id_sub1' && $Indice != 'id_sub2' && $Indice != 'id_sub3'):
                    $e = new Exception("Campo obrigatório#{$Indice}", E_USER_NOTICE);
                    $this->errors=['erros' => $e->getMessage()];
                    echo json_encode($this->errors);
                    exit;
                endif;
             endforeach;
        endif;
    }

    /**
     * <b>createBindValues: </b> Create bindValues in format :bind | =value to check that the record alread exists in $var Table
     * on this method @checkAlreadyExists
     *
     * @return array Return the bindValues for the query
     */
    private function createBindValues() {       
        foreach($this->itens as $itens => $val):
            $this->itens .= $itens . ' = :' . $itens . ' AND ';
            $this->parse .= $itens . '=' . $val . '&';
        endforeach;
        
        $this->itens = substr($this->itens, 0, strrpos($this->itens, 'AND'));
        $this->parse = substr($this->parse, 0, strrpos($this->parse, '&'));
        $this->itens = str_replace('Array', '', $this->itens);
    }
    
    /**
     * <b>checkAlreadyExists: </b> Compare the @array Iten[key] whith @var Iten[val]
     * If match it that mean the row already exists in the @var  Table so the method stop and return throw new Exception
     *
     * @return \Exception Case this params match
     */
    private function checkAlreadyExists() {
        if(!empty($this->itens)):
            try {
                if(!isset($this->dataObject['id'])):
                    $this->dataObject['id'] = 0;
                endif;
            
                $this->createBindValues();
                $ReadItens = new Read;
                $ReadItens->ExeRead($this->table, '*', "WHERE {$this->itens} AND id != :id", $this->parse . "&id={$this->dataObject['id']}");
                
                if($ReadItens->getResult()):
                    throw new Exception("Esse registro já existe.#exibir_erros", E_USER_NOTICE);
                endif;
            } catch (Exception $e) {
                $this->errors=['erros' => $e->getMessage()];
                echo json_encode($this->errors);
                exit;
            }
        else:
            return true;
        endif;
    }
    
    /**
     * <b>changeDataUser: </b> Check for content in a input
     * Try if all this is null if not, try if either is empty and return the message error
     *
     * @return Exception Return it in json format
     */
    private function changeDataUser() {
         if($this->dataObject['action']=='validate_data_access'):
            if(empty($this->dataObject['email']) && empty($this->dataObject['senha'])):
                $this->errors=['erros' => "Preencha ou o campo com o novo e-mail ou o campo com a nova senha. E informe a senha atual para concluir.#exibir_erros"];
                echo json_encode($this->errors);
                exit;
            elseif(!empty($this->dataObject['email']) && empty($this->dataObject['senha']) && empty($this->dataObject['atual_pass'])
                || (empty($this->dataObject['email']) && !empty($this->dataObject['senha']) && empty($this->dataObject['atual_pass']))):
                $this->Errors=['erros' => "Tudo certo. Basta informar sua senha atual.#exibir_erros"];
                echo json_encode($this->Errors);
                exit;
            endif;
        endif;
    }
    
    /**
     * <b>fFriendUrlModelProduct: </b> Transforms the product model to work with url's friendly
     *
     * @return array Increment @var mixed[] $dataObject with the new index
     */
    private function friendUrlModelProduct() {
        if(isset($this->dataObject['modelo']) && !empty($this->dataObject['modelo'])):
            $Funcoes=new Valid;
            $this->dataObject['modelo_tratado'] = $Funcoes->retira_acentos(utf8_decode($this->dataObject['modelo']), '-');
        endif;
    }
    
    /**
     * <b>removeMask: </b> Remove the characters aditionais from maks plugin jQuery
     *
     * @return array All set fields without the characters from mask
     */
    private function removeMask() {
        if(isset($this->dataObject['preco']) && !empty($this->dataObject['preco'])):
            $this->dataObject['preco'] = str_replace('.', '', $this->dataObject['preco']);
            $this->dataObject['preco'] = str_replace(',', '.', $this->dataObject['preco']);
        endif;
        
        foreach($this->dataObject as $IndiceObj):
            if($IndiceObj=='cnpj' || $IndiceObj=='cpf' || $IndiceObj=='cep' || $IndiceObj=='telefone'):
                $this->dataObject = str_replace(['_', '-', '.', '/'], '', $this->dataObject);
            endif;
        endforeach;
    }
    
    /**
     * <b>encodingSha1</b> Encoding password fields with sha1
     *
     * @return array Return it encoding by sha1
     */
    private function encodingSha1() {
         if(isset($this->dataObject['senha']) && !empty($this->dataObject['senha'])):
            $this->dataObject['senha'] = sha1($this->dataObject['senha']);
        endif;
    }
    
    /**
     * <b>checkPassActual:</b> Check if this pass actual password value is true
     *
     * @return \Exception Return it in json format
     */
    private function checkPassActual() {
        if(isset($this->dataObject['atual_pass']) && !empty($this->dataObject['atual_pass'])):
            $this->dataObject['atual_pass'] = sha1($this->dataObject['atual_pass']);

            try{
                $ReadPass = new Read;
                $ReadPass->ExeRead('rio_clientes', 'senha,id,email', 'WHERE senha = :senha_atual', "senha_atual={$this->dataObject['atual_pass']}");

                 if(!$ReadPass->getResult() && empty($this->success)):
                     throw new Exception("A senha atual está incorreta.#exibir_erros", E_USER_NOTICE);
                 endif;
            } catch (Exception $e) {
                $this->errors=['erros' => $e->getMessage()];
                echo json_encode($this->errors);
                exit;
            }  
         endif;          
    }
    
    /**
     * <b>unsetFields: </b> Unset indexes from @var mixed[] dataObject
     *
     * @return array Return it with removed indexes
     */
    private function unsetFields() {
        unset($this->dataObject['id']);
        unset($this->dataObject['action']);
        unset($this->dataObject['atual_pass']);
        
        if(empty($this->dataObject['email'])):
            unset($this->dataObject['email']);
        endif;
        
        if(empty($this->dataObject['senha'])):
            unset($this->dataObject['senha']);
        endif;
    }
    
    /**
     * <b>setActions: </b> Execute the principals methods
     * Can be a insert or a update in a @var string $table after clean indexes
     *
     * @return \Exception Contains the message successful
     */
    private function setActions() {
        $this->unsetFields();
        
        if(!isset($this->fields['id']) || empty($this->fields['id'])):
            $this->insertNewRow();
        else:
            $this->updateNewRow();
        endif;
    }
    
    /**
     * <b>setNotExistsFields: </b> Create a new indexes in a @var mixed[] dataObject
     *
     * @return array $dataObject with the new indexes
     */
    private function setNotExistsFields() {
        if(!empty($this->dataObject['senha'])):
            $this->dataObject['data_alteracao_senha'] = $this->actualData->format('Y-m-d H:i:S');
        endif;     
    }
    
    /**
     * <b>updateSession: </b> Update index session when e-mail is update in a @var string $table
     *
     * @return array New email value for currenctly session
     */
    private function updateSession() {
        if(!empty($this->dataObject['email'])):
            $sessao = new Session;
            $_SESSION['logado'] = $this->dataObject['email'];
        endif;
    }
    
    /**
     * <b>insertNewRow: </b> Insert a new row in a @var string $table
     *
     * @return boolean
     */
    private function insertNewRow() {
        try {
            $InsertData = new Create;
            $InsertData->ExeCreate($this->table, $this->dataObject);

            if($InsertData->getResult()):
                 throw new Exception("Registro inserido com sucesso.", E_USER_NOTICE);
            endif;
        } catch (Exception $e) {
            $this->success=['sucesso' => $e->getMessage()];
            echo json_encode($this->success);
            exit;
        }
    }
    
    /**
     * <b>updateNewRow: </b> Update a exists row in a @var string $table
     * Create the indexes when it not exist but it is necessary for work right
     * Updates the session when the email is changed
     *
     *  @return boolean
     */
    private function updateNewRow() {
        $this->setNotExistsFields();   

        try {
            $UpdateData = new Update;
            $UpdateData->ExeUpdate($this->table,$this->dataObject, "WHERE id=:id", "id={$this->fields['id']}");
            $this->updateSession();

            if($UpdateData->getResult()):
                 throw new Exception("Registro atualizado com sucesso.", E_USER_NOTICE);
            endif;
        } catch (Exception $e) {
            $this->success=['sucesso' => $e->getMessage()];
            echo json_encode($this->success);
            exit;
        }
    }
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Aproveitando o andamento do enredo do filme, tem como fazer isso de forma a manter apenas um nível de indentação?

 

 

/** @return array Contains a list of sub3 registry or message not found any itens */
if($post_data['action']=='search_for_sub2'):
    try {
        $ReadSu3 = new Read;
        $ReadSu3->ExeRead('rio_sub3', 'nome,id,sub2', 'WHERE status = :status AND sub2 = :id_sub2 ORDER BY nome', "status=1&id_sub2={$post_data['id_sub2']}");

        if($ReadSu3->getResult()):
            $array_data = "<option value=\"0\">Selecione</option>";
            
            foreach($ReadSu3->getResult() as $Sub3):
                $array_data .= "<option value=\"{$Sub3->id}\">{$Sub3->nome}</option>";
            endforeach;
            
            throw new Exception($array_data, E_USER_NOTICE);
        else:
            throw new Exception("<option value=\"0\">Nenhuma sub de nível 3   encontrada</option>", E_USER_NOTICE);
        endif;
    } catch (Exception $e) {
        echo json_encode($e->getMessage());
    }
endif;

 

Porque pelo que vi, um if else sempre vai acrescentar um tab na indentação do código.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sempre há, e veja que não vou utilizar ELSE:

 

Primeiramente, eu vou imaginar que tudo isso fica dentro de um metodo action, então ou colocar dessa forma:

public function action($post_data) {
   /** seu código aqui **/
}

Primeiramente, vou separar as responsabilidades, uma vez definida, chamo uma nova action, pois realmente está sendo realizada uma nova ação conforme o IF definido:

public function action($post_data) {
    /** @return array Contains a list of sub3 registry or message not found any itens */
    if($post_data['action']=='search_for_sub2'):
        $this->actionSearchSub2();
    endif;
}

Segundo o autor Robert "UncleBob" Martin, tudo dentro de um try, deve ser tratada como "uma só coisa" (realmente ele define dessa maneira). Dessa forma, ele indica para separar em um método a execução do comando que deve ser tratado em caso de uma exceção:

private function actionSearchSub2() {    
    try {
        /** eu adicionei o echo json_encode aqui **/
        echo json_encode($this->readSub3());
    } catch (Exception $e) {
        echo json_encode($e->getMessage());
    }
}

E por último, mas não menos importante:

private function readSub3() {
    $ReadSu3 = new Read;
    $ReadSu3->ExeRead('rio_sub3', 'nome,id,sub2', 'WHERE status = :status AND sub2 = :id_sub2 ORDER BY nome', "status=1&id_sub2={$post_data['id_sub2']}");

    if($ReadSu3->getResult()):
        throw new Exception("<option value=\"0\">Nenhuma sub de nível 3   encontrada</option>", E_USER_NOTICE);
    endif;
    
    $array_data = "<option value=\"0\">Selecione</option>";    
    foreach($ReadSu3->getResult() as $Sub3):
        $array_data .= "<option value=\"{$Sub3->id}\">{$Sub3->nome}</option>";
    endforeach;    
    return $array_data;
}

Veja que, alterei a lógica da sua verificação e coloquei um early return na questão de lançamento da exception (removendo, então, o else utilizado). E, mais abaixo, utilize return $array_data ao invés do lançamento da exception, pois o fluxo ocorreu conforme o esperado, e não conforme a exception.

 

O que pode ser modificado, já que existe uma certa duplicação de código, é o seguinte:

private function actionSearchSub2() {    
    try {
        $data = $this->readSub3();
    } catch (Exception $e) {
        $data = $e->getMessage();
    } finally {
        echo json_encode($data);
    }
}

dessa forma, o output ocorre somente em um lugar e, ainda por cima, cumprindo o fluxo de execução desejado.

 

Apesar do resultado final ter mais linhas de código, ficou visivelmente mais limpo e mais fácil de ler, uma vez que a execução do código é linear e não mais condicionada.

 

Sobre o tópico principalmente, eu ainda não esqueci :D

Mas acho que esse exemplo agora, pode ser aplicado ao seu código atual.

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.