Issue
I am having a problem with my namespace fallbacks and using PSR-4 loader in Composer.
What I am trying to do is this:
- Have a core which can overwritten / extended.
- The core is based off an interface.
The directory structure is like so:
site/app/View/Example.php
site/src/ACME/app/View/Example.php
site/src/ACME/app/Interface/View.php
I am not set on this configuration so if you have a better suggestion then go for it.
My composer json is like so for psr-4:
"autoload": {
"psr-4": {
"ACME\\App\\Site\\" : "app/",
"ACME\\App\\" : "src/AMCE/app/"
}
}
I thought this would make ACME\App\Site\View fallback to ACME\App\View if the site one was not found (Note I haven't done the interface part yet...).
My code for site/app/View/Example.php is like so:
namespace ACME\App\Site\View;
class ViewExample extends View {
Which works, when I have site/app/View/View.php as well. That looks like:
namespace ACME\App\Site\View;
class View extends \ACME\App\View\View {
The site/src/app/View/View.php look like this:
namespace ACME\APP\View;
class View {
This one should use the interface (I haven't tried yet).
So what I really want to do is make it so I don't have to have site/app/View/View.php, and I don't have to have site/app/View/Example.php - it can use site/src/ACME/app/View/Example.php.
Sorry I'm new to namespaces so I may not of phrased it very well.
What I am getting at is I thought ACME\App\Site would fallback to ACME\App - it doesn't? Or I am doing it wrong? At the moment it needs all the files in place.
Solution
Edit: Turns out I was originally wrong, it is possible to get your example working with PSR-4! You just need to specify an array of directories for namespaces that can be loaded from different places.
Easy solution
{
"autoload": {
"psr-4": {
"ACME\\App\\Site\\": ["app/", "src/ACME/app"],
"ACME\\App\\": "src/ACME/app/"
}
}
}
Personally, I would rather name my namespaces more explicitly, see below.
Original Answer
The composer PSR-4 loader does not fall back when trying to load files that do not exist. It just fails immediately. Its flow looks like:
\ACME\App\Site\View
is not loaded- Scan PSR-4 entries for matching namespaces
- Class name matches the namespace
\ACME\App\Site
(your first PSR-4 entry). - Load file
app/View.php
- File does not exist. Error.
It never goes back to step 3 and tries the next namespace.
So how do I fix it?
It looks like you want to separate your reusable library code from your site code. If that's the case, I would use separate namespaces. For example, use the ACME\Site
namespace to hold your reusable code, and use ACME\MySiteName
for your site-specific code. Then there will be no ambiguity, and composer will have no trouble loading your classes.
But I don't want to rearrange my namespaces!
Ok, that's fine, but you'll have to use a hack to get around your problem. Composer has a classmap
loader, and you'll have to use that instead of the preferred PSR-4 loader.
{
"autoload": {
"classmap": ["app/", "src/"]
}
}
Answered By - Justin Howard
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.