【问题标题】:Dynamic loading of classes can't address namespace/use类的动态加载无法解决命名空间/使用
【发布时间】:2013-03-12 17:20:21
【问题描述】:

我注意到,当我使用命名空间时,动态加载类与静态加载类的工作方式不同。因此,例如,在不使用命名空间的情况下,以下在实例化名为FooBar 的类的操作中是等效的:

$foobar = new FooBar();

$classname = "FooBar";
$foobar = new $classname;

但是,如果在使用命名空间时我有一些这样的代码:

<?php

namespace Structure\Library;

$foobar = new UserService();
$classname = "UserService";
$barfoo = new $classname;

在这种情况下,UserService 类的完全限定名称是 Structure\Library\UserService,如果我使用完全限定名称,它在两种情况下都有效,但如果我只使用 'UserService' 的快捷方式名称,它只有 em> 在使用静态方法实例化时有效。有没有办法让它对两者都有效?

附:我正在为所有类使用自动加载器......但我假设问题发生在自动加载器之前,并且正在影响传递给自动加载器的类字符串。

【问题讨论】:

  • 被“它仅在使用静态方法实例化时才有效”感到困惑。您在哪里使用静态::?对'Global Space'的问题理解?
  • 不抱歉,我的意思是对类的静态引用,而不是“静态类”。 :^) 明确地说,$foobar=new UserService();
  • 你能告诉我们你的自动加载器的逻辑吗?我想在里面,你使用命名空间来计算加载类文件的路径。那正确吗?难道你不能从自动加载器内部echo你的$class名字,给我们一个更好的线索吗?正如 Allender 所回答的那样,我想正在发生的事情是正在处理的类名在一个实例中包含命名空间,但不包含在另一个实例中。本质上,您的代码的最后一行类似于编写:$barfoo = new \UserService();,但失败了,因为该类不在全局命名空间中。

标签: php namespaces


【解决方案1】:

我认为这是一个阅读文档的案例。参见示例 3:

http://php.net/manual/en/language.namespaces.importing.php

似乎证实了我之前的评论。

<?php
    namespace foo\bar;

    $classStr = "myClass";    
    $nsClass = "\\foo\\bar\\myClass";

    $x = new myClass;    // instantiates foo\bar\myClass, because of declared namespace at top of file
    $y = new $classStr;  // instantiates \myClass, ignoring declared namespace at top of file
    $z = new $nsClass    // instantiates foo\bar\myClass, because it's an absolute reference!
?>

【讨论】:

  • 谢谢@cartbeforehorse,我会在几周后看看这个。很抱歉我没有回复,但问题是从 6 个月前开始的,在我让一切工作足够好的间隙中的某个地方。话虽如此,我仍然觉得我需要巩固自己的理解。
  • @ken 我填写这些类型的问题是为了我自己的未来参考,以及您的信息。我没想到会收到回复,并想象在接下来的 6 个月内你的工作会有所进展。
  • @ken 实际上,这个回复(技术上)与 Allendar 几乎相同。但是,我发现该回复的格式非常难以理解。
  • 好吧,这是不可能的,无论如何,这种情况不被php支持是不好的:-(
  • @nikoss 仅仅因为你的代码是 duff,并不意味着我的就是! $c = "\\Carbon\\Carbon"; $x = new $c(); dd ($x); 工作得很好。无论出于何种原因,虽然你不能做$x = new "\\Carbon\\Carbon"();。我不知道技术原因是什么,但世界就是这样。
【解决方案2】:

这将是我能找到的最接近的解决方案:

define('__NSNAME__', __NAMESPACE__.'\\');

$foobar = new UserService();
$classname = __NSNAME__."UserService";
$barfoo = new $classname;

祝你好运!

更新 1

这可能有助于进一步阅读:http://www.php.net/manual/en/language.namespaces.importing.php

use My\Full\UserService as UserService;

更新 2

这是我现在的进度:

namespace Structure\Library\Home;

class UserService {

}

namespace Structure\Library;

use Structure\Library\Home\UserService as UserService;

define('UserService', __NAMESPACE__.'\\Home\\UserService', TRUE);

$foobar = new UserService();
$classname = UserService;
$barfoo = new $classname;

或者这个变体以获得更大的灵活性:

define('Home', __NAMESPACE__.'\\Home\\', TRUE);

$foobar = new UserService();
$classname = Home.'UserService';
$barfoo = new $classname;

文档

【讨论】:

  • 我尝试过使用您建议的 use 语法,但它似乎对动态类加载没有帮助(它对静态类有用)。
  • 您阅读了链接吗?如果您链接其他类它的位置(使用),那么您应该能够做到:$obj = new Another;,在您的情况下为$barfoo = new UserService;。偏离我上面的示例(My\Full)需要替换为类所在的路径。
  • 是的,但 use 运算符在动态实例化类时似乎不会被评估。我经常使用use,在这种情况下,我已经明确尝试过但无济于事。在许多方面,这种情况下您不会真的想使用use,尽管我正在尝试创建动态响应并且使用语句是静态的。无论如何,它不起作用。 ;^)
  • 我很遗憾听到这个 ken :(。我会尝试做更多的研究。如果我发现任何有用的东西;我会把它添加到这个线程中。
  • 我添加了第二个更新令牌。我希望它可以帮助您(可能还有其他人)在头脑风暴中更接近统一的解决方案。
【解决方案3】:

以下动态将 $barfoo 实例化为 Structure\Library\UserService 对象:

namespace Structure\Library;

$classname = __NAMESPACE__ . "\\" . "UserService";
$barfoo = new $classname;

【讨论】:

    猜你喜欢
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2011-06-22
    • 2017-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多