douling0053 2016-02-18 16:02
浏览 73
已采纳

PSR-4:自动加载器(编写器)和扩展名称空间确保回退php

I am having a problem with my namespace fallbacks and using PSR-4 loader in Composer.

What I am trying to do is this:

  1. Have a core which can overwritten / extended.
  2. 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.

  • 写回答

3条回答 默认 最新

  • drrc61668568 2016-02-19 16:50
    关注

    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:

    1. \ACME\App\Site\View is not loaded
    2. Scan PSR-4 entries for matching namespaces
    3. Class name matches the namespace \ACME\App\Site (your first PSR-4 entry).
    4. Load file app/View.php
    5. 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/"]
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大