【问题标题】:PHP: Is AutoLoader able to load multiple class in a single php file?PHP:AutoLoader 能否在一个 php 文件中加载多个类?
【发布时间】:2016-10-25 05:17:49
【问题描述】:

引用Autoloading Classes

许多编写面向对象应用程序的开发人员创建了一个 PHP 每个类定义的源文件。最大的烦恼之一是 必须在开头写一长串所需的包含 每个脚本(每个类一个)。

在 PHP 5 中,这不再是必需的。 spl_autoload_register() 函数注册任意数量的自动加载器,启用类和 如果当前未加载接口,则自动加载 定义。通过注册自动加载器,PHP 获得了最后的机会 在类或接口因错误而失败之前加载它。

问题来了,如果一个php文件中有多个类,是否适合自动加载使用?还是我必须使用require filepath 声明?

比如我在Protobuf\Client.php下有个协议文件:

<?php

namespace Protobuf;
class A {
...
}
class B {
...
}

【问题讨论】:

  • 您必须有一些复杂的函数才能从名为Client.php 的文件中自动加载这些类。这个想法是将您的命名空间\类名转换为directory\filename.php
  • 在这种情况下,您需要将文件命名为 A.php,然后当您调用 new Protobuf\A() 时,它会找到它。否则你将不得不创建一个过于复杂的自动加载器。
  • 最后,如果你创建它以便自动加载器找到A 类,那么你可以在同一个文件上拥有B,但前提是你已经自动加载了A,否则你有做一些算法来知道AB 在同一页上。
  • @Rasclatt,“复制粘贴”你的三个 cmets 作为答案,你是对的。
  • @P0lT10n 是的,我可能应该这样做。这是一个滚动的想法,我一直在阐述……有点啰嗦。

标签: php autoload


【解决方案1】:

您必须有一些复杂的函数才能从名为Client.php 的文件中自动加载这些类。我们的想法是将您的namespace\classname 翻译成directory\filename.php

在这种情况下,您需要将文件命名为 A.php,然后当您调用 new Protobuf\A() 时,它会找到它。否则你将不得不创建一个过于复杂的自动加载器。

假设您确实创建了自动加载器,以便它找到A 类,那么您可以在同一个文件中拥有B,但前提是您已经自动加载了A,否则您必须进行一些算法才能知道AB 在同一页面上。

我会采用上述模式或 Magento 等应用程序采用的模式,通过替换下划线将类名转换为目录路径:

$class = new Core_Classes_MyClass_Client();

您的自动加载器将替换下划线并加载:

Core/Classes/MyClass/Client.php //or similar scheme

这对我来说是一种简单的方法,但我更喜欢使用命名空间和类。上述方法目前不受欢迎,从命名的角度来看,很容易混淆,因为很多类可能在同一个文件夹中或嵌套在子文件夹中很深。你可以得到一些非常长的类命名。

【讨论】:

  • psr-0 命名空间ftw。
  • 我可以添加到这个答案中,最好的方法是将每个类都放在一个文件中,因此自动加载器(如作者的回答所述)将找到您通过 @987654333 调用的任何类@约定
  • 我很高兴找到这样内容丰富的讨论。谢谢大家!
【解决方案2】:

为了扩展 Rasclatts 非常丰富的答案,

理想情况下,在自动加载方面,将类分开总是一种很好的做法。我强烈建议研究作曲家 PSR-0 命名空间自动加载

PSR-0 让你可以将所有类精美地组织到无限深度的子文件夹中,采用以下文件夹结构

\system
 - Members
     - Members.php
 - Auth
     - Auth.php
 - Database
     - Database.php

对于此示例,在上面的每个 php 文件中,您的类声明之前都会有 namespace MyNameSpace;,然后在您的 composer.json 中,您将有类似于 (documentation) 的内容:

"autoload": {
    "psr-0": { "MyNameSpace": "/system" }
}

Composer 应该安装在您的本地/主机上,以便您编译您的自动加载文件,打开终端并导航到您的项目目录并输入:

composer dump-autoload -o

现在一切都井井有条,您可以访问类似于以下内容的课程:

\MyNameSpace\Auth::staticFunction();

【讨论】:

    【解决方案3】:

    是和否, 但是,如果我确实为非常大的 WSDL 生成(自动)类和方法怎么办?

    即。一百多个方法 你可能有一百个 methodRequests(作为一个类对象),下一个一百个 methodResponse(作为一个类对象)和大型数组,即 ClassMap。

    有时最好在一个文件中处理这些内容,尤其是在没有好的 WSDL 文档的情况下进行开发。

    【讨论】:

      【解决方案4】:

      要直接回答这个问题,我们可以在composer.json中使用classmap for autoload来支持单个文件包含多个类。

      例如我们要支持单个文件Protobuf\Client.php,其中有两个类AB

      <?php
      
      namespace Protobuf;
      
      class A {
      }
      
      class B {
      }
      

      我们在composer.json 中添加classmap 如下:

      {
          "name": "hailong/myproj",
          "autoload": {
              "classmap": [
                  "Protobuf/Client.php"
              ]
          }
      }
      

      然后,在main.php 中,我们可以使用AB 类:

      <?php
      
      require __DIR__.'/vendor/autoload.php';
      
      use Protobuf\A;
      use Protobuf\B;
      
      $a = new A();
      
      $b = new B();
      

      最后,不要忘记在更改composer.json 后运行composer dump-autoload,它会神奇地生成我们main.php 所需的autoload.php

      对于还不熟悉composer 的人,这是我们将获得的最终文件结构:

      myproj % tree
      .
      ├── Protobuf
      │   └── Client.php
      ├── composer.json
      ├── main.php
      └── vendor
          ├── autoload.php
          └── composer
              ├── ClassLoader.php
              ├── LICENSE
              ├── autoload_classmap.php
              ├── autoload_namespaces.php
              ├── autoload_psr4.php
              ├── autoload_real.php
              ├── autoload_static.php
              └── installed.json
      
      3 directories, 12 files
      

      【讨论】:

        猜你喜欢
        • 2013-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-02
        • 2011-04-15
        • 2011-09-04
        相关资源
        最近更新 更多