【问题标题】:Using namespace in if / else statements在 if / else 语句中使用命名空间
【发布时间】:2013-11-23 22:20:39
【问题描述】:

我正在操作同一个文件来管理两个外部 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 中有错误?
  • 我在一个独立文件中测试了 bar.php,如果我在 if() 语句中包含“use”,则会抛出“语法错误,意外 T_USE”。
  • 我发布了一个解决办法
  • 我接受了 Phil 的回答,这对我有用,无论如何感谢 Daryl

标签: php namespaces


【解决方案1】:

好吧,只是确认我说的是真的..试试这样的:

*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"; 
    }
}

运行起来很顺利

【讨论】:

    【解决方案2】:

    请看Scoping rules for importing

    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);
    }
    

    【讨论】:

    • 非常感谢菲尔您的超级清晰和详细的回答。现在这是有道理的,使用 new \xxxx\TheClass() 解决了这个问题。
    • @Vincent 我刚刚在您发表评论后添加了一些信息
    【解决方案3】:

    Use 语句应该放在任何可执行代码之前(你可以有命名空间、类、函数和常量定义)。 实际上可以,只是必须无条件地放置在某个命名空间中,所以没有ifs 或内部函数。 不要害怕将 use 放在顶部,它不会加载任何类或实例化对象。它仅充当稍后在执行期间遇到时使用的别名。

    至于将它们放在一个文件中,可以在一个文件中包含多个命名空间,甚至是全局命名空间:

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

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

    【讨论】:

    • TIL:use 语句不会触发自动加载器,也不需要定义符号名称:)
    【解决方案4】:

    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();
    

    【讨论】:

      猜你喜欢
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多