0

I am using PSR-0 for auto loading, I know that I need to use PSR-4 which I will do it latter part. Even if PSR-4, answers are welcome.

I am having the following directory structure for which the auto loading works fine.

+ www/entity
|__ /EntityGenerator
|       |__ /Database
|       |       |__ DatabaseConnection
|       |       |__ DatabaseConnectionInterface
|       |       |__ DatabaseRepositoryInterface
|       |       
|       |__ /Exception
|
|__ autoload.php
|__ index.php

For the following directory structure its giving error as follows

Warning: require(EntityGenerator\Database\DatabaseConnection.php): failed to open stream: No such file or directory in C:\wamp\www\entity\EntityGenerator\autoload.php on line 15

+ www/entity
| __ /EntityGenerator
        |__ /Database
        |       |__ DatabaseConnection
        |       |__ DatabaseConnectionInterface
        |       |__ DatabaseRepositoryInterface
        |       
        |__ /Exception
        |__ autoload.php
        |__ index.php

Can anyone explain why I am getting the error with second directory structure.

If anyone needs the whole code for testing, please find the below link

https://github.com/channaveer/EntityGenerator

Channaveer Hakari
  • 2,769
  • 3
  • 34
  • 45
  • you are not supposed to link to the whole code. you are supposed to **include** relevant pieces of code **in** your question. most notably: a look at your autoload.php would be very helpful. – Franz Gleichmann Jan 24 '17 at 06:53
  • @Franz Actually I was planning out for that but the sometimes it might be confusing to others what actually I am looking out so thought to add my code link. Anyway it will be open source in future. Thanks. – Channaveer Hakari Jan 24 '17 at 06:59
  • 1
    Is it just me or do you only use relative paths when autoloading? If so that's a big no no. – apokryfos Jan 24 '17 at 07:00

2 Answers2

1

It's because directory structure. You're trying to load EntityGenerator\Database\DatabaseConnection. it's match with path in the first example but not for second one. Just look at the path from autoload.php. It's looking for paths in it's path. EntityGenerator is a valid path in www/entity which's path for autoload.php. But not for www/entity/EntityGenerator at second example.

  • When I **echo ** the path in autoload function both directory structures shows the same path. Whats your opinion on that. – Channaveer Hakari Jan 24 '17 at 07:06
  • path should right i agree but autoload.php can't access that path in second example cause there's no EntityGenerator path in www/entity/EntityGenerator where's your autoload.php's path. Just put a file near autoload.php in second example and require the path which's you get from "echo". You'll see what's wrong. And try to use absolute paths for require/include if you can. – Mehmet SÖĞÜNMEZ Jan 24 '17 at 07:15
1

Your problem is you're using a relative path, which is not always set as the current script's directory. You need to use absolute paths to be sure you're loading what you need to load.

function autoload($className)
{
    $namespaceRoot = "EntityGenerator"; 
    $className = ltrim($className, '\\');
    if (strpos($className,$namespaceRoot) !== 0) { return; } //Not handling other namespaces
    $className = substr($className, strlen($namespaceRoot));
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
    require __DIR__.DIRECTORY_SEPARATOR.$fileName; //absolute path now
}
spl_autoload_register('autoload');

__DIR__ is guaranteed to return the directory which the current script is in.

apokryfos
  • 38,771
  • 9
  • 70
  • 114
  • I tried with your change and got the following when I echoed in autoload "C:\wamp\www\entity\EntityGenerator\EntityGenerator\Database\DatabaseConnection.php". Even now the same problem with 2 structure. The error is as follows "Warning: require(C:\wamp\www\entity\EntityGenerator\EntityGenerator\Database\DatabaseConnection.php): failed to open stream". Can you please help me out with that. – Channaveer Hakari Jan 24 '17 at 07:33
  • @ChannaveerHakari your problem is that you moved the autoloader inside your namespace. Normally autoloaders reside outside the namespace. However you can fix that by specifying the root namespace and thus the directory you're already in. Check the updated code – apokryfos Jan 24 '17 at 07:53
  • Thanks that worked. Just wanted to know the different ways. Your answer made me clear – Channaveer Hakari Jan 24 '17 at 08:45
  • @ChannaveerHakari if this is not just code you use to learn about autoloading I suggest you look into [composer](https://getcomposer.org/)'s autoloading which will take care of all the heavy lifting for you and is already PSR-4. – apokryfos Jan 24 '17 at 09:05
  • Apokryfos - Hi I am aware of Composer, I am working on Symfony. Wanted to try out of the box and how actually these are built from scratch just for my learning purpose. Thanks for your help and suggestions. – Channaveer Hakari Jan 25 '17 at 06:13