关键字“ use”在PHP中如何工作,我可以用它导入类吗?


136

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

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

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

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

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

$a = new Resp();

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

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

但是我想不使用require或导入类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运作?我可以用它导入课程吗?


1
您不能不导入文件。请不要更改流程。同样,名称空间实际上并没有在PHP中使用。就像VB.NET
Cole Johnson

13
@ cole-johnson,不同意您的意见。Symfony是围绕namespaces 构建的。实际上,如果您不使用名称空间,则不会有任何Symfony
Green Green

Answers:



188

不可以,您不能导入带有use关键字的类。您必须使用include/ require语句。即使您使用PHP自动加载器,自动加载器仍必须在内部includerequire内部使用。

目的使用关键字:

考虑一下您有两个同名类的情况。您会发现它很奇怪,但是当您使用大型MVC结构时,它就会发生。因此,如果您有两个同名的类,请将它们放在不同的名称空间中。现在考虑一下您的自动加载器何时加载两个类(由by进行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使用该类执行语句以用作参数时,该函数将被自动调用,这可以帮助您在运行时根据需要动态加载该类。

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


为什么不只是使用不同的类名?

15
@神 这些课程可能来自第三方供应商
Dayo,2017年

3
@神 如果两个冲突类别都来自第三方怎么办?
Dayo

2
@divine按照约定,名称空间将为<vendorName> / <packageName>,因此已经解决了该问题。按照约定,包装师不可能从其他人那里接受相同的供应商名称。而packagist.org是PHP库,用于作曲家安装软件包。
Tpojka '17

1
@root没关系,它只是告诉运行时要使用什么。就像您驾驶汽车并发出信号告诉您撞车然后摔坏一样,例如way use语句将告诉编译器现在为我加载。亲爱的!
Rajan Rawal '18

23

不要想太多命名空间是什么。

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

同样为了使事情更清楚一点,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


8

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


4

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

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

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


但是有一个问题。它需要一个递归模型来建立完整的路径。现在,它仅处理单级名称空间。
泰勒·卡特

3

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

这是示例控制器类开始的方式:

命名空间Acme \ DemoBundle \ Controller;

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

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


3

我可以用它导入课程吗?

除了上面的示例,您不能那样做。您还可以use在类内部使用关键字来导入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'

3

use关键字是在PHP混淆,并没有导入类。这确实有帮助
1)当您在不同的命名空间中具有相同名称的类时
2)避免一遍又一遍地使用非常长的类名。


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
}

注意:不要使用包含要实现的类的文件的路径,不要扩展用于实例化对象的用途,而只能使用名称空间。


2

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

<?php
    use foo\bar\lastPart;
    $obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.