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

spl_autoload_register() não funciona sem __DIR__

Meu autoloader não está funcionando como o esperado com o código da aula.

<?php

spl_autoload_register(function (string $nomeCompletoDaClasse){
    $caminhoArquivo = str_replace('Alura\\Banco', 'src', $nomeCompletoDaClasse);
    $caminhoArquivo = str_replace('\\', DIRECTORY_SEPARATOR, $caminhoArquivo);
    $caminhoArquivo .= '.php';

    if(file_exists($caminhoArquivo)) {
        require_once $caminhoArquivo;
    }
});

Para funcionar tive que adicionar o __DIR__ e o separador de diretórios na verificação e no require_once().

<?php

// Executes the given function when failing to load a class
spl_autoload_register(function (string $nomeClasse){

    $basePath = __DIR__ . DIRECTORY_SEPARATOR;

    $caminhoArquivo = str_replace('Alura\\Banco', "$basePath\src", $nomeClasse);
    $caminhoArquivo = str_replace('\\', DIRECTORY_SEPARATOR, $caminhoArquivo); // DIRECTORY_SEPARATOR is a default constant of PHP
    $caminhoArquivo .= '.php';

    if (file_exists($caminhoArquivo)) {
        require_once $caminhoArquivo;
    } else {
        echo "Caminho \"$caminhoArquivo\" não encontrado!";
        exit();
    }
});

A árvore de diretórios está assim:

Listagem de caminhos de pasta

C:\USERS\ALEXANDRE CARRETERO\GOOGLE DRIVE\ESTUDOS\PROGRAMACAO\ALURA\PHP\ALURA\ROOT

Alura-Banco
   autoload.php
   banco.php
   README.md

    src
        Modelo
           CPF.php
           Endereco.php
           Funcionario.php
           Pessoa.php

            Conta
                Conta.php
                Titular.php

Alguém pode me ajudar a entender o porquê?

5 respostas

Alexandre, beleza? Tudo bem contigo?

Eu carreguei os teus 2 arquivos de Autoloader, ambos funcionaram no meu projeto. Estão localizando e carregando normalmente as classes.

Minha primeira dúvida era se o file_exists só testava caminho absoluto, e não é o caso, ele vai conseguir testar um caminho relativo também.

Dai 3 sugestões, em cima do primeiro autoloader, para tentarmos achar a diferença: 1) Dependendo da classe que apresentar erro, verifique se você definiu o namespace e se ele esta correto. 2) Verifique se no arquivo que esta executando, por exemplo banco.php, se você indicou a classe na clausula use, ou se esta chamando o caminho completo na declaração da classe. 3) Usando o primeiro Autoloader, se preciso poste aqui o erro que é lançado.

Obs: Não sei se mais para frente do curso o próprio instrutor fará esta mudança. Mas na minha estrutura de diretórios, a classe Funcionario.php esta dentro de uma pasta Funcionario. Caminho: \src\Modelo\Funcionario\Funcionario.php

Caso não avance, poste aqui por favor as suas tentativas ainda. Se não caso lhe ajude, marcar o tópico como resolvido. Um abraço!

Olá, Marco!

Obrigado pela resposta!

Eu modifiquei o autoloader para não usar mais o __DIR__. Ficou da seguinte forma:

<?php

// Executes the given function when failing to load a class
spl_autoload_register(function (string $nomeClasse){

    // $basePath = __DIR__ . DIRECTORY_SEPARATOR;

    // $caminhoArquivo = str_replace('Alura\\Banco', "$basePath\src", $nomeClasse);
    $caminhoArquivo = str_replace('Alura\\Banco', "src", $nomeClasse);
    $caminhoArquivo = str_replace('\\', DIRECTORY_SEPARATOR, $caminhoArquivo); // DIRECTORY_SEPARATOR is a default constant of PHP
    $caminhoArquivo .= '.php';

    if (file_exists($caminhoArquivo)) {
        require_once $caminhoArquivo;
    } else {
        echo "Caminho \"$caminhoArquivo\" não encontrado!";
        exit();
    }
});

O erro encaminhado é a mensagem do else, o que me indica que o file_exists está falhando por alguma razão: Caminho "src\Modelo\Endereco.php" não encontrado!

Os namespaces estão corretos e o use está sendo usado:

Banco.php (CPF e endereços ocultados):

<?php

require_once 'autoload.php';

use Alura\Banco\Modelo\CPF;
use Alura\Banco\Modelo\Endereco;
use Alura\Banco\Modelo\Conta\Conta;
use Alura\Banco\Modelo\Conta\Titular;

$endereco = new Endereco('Osasco', 'Novo Osasco', '#############', '###');

$alexandre = new Titular(new CPF('###########'), 'Alexandre Carretero', $endereco);
$primeiraConta = new Conta($alexandre);
$primeiraConta->depositar(500);
$primeiraConta->sacar(300);


echo 'Numero total de contas: ' . Conta::getNumeroDeContas() . PHP_EOL;

$outroEndereco = new Endereco('Osasco', 'Jardim Cipava', '##########', '###');

$marcio = new Titular(new CPF('###########'), 'Marcio Carretero', $outroEndereco);
$segundaConta = new Conta($marcio);
$segundaConta->depositar(1000);
$segundaConta->sacar(100);
$segundaConta->transferir(150,$primeiraConta);

echo 'Numero total de contas: ' . Conta::getNumeroDeContas() . PHP_EOL;

$primeiraConta->printSummary();
$segundaConta->printSummary();

.\scr\Modelo\Endereco.php:

<?php

namespace Alura\Banco\Modelo;

class Endereco {

    private string $cidade;
    private string $bairro;
    private string $rua;
    private string $numero;

    // Constructor
        public function __construct(string $cidade, string $bairro, string $rua, string $numero){
            $this->cidade = $cidade;
            $this->bairro = $bairro;
            $this->rua = $rua;
            $this->numero = $numero;
        }

    // Getters
        public function getCidade(): string {
            return $this->cidade;
        }

        public function getBairro(): string {
            return $this->bairro;
        }

        public function getRua(): string {
            return $this->rua;
        }

        public function getNumero(): string {
            return $this->numero;
        }

    // Formatter
        // Endereco
        public function formatEndereco(): string {
            return 
            "$this->rua" . " " . 
            "$this->numero" . ", " . 
            "$this->bairro" . " - " .
            "$this->cidade";
        }
}

Alexandre,

Carreguei teu Autoloader, Banco e Endereco.php. Não consegui gerar o erro. O sistema carrega normalmente, consigo inclusive executar tua função formatEndereco().

Um detalhe que observei, mas acredito seja erro de digitação somente aqui no forum é para a classe Endereco.php, você indicou o caminho: .\scr\Modelo\Endereco.php:

Sendo o correto: .\src\Modelo\Endereco.php:

solução!

Fala, Alexandre.

Cada sistema operacional acaba identificando o "diretório atual" de forma um pouco diferente. Se não me engano (posso estar errado), no Linux o diretório atual é o diretório do arquivo, por padrão, enquanto no Windows é o diretório onde o comando foi executado.

Pra se blindar desse tipo de bobeira (que nem eu me lembro de cabeça), sempre use caminhos absolutos (com o __DIR__).

Honestamente foi um erro meu não ter feito assim no curso, então compreendo sua dúvida. Perdão.

Ah, sim. Entendi!

Muito obrigado, gente. Marco pelo esforço em testar tudo e Vinicius pelo esclarecimento.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software