我有一个类Resp
的文件。路径是:
C:\xampp\htdocs\One\Classes\Resp.php
我在这个目录中有一个index.php
文件:
C:\xampp\htdocs\Two\Http\index.php
在这个index.php
文件中,我想实例化一个类Resp
。
$a = new Resp();
我知道我可以使用require
或include
关键字来包含一个类的文件:
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
如何运作?我可以用它来导入课程吗?
use
不包括任何内容。它只是将指定的命名空间(或类)导入当前范围
如果您希望自动加载类 - 请阅读autoloading
命名空间用于定义包含类的特定文件的路径,例如
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
}
注意:不要使用包含要实现的类的文件的路径,扩展用于实例化对象但仅使用命名空间。
不,您不能使用use
关键字导入类。你必须使用include
/ require
声明。即使你使用PHP自动加载器,仍然自动加载器必须在内部使用include
或require
。
使用目的关键字:
考虑一个你有两个同名的类的情况;你会发现它很奇怪,但当你使用一个大的MVC结构时,它就会发生。因此,如果您有两个具有相同名称的类,请将它们放在不同的名称空间中。现在考虑一下你的自动加载器加载两个类(由require
做),你将要使用类的对象。在这种情况下,编译器会混淆哪两个类对象加载。为了帮助编译器做出决定,您可以使用use
语句,以便它可以决定将使用哪一个。
如今主要的框架确实通过include
和require
使用composer
或psr
1)composer
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
语句被执行时,将自动调用该类作为参数,这可以帮助您在运行时根据需要随时加载类。
请参阅此answer以了解有关类自动加载器的更多信息。
不要过分思考命名空间。
Namespace基本上只是一个Class前缀(就像操作系统中的目录一样),以确保Class路径的唯一性。
另外,为了清楚起见,use语句不会对命名空间进行别名操作,因此您可以使用快捷方式或在同一文件中包含具有相同名称但名称空间不同的类。
E.g:
// 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
您无论如何都必须包含/要求该类,否则PHP将不知道该命名空间。 但是,您不必在同一个文件中执行此操作。例如,您可以在引导程序文件中执行此操作。 (或使用自动加载器,但实际上这不是主题)
问题很可能是你需要使用一个自动加载器来获取类的名称(在这种情况下由'\'分解)并将其映射到目录结构。
您可以查看有关PHP的autoloading功能的这篇文章。在框架中已经有许多这种类型的功能实现。
我以前实际上实现了一个。这是一个link。
我同意Green,Symfony需要名称空间,所以为什么不使用它们呢?
这是示例控制器类的启动方式:
命名空间Acme \ DemoBundle \ Controller;
使用Symfony \ Bundle \ FrameworkBundle \ Controller \ Controller;
class WelcomeController扩展Controller {...}
我可以用它来导入课程吗?
除了上面的例子,你不能这样做。您还可以在类中使用关键字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'
use
关键字用于PHP中的别名,它不会导入类。这确实有帮助
1)当您在不同的命名空间中具有相同名称的类时
2)避免一遍又一遍地使用真正长的名字。
使用关键字“use”可缩短命名空间文字。你可以使用别名和没有它。如果没有别名,则必须使用完整命名空间的最后部分。
<?php
use foo\bar\lastPart;
$obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>