Autoload and Namespaces in PHP

1

I can not link the php autoload with the namespaces of each class, I have the following directory

App
   Controller
      usuarioController.php
public
   index.php
.htaccess

And in each file I have the following

.htaccess

Options -Multiviews

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f

RewriteRule ^(.+)$ public/index.php?route=$1 [QSA]

App / Controller / userController.php

<?php 
    class usuarioController {
        function saludar() {
            echo "hola";
        }
    }

public / index.php

<?php

    define("PROJECTPATH", dirname(__DIR__));

    spl_autoload_register(function($class) {
        $filename = PROJECTPATH . '/App/Controller/' . $class . '.php';
        include_once $filename; 
    });

    $var = new usuarioController();
    echo $var->saludar();

The previous code works perfectly, that is, the autoload is working but when I add the namespace it gives me 500 error, and I really do not understand why.

These would be the codes that are generating me the error, they are in bold. help

<?php 
    namespace App\Controller\Usuario;
    class usuarioController {
        function saludar() {
            echo "hola";
        }
    }

and in the index I call the namespace in the following way

<?php

    define("PROJECTPATH", dirname(__DIR__));

    spl_autoload_register(function($class) {
        $filename = PROJECTPATH . '/App/Controller/' . $class . '.php';
        include_once $filename; 
    });

    use App\Controller\Usuario;
    $var = new usuarioController();
    echo $var->saludar();
    
asked by Anthony Medina 08.10.2017 в 20:24
source

1 answer

1

I will correct all my answer among other things, because I confused the% namespace with use «Question of copy-paste»

Let's take your example:

define("PROJECTPATH", dirname(__DIR__));

spl_autoload_register(function($class) {
    $filename = PROJECTPATH . '/App/Controller/' . $class . '.php';
    include_once $filename; 
});

use App\Controller\Usuario;
$var = new usuarioController();
echo $var->saludar(); 

When you use the line

use App\Controller\Usuario;
  

It's as if you told the interpreter "it matters {SOMETHING} that it's called App\Controller\Usuario and would like to give it a short alias like Usuario "

 //Este es el equivalente
 use App\Controller\Usuario as Usuario;
     

link

Considering how you define the class

namespace App\Controller\Usuario;

class usuarioController {
    function saludar() {
        echo "hola";
    }
}

The right thing to do is to import in this way

use App\Controller\Usuario\usuarioController;

The above solves the problem as to how you import, the detail is that you were misusing the% use . Now Once this has been resolved, let's go into another detail The path of the file that contains the definition of the class

spl_autoload_register(function($class) {
    $filename = PROJECTPATH . '/App/Controller/' . $class . '.php';
    include_once $filename; 
});
$var = new App\Controller\Usuario\usuarioController();

When executing this line

$var = new App\Controller\Usuario\usuarioController();

The interpreter will try to find the definition of the class you want to instantiate and when you do not find it will trigger the __autoload queue provided by spl, in simpler terms more or less «Execute the function you registered with the spl_autoload_register by passing it through parameter the full name of the class you want to instantiate, ie 'App \ Controller \ User \ userController' »

function($class) {
   $filename = PROJECTPATH . '/App/Controller/' . $class . '.php';
   include_once $filename; 
}
// Así $class = 'App\Controller\Usuario\usuarioController'
// Por tanto $filename = PROJECTPATH . '/App/Controller/App\Controller\Usuario\usuarioController.php'

Possibly you have already realized the failure, in windows whose delimiter by default of directories is '\' this would translate to a structure like this:

App
+-Controller
  +-App
    +-Controller
      +-Usuario
        +-usuarioController.php

Very different from what you have, right?

Possible solution

I think what you're trying is this

  

File: App / Controller / userController.php

<?php 
    namespace App\Controller;

    class usuarioController {
        function saludar() {
            echo "hola";
        }
    }
  

File to execute

<?php

    define("PROJECTPATH", dirname(__DIR__));

    spl_autoload_register(function($class) {
        $filename = PROJECTPATH . "/$class.php";
        include_once $filename; 
    });

    use App\Controller\usuarioController as Usuario;
    $usuario = new Usuario();
    echo $usuario->saludar();

Now this exposed above will only work in windons since looking for PROJECTPATH . '/App\Controller\usuarioController.php' this will interpret something like C:\...\App\Controller\usuarioController.php while in linux the situation will be somewhat different considering that the directory separator is '/' then .../App\Controller\usuarioController.php will not be interpreted as you would expect but more or less something like this:

App
   Controller\usuarioController.php //La barra invertida puede contituir parte del nombre

To correct this you must tell PHP to replace the '\' and '/' bars with the corresponding delimiter, like this:

spl_autoload_register(function($class) {
   $filename = PROJECTPATH . "/$class.php";
   $filename_real = str_replace(['/',"\"],DIRECTORY_SEPARATOR,$filename);
   include_once $filename_real; 
});

To be more didactic I have shown it in an extra line

$filename_real = str_replace(['/',"\"],DIRECTORY_SEPARATOR,$filename);
    
answered by 08.10.2017 / 20:48
source