【问题标题】:how to import multiple namespaces properly如何正确导入多个命名空间
【发布时间】:2014-06-19 20:53:42
【问题描述】:

我对 PHP 命名空间非常陌生,我有一个问题:

如果我们使用“use”命令导入多个命名空间,我们不应该遇到问题吗? 我一直在阅读这篇文章http://www.sitepoint.com/php-namespaces-import-alias-resolution/,在关于命名空间导入的部分中,它说您仍然需要在函数旁边有一个合格的前缀(即:Lib2),但是在查看一些 Symfony 2 示例文件时,我不认为会发生这种情况。 命名空间如何解决(在下面的示例文件中)解决名称冲突?

namespace Acme\DemoBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Acme\DemoBundle\Form\ContactType;

// these import the "@Route" and "@Template" annotations
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class DemoController extends Controller
{
/**
 * @Route("/", name="_demo")
 * @Template()
 */
public function indexAction()
{
    return array();
}

/**
 * @Route("/hello/{name}", name="_demo_hello")
 * @Template()
 */
public function helloAction($name)
{
    return array('name' => $name);
}

/**
 * @Route("/contact", name="_demo_contact")
 * @Template()
 */
public function contactAction(Request $request)
{
    $form = $this->createForm(new ContactType());
    $form->handleRequest($request);

    if ($form->isValid()) {
        $mailer = $this->get('mailer');

        // .. setup a message and send it
        // http://symfony.com/doc/current/cookbook/email.html

        $request->getSession()->getFlashBag()->set('notice', 'Message sent!');

        return new RedirectResponse($this->generateUrl('_demo'));
    }

    return array('form' => $form->createView());
}
}

【问题讨论】:

  • 只有在发生冲突时才需要别名。许多用途不是问题。如果发生冲突,只需添加别名即可。

标签: php symfony namespaces


【解决方案1】:

我认为误解来自帖子的文件名。请记住:

  • 带有namespace Acme/AcmeBundle/Controller/ 的DefaultController.php 将包含在use Acme/AcmeBundle/Controller/DefaultController

  • 带有namespace Acme/AcmeBundle/Controller2/ 的DefaultController2.php 将包含在use Acme/AcmeBundle/Controller2/DefaultController2

要产生冲突,您需要包含两个名为 DefaultController.php 的文件

  • DefaultController.php 与namespace Acme/AcmeBundle/Controller
  • DefaultController.php 和namespace Acme/AcmeBundle/Controller2

然后需要凯文指出的别名

  • DefaultController.php 和namespace Acme/AcmeBundle/Controller => use Acme/AcmeBundle/Controller/DefaultController
  • DefaultController.php 和namespace Acme/AcmeBundle/Controller2 => use Acme/AcmeBundle/Controller2/DefaultController as DefaultController2

【讨论】:

    【解决方案2】:

    也许解释这一点的最好方法是从命名空间解析开始。

    假设你有如下一行:

    $newFoo = new Foo();
    

    PHP 将在当前符号表中查找类 Foo。该符号表包括当前命名空间和任何导入(使用)的命名空间(以及内置 PHP 符号)。

    例如,假设类 Foo 在 Foo.php 中声明:

    <?php //Baz/Foo.php
    namespace Baz\Foo;
    
    class Foo{}
    

    如果您在 Bar.php 中工作,您可以参考以下内容:

    <?php //Baz/Bar.php
    namespace Baz\Bar;
    use Baz\Foo;
    //The following lines are equivalent
    $newFoo = new Foo\Foo(); //Local namespace
    $newFoo = new \Baz\Foo\Foo(); //Fully qualified namespace
    

    您也可以在使用时直接引用 Foo 类,而不是引用 Foo 命名空间。

    <?php //Baz/Bar.php
    namespace Baz\Bar;
    use Baz\Foo\Foo;
    //The following lines are equivalent
    $newFoo = new Foo(); //Local namespace
    //$newFoo = new Foo\Foo(); //This will fail, as the symbol Foo is a class, not a namespace
    $newFoo = new \Baz\Foo\Foo(); //Fully qualified namespace still works.
    

    如果您想直接引用 Namespace 和 Class Foo,则需要解决与 Alias 的冲突。

    <?php //Baz/Bar.php
    namespace Baz\Bar;
    use Baz\Foo;
    use Baz\Foo\Foo as FooClass;
    //The following lines are equivalent
    $newFoo = new FooClass(); //Notice the new aliased symbol.
    $newFoo = new Foo\Foo(); //This works now.
    $newFoo = new \Baz\Foo\Foo(); //Fully qualified namespace still works.
    //$newFoo = new \Baz\Foo\FooClass(); //This will fail, aliases don't work for fully qualified names.
    

    另外,比如说,除了您的 Baz/Foo.php 文件之外,您还有一个 Bar/Foo.php 文件:

    <?php //Bar/Foo.php
    namespace Bar\Foo;
    
    class Foo{}
    

    如果您想在本地引用这两个命名空间,则需要别名来解决名称冲突:

    <?php //Baz/Bar.php
    namespace Baz\Bar;
    use Baz\Foo as Foo1;
    use Baz\Foo\Foo as Foo1Class;
    use Bar\Foo as Foo2;
    use Bar\Foo\Foo as Foo2Class;
    //The following lines are equivalent, referencing Baz\Foo\Foo
    $newBazFoo = new Foo1Class(); //Object alias.
    $newBazFoo = new Foo1\Foo();  //Namespace alias.
    $newBazFoo = new \Baz\Foo\Foo(); //Fully qualified namespaces don't need any aliases.
    //The following lines are equivalent, referencing Bar\Foo\Foo
    $newBarFoo = new Foo2Class(); //Object alias.
    $newBarFoo = new Foo2\Foo();  //Namespace alias.
    $newBarFoo = new \Bar\Foo\Foo(); //Fully qualified namespaces don't need any aliases.
    

    除了使用 use 语句导入命名空间外,您还需要包含包含该命名空间的文件。这可以使用 require_once() 手动完成,但通常由自动加载器自动处理。

    更多详情请见Symfony Class Loader

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 2018-01-05
      • 1970-01-01
      • 2023-03-02
      • 2016-04-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多