在if/else语句中使用命名空间

9

我正在操作同一个文件,来管理两个外部API类。

其中一个API类基于命名空间,而另一个则不是。

我想要做的是像这样:

if($api == 'foo'){
   require_once('foo.php');
}
if($api == 'bar'){
   require_once('bar.php');
   use xxxx\TheClass;
}

问题在于当我这样做时,会返回以下错误信息:
Parse error: syntax error, unexpected T_USE in etc...

问题1:我是否必须使用两个不同的文件来管理这两个类,或者在文档中使用命名空间时可以同时管理两个类?从我所看到的情况来看,似乎不行。

问题2:为什么不能在if()语句内使用命名空间?

感谢您的帮助。


据我上次检查,这是可能的。也许你在bar.php中有一个错误? - Daryl Gill
我已经在一个独立的文件中测试了bar.php,如果我在if()语句内部包含"use",则会抛出“语法错误,意外的T_USE”。 - Vincent
我发布了一个有点儿变通的答案。 - Daryl Gill
我选择了Phil的答案,它对我很有帮助,不管怎样还是谢谢Daryl。 - Vincent
4个回答

19
请参阅 导入的作用域规则

use 关键字必须在文件的最外层作用域(全局作用域)或命名空间声明内部声明。这是因为导入是在编译时而不是运行时进行的,因此它不能被块范围所限制。

use 做的就是将一个符号名称导入到当前命名空间中。我会省略导入并使用完全限定类名,例如:

switch ($api) {
    case 'foo' :
        require_once('foo.php');
        $someVar = new SomeClass();
        break;
    case 'bar' :
       require_once('bar.php');
       $someVar = new \xxxx\TheClass();
       break;
   default :
       throw new UnexpectedValueException($api);
}

您也可以直接在脚本的顶部添加use语句。添加它并不意味着您必须包含任何文件,也不需要知道该符号,例如:

use xxxx\TheClass;

switch ($api) {
    case 'foo' :
        require_once('foo.php');
        $someVar = new SomeClass();
        break;
    case 'bar' :
       require_once('bar.php');
       $someVar = new TheClass(); // imported above
       break;
   default :
       throw new UnexpectedValueException($api);
}

非常感谢Phil提供的超级清晰和详细的答案。现在这有意义了,使用新的\xxxx\TheClass()解决了问题。 - Vincent
@Vincent 我在你评论后添加了更多信息。 - Phil

1
使用语句应该放在任何可执行代码之前(您可以有命名空间、类、函数和常量定义)。 实际上它可以,只需要无条件地放置在某个命名空间中,因此没有if或函数内部。 此外,不要害怕将use放在顶部,它不会加载任何类或实例化对象。 它仅充当别名,在执行过程中遇到时才使用。

至于在一个文件中拥有它们,可以在一个文件中拥有许多命名空间甚至全局命名空间:

<?php   
namespace
{
    class myclass{}
}
namespace mynamespace 
{
    class myclass{}
}

但我强烈反对这种代码的“管理”方式。每个类应该有自己的文件。

TIL:use语句不会触发自动加载器,也不需要定义符号名称 :) - Phil

0

好的,只是确认一下我说的是真的.. 试试像这样:

*Test_1.php*

$API = "test_1";
if ($API === "test"){

}elseif ($API === "test_1"){
    require ("test.php");
    $API = new daryls\testt;
}

$API->test();

test.php

namespace daryls;
class  testt {
    public function test(){
        echo "Started"; 
    }
}

运行这个程序一切顺利


0

API类版本控制的另一个选项是有条件地将类名设置为变量。

// Get class name
switch ($api_version) {
  case 'v0':
    // No class namespace
    $class = 'Handler';
    break;
  case 'v1':
    // Namespaced class
    $class = 'API\App\v1\Handler';
    break;
  case 'v2':
    // Namespaced class
    $class = 'API\App\v2\Handler';
   break;
 default:
   throw new Exception('Unknown API version: ' . $api_version);
}
// Get class object
$handler = new $class();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接