TransWikia.com

Validações de endereço / classe / método

Stack Overflow em Português Asked on December 23, 2020

Cenário

Utilizo um método para instanciar classes e métodos dinamicamente.

Propriedades recebidas:

  • modulo = nome da pasta com os arquivos .class.php
  • ferramenta = nome do arquivo .class.php
  • acao = nome do método

Método que executa a solicitação:

private function executar()
{
    try {
        # Monta o patch e faz require da classe
        $classe     = DIR_MODULOS . $this -> modulo . DS . $this -> ferramenta . '.class.php';
        require_once $classe;
        # Instancia o objeto e executa o método
        $obj        = new $this -> ferramenta();
        $resposta   = $obj -> {$this -> acao}($this -> dados);
        # Retorna a resposta
        $this -> retorno = $resposta;

        } catch (Exception $e) {

            $this -> error =  $e->getMessage();
    }
}

Problemas

  • Se a propriedade modulo vier incorreta, não irá achar o caminho da pasta.
    • Erro: Warning e Fatal Error de require.
  • Se a propriedade ferramenta vier incorreta, não irá achar o arquivo da classe.
    • Erro: Warning e Fatal Error de require.
  • Se a propriedade acao vier incorreta, não irá achar o método na classe.
    • Erro: Erro na chamada do método: Fatal error: Call to undefined method

Dúvida

  • Qual a melhor forma de tratar os erros já que o try-catch não os trata?

    (de preferência, funções nativas)


Objetivo

A ideia é retornar apenas uma string simples conforme o erro.

Exemplo:

  • “Módulo inválido”
  • “Ferramenta inválida”
  • “Ação inválida”

2 Answers

Consegui resolver utilizando o file_exists, class_exists e method_exists.

PS: Como citado pelo Maniero, por ser dinâmico poderá trazer falhas de segurança. No meu caso tratadas antes de chegar a esse método, mas segurança nunca é muito.


Como ficou:

private function executar()
{
    # Verifica ...
    if (...) {

        # Verifica propriedades mínimas
        if (...) {

            # Monta o path do diretório
            $dir  = DIR_MODULOS . $this -> modulo;
            # Verifica se existe o diretório
            if (file_exists($dir)) {

                # Monta o path do arquivo
                $classe  = DIR_MODULOS . $this -> modulo . DS . $this -> ferramenta . '.class.php';
                # Verifica se existe o arquivo
                if (file_exists($classe)) {

                    # Inclui a classe
                    require_once $classe;
                    # Verifica se existe a classe no arquivo
                    if (class_exists($this -> ferramenta)) {

                        # Cria objeto
                        $obj = new $this -> ferramenta();
                        # Verifica se o método existe
                        if (method_exists($obj, $this -> acao)) {

                            # Executa o método
                            $retorno = $obj -> {$this -> acao}($this -> dados);
                            # Retorna a resposta
                            $this -> retorno = $retorno;

                        } else {
                            $this -> error = "Ação inexistente.";
                        }

                    } else {
                        $this -> error = "Ferramenta inválida 2.";
                    }

                } else {
                    $this -> error = "Ferramenta inválida 1.";
                }

            } else {
                $this -> error = "Módulo inválido.";
            }

        } else {
            $this -> error = "Erro na estrutura JSON.";
        }

    } else {
        $this -> error = "Erro ...!";
    }

}

Links úteis:

file_exists

class_exists

method_exists

Correct answer by rbz on December 23, 2020

O uso de try-catch aí já é errado. Eu respondo isso em várias perguntas aqui no SOpt (recomendo seguir os links fortemente). Não capture Exception a não ser na saída final do código e não capture uma exceção para fazer nada útil.

O que está reportando é um erro de programação, e erros de programação a gente corrige e não tenta se recuperar. Exceção é para se recuperar de uma falha não esperada, mas não um erro de programação.

Em códigos de natureza dinâmica, e em linguagem de tipagem dinâmica tudo é mais ou menos de natureza dinâmica, você deve verificar o que vai usar antes de usar. A verificação só não precisa ser feita onde é garantido que dará certo.

O erro de programação aí é não considerar que o dado pode vir errado. Então antes de usar algo com potencial de estar errado verifique se está certo e decida o que fazer se estiver errado. Só execute se tudo está correto. Quase sempre o if é seu amigo.

Quem sabe um dia eu escreva um livro sobre o assunto :). Sim, para dominar exceção e tratamento de erro precisa de um livro. Por isso mesmo a maioria das pessoas não vão aprender, quase todo mundo hoje em dia não quer ler, não quer gastar tempo aprendendo, faz o que é simples, mesmo que seja errado e se funcionar, tá bom. É bem complicado tratar erros corretamente, e mais ainda usar exceção. Uma coisa que sempre falo é que se não domina um recurso, não o use, e este é o caso da exceção, por isso tenho uma palestra chama "Exceção - o goto do século XXI" já que é o mecanismo que mais causa problemas para as pessoas, causa muito mais que o goto que todo mundo sabe que não é para usar.

Answered by Maniero on December 23, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP