Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Comando personalizado do Artisan para execução mesmo que o erro esteja sendo tratado com try catch

Boa tarde! Escrevi um comando no Laravel para utilizar pelo php artisan, contudo, mesmo tratando a exceção com try catch, ele para a execução no primeiro lançamento de exceção que encontra. Porque isso acontece?Classe Person.php:

<?php

namespace Domain\Person;

use DomainException;
use Domain\Phone;
use LaravelLegends\PtBrValidator\Rules\Cpf;
use LaravelLegends\PtBrValidator\Rules\Cnpj;

class Person
{
    private string $name;
    private string $document;
    private string $personNature;
    private string $status;
    private array $phones = [];

    public function __construct(
        string $name, 
        string $document, 
        string $phones,
        string $personNature,
        string $status
    )
    {
        $this->setName($name);
        $this->setPersonNature($personNature);
        $this->setDocument($document);
        $this->setPhones($phones);
        $this->setStatus($status);
    }

    public function setStatus($status): void
    {
        $this->status = $status;
    }

    public function getStatus(): string
    {
        return $this->status;
    }

    public function setPersonNature(string $personNature): void
    {
        if (($personNature <> 'F') and ($personNature <> 'J')) {
            throw new DomainException('Natureza da pessoa inválida');
        }

        $this->personNature = $personNature;
    }

    public function setDocument(string $document): void
    {
        $cpfValidator = new Cpf();
        $cnpjValidator = new Cnpj();
        
        if (strlen($document) == 0) throw new DomainException("Sem número do CNPJ/CPF.");

        if ($this->personNature = 'F') {
            $document = str_pad($document, 11, '0', STR_PAD_LEFT);
            if (!$cpfValidator->passes('', $document)) throw new DomainException("Documento $document inválido");
        } else {
            $document = str_pad($document, 14, '0', STR_PAD_LEFT);
            if (!$cnpjValidator->passes('', $document)) throw new DomainException("Documento $document inválido");
        }

        $this->document = $document;
    }

    public function setName(string $name): void
    {
        if (str_word_count($name) < 2) throw new DomainException("Nome do cliente incompleto: $name");
        
        $this->name = ucwords(strtolower($name));
    }

    public function setPhones(string $phones): void
    {
        $phonesArray = explode(',', $phones);

        foreach ($phonesArray as $phoneNumber) {
            $phoneNumber = preg_replace('/[^0-9]/', '', $phones);
            try {
                array_push($this->phones, new Phone($phoneNumber));
            } finally {
            }
        }
    }

    public function getPhones(): array
    {
        return $this->phones;
    }

    public function __toString(): string
    {
        $strReturn = "Nome: $this->name / ";
        $strReturn .= ($this->personNature = 'F') ? "CPF: " : "CNPJ: ";
        $strReturn .= $this->document . " / ";

        $phones = "Telefones: ";
        foreach ($this->phones as $phone) {
            $phones .= $phone . " / ";
        }
        $strReturn .= $phones;

        $strReturn .= "Natureza: $this->personNature" . PHP_EOL;
        return $strReturn;
    }
}

Command:

<?php

namespace App\Console\Commands;

use Domain\Person\Person;
use Illuminate\Console\Command;

class IntegratePeople extends Command
{   
    protected string $signature = 'app:integrate-people';

    protected string $description = 'Command description';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $this->info("Integrando pessoas...");

        $csvFile = '/var/www/DadosClientes.csv';
        if (($handle = fopen($csvFile, 'r')) !== FALSE) {
            $qtyRegisters = 0;
            $qtyRegistersValids = 0;
            while (($data = fgetcsv($handle, 1000, ',')) !== FALSE) {
                if ($data[0] != 'Código') {
                    try {
                        $person = new Person($data[1], $data[3], $data[18], $data[4], $data[7]);
                        if ($person->getStatus() == 'Ativo') $qtyRegistersValids++;
                    } catch (Exception $e) {
                        $this->error($e->getMessage());
                    }
                    $qtyRegisters++;
                }
            }
            // Fecha o arquivo
            $this->info("Total de registros: $qtyRegisters / Válidos: $qtyRegistersValids");
            fclose($handle);
        } else {
            $this->error("Não foi possível abrir o arquivo CSV.");
        }
    }
}

Obrigado.

2 respostas
solução!

Olá Daniel, boa tarde! Tudo joia?

Pelo que você descreveu, parece que o comando está parando a execução mesmo com o try catch em volta do código que pode lançar exceções. Vamos analisar alguns pontos que podem estar causando esse comportamento, principalmente, os possíveis problemas e soluções:

  1. Erro de Sintaxe ou Lógica no Código:

    • No método setPhones da classe Person, você está usando $phones dentro do preg_replace em vez de $phoneNumber. Isso pode estar causando problemas.
    • No método setDocument, você está usando uma atribuição (=) em vez de uma comparação (== ou ===) na linha if ($this->personNature = 'F'). Isso sempre vai definir $this->personNature como 'F'.
  2. Tratamento de Exceção:

    • Certifique-se de que todas as exceções possíveis estão sendo capturadas. No seu catch, você está capturando a exceção base Exception, mas algumas exceções específicas podem não estar sendo capturadas corretamente.

Aqui estão algumas sugestões de ajustes no seu código:

Classe Person

public function setDocument(string $document): void
{
    $cpfValidator = new Cpf();
    $cnpjValidator = new Cnpj();
    
    if (strlen($document) == 0) throw new DomainException("Sem número do CNPJ/CPF.");

    if ($this->personNature == 'F') { // Corrigido para comparação
        $document = str_pad($document, 11, '0', STR_PAD_LEFT);
        if (!$cpfValidator->passes('', $document)) throw new DomainException("Documento $document inválido");
    } else {
        $document = str_pad($document, 14, '0', STR_PAD_LEFT);
        if (!$cnpjValidator->passes('', $document)) throw new DomainException("Documento $document inválido");
    }

    $this->document = $document;
}

public function setPhones(string $phones): void
{
    $phonesArray = explode(',', $phones);

    foreach ($phonesArray as $phoneNumber) {
        $phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber); // Corrigido para usar $phoneNumber
        try {
            array_push($this->phones, new Phone($phoneNumber));
        } catch (Exception $e) {
            // Log ou tratamento adicional
        }
    }
}

Comando IntegratePeople

Certifique-se de que o arquivo CSV está sendo lido corretamente e que o formato dos dados está correto.

public function handle()
{
    $this->info("Integrando pessoas...");

    $csvFile = '/var/www/DadosClientes.csv';
    if (($handle = fopen($csvFile, 'r')) !== FALSE) {
        $qtyRegisters = 0;
        $qtyRegistersValids = 0;
        while (($data = fgetcsv($handle, 1000, ',')) !== FALSE) {
            if ($data[0] != 'Código') {
                try {
                    $person = new Person($data[1], $data[3], $data[18], $data[4], $data[7]);
                    if ($person->getStatus() == 'Ativo') $qtyRegistersValids++;
                } catch (DomainException $e) {
                    $this->error($e->getMessage());
                } catch (Exception $e) {
                    $this->error("Erro inesperado: " . $e->getMessage());
                }
                $qtyRegisters++;
            }
        }
        // Fecha o arquivo
        $this->info("Total de registros: $qtyRegisters / Válidos: $qtyRegistersValids");
        fclose($handle);
    } else {
        $this->error("Não foi possível abrir o arquivo CSV.");
    }
}

Esses ajustes devem ajudar a capturar todas as exceções corretamente e garantir que a execução continue mesmo que uma exceção seja lançada. Verifique também se há algum outro ponto no código que possa estar lançando exceções não tratadas.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

Boa tarde @armano-junior! Com suas dicas pude perceber meu erro. Minha IDE estava com uma falha que fez com que eu não importasse a classe Exception através do use Exception. Era isso que fazia não capturar corretamente a exceção. Muito obrigado.