Autoload PSR4 class

Asked

Viewed 930 times

2

I would like to create a class of autoload to follow the recommendations of PSR4 which can be used jointly and independently of the autoload of the Composer.

The application I’m creating will have the following structure:

/root
 |--/src                
      |-- /App
            |-- /Config
            |-- /Controller
            |-- /Model
      |-- /Core
            |-- /Helper
            |-- /lib
                  |-- Autoload.class.php
  |-- /public_html
        |-- ...
  |-- /vendor  
        |-- ...
  |-- index.php      

In the future I will integrate new components in my application through Composer but, I would like an autoload class for the classes of my application.

  • 1

    you have the example on php-fig.org

  • From what I saw in the PSR-4 implementation example at this link, for every new namespace that I create I should add it along with the file path as in this example: $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src');. Wanted, however, to make it automatic.

  • the example is merely didactic... implementations as the automation you want to do, is on account of the

  • But if you come out of the psr-4 proposal, you’re no longer psr-4, you understand? The pattern serves precisely to avoid those monstrous gambiarras in autoloaders... I myself have created many of these monsters... today I try to follow the psr-4.. It may seem illogical to have several autoloaders files, but it’s better.. In the end you won’t even have much... usually I use only 2, being 1 for core functions and another for the application where contain business models

  • Yes. As for the use of 2 or more autoloads I see no problem. But having to register the namespaces I found it a little confusing. Apparently there is no restriction to this registration. That would be a step backwards in my opinion.

  • i also do not use the "record" technique present in the site example.. alias was the first thing I removed rsrsr

Show 1 more comment

1 answer

4


Following the structure you used, simply create an event in a . php file that will be included within the index.php (which should go inside of public_html), note that the public_html will be your root (pro server), however this is not a must, I’m just following your folder structure.

For this you will have to use the spl_autoload_register, the link http://www.php-fig.org/psr/psr-4/examples/ - I made an example, with some modifications:

<?php
function myAutoLoader($class)
{
    // Diretório aonde ficam as bibliotecas
    $base_dir = __DIR__ . '/src/App/'; //A pasta que conterá os arquivos que serão autocarregados

    //Transforma namespace no caminho do arquivo
    $file = $base_dir . str_replace('\\', '/', $class) . '.php';

    // Verifica se o arquivo existe, se existir então inclui ele
    if (is_file($file)) {
        include_once $file;
    }
}

spl_autoload_register('myAutoLoader');

You can put it in (or use include) inside your index.php, or create a file within Core and use include calling him.

For more details, see this answer I made: What is spl_autoloader_register in PHP?

Notes on the code

  • Note: Other than http://www.php-fig.org I used include_once instead of require, because if the file has already been manually included or it is not a class, it will present more errors than it should and the only error that the PSR-4 standard should present is that of undefined class.

  • Note 2: I used is_file instead of file_existes, because although it is almost impossible yet a developer who use your project may end up creating a folder called ./src/App/Controller/foo.php/index.html, of course this is a user error, but as I said in the other note, PSR-4 shall only contain errors of undefined class (which is the standard) however if the require trying to call a folder will present an error as it file_exists returns true to directories:

    Warning: require(src/App/Controller/foo.php): failed to open stream: No such file or directory in Z: www project server.php on line 22

    Fatal error: require(): Failed Opening required 'src/App/Controller/foo.php' (include_path='.') in Z: www project server.php on line 22

The reason for this is because it is described here http://www.php-fig.org/psr/psr-4/#2-Specification:

Autoloader implementations MUST NOT release exceptions, must not generate errors of any level and must not return any value.

  • Hello, William! Can you add an example of how to do Unit Tests in your code above? Thank you.

  • 1

    @Nottherealhemingway o Phpunit usa _ as a namespace separator, the above code is based on the PSR-4, which requires as separators (which is supported from php5.3). Anyway you can use the Composer-autoload that supports both formats, I believe that in the next build of phpunit they will use ;D

  • I will use your code with a different directory structure, but it has worked. Thank you!

  • @Nottherealhemingway recalled that I had made an example to work with PSR0 (which accepts and _ as namespaces): http://answall.com/a/157958/3635

  • There’s something missing in that code there, isn’t there? Where is it defined $np?

  • Thanks @Mestrelion this corrected

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.