159

我有一个带有类的文件Resp。路径是:

C:\xampp\htdocs\One\Classes\Resp.php

index.php在这个目录中有一个文件:

C:\xampp\htdocs\Two\Http\index.php

在这个index.php文件中,我想实例化一个类Resp

$a = new Resp();

我知道我可以使用requireorinclude关键字将文件包含在一个类中:

require("One\Classes\Resp.php");       // I've set the include_path correctly already ";C:\xampp\htdocs". It works.
$a = new Resp();

但我想在不使用requireor的情况下导入类include。我试图了解use关键字的工作原理。我尝试了这些步骤,但没有任何效果:

use One\Classes\Resp;
use xampp\htdocs\One\Classes\Resp;
use htdocs\One\Classes\Resp;
use One\Classes;
use htdocs\One\Classes;    /* nothing works */

$a = new Resp();

它说:

Fatal error: Class 'One\Classes\Resp' not found in C:\xampp\htdocs\Two\Http\index.php

关键字是如何use工作的?我可以用它来导入类吗?

4

10 回答 10

211

不,您不能使用use关键字导入类。你必须使用include/require声明。即使您使用 PHP 自动加载器,自动加载器仍然必须使用其中一个include或在require内部使用。

使用关键字的目的:

考虑一个例子,你有两个同名的类;你会觉得很奇怪,但是当你使用一个大型的 MVC 结构时,它就会发生。因此,如果您有两个具有相同名称的类,请将它们放在不同的名称空间中。现在考虑您的自动加载器何时加载两个类(由 执行require),并且您将要使用类的对象。在这种情况下,编译器会混淆在两个类对象中加载哪个类对象。为了帮助编译器做出决定,您可以使用该use语句,以便它可以决定将使用哪个语句。

如今主要框架确实使用includerequire通过composerpsr

1)作曲家

2) PSR-4自动装弹机

浏览它们可能会进一步帮助您。您还可以使用别名来处理确切的类。假设你有两个同名的类,比如Mailer有两个不同的命名空间:

namespace SMTP;
class Mailer{}

namespace Mailgun;
class Mailer{}

如果您想同时使用两个 Mailer 类,那么您可以使用别名。

use SMTP\Mailer as SMTPMailer;
use Mailgun\Mailer as MailgunMailer;

稍后在您的代码中,如果您想访问这些类对象,那么您可以执行以下操作:

$smtp_mailer = new SMTPMailer;
$mailgun_mailer = new MailgunMailer;

它将引用原始类。

有些人可能会感到困惑,如果没有相似的类名,那么就没有使用use关键字。好吧,您可以使用将在执行语句时__autoload($class)自动调用的函数,并将use类用作参数,这可以帮助您在需要时在运行时动态加载类。

请参阅此答案以了解有关类自动加载器的更多信息。

于 2014-08-05T12:34:39.403 回答
100

use不包括任何东西。它只是将指定的命名空间(或类)导入到当前范围

如果您希望自动加载类 - 请阅读有关自动加载的信息

于 2012-06-10T00:00:14.600 回答
33

不要过度思考命名空间是什么。

命名空间基本上只是一个前缀(如操作系统中的目录),以确保路径的唯一性。

同样为了清楚起见,use语句并没有做任何事情,只是为您的命名空间设置别名,因此您可以使用快捷方式或在同一文件中包含具有相同名称但不同命名空间的类。

例如:

// You can do this at the top of your Class
use Symfony\Component\Debug\Debug;

if ($_SERVER['APP_DEBUG']) {
    // So you can utilize the Debug class it in an elegant way
    Debug::enable();
    // Instead of this ugly one
    // \Symfony\Component\Debug\Debug::enable();
}

如果你想知道 PHP 命名空间和自动加载(旧的方式以及 Composer 的新方式)是如何工作的,你可以阅读我刚刚写的关于这个主题的博客文章:https ://enterprise-level-php.com/ 2017/12/25/the-magic-behind-autoloading-php-files-using-composer.html

于 2017-12-26T15:43:51.777 回答
8

无论如何,您都必须包含/要求该类,否则 PHP 将不知道命名空间。
不过,您不必在同一个文件中执行此操作。例如,您可以在引导文件中执行此操作。(或使用自动加载器,但实际上这不是主题)

于 2012-06-10T00:00:31.857 回答
4

问题很可能是您需要使用自动加载器来获取类的名称(在这种情况下以“\”分隔)并将其映射到目录结构。

您可以查看这篇关于PHP自动加载功能的文章。框架中已经有许多此类功能的实现。

我之前实际上已经实现了一个。这是一个链接

于 2012-06-10T00:00:39.840 回答
3

我同意 Green,Symfony 需要命名空间,那么为什么不使用它们呢?

这是示例控制器类的启动方式:

命名空间 Acme\DemoBundle\Controller;

使用 Symfony\Bundle\FrameworkBundle\Controller\Controller;

类 WelcomeController 扩展控制器 { ... }

于 2014-12-01T21:49:30.947 回答
3

use关键字用于 PHP 中的别名,它不导入类。这真的很有帮助
1) 当你在不同的命名空间中有同名的类时
2) 避免一遍又一遍地使用很长的类名。

于 2016-04-05T06:54:45.420 回答
3

我可以用它来导入类吗?

除了上面的例子,你不能这样做。您还可以use在 classes 中使用关键字来导入traits,如下所示:

trait Stuff {
    private $baz = 'baz';
    public function bar() {
        return $this->baz;
    }
}

class Cls {
    use Stuff;  // import traits like this
}

$foo = new Cls;
echo $foo->bar(); // spits out 'baz'
于 2017-06-26T09:19:05.360 回答
2

命名空间用于定义包含类的特定文件的路径,例如

namespace album/className; 

class className{
//enter class properties and methods here
}

然后,您可以使用关键字“use”将这个特定的类包含到另一个 php 文件中,如下所示:

use album/className;

class album extends classname {
//enter class properties and methods
}

注意:不要使用包含要实现的类的文件的路径,使用扩展来实例化对象,而仅使用命名空间。

于 2019-01-18T21:26:59.197 回答
2

使用关键字“use”是为了缩短命名空间文字。您可以同时使用别名和不使用别名。如果没有别名,您必须使用完整命名空间的最后一部分。

<?php
    use foo\bar\lastPart;
    $obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
于 2019-03-09T17:40:19.177 回答