调用/扩展类时如何确保正确的类文件已加载 [英] How to make sure the correct class file is loaded when calling / extending class

查看:92
本文介绍了调用/扩展类时如何确保正确的类文件已加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我浏览了问题页面的 ,但是我觉得给出的答案不足以回答我正在努力解决的问题.

I did brows through that question page but the answers given, I felt, didn't sufficiently answer the question I was struggling with.

我有一个小的php项目.在这个项目中,我在各自的文件中定义了两个类.第二类扩展了第一类.在app.php文件中,我实例化了第二个类并调用一个方法.

I have a little php project. In this project I define two classes both in their own files. The second class extends the first class. In the app.php file I instantiate the second class and call a method.

├── Models/
│   ├── Class1.php
│   └── Class2.php
└── app.php

<?php
// Class1.php

namespace Models\Class1;

/**
 * Class1 does things
 */
class Class1 {
  public function someMethod() {
    // code
  }
}

<?php
// Class2.php

namespace Models\Class2;

use \Models\Class1\Class1;

include('./Class1.php');


/**
 * Class2 does other things
 */
class Class2 extends Class1 {
  public function someMethod() {
    // code
  }
}

<?php
// app.php

use Models\Class1\Class1;
use Models\Class2\Class2;

require('Models/Class1.php');
require('Models/Class2.php');

$c1 = new Class1();
$c2 = new Class2();

现在我不是一个真正有经验的php程序员,但我认为我对此类/命名空间业务以及包括/需要文件有扎实的了解,但显然我没有. 如果我将所需的方法从Class1复制到Class2,而不扩展/包含/使用Class2,则一切正常,但想扩展Class1,因此不必重复我的工作!妈的!

Now I'm not a really experienced php programmer but I thought I had a solid grasp of this class/namespace business and including/requiring files, but apparently I don't. If I copy the methods I need from Class1 to Class2 and not extend/include/use Class2 everything works fine, but want to extend Class1, so I don't have to repeat myself! Damn it!

这是运行app.php文件时得到的.

This is what I get when running the app.php file.

警告:include(../Models/Class1.php):无法打开流:在第8行的C:\ wamp64 \ www \ project \ Models \ Class2.php中没有此类文件或目录

Warning: include(../Models/Class1.php): failed to open stream: No such file or directory in C:\wamp64\www\project\Models\Class2.php on line 8

警告:include():无法在C:\ wamp64 \ www \ project \ Models \ Class2中打开'../Models/Class1.php'以包含(include_path ='.; C:\ php \ pear') .php在第7行

Warning: include(): Failed opening '../Models/Class1.php' for inclusion (include_path='.;C:\php\pear') in C:\wamp64\www\project\Models\Class2.php on line 7

我一直在阅读我在网上可以找到的所有关于这些东西的信息,已经用十几种不同的方式编写和重写了我的代码,但是还没有找到解决方案.一些帮助将不胜感激!

I've been reading all I can find online about this stuff, have written and rewritten my code in a dozen different ways but have yet to find a solution. Some help would be greatly appreciated!

推荐答案

快速解答

除非您指定了包含文件的完整路径,否则PHP将始终尝试根据输入脚本的位置来解析文件.就您而言,您的输入脚本似乎在应用程序的根目录中为app.php.

因此,在您的Class2.php中,您应该编写include('Models/Class1.php');而不是include('./Class1.php');,并且一切正常.但是,尽管它解决了一个短期问题,但是您的代码实际上是不可移植的.此外,两次包含相同文件会导致另一个错误(例如,重新声明类).

So in your Class2.php, instead of include('./Class1.php');, you should write include('Models/Class1.php'); and things should work. But while it fix a short term problem, your code would be really non-portable. Besides, including the same file twice would result in another error (e.g. re-declaring class).

一个更聪明的方法是在Class2.php中执行此操作.

A slightly smarter would be to do this in Class2.php instead.

<?php
// Class2.php

namespace Models\Class2;

use \Models\Class1\Class1;

include_once __DIR__ . '/Class2.php';

/**
 * Class2 does other things
 */
class Class2 extends Class1 {
  public function someMethod() {
    // code
  }
}

变量__DIR__将始终解析为脚本文件的目录,而不是入口脚本.

The variable __DIR__ will always be resolved to the directory of the script file, not the entry script.

但同样,它很笨拙并且容易出错,需要手动添加文件.

But again, it is clumsy and error prone to do file includes by hand.

PHP支持在声明类时自动加载文件 .那就是在调用一个类时要有一段代码来做文件包含.如果您想玩得开心,欢迎您编写自己的自动加载器功能并注册到 spl_autoload_register .结合我们所讨论的__DIR__技术,您可以轻松地从名称空间解析自动加载路径.

PHP supports file autoloading when a class is declare. That is to have a piece of code to do the file include when a class is called. If you want to have fun, you're welcome to write your own autoloader function and register to spl_autoload_register. With a combination of the __DIR__ technique we talked about, you can easily resolve the autoloading path from namespace.

快速且丑陋的自动加载app.php可能看起来像这样:

A quick and ugly autoloading app.php would probably look like this:

<?php
// app.php

use Models\Class1\Class1;
use Models\Class2\Class2;

spl_autoload_register(function ($class_name) {
        $realClassName = basename(str_replace('\\', DIRECTORY_SEPARATOR, $class_name));
        include_once __DIR__ . DIRECTORY_SEPARATOR . 'Models' . DIRECTORY_SEPARATOR . $realClassName . '.php';
});

$c1 = new Class1();
$c2 = new Class2();

智能方法:作曲家自动加载

如果您今天正在学习OOP PHP,我强烈建议您学习作曲家 PSR-4 . PSR-4定义了如何构造PHP应用程序以进行类自动加载.默认情况下,Composer实现PSR-4自动加载器.

The Smart Approach: Composer Autoload

If you're learning OOP PHP today, I'd highly recommend you to learn Composer and PSR-4. PSR-4 defines how you should structure a PHP application for class autoloading. Composer implements a PSR-4 autoloader by default.

首先,您应该遵守命名空间标准.要做的最小更改是在名称空间中松散多余的"Class1"和"Class2":

First you should comply with the namespace standard. The least change to do is to loose the extra "Class1" and "Class2" in your namespace:

<?php
// Class1.php

namespace Models;

/**
 * Class1 does things
 */
class Class1 {
  public function someMethod() {
    // code
  }
}

<?php
// Class2.php

namespace Models;

use \Models\Class1;


/**
 * Class2 does other things
 */
class Class2 extends Class1 {
  public function someMethod() {
    // code
  }
}

具有结构良好的应用程序文件夹,名称空间结构和正确编写的自动加载. composer.json中的psr-4部分,composer将帮助您生成类自动加载器.您的composer.json可能看起来像这样:

With a nicely structured application folder, namespace structure and a correctly written autoload.psr-4 section in composer.json, composer will help you to generate a class autoloader. Your composer.json would probably look like this:

{
    "autoload": {
        "psr-4": {
            "Model\\": "Model/"
        }
    }
}

您现在可以运行composer dump-autoload来创建自动加载器.然后,您可以简单地将其添加到输入脚本app.php中.准备就绪后,您只需在应用程序中的任何位置添加usenew语句即可.

You may now run composer dump-autoload to create the autoloader. Then you can simply add this to your entry script app.php. When things are ready, you may simply add use and new statement anywhere in the application.:

<?php
// app.php

use Models\Class1;
use Models\Class2;

require_once './vendor/autoload.php';

$c1 = new Class1();
$c2 = new Class2();

所有包含项均由自动加载器处理.免提.

All includes are handled by the autoloader. Hands free.

这篇关于调用/扩展类时如何确保正确的类文件已加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆