mirror of
https://github.com/php/doc-pt_br.git
synced 2026-03-23 22:52:12 +01:00
1566 lines
52 KiB
XML
1566 lines
52 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: 1651836ff309efd14a795eff44ee51455f66c7d3 Maintainer: leonardolara Status: ready --><!-- CREDITS: dcbmariano,lhsazevedo,ae,nawarian,adiel,leonardolara -->
|
|
<chapter xml:id="language.namespaces" xmlns="http://docbook.org/ns/docbook"
|
|
version="1.1">
|
|
<title>Namespaces</title>
|
|
|
|
<sect1 xml:id="language.namespaces.rationale">
|
|
<title>Visão geral de Namespaces</title>
|
|
<titleabbrev>Visão Geral</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<simpara>
|
|
O que são namespaces? Na definição mais ampla, os namespaces (na tradução literal, "espaços de nomes") são uma forma de encapsular
|
|
itens. Isso é visto como um conceito abstrato em muitos lugares. Por exemplo, em qualquer
|
|
sistema operacional, os diretórios servem para agrupar arquivos relacionados, e agem como um namespace para
|
|
os arquivos dentro deles. Como um exemplo concreto, o arquivo <literal>foo.txt</literal> pode
|
|
existir em ambos os diretórios <literal>/home/greg</literal> e <literal>/home/other</literal>,
|
|
mas duas cópias de <literal>foo.txt</literal> não podem coexistir em um mesmo diretório. Além
|
|
disso, para acessar o arquivo <literal>foo.txt</literal> fora do
|
|
diretório <literal>/home/greg</literal>, o nome do diretório deve ser prefixado ao nome
|
|
do arquivo usando o separador de diretórios para obter <literal>/home/greg/foo.txt</literal>. Esse
|
|
mesmo princípio se estende a namespaces no mundo da programação.
|
|
</simpara>
|
|
|
|
<simpara>
|
|
No mundo PHP, os namespaces são projetados para resolver dois problemas que os autores
|
|
de bibliotecas e aplicações encontram ao criar elementos de código reutilizáveis,
|
|
como classes ou funções:
|
|
</simpara>
|
|
<para>
|
|
<orderedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Colisões de nomes entre o código criado e
|
|
classes/funções/constantes internas do PHP ou classes/funções/constantes de terceiros.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Capacidade de criar apelidos (ou encurtar) Nomes_Extralongos projetados para aliviar o primeiro problema,
|
|
melhorando a legibilidade do código-fonte.
|
|
</simpara>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
<simpara>
|
|
Os Namespaces do PHP fornecem uma maneira de agrupar classes, interfaces,
|
|
funções e constantes relacionadas. Aqui está um exemplo da sintaxe de namespace em PHP:
|
|
</simpara>
|
|
<example>
|
|
<title>Exemplo da sintaxe de namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace meu\nome; // veja a seção "Definindo Namespaces"
|
|
|
|
class MinhaClasse {}
|
|
function minhafuncao() {}
|
|
const MINHACONST = 1;
|
|
|
|
$a = new MinhaClasse;
|
|
$c = new \meu\nome\MinhaClasse; // veja a seção "Espaço Global"
|
|
|
|
$a = strlen('oi'); // veja a seção "Usando namespaces: recorrendo a
|
|
// funções/constantes globais"
|
|
|
|
$d = namespace\MINHACONST; // veja a seção "operador de namespace
|
|
// e constante __NAMESPACE__"
|
|
$d = __NAMESPACE__ . '\MINHACONST';
|
|
echo constant($d); // veja a seção "Namespaces e recursos de linguagem dinâmica"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<note>
|
|
<simpara>
|
|
Nomes de namespace não diferenciam maiúsculas de minúsculas.
|
|
</simpara>
|
|
</note>
|
|
<note>
|
|
<para>
|
|
O nome do namespace <literal>PHP</literal> e os nomes compostos que começam
|
|
com esse nome (como <literal>PHP\Classes</literal>) são reservados para uso interno da linguagem
|
|
e não devem ser usados no código criado pelo usuário.
|
|
</para>
|
|
</note>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.namespaces.definition">
|
|
<title>Definindo namespaces</title>
|
|
<titleabbrev>Namespaces</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
Embora qualquer código PHP válido possa estar contido em um namespace, apenas os seguintes
|
|
tipos de código são afetados por namespaces: classes (incluindo abstratas, traits e enumerações), interfaces,
|
|
funções e constantes.
|
|
</para>
|
|
<para>
|
|
Namespaces são declarados usando a palavra-chave <literal>namespace</literal>.
|
|
Um arquivo contendo um namespace deve declarar o namespace
|
|
no início do arquivo antes de qualquer outro código - com uma exceção: a
|
|
palavra-chave <xref linkend="control-structures.declare" />.
|
|
<example>
|
|
<title>Declarando um único namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace MeuProjeto;
|
|
|
|
const CONEXAO_OK = 1;
|
|
class Conexao { /* ... */ }
|
|
function conectar() { /* ... */ }
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<note>
|
|
<simpara>
|
|
Nomes totalmente qualificados (ou seja, nomes que começam com uma barra invertida) não são permitidos em declarações
|
|
de namespace, por serem construções interpretadas como expressões de namespace relativos.
|
|
</simpara>
|
|
</note>
|
|
A única construção de código permitida antes de uma declaração de namespace é a
|
|
declaração <literal>declare</literal>, para definir a codificação de um arquivo-fonte. Além disso,
|
|
nenhum código não-PHP pode preceder uma declaração de namespace, incluindo espaço em branco extra:
|
|
<example>
|
|
<title>Declarando um único namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<html>
|
|
<?php
|
|
namespace MeuProjeto; // erro fatal - namespace precisa ser a primeira declaração no script
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Além disso, ao contrário de qualquer outra construção do PHP, o mesmo namespace pode ser definido
|
|
em vários arquivos, permitindo a divisão do conteúdo de um namespace no sistema de arquivos.
|
|
</para>
|
|
</sect1>
|
|
<sect1 xml:id="language.namespaces.nested">
|
|
<title>Declarando sub-namespaces</title>
|
|
<titleabbrev>Sub-namespaces</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
Assim como diretórios e arquivos, os namespaces do PHP podem especificar
|
|
uma hierarquia de namespaces. Assim, um namespace pode ser definido com
|
|
subníveis.
|
|
<example>
|
|
<title>Declarando um único namespace com hierarquia</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace MeuProjeto\Nivel\SubNivel;
|
|
|
|
const CONEXAO_OK = 1;
|
|
class Conexao { /* ... */ }
|
|
function conectar() { /* ... */ }
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
O exemplo acima cria a constante <literal>MeuProjeto\Nivel\SubNivel\CONEXAO_OK</literal>,
|
|
a classe <literal>MeuProjeto\Nivel\SubNivel\Conexao</literal> e a função
|
|
<literal>MeuProjeto\Nivel\SubNivel\conectar</literal>.
|
|
</para>
|
|
</sect1>
|
|
<sect1 xml:id="language.namespaces.definitionmultiple">
|
|
<title>Definindo vários namespaces no mesmo arquivo</title>
|
|
<titleabbrev>Definindo vários namespaces no mesmo arquivo</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
Vários namespaces também podem ser declarados no mesmo arquivo. Existem duas sintaxes
|
|
permitidas.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Declarando vários namespaces, sintaxe de combinação simples</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace MeuProjeto;
|
|
|
|
const CONEXAO_OK = 1;
|
|
class Conexao { /* ... */ }
|
|
function conectar() { /* ... */ }
|
|
|
|
namespace OutroProjeto;
|
|
|
|
const CONEXAO_OK = 1;
|
|
class Conexao { /* ... */ }
|
|
function conectar() { /* ... */ }
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Essa sintaxe não é recomendada para combinar namespaces em um único arquivo.
|
|
Em vez disso, é recomendado usar a sintaxe alternativa de colchetes.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Declarando vários namespaces, sintaxe de colchetes</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace MeuProjeto {
|
|
|
|
const CONEXAO_OK = 1;
|
|
class Conexao { /* ... */ }
|
|
function conectar() { /* ... */ }
|
|
}
|
|
|
|
namespace OutroProjeto {
|
|
|
|
const CONEXAO_OK = 1;
|
|
class Conexao { /* ... */ }
|
|
function conectar() { /* ... */ }
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
É altamente desaconselhado como prática de programação combinar vários namespaces no
|
|
mesmo arquivo. O principal caso de uso é combinar vários scripts PHP no mesmo
|
|
arquivo.
|
|
</para>
|
|
<para>
|
|
Para combinar código global sem namespace com código com namespace, apenas a sintaxe de colchetes é
|
|
suportada. O código global deve ser
|
|
encapsulado em uma declaração de namespace sem nome de namespace, como em:
|
|
<example>
|
|
<title>Declarando vários namespaces e código sem namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace MeuProjeto {
|
|
|
|
const CONEXAO_OK = 1;
|
|
class Conexao { /* ... */ }
|
|
function conectar() { /* ... */ }
|
|
}
|
|
|
|
namespace { // código global
|
|
session_start();
|
|
$a = MeuProjeto\conectar();
|
|
echo MeuProjeto\Conexao::iniciar();
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Nenhum código PHP pode existir fora dos colchetes do namespace, exceto uma declaração
|
|
declare de abertura.
|
|
<example>
|
|
<title>Declarando vários namespaces e código sem namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
declare(encoding='UTF-8');
|
|
namespace MeuProjeto {
|
|
|
|
const CONEXAO_OK = 1;
|
|
class Conexao { /* ... */ }
|
|
function conectar() { /* ... */ }
|
|
}
|
|
|
|
namespace { // código global
|
|
session_start();
|
|
$a = MeuProjeto\conectar();
|
|
echo MeuProjeto\Conexao::iniciar();
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect1>
|
|
<sect1 xml:id="language.namespaces.basics">
|
|
<title>Usando namespaces: Fundamentos</title>
|
|
<titleabbrev>Fundamentos</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
Antes de discutir o uso de namespaces, é importante entender como o PHP
|
|
sabe qual elemento de namespace seu código está solicitando. Uma analogia simples pode ser feita
|
|
entre os namespaces do PHP e um sistema de arquivos. Existem três maneiras de acessar um arquivo em um
|
|
sistema de arquivos:
|
|
<orderedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Nome de arquivo relativo como <literal>foo.txt</literal>. Será resolvido para
|
|
<literal>diretorioatual/foo.txt</literal> onde <literal>diretorioatual</literal> é o
|
|
diretório ocupado atualmente. Então, se o diretório atual for
|
|
<literal>/home/foo</literal>, o nome será resolvido para <literal>/home/foo/foo.txt</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Nome de caminho relativo como <literal>subdiretorio/foo.txt</literal>. Será resolvido
|
|
para <literal>diretorioatual/subdiretorio/foo.txt</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Nome de caminho absoluto como <literal>/main/foo.txt</literal>. Será resolvido
|
|
para <literal>/main/foo.txt</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
</orderedlist>
|
|
O mesmo princípio pode ser aplicado a elementos com namespace no PHP. Por
|
|
exemplo, um nome de classe pode ser referenciado de três maneiras:
|
|
<orderedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Nome não qualificado ou nome de classe sem prefixo como
|
|
<literal>$a = new foo();</literal> ou
|
|
<literal>foo::metodoestatico();</literal>. Se o namespace atual for
|
|
<literal>namespaceatual</literal>, ele será resolvido para
|
|
<literal>namespaceatual\foo</literal>. Se
|
|
o código for global, sem namespace, ele será resolvido para <literal>foo</literal>.
|
|
</simpara>
|
|
<simpara>
|
|
Uma ressalva: nomes não qualificados para funções e constantes
|
|
serão resolvidos para funções e constantes globais se a função ou constante com namespace
|
|
não for definida. Veja <link linkend="language.namespaces.fallback">Usando namespaces:
|
|
recorrendo a funções/constantes globais</link> para obter detalhes.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Nome qualificado ou um nome de classe prefixado como
|
|
<literal>$a = new subnamespace\foo();</literal> ou
|
|
<literal>subnamespace\foo::metodoestatico();</literal>. Se o namespace atual for
|
|
<literal>namespaceatual</literal>, ele será resolvido para
|
|
<literal>namespaceatual\subnamespace\foo</literal>. Se
|
|
o código for global, sem namespace, ele será resolvido para <literal>subnamespace\foo</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Nome totalmente qualificado ou um nome prefixado com um operador de prefixo global como
|
|
<literal>$a = new \namespaceatual\foo();</literal> ou
|
|
<literal>\namespaceatual\foo::metodoestatico();</literal>. Ele sempre será resolvido
|
|
para o nome literal especificado no código, <literal>namespaceatual\foo</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
<para>
|
|
Aqui está um exemplo dos três tipos de sintaxe em código real:
|
|
<informalexample>
|
|
<simpara>arquivo1.php</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace Foo\Bar\subnamespace;
|
|
|
|
const FOO = 1;
|
|
function foo() {}
|
|
class foo
|
|
{
|
|
static function metodoestatico() {}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
<simpara>arquivo2.php</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace Foo\Bar;
|
|
include 'arquivo1.php';
|
|
|
|
const FOO = 2;
|
|
function foo() {}
|
|
class foo
|
|
{
|
|
static function metodoestatico() {}
|
|
}
|
|
|
|
/* Nome não qualificado */
|
|
foo(); // será resolvido para a função Foo\Bar\foo
|
|
foo::metodoestatico(); // será resolvido para a classe Foo\Bar\foo, método metodoestatico
|
|
echo FOO; // será resolvido para a constante Foo\Bar\FOO
|
|
|
|
/* Nome qualificado */
|
|
subnamespace\foo(); // será resolvido para a função Foo\Bar\subnamespace\foo
|
|
subnamespace\foo::metodoestatico(); // será resolvido para a classe Foo\Bar\subnamespace\foo,
|
|
// método metodoestatico
|
|
echo subnamespace\FOO; // será resolvido para a constante constant Foo\Bar\subnamespace\FOO
|
|
|
|
/* Nome totalmente qualificado */
|
|
\Foo\Bar\foo(); // será resolvido para a função Foo\Bar\foo
|
|
\Foo\Bar\foo::metodoestatico(); // será resolvido para a classe Foo\Bar\foo, método metodoestatico
|
|
echo \Foo\Bar\FOO; // será resolvido para a constante Foo\Bar\FOO
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
Note que para acessar qualquer classe,
|
|
função ou constante global, um nome totalmente qualificado pode ser usado, como
|
|
<function>\strlen</function> ou <classname>\Exception</classname> ou
|
|
\<constant>INI_ALL</constant>.
|
|
<example>
|
|
<title>Acessando classes, funções e constantes globais em um namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace Foo;
|
|
|
|
function strlen() {}
|
|
const INI_ALL = 3;
|
|
class Exception {}
|
|
|
|
$a = \strlen('oi'); // chama a função global strlen
|
|
$b = \INI_ALL; // acessa a constante global INI_ALL
|
|
$c = new \Exception('erro'); // instancia um objeto da classe global Exception
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect1>
|
|
<sect1 xml:id="language.namespaces.dynamic">
|
|
<title>Namespaces e recursos de linguagem dinâmica</title>
|
|
<titleabbrev>Namespaces e recursos de linguagem dinâmica</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
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:
|
|
<example>
|
|
<title>Acessando elementos dinamicamente</title>
|
|
<simpara>exemplo1.php:</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?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
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
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.
|
|
<example>
|
|
<title>Acessando dinamicamente elementos com namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?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
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Certifique-se de ler a <link linkend="language.namespaces.faq.quote">nota sobre
|
|
escapamento de namespaces em strings</link>.
|
|
</para>
|
|
</sect1>
|
|
<sect1 xml:id="language.namespaces.nsconstants">
|
|
<title>Palavra-chave namespace e constante __NAMESPACE__</title>
|
|
<titleabbrev>Palavra-chave namespace e __NAMESPACE__</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
O PHP suporta duas maneiras de acessar elementos de forma abstrata dentro do namespace atual,
|
|
a constante mágica <constant>__NAMESPACE__</constant> e a palavra-chave
|
|
<literal>namespace</literal>.
|
|
</para>
|
|
<para>
|
|
O valor de <constant>__NAMESPACE__</constant> é uma string que contém o nome do namespace
|
|
atual. Em código global, sem namespace, ela contém uma string vazia.
|
|
<example>
|
|
<title>Exemplo de __NAMESPACE__, código com namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace MeuProjeto;
|
|
|
|
echo '"', __NAMESPACE__, '"'; // produz "MeuProjeto"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<example>
|
|
<title>Exemplo de __NAMESPACE__, código global</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
echo '"', __NAMESPACE__, '"'; // produz ""
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
A constante <constant>__NAMESPACE__</constant> é útil para construir nomes de forma
|
|
dinâmica, por exemplo:
|
|
<example>
|
|
<title>Usando __NAMESPACE__ para construção dinâmica de nomes</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace MeuProjeto;
|
|
|
|
function get($nomedaclasse)
|
|
{
|
|
$a = __NAMESPACE__ . '\\' . $nomedaclasse;
|
|
return new $a;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
A palavra-chave <literal>namespace</literal> pode ser usada para solicitar explicitamente
|
|
um elemento do namespace atual ou um subnamespace. Ela é o equivalente
|
|
para namespaces do operador <literal>self</literal> para classes.
|
|
<example>
|
|
<title>O operador namespace, em um namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace MeuProjeto;
|
|
|
|
use bla\bla as meu; // Veja "Usando namespaces: Apelidando/Importando"
|
|
|
|
bla\meu(); // chama a função MeuProjeto\bla\meu()
|
|
namespace\bla\meu(); // chama a função MeuProjeto\bla\meu()
|
|
|
|
namespace\funcao(); // chama a função MeuProjeto\funcao()
|
|
namespace\sub\funcao(); // chama a função MeuProjeto\sub\funcao()
|
|
namespace\nomedaclasse::metodo(); // chama o método estático "metodo" da classe MeuProjeto\nomedaclasse
|
|
$a = new namespace\sub\nomedaclasse(); // instancia um objeto da classe MeuProjeto\sub\nomedaclasse
|
|
$b = namespace\CONSTANTE; // atribui o valor da constante MeuProjeto\CONSTANTE a $b
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<example>
|
|
<title>O operador namespace, em código global</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
namespace\funcao(); // chama a função funcao()
|
|
namespace\sub\funcao(); // chama a função sub\funcao()
|
|
namespace\nomedaclasse::metodo(); // chama o método estático "metodo" da classe nomedaclasse
|
|
$a = new namespace\sub\nomedaclasse(); // instancia um objeto da classe sub\nomedaclasse
|
|
$b = namespace\CONSTANTE; // atribui o valor da constante CONSTANTE a $b
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.namespaces.importing">
|
|
<title>Usando namespaces: Apelidando/Importando</title>
|
|
<titleabbrev>Apelidando e Importando</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
A capacidade de se referir a um nome totalmente qualificado externo com um apelido, ou importação,
|
|
é um recurso importante dos namespaces. Isso é semelhante à
|
|
capacidade dos sistemas de arquivos baseados em Unix de criar links simbólicos para um arquivo ou diretório.
|
|
</para>
|
|
<para>
|
|
O PHP pode apelidar ou importar constantes, funções, classes, interfaces, traits, enums e namespaces.
|
|
</para>
|
|
<para>
|
|
A criação de apelidos é realizada com o operador <literal>use</literal>.
|
|
Aqui está um exemplo mostrando todos os 5 tipos de importação:
|
|
<example>
|
|
<title>Importando ou apelidando com o operador use</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace foo;
|
|
use Caminho\Completo\Classe as Outra;
|
|
|
|
// Isso é o mesmo que use Caminho\Completo\NomeNamespace as NomeNamespace
|
|
use Caminho\Completo\NomeNamespace;
|
|
|
|
// Importando uma classe global
|
|
use ArrayObject;
|
|
|
|
// Importando uma função
|
|
use function Caminho\Completo\nomeFuncao;
|
|
|
|
// Apelidando uma função
|
|
use function Caminho\Completo\nomeFuncao as funcao;
|
|
|
|
// Importando uma constante
|
|
use const Caminho\Completo\CONSTANTE;
|
|
|
|
$obj = new namespace\Outra; // Instancia um objeto da classe foo\Outra
|
|
$obj = new Outra; // Instancia um objeto da classe Caminho\Completo\Classe
|
|
NomeNamespace\SubNamespace\funcao(); // Chama a função Caminho\Completo\NomeNamespace\SubNamespace\funcao
|
|
$a = new ArrayObject(array(1)); // Instancia um objeto da classe ArrayObject
|
|
// Sem a declaração "use ArrayObject" teria sido instanciado um objeto da classe foo\ArrayObject
|
|
funcao(); // chama a função Caminho\Completo\nomeFuncao
|
|
echo CONSTANTE; // imprime o valor de Caminho\Completo\CONSTANTE
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Note que para nomes com namespaces (nomes de namespaces totalmente qualificados contendo
|
|
o separador de namespace, como <literal>Foo\Bar</literal>, em oposição a nomes globais sem
|
|
separadores, como <literal>FooBar</literal>), a barra invertida inicial não é necessária e não
|
|
é recomendada, pois nomes importados precisam
|
|
ser totalmente qualificados e não são processados em relação ao namespace atual.
|
|
</para>
|
|
<para>
|
|
O PHP também suporta um atalho de conveniência para colocar várias instruções use
|
|
na mesma linha.
|
|
<example>
|
|
<title>Importando ou criando apelidos com várias declarações use combinadas</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
use Caminho\Completo\Classe as Outra, Caminho\Completo\NomeNamespace;
|
|
|
|
$obj = new Outra; // Instancia um objeto da classe Caminho\Completo\Classe
|
|
NomeNamespace\SubNamespace\funcao(); // Chama a função Caminho\Completo\NomeNamespace\SubNamespace\funcao
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
A importação é realizada em tempo de compilação e por isso, não afeta classes, funções
|
|
ou nomes de constantes gerados dinamicamente.
|
|
<example>
|
|
<title>Importação e nomes dinâmicos</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
use Caminho\Completo\Classe as Outra, Caminho\Completo\NomeNamespace;
|
|
|
|
$obj = new Outra; // Instancia um objeto da classe Caminho\Completo\Classe
|
|
$a = 'Outra';
|
|
$obj = new $a; // Instancia um objeto da classe Outra
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Além disso, a importação afeta apenas nomes não qualificados e qualificados. Nomes totalmente
|
|
qualificados são absolutos e não são afetados pelas importações.
|
|
<example>
|
|
<title>Importação e nomes completamente qualificados</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
use Caminho\Completo\Classe as Outra, Caminho\Completo\NomeNamespace;
|
|
|
|
$obj = new Outra; // Instancia um objeto da classe Caminho\Completo\Classe
|
|
$obj = new \Outra; // Instancia um objeto da classe Outra
|
|
$obj = new Outra\Coisa; // Instancia um objeto da classe Caminho\Completo\Classe\Coisa
|
|
$obj = new \Outra\Coisa; // Instancia um objeto da classe Outra\Coisa
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<sect2 xml:id="language.namespaces.importing.scope">
|
|
<title>Regras de escopo para importação</title>
|
|
<para>
|
|
A palavra-chave <literal>use</literal> precisa ser declarada no
|
|
escopo mais externo do arquivo (o escopo global) ou dentro de declarações
|
|
de namespaces. Isso ocorre por a importação ser realizada em tempo de
|
|
compilação e não em tempo de execução, portanto, não pode ter escopo de bloco. O exemplo
|
|
a seguir mostra um uso inválido da palavra-chave
|
|
<literal>use</literal>:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Regra de importação inválida</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace Linguas;
|
|
|
|
function paraGroenlandes()
|
|
{
|
|
use Linguas\Dinamarques;
|
|
|
|
// ...
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<note>
|
|
<para>
|
|
As regras de importação são por arquivo, o que significa que os arquivos incluídos
|
|
<emphasis>NÃO</emphasis> herdarão as regras de importação do arquivo pai.
|
|
</para>
|
|
</note>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.importing.group">
|
|
<title>Declarações <literal>use</literal> em grupo</title>
|
|
<para>
|
|
Classes, funções e constantes importadas do
|
|
mesmo &namespace; podem ser agrupadas numa única declaração
|
|
&use.namespace;.
|
|
</para>
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
use algum\namespace\ClasseA;
|
|
use algum\namespace\ClasseB;
|
|
use algum\namespace\ClasseC as C;
|
|
|
|
use function algum\namespace\fn_a;
|
|
use function algum\namespace\fn_b;
|
|
use function algum\namespace\fn_c;
|
|
|
|
use const algum\namespace\ConstA;
|
|
use const algum\namespace\ConstB;
|
|
use const algum\namespace\ConstC;
|
|
|
|
// É equivalente à seguinte declaração use agrupada
|
|
use algum\namespace\{ClasseA, ClasseB, ClasseC as C};
|
|
use function algum\namespace\{fn_a, fn_b, fn_c};
|
|
use const algum\namespace\{ConstA, ConstB, ConstC};
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</sect2>
|
|
</sect1>
|
|
<sect1 xml:id="language.namespaces.global">
|
|
<title>Espaço Global</title>
|
|
<titleabbrev>Espaço Global</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
Quando um namespace não é definido, todas as definições de classes e funções são
|
|
colocadas no espaço global, como era no PHP antes de os namespaces serem
|
|
suportados. Prefixar um nome com <literal>\</literal> especificará que
|
|
o nome é necessário no espaço global, mesmo no contexto do
|
|
namespace.
|
|
<example>
|
|
<title>Usando a especificação do espaço global</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace A\B\C;
|
|
|
|
/* Esta função é A\B\C\fopen */
|
|
function fopen() {
|
|
/* ... */
|
|
$f = \fopen(...); // chama a função fopen global
|
|
return $f;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect1>
|
|
<sect1 xml:id="language.namespaces.fallback">
|
|
<title>Usando namespaces: recorrendo ao espaço global para funções e constantes</title>
|
|
<titleabbrev>Recorrendo ao espaço global</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
Dentro de um namespace, quando o PHP encontra um nome não qualificado em um nome de classe, função ou
|
|
contexto de constante, eles são resolvidos com diferentes prioridades. Nomes de classe sempre
|
|
são resolvidos para o nome do namespace atual. Portanto, para acessar classes internas ou classes de usuário
|
|
sem namespace, deve-se referir a elas com o nome totalmente qualificado como em:
|
|
<example>
|
|
<title>Acessando classes globais em um namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace A\B\C;
|
|
class Exception extends \Exception {}
|
|
|
|
$a = new Exception('oi'); // $a é um objeto da classe A\B\C\Exception
|
|
$b = new \Exception('oi'); // $b é um objeto da classe Exception
|
|
|
|
$c = new ArrayObject; // erro fatal, classe A\B\C\ArrayObject não encontrada
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Para funções e constantes, o PHP recorrerá a funções ou constantes globais
|
|
se a função ou constante com namespace não existir.
|
|
<example>
|
|
<title>Recorrendo a funções/constantes globais em um namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace A\B\C;
|
|
|
|
const E_ERROR = 45;
|
|
function strlen($str)
|
|
{
|
|
return \strlen($str) - 1;
|
|
}
|
|
|
|
echo E_ERROR, "\n"; // imprime "45"
|
|
echo INI_ALL, "\n"; // imprime "7" - recorre à constante INI_ALL global
|
|
|
|
echo strlen('oi'), "\n"; // imprime "1"
|
|
if (is_array('oi')) { // imprime "não é array"
|
|
echo "é array\n";
|
|
} else {
|
|
echo "não é array\n";
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.namespaces.rules">
|
|
<title>Regras de resolução de nomes</title>
|
|
<titleabbrev>Regras de resolução de nomes</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
Para efeitos destas regras de resolução, aqui estão algumas definições importantes:
|
|
<variablelist>
|
|
<title>Definições de nomes de namespace</title>
|
|
<varlistentry>
|
|
<term>Nome não qualificado</term>
|
|
<listitem>
|
|
<para>
|
|
Este é um identificador sem separador de namespace, como <literal>Foo</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Nome qualificado</term>
|
|
<listitem>
|
|
<para>
|
|
Este é um identificador com separador de namespace, como <literal>Foo\Bar</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Nome totalmente qualificado</term>
|
|
<listitem>
|
|
<para>
|
|
Este é um identificador com separador de namespace que começa com um
|
|
separador de namespace, como <literal>\Foo\Bar</literal>. O namespace
|
|
<literal>\Foo</literal> também é um nome totalmente qualificado.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Nome relativo</term>
|
|
<listitem>
|
|
<para>
|
|
Este é um identificador que começa com <literal>namespace</literal>, como
|
|
<literal>namespace\Foo\Bar</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
<para>
|
|
Os nomes são resolvidos seguindo estas regras de resolução:
|
|
<orderedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Nomes totalmente qualificados sempre são resolvidos para o nome sem separador de namespace à esquerda.
|
|
Por exemplo, <literal>\A\B</literal> será resolvido para <literal>A\B</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Nomes relativos sempre são resolvidos para o nome com <literal>namespace</literal> substituído
|
|
pelo namespace atual. Se o nome ocorrer no namespace global, o
|
|
prefixo <literal>namespace\</literal> será removido. Por exemplo, <literal>namespace\A</literal>
|
|
dentro do namespace <literal>X\Y</literal> será resolvido para <literal>X\Y\A</literal>. O mesmo nome
|
|
dentro do namespace global será resolvido para <literal>A</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Para nomes qualificados, o primeiro segmento do nome será traduzido conforme a tabela
|
|
de importação de classe/namespace atual. Por exemplo, se o namespace <literal>A\B\C</literal> for
|
|
importado como <literal>C</literal>, o nome <literal>C\D\E</literal> será traduzido para
|
|
<literal>A\B\C\D\E</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Para nomes qualificados, se nenhuma regra de importação se aplicar, o namespace atual será prefixo ao
|
|
nome. Por exemplo, o nome <literal>C\D\E</literal> dentro do namespace <literal>A\B</literal>,
|
|
será resolvido para <literal>A\B\C\D\E</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Para nomes não qualificados, o nome será traduzido conforme a tabela de importação atual para o
|
|
respectivo tipo de símbolo. Isso significa que nomes semelhantes a classes serão traduzidos conforme a
|
|
tabela de importação de classe/namespace, nomes de funções conforme a tabela de importação de funções e
|
|
constantes conforme a tabela de importação de constantes. Por exemplo, após a declaração
|
|
<literal>use A\B\C;</literal> um uso como <literal>new C()</literal> será resolvido para o nome
|
|
<literal>A\B\C()</literal>. Da mesma forma, após a declaração <literal>use function A\B\foo;</literal> um uso
|
|
como <literal>foo()</literal> será resolvido para o nome <literal>A\B\foo</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Para nomes não qualificados, se nenhuma regra de importação se aplicar e o nome se referir a um símbolo de classe,
|
|
o namespace atual será prefixo. Por exemplo <literal>new C()</literal> dentro do namespace
|
|
<literal>A\B</literal> será resolvido para o nome <literal>A\B\C</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Para nomes não qualificados, se nenhuma regra de importação se aplicar e o nome se referir a uma função ou constante
|
|
e o código estiver fora do namespace global, o nome será resolvido em tempo de execução.
|
|
Supondo que o código esteja no namespace <literal>A\B</literal>, é assim que uma chamada para a função
|
|
<literal>foo()</literal> será resolvida:
|
|
</simpara>
|
|
<orderedlist>
|
|
<listitem>
|
|
<simpara>
|
|
Procura pela função no namespace atual:
|
|
<literal>A\B\foo()</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Tenta encontrar e chamar a função <emphasis>global</emphasis>
|
|
<literal>foo()</literal>.
|
|
</simpara>
|
|
</listitem>
|
|
</orderedlist>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
<example>
|
|
<title>Resoluções de nomes ilustradas</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace A;
|
|
use B\D, C\E as F;
|
|
|
|
// chamadas de funções
|
|
|
|
foo(); // primeiro tenta chamar "foo" definida no namespace "A"
|
|
// então chama a função global "foo"
|
|
|
|
\foo(); // chama a função "foo" definida no escopo global
|
|
|
|
minha\foo(); // chama a função "foo" definida no namespace "A\minha"
|
|
|
|
F(); // primeiro tenta chamar "F" definida no namespace "A"
|
|
// e então chama a função global "F"
|
|
|
|
// referências de classe
|
|
|
|
new B(); // cria um objeto da classe "B" definida no namespace "A"
|
|
// se não for encontrada, tenta carregar automaticamente a classe "A\B"
|
|
|
|
new D(); // usando regras de importação, cria um objeto da classe "D" definida no namespace "B"
|
|
// se não for encontrada, tenta carregar automaticamente a classe "B\D"
|
|
|
|
new F(); // usando regras de importação, cria um objeto da classe "E" definida no namespace "C"
|
|
// se não for encontrada, tenta carregar automaticamente a classe "C\E"
|
|
|
|
new \B(); // cria um objeto da classe "B" definida no escopo global
|
|
// se não for encontrada, tenta carregar automaticamente a classe "B"
|
|
|
|
new \D(); // cria um objeto da classe "D" definida no escopo global
|
|
// se não for encontrado, tenta carregar automaticamente a classe "D"
|
|
|
|
new \F(); // cria um objeto da classe "F" definida no escopo global
|
|
// se não for encontrada, tenta carregar automaticamente a classe "F"
|
|
|
|
// métodos estáticos/funções de namespace de outro namespace
|
|
|
|
B\foo(); // chama a função "foo" do namespace "A\B"
|
|
|
|
B::foo(); // chama o método "foo" da classe "B" definida no namespace "A"
|
|
// se a classe "A\B" não for encontrada, tenta carregar automaticamente a classe "A\B"
|
|
|
|
D::foo(); // usando regras de importação, chama o método "foo" da classe "D" definida no namespace "B"
|
|
// se a classe "B\D" não for encontrada, tenta carregar automaticamente a classe "B\D"
|
|
|
|
\B\foo(); // chama a função "foo" do namespace "B"
|
|
|
|
\B::foo(); // chama o método "foo" da classe "B" do escopo global
|
|
// se a classe "B" não for encontrada, tenta carregar automaticamente a classe "B"
|
|
|
|
// métodos estáticos/funções de namespace do namespace atual
|
|
|
|
A\B::foo(); // chama o método "foo" da classe "B" do namespace "A\A"
|
|
// se a classe "A\A\B" não for encontrada, tenta carregar automaticamente a class "A\A\B"
|
|
|
|
\A\B::foo(); // chama o método "foo" da classe "B" do namespace "A"
|
|
// se a classe "A\B" não for encontrada, tenta carregar automaticamente a classe "A\B"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect1>
|
|
<sect1 xml:id="language.namespaces.faq">
|
|
<title>Perguntas Frequentes: Coisas que você precisa saber sobre namespaces</title>
|
|
<titleabbrev>Perguntas Frequentes</titleabbrev>
|
|
<?phpdoc print-version-for="namespaces"?>
|
|
<para>
|
|
Estas perguntas frequentes são divididas em duas seções: perguntas comuns e alguns detalhes de
|
|
implementação úteis para entender os pormenores.
|
|
</para>
|
|
<para>
|
|
Primeiro, as perguntas comuns.
|
|
<orderedlist>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.shouldicare">Se não usar namespaces, devo
|
|
me importar com esta documentação?</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.globalclass">Como usar classes internas ou globais
|
|
em um namespace?</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.innamespace">Como usar classes,
|
|
funções ou constantes de namespace em seu próprio namespace?</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.full">
|
|
Como nomes como <literal>\meu\nome</literal> ou <literal>\nome</literal>
|
|
são resolvidos?
|
|
</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.qualified">Como um nome como
|
|
<literal>meu\nome</literal> é resolvido?</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.shortname1">Como um nome de classe não qualificado
|
|
como <literal>nome</literal> é resolvido?</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.shortname2">Como um nome de função
|
|
não qualificado ou nome de constante não qualificado
|
|
como <literal>nome</literal> é resolvido?</link>
|
|
</simpara>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
<para>
|
|
Há alguns detalhes de implementação dos namespaces úteis para
|
|
entendê-los melhor.
|
|
<orderedlist>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.conflict">Nomes de importação não devem entrar em conflito com
|
|
classes definidas no mesmo arquivo</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.nested">Namespaces aninhados não são permitidos.
|
|
</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.quote">Nomes de namespace dinâmicos (identificadores
|
|
entre aspas) devem escapar a barra invertida</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.constants">Constantes indefinidas referenciadas
|
|
usando qualquer barra invertida geram erro fatal</link>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
<link linkend="language.namespaces.faq.builtinconst">Não é possível substituir
|
|
as constantes especiais &null;, &true; ou &false;</link>
|
|
</simpara>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
<sect2 xml:id="language.namespaces.faq.shouldicare">
|
|
<title>Se não usar namespaces, devo me importar com esta documentação?</title>
|
|
<para>
|
|
Não. Namespaces não afetam nenhum código existente de forma alguma, ou qualquer
|
|
código ainda a ser escrito que não contenha namespaces. Você pode
|
|
escrever este código se desejar:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Acessando classes globais fora de um namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = new \stdClass;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
O exemplo acima é equivalente ao seguinte código:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Acessando classes globais fora de um namespace</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = new stdClass;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.globalclass">
|
|
<title>Como usar classes internas ou globais em um namespace?</title>
|
|
<para>
|
|
<example>
|
|
<title>Acessando classes internas em namespaces</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace foo;
|
|
$a = new \stdClass;
|
|
|
|
function test(\ArrayObject $exemplo_com_tipo_de_parametro = null) {}
|
|
|
|
$a = \DirectoryIterator::CURRENT_AS_FILEINFO;
|
|
|
|
// estendendo uma classe interna ou global
|
|
class MinhaExcecao extends \Exception {}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.innamespace">
|
|
<title>
|
|
Como usar classes, funções ou constantes de namespace em seu próprio
|
|
namespace?
|
|
</title>
|
|
<para>
|
|
<example>
|
|
<title>Acessando classes, funções ou constantes internas em namespaces</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace foo;
|
|
|
|
class MinhaClasse {}
|
|
|
|
// usando uma classe do namespace atual como tipo de parâmetro
|
|
function test(MinhaClasse $exemplo_com_tipo_de_parametro = null) {}
|
|
// outra forma de usar a classe do namespace atual como tipo de parâmetro
|
|
function test(\foo\MinhaClasse $exemplo_com_tipo_de_parametro = null) {}
|
|
|
|
// estendendo uma classe do namespace atual
|
|
class Estendida extends MinhaClasse {}
|
|
|
|
// acessando uma função global
|
|
$a = \funcao_global();
|
|
|
|
// acessando uma constante global
|
|
$b = \INI_ALL;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.full">
|
|
<title>
|
|
Como nomes como <literal>\meu\nome</literal> ou <literal>\nome</literal>
|
|
são resolvidos?
|
|
</title>
|
|
<para>
|
|
Nomes que começam com uma barra invertida (<literal>\</literal>) sempre são resolvidos
|
|
para seu conteúdo exato, então <literal>\meu\nome</literal> é o mesmo que <literal>meu\nome</literal>
|
|
e <literal>\Exception</literal> é o mesmo que <literal>Exception</literal>.
|
|
<example>
|
|
<title>Nomes totalmente qualificados</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace foo;
|
|
$a = new \meu\nome(); // instancia um objeto da classe "meu\nome"
|
|
echo \strlen('olá'); // invoca a função "strlen"
|
|
$a = \INI_ALL; // define $a com o valor da constante "INI_ALL"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.qualified">
|
|
<title>Como um nome como <literal>meu\nome</literal> é resolvido?</title>
|
|
<para>
|
|
Nomes que contêm barra invertida, mas não começam com uma barra invertida, como
|
|
<literal>meu\nome</literal> podem ser resolvidos de duas maneiras diferentes.
|
|
</para>
|
|
<para>
|
|
Se houver
|
|
uma instrução de importação que cria o apelido <literal>meu</literal> para outro nome, então
|
|
o apelido da importação será aplicado ao <literal>meu</literal> em <literal>meu\nome</literal>.
|
|
</para>
|
|
<para>
|
|
Caso contrário, o nome do namespace atual será prefixado a <literal>meu\nome</literal>.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Nomes qualificados</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace foo;
|
|
use bla\bla as foo;
|
|
|
|
$a = new meu\nome(); // instancia um objeto da classe "foo\meu\nome"
|
|
foo\bar::nome(); // chama o método estático "nome" na classe "bla\bla\bar"
|
|
minha\bar(); // chama a função "foo\minha\bar"
|
|
$a = minha\BAR; // define $a com o valor da constante "foo\minha\BAR"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.shortname1">
|
|
<title>Como um nome de classe não qualificado como <literal>nome</literal> é resolvido?</title>
|
|
<para>
|
|
Nomes de classes que não contêm barra invertida como
|
|
<literal>nome</literal> podem ser resolvidos de duas maneiras diferentes.
|
|
</para>
|
|
<para>
|
|
Se houver
|
|
uma instrução de importação que cria o apelido <literal>nome</literal> para outro nome, então
|
|
o apelido da importação será aplicado.
|
|
</para>
|
|
<para>
|
|
Caso contrário, o nome do namespace atual será prefixado a <literal>nome</literal>.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Nomes de classe não qualificados</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace foo;
|
|
use bla\bla as foo;
|
|
|
|
$a = new nome(); // instancia um objeto da classe "foo\nome"
|
|
foo::nome(); // chama o método estático "nome" na classe "bla\bla"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.shortname2">
|
|
<title>
|
|
Como um nome de função não qualificado ou nome de constante não qualificado
|
|
como <literal>nome</literal> é resolvido?
|
|
</title>
|
|
<para>
|
|
Nomes de funções ou constantes que não contêm barra invertida como
|
|
<literal>nome</literal> podem ser resolvidos de duas maneiras diferentes.
|
|
</para>
|
|
<para>
|
|
Primeiro, o nome do namespace atual será prefixado a <literal>nome</literal>.
|
|
</para>
|
|
<para>
|
|
Finalmente, se a constante ou função <literal>nome</literal> não existir
|
|
no namespace atual, uma constante ou função global <literal>nome</literal>
|
|
será usada se existir.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Nomes de funções ou constantes não qualificados</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace foo;
|
|
use bla\bla as foo;
|
|
|
|
const FOO = 1;
|
|
|
|
function minha() {}
|
|
function foo() {}
|
|
function sort(&$a)
|
|
{
|
|
\sort($a); // chama a função global "sort"
|
|
$a = array_flip($a);
|
|
return $a;
|
|
}
|
|
|
|
minha(); // chama "foo\minha"
|
|
$a = strlen('hi'); // chama a função global "strlen" porque não existe "foo\strlen"
|
|
$arr = array(1,3,2);
|
|
$b = sort($arr); // chama a função "foo\sort"
|
|
$c = foo(); // chama a função "foo\foo" - a importação não é aplicada
|
|
|
|
$a = FOO; // define $a com o valor da constante "foo\FOO" - a importação não é aplicada
|
|
$b = INI_ALL; // define $b com o valor da constante global "INI_ALL"
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.conflict">
|
|
<title>Nomes de importação não devem entrar em conflito com classes definidas no mesmo arquivo</title>
|
|
<para>
|
|
As seguintes combinações de script são válidas:
|
|
<informalexample>
|
|
<simpara>arquivo1.php</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace minha\coisa;
|
|
class MinhaClasse {}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
<simpara>outra.php</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace outra;
|
|
class coisa {}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
<simpara>arquivo2.php</simpara>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace minha\coisa;
|
|
include 'arquivo1.php';
|
|
include 'outra.php';
|
|
|
|
use outra\coisa as MinhaClasse;
|
|
$a = new MinhaClasse; // instancia um objeto da classe coisa do namespace outra
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
<para>
|
|
Não há conflito de nomes, mesmo que a classe <literal>MinhaClasse</literal> exista
|
|
dentro do namespace <literal>minha\coisa</literal>, porque a definição de MinhaClasse está
|
|
em um arquivo separado. No entanto, o próximo exemplo causa um erro fatal de conflito de nomes
|
|
porque MinhaClasse está definida no mesmo arquivo que a declaração use.
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace minha\coisa;
|
|
use outra\coisa as MinhaClasse;
|
|
class MinhaClasse {} // erro fatal: MinhaClasse está em conflito com a declaração de importação
|
|
$a = new MinhaClasse;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.nested">
|
|
<title>Namespaces aninhados não são permitidos</title>
|
|
<para>
|
|
O PHP não permite aninhar namespaces.
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace minha\coisa {
|
|
namespace aninhada {
|
|
class foo {}
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
No entanto, é fácil simular namespaces aninhados da seguinte forma:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace minha\coisa\aninhada {
|
|
class foo {}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.namespaces.faq.quote">
|
|
<title>Nomes de namespace dinâmicos (identificadores entre aspas) devem escapar a barra invertida</title>
|
|
<para>
|
|
É muito importante perceber que, como a barra invertida é usada como um caractere de escape
|
|
dentro de strings, ela sempre deve ser duplicada quando usada em uma string. Caso contrário,
|
|
existe o risco de consequências não desejadas:
|
|
<example>
|
|
<title>Perigos do uso de nomes com namespace em uma string com aspas duplas</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$a = "\nome\perigoso"; // \n é uma nova linha dentro de strings com aspas duplas!
|
|
$obj = new $a;
|
|
|
|
$a = 'nada\perigoso'; // não há problemas aqui.
|
|
$obj = new $a;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
Dentro de uma string com aspas simples, a sequência de escape da barra invertida é muito mais segura de usar, mas
|
|
ainda é uma prática recomendada escapar as barras invertidas em todas as strings.
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.constants">
|
|
<title>Constantes indefinidas referenciadas usando qualquer barra invertida geram erro fatal</title>
|
|
<para>
|
|
Qualquer constante indefinida não qualificada como <literal>FOO</literal> gerará
|
|
um alerta explicando que o PHP assumiu que <literal>FOO</literal> era o valor
|
|
da constante. Qualquer constante, qualificada ou totalmente qualificada, que contenha
|
|
uma barra invertida produzirá um erro fatal se não for encontrada.
|
|
<example>
|
|
<title>Constantes não definidas</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace bar;
|
|
$a = FOO; // Produz um alerta - constante indefinida FOO assumiu "FOO"
|
|
$a = \FOO; // Erro fatal, constante de namespace indefinida FOO
|
|
$a = Bar\FOO; // Erro fatal, constante de namespace indefinida bar\Bar\FOO
|
|
$a = \Bar\FOO; // Erro fatal, constante de namespace indefinida Bar\FOO
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="language.namespaces.faq.builtinconst">
|
|
<title>Não é possível substituir as constantes especiais &null;, &true; ou &false;</title>
|
|
<para>
|
|
Qualquer tentativa de definir uma constante de namespace que seja uma constante especial nativa
|
|
resultará em um erro fatal.
|
|
<example>
|
|
<title>Constantes não definidas</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
namespace bar;
|
|
const NULL = 0; // Erro fatal
|
|
const true = 'verdadeiro'; // Também um erro fatal
|
|
// etc.
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|