как правильно импортировать несколько пространств имен

#php #symfony #namespaces

#php #symfony #пространства имен

Вопрос:

Я очень новичок в пространствах имен PHP, и у меня есть вопрос:

Если мы импортируем несколько пространств имен с помощью команды ‘use’, не должны ли мы столкнуться с проблемами? Я читал этот пост http://www.sitepoint.com/php-namespaces-import-alias-resolution /, а в разделе об импорте пространства имен говорится, что вам все равно нужно иметь определенный префикс рядом с функцией (например: Lib2), но при просмотре некоторых файлов примеров Symfony 2 я не вижу, чтобы это происходило. Как пространство имен решает (в файле примера ниже) конфликты имен?

 namespace AcmeDemoBundleController;

use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationRequest;
use AcmeDemoBundleFormContactType;

// these import the "@Route" and "@Template" annotations
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationTemplate;

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

Комментарии:

1. Псевдонимы требуются только в случае конфликта. Многие варианты использования не являются проблемой. В случае конфликта просто добавьте псевдоним.

Ответ №1:

Я думаю, что недоразумение происходит из-за имен файлов сообщения. имейте в виду:

  • DefaultController.php с namespace Acme/AcmeBundle/Controller/ будет включено с use Acme/AcmeBundle/Controller/DefaultController
  • DefaultController2.php с namespace Acme/AcmeBundle/Controller2/ будет включено с 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 BazFoo;

class Foo{}
 

Если вы работали в Bar.php , вы могли бы сослаться на следующее:

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

Вы также можете ссылаться на класс Foo непосредственно в вашем использовании, а не ссылаться на пространство имен Foo.

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

Если вы хотите напрямую ссылаться как на пространство имен, так и на класс Foo, вам нужно будет разрешить конфликт с помощью псевдонима.

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

Кроме того, скажем, в дополнение к вашему Baz/Foo.php файл, у вас есть Bar/Foo.php файл как таковой:

 <?php //Bar/Foo.php
namespace BarFoo;

class Foo{}
 

Если вы хотите локально ссылаться на оба пространства имен, вам понадобятся псевдонимы для разрешения конфликта имен:

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

В дополнение к импорту пространства имен с помощью инструкции use, вам также потребуется включить файл, содержащий это пространство имен. Это можно сделать вручную с помощью require_once(), но обычно это обрабатывается автоматически автозагрузчиком.

Более подробную информацию см. в разделе Загрузчик классов Symfony.

Надеюсь, это поможет.