Namespaces e recursos de linguagem dinâmica

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

A implementação de namespaces do PHP é influenciada por sua natureza dinâmica como linguagem de programação. Assim, para converter código como o exemplo a seguir em código com namespace:

Exemplo #1 Acessando elementos dinamicamente

exemplo1.php:

<?php
class nomedaclasse
{
function
__construct()
{
echo
__METHOD__,"\n";
}
}
function
nomedafuncao()
{
echo
__FUNCTION__,"\n";
}
const
nomedaconstante = "global";

$a = 'nomedaclasse';
$obj = new $a; // imprime nomedaclasse::__construct
$b = 'nomedafuncao';
$b(); // imprime nomedafuncao
echo constant('nomedaconstante'), "\n"; // imprime global
?>
Deve-se usar o nome totalmente qualificado (nome da classe prefixado com o namespace). Observe que, como não há diferença entre um nome qualificado e um nome totalmente qualificado em um nome de classe, nome de função ou nome de constante dinâmico, a barra invertida inicial não é necessária.

Exemplo #2 Acessando dinamicamente elementos com namespace

<?php
namespace nomedonamespace;
class
nomedaclasse
{
function
__construct()
{
echo
__METHOD__,"\n";
}
}
function
nomedafuncao()
{
echo
__FUNCTION__,"\n";
}
const
nomedaconstante = "comnamespace";

/* note que, ao usar aspas duplas, "\\nomedonamespace\\nomedaclasse" deve ser usado */
$a = '\nomedonamespace\nomedaclasse';
$obj = new $a; // imprime nomedonamespace\nomedaclasse::__construct
$a = 'nomedonamespace\nomedaclasse';
$obj = new $a; // também imprime nomedonamespace\nomedaclasse::__construct
$b = 'nomedonamespace\nomedafuncao';
$b(); // imprime nomedonamespace\nomedafuncao
$b = '\nomedonamespace\nomedafuncao';
$b(); // também imprime nomedonamespace\nomedafuncao
echo constant('\nomedonamespace\nomedaconstante'), "\n"; // imprime comnamespace
echo constant('nomedonamespace\nomedaconstante'), "\n"; // também imprime comnamespace
?>

Certifique-se de ler a nota sobre escapamento de namespaces em strings.

adicione uma nota

Notas Enviadas por Usuários (em inglês) 8 notes

up
75
Alexander Kirk
14 years ago
When extending a class from another namespace that should instantiate a class from within the current namespace, you need to pass on the namespace.<?php // File1.phpnamespace foo;class A {    public function factory() {        return new C;    }}class C {    public function tell() {        echo "foo";    }}?><?php // File2.phpnamespace bar;class B extends \foo\A {}class C {    public function tell() {        echo "bar";    }}?><?phpinclude "File1.php";include "File2.php";$b = new bar\B;$c = $b->factory();$c->tell(); // "foo" but you want "bar"?>You need to do it like this:When extending a class from another namespace that should instantiate a class from within the current namespace, you need to pass on the namespace.<?php // File1.phpnamespace foo;class A {    protected $namespace = __NAMESPACE__;    public function factory() {        $c = $this->namespace . '\C';        return new $c;    }}class C {    public function tell() {        echo "foo";    }}?><?php // File2.phpnamespace bar;class B extends \foo\A {    protected $namespace = __NAMESPACE__;}class C {    public function tell() {        echo "bar";    }}?><?phpinclude "File1.php";include "File2.php";$b = new bar\B;$c = $b->factory();$c->tell(); // "bar"?>(it seems that the namespace-backslashes are stripped from the source code in the preview, maybe it works in the main view. If not: fooA was written as \foo\A and barB as bar\B)
up
9
Daan
5 years ago
Important to know is that you need to use the *fully qualified name* in a dynamic class name. Here is an example that emphasizes the difference between a dynamic class name and a normal class name.<?phpnamespace namespacename\foo;class classname      {                                                                                            function __construct()                                                                   {                                                                                            echo 'bar';    }                                                                                    }                                                                                        $a = '\namespacename\foo\classname'; // Works, is fully qualified name                   $b = 'namespacename\foo\classname'; // Works, is treated as it was with a prefixed "\"   $c = 'foo\classname'; // Will not work, it should be the fully qualified name            // Use dynamic class name                                                                                         new $a; // barnew $b; // barnew $c; // [500]: / - Uncaught Error: Class 'foo\classname' not found in // Use normal class name                                                                                         new \namespacename\foo\classname; // barnew namespacename\foo\classname; // [500]: / - Uncaught Error: Class 'namespacename\foo\namespacename\foo\classname' not foundnew foo\classname; // [500]: / - Uncaught Error: Class 'namespacename\foo\foo\classname' not found
up
6
museyib dot e at gmail dot com
6 years ago
Be careful when using dynamic accessing namespaced elements. If you use double-quote backslashes will be parsed as escape character.<?php    $a="\namespacename\classname"; //Invalid use and Fatal error.    $a="\\namespacename\\classname"; //Valid use.    $a='\namespacename\classname'; //Valid use.?>
up
16
guilhermeblanco at php dot net
16 years ago
Please be aware of FQCN (Full Qualified Class Name) point.
Many people will have troubles with this:

<?php

// File1.php
namespace foo;

class Bar { ... }

function factory($class) {
    return new $class;
}

// File2.php
$bar = \foo\factory('Bar'); // Will try to instantiate \Bar, not \foo\Bar

?>

To fix that, and also incorporate a 2 step namespace resolution, you can check for \ as first char of $class, and if not present, build manually the FQCN:

<?php

// File1.php
namespace foo;

function factory($class) {
    if ($class[0] != '\\') {
        echo '->';
         $class = '\\' . __NAMESPACE__ . '\\' . $class;
    }

    return new $class();
}

// File2.php
$bar = \foo\factory('Bar'); // Will correctly instantiate \foo\Bar

$bar2 = \foo\factory('\anotherfoo\Bar'); // Wil correctly instantiate \anotherfoo\Bar

?>
up
6
akhoondi+php at gmail dot com
12 years ago
It might make it more clear if said this way: One must note that when using a dynamic class name, function name or constant name, the "current namespace", as in http://www.php.net/manual/en/language.namespaces.basics.php is global namespace.One situation that dynamic class names are used is in 'factory' pattern. Thus, add the desired namespace of your target class before the variable name.namespaced.php<?php// namespaced.phpnamespace Mypackage;class Foo {    public function factory($name, $global = FALSE)    {        if ($global)            $class = $name;        else            $class = 'Mypackage\\' . $name;        return new $class;    }}class A {    function __construct()    {        echo __METHOD__ . "<br />\n";    }}class B {    function __construct()    {        echo __METHOD__ . "<br />\n";    }}?>global.php<?php // global.phpclass A {    function __construct()    {        echo  __METHOD__;    }}?>index.php<?php//  index.phpnamespace Mypackage;include('namespaced.php');include('global.php');    $foo = new Foo();    $a = $foo->factory('A');        // Mypackage\A::__construct   $b = $foo->factory('B');        // Mypackage\B::__construct    $a2 = $foo->factory('A',TRUE);    // A::__construct  $b2 = $foo->factory('B',TRUE);    // Will produce : Fatal error: Class 'B' not found in ...namespaced.php on line ...?>
up
2
m dot mannes at gmail dot com
8 years ago
Case you are trying call a static method that's the way to go:<?phpclass myClass {    public static function myMethod()     {      return "You did it!\n";    }}$foo = "myClass";$bar = "myMethod";echo $foo::$bar(); // prints "You did it!";?>
up
2
anisgazig at gmail dot com
3 years ago
<?php//single or double quotes with single or double backslash in dynamic namespace class.namespace Country_Name{class Mexico{function __construct(){echo __METHOD__,"<br>";}}$a = 'Country_Name\Mexico';//Country_Name\Mexico::__construct$a = "Country_Name\Mexico";//Country_Name\Mexico::__construct$a = '\Country_Name\Mexico';//Country_Name\Mexico::__construct$a = "\Country_Name\Mexico";//Country_Name\Mexico::__construct$a = "\\Country_Name\\Mexico";//Country_Name\Mexico::__construct$o = new $a;}/* if your namespace name or class name start with lowercase n then you should be alart about the use of single or double quotes with backslash  */namespace name_of_country{class Japan{function __construct(){    echo __METHOD__,"<br>";}}$a = 'name_of_country\Japan';//name_of_country\Japan::__construct$a = "name_of_country\Japan";//name_of_country\Japan::__construct$a = '\name_of_country\Japan';//name_of_country\Japan::__construct//$a = "\name_of_country\Japan";//Fatal error: Uncaught Error: Class ' ame_of_country\Japan' not found //In this statement "\name_of_country\Japan" means -first letter n with "\ == new line("\n). for fix it we can use double back slash or single quotes with single backslash. $a = "\\name_of_country\\Japan";//name_of_country\Japan::__construct$o = new $a;}namespace Country_Name{class name{function __construct(){echo __METHOD__,"<br>";}}$a = 'Country_Name\name';//Country_Name\Norway::__construct$a = "Country_Name\name";//Country_Name\Norway::__construct$a = '\Country_Name\name';//Country_Name\Norway::__construct//$a = "\Country_Name\name";//Fatal error: Uncaught Error: Class '\Country_Name ame' not found //In this statement "\Country_Name\name" at class name's first letter n with "\ == new line("\n). for fix it we can use double back slash or single quotes with single backslash$a = "\\Country_Name\\name";//Country_Name\name::__construct$o = new $a;}//"\n == new line are case insensitive so "\N could not affected ?>
up
1
scott at intothewild dot ca
16 years ago
as noted by guilhermeblanco at php dot net, <?php  // fact.php  namespace foo;  class fact {    public function create($class) {      return new $class();    }  }?><?php   // bar.php  namespace foo;  class bar {  ...   }?><?php  // index.php   namespace foo;  include('fact.php');    $foofact = new fact();  $bar = $foofact->create('bar'); // attempts to create \bar                                  // even though foofact and                                  // bar reside in \foo?>
To Top