#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.
Надеюсь, это поможет.