<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/language.namespaces.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'zh',
  ),
  'this' => 
  array (
    0 => 'language.namespaces.rules.php',
    1 => '名称解析规则',
    2 => '名称解析规则',
  ),
  'up' => 
  array (
    0 => 'language.namespaces.php',
    1 => '概述',
  ),
  'prev' => 
  array (
    0 => 'language.namespaces.fallback.php',
    1 => '回退到全局空间',
  ),
  'next' => 
  array (
    0 => 'language.namespaces.faq.php',
    1 => 'FAQ',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'zh',
    'path' => 'language/namespaces.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.namespaces.rules" class="sect1">
  <h2 class="title">名称解析规则</h2>
  
  <p class="verinfo">(PHP 5 &gt;= 5.3.0, PHP 7, PHP 8)</p>
  <p class="para">
   在说明名称解析规则之前，我们先看一些重要的定义：
   <dl>
    <strong class="title">命名空间名称定义</strong>
    
     <dt>非限定名称（Unqualified name）</dt>
     <dd>
      <p class="para">
       名称中不包含命名空间分隔符的标识符，例如 <code class="literal">Foo</code>
      </p>
     </dd>
    
    
     <dt>限定名称（Qualified name）</dt>
     <dd>
      <p class="para">
       名称中含有命名空间分隔符的标识符，例如 <code class="literal">Foo\Bar</code>
      </p>
     </dd>
    
    
     <dt>完全限定名称（Fully qualified name）</dt>
     <dd>
      <p class="para">
       名称中包含命名空间分隔符，并以命名空间分隔符开始的标识符，例如 <code class="literal">\Foo\Bar</code>。
       <code class="literal">namespace\Foo</code> 也是一个完全限定名称。
      </p>
     </dd>
    
    
     <dt>相对名称（Relative name）</dt>
     <dd>
      <p class="para">
       这是个以 <code class="literal">namespace</code> 开头的标识符，
       例如
       <code class="literal">namespace\Foo\Bar</code>。
      </p>
     </dd>
    
   </dl>
  </p>
  <p class="para">
   名称解析遵循下列规则：
   <ol type="1">
    <li class="listitem">
     <span class="simpara">
       完全限定名称总是会解析成没有前缀符号的命名空间名称。
       <code class="literal">\A\B</code> 解析为 <code class="literal">A\B</code>。
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      解析相对名称时，会用当前命名空间的名称替换掉 <code class="literal">namespace</code>。
      如果名称出现在全局命名空间，会截掉 <code class="literal">namespace\</code> 前缀。
      例如，在命名空间 <code class="literal">X\Y</code> 里的 <code class="literal">namespace\A</code> 会被解析成 <code class="literal">X\Y\A</code>。
      在全局命名空间里，同样的名字却被解析成 <code class="literal">A</code>。
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      对于限定名称，名字的第一段会根据当前 class/namespace 导入表进行翻译。
      比如命名空间 <code class="literal">A\B\C</code> 被导入为 <code class="literal">C</code>，
      名称 <code class="literal">C\D\E</code> 会被翻译成
      <code class="literal">A\B\C\D\E</code>。
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      对于限定名称，如果没有应用导入规则，就将当前命名空间添加为名称的前缀。
      例如，位于命名空间 <code class="literal">A\B</code> 内的名称 <code class="literal">C\D\E</code>
      会解析成 <code class="literal">A\B\C\D\E</code>。
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      根据符号类型和对应的当前导入表，解析非限定名称。
      这也就是说，根据 class/namespace 导入表翻译类名称；
      根据函数导入表翻译函数名称；
      根据常量导入表翻译常量名称。
      比如，在
      <code class="literal">use A\B\C;</code> 后，类似 <code class="literal">new C()</code> 这样的名称会解析为
      <code class="literal">A\B\C()</code>。
      类似的，<code class="literal">use function A\B\foo;</code> 后，
      <code class="literal">foo()</code> 的用法，解析名称为 <code class="literal">A\B\foo</code>。
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      如果没有应用导入规则，对于类似 class 符号的非限定名称，会添加当前命名空间作为前缀。
      比如命名空间 <code class="literal">A\B</code> 内的 <code class="literal">new C()</code>
      会把名称解析为 <code class="literal">A\B\C</code>。
     </span>
    </li>
    <li class="listitem">
     <span class="simpara">
      如果没有应用导入规则，非限定名称指向函数或常量，且代码位于全局命名空间之外，则会在运行时解析名称。
      假设代码位于命名空间 <code class="literal">A\B</code> 中，
      下面演示了调用函数
      <code class="literal">foo()</code> 是如何解析的：
     </span>
     <ol type="1">
      <li class="listitem">
       <span class="simpara">
        在当前命名空间中查找函数：
        <code class="literal">A\B\foo()</code>。
       </span>
      </li>
      <li class="listitem">
       <span class="simpara">
        它会尝试找到并调用 <em>全局</em> 的函数
        <code class="literal">foo()</code>。
       </span>
      </li>
     </ol>
    </li>
   </ol>
  </p>
  <div class="example" id="example-1">
   <p><strong>示例 #1 名称解析示例</strong></p>
   <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">namespace </span><span style="color: #0000BB">A</span><span style="color: #007700">;<br />use </span><span style="color: #0000BB">B\D</span><span style="color: #007700">, </span><span style="color: #0000BB">C\E </span><span style="color: #007700">as </span><span style="color: #0000BB">F</span><span style="color: #007700">;<br /><br /></span><span style="color: #FF8000">// 函数调用<br /><br /></span><span style="color: #0000BB">foo</span><span style="color: #007700">();      </span><span style="color: #FF8000">// 首先尝试调用定义在命名空间"A"中的函数foo()<br />            // 再尝试调用全局函数 "foo"<br /><br /></span><span style="color: #0000BB">\foo</span><span style="color: #007700">();     </span><span style="color: #FF8000">// 调用全局空间函数 "foo" <br /><br /></span><span style="color: #0000BB">my\foo</span><span style="color: #007700">();   </span><span style="color: #FF8000">// 调用定义在命名空间"A\my"中函数 "foo"<br /><br /></span><span style="color: #0000BB">F</span><span style="color: #007700">();        </span><span style="color: #FF8000">// 首先尝试调用定义在命名空间"A"中的函数 "F"<br />            // 再尝试调用全局函数 "F"<br /><br />// 类引用<br /><br /></span><span style="color: #007700">new </span><span style="color: #0000BB">B</span><span style="color: #007700">();    </span><span style="color: #FF8000">// 创建命名空间 "A" 中定义的类 "B" 的一个对象<br />            // 如果未找到，则尝试自动装载类 "A\B"<br /><br /></span><span style="color: #007700">new </span><span style="color: #0000BB">D</span><span style="color: #007700">();    </span><span style="color: #FF8000">// 使用导入规则，创建命名空间 "B" 中定义的类 "D" 的一个对象<br />            // 如果未找到，则尝试自动装载类 "B\D"<br /><br /></span><span style="color: #007700">new </span><span style="color: #0000BB">F</span><span style="color: #007700">();    </span><span style="color: #FF8000">// 使用导入规则，创建命名空间 "C" 中定义的类 "E" 的一个对象<br />            // 如果未找到，则尝试自动装载类 "C\E"<br /><br /></span><span style="color: #007700">new </span><span style="color: #0000BB">\B</span><span style="color: #007700">();   </span><span style="color: #FF8000">// 创建定义在全局空间中的类 "B" 的一个对象<br />            // 如果未发现，则尝试自动装载类 "B"<br /><br /></span><span style="color: #007700">new </span><span style="color: #0000BB">\D</span><span style="color: #007700">();   </span><span style="color: #FF8000">// 创建定义在全局空间中的类 "D" 的一个对象<br />            // 如果未发现，则尝试自动装载类 "D"<br /><br /></span><span style="color: #007700">new </span><span style="color: #0000BB">\F</span><span style="color: #007700">();   </span><span style="color: #FF8000">// 创建定义在全局空间中的类 "F" 的一个对象<br />            // 如果未发现，则尝试自动装载类 "F"<br /><br />// 调用另一个命名空间中的静态方法或命名空间函数<br /><br /></span><span style="color: #0000BB">B\foo</span><span style="color: #007700">();    </span><span style="color: #FF8000">// 调用命名空间 "A\B" 中函数 "foo"<br /><br /></span><span style="color: #0000BB">B</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">();   </span><span style="color: #FF8000">// 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法<br />            // 如果未找到类 "A\B" ，则尝试自动装载类 "A\B"<br /><br /></span><span style="color: #0000BB">D</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">();   </span><span style="color: #FF8000">// 使用导入规则，调用命名空间 "B" 中定义的类 "D" 的 "foo" 方法<br />            // 如果类 "B\D" 未找到，则尝试自动装载类 "B\D"<br /><br /></span><span style="color: #0000BB">\B\foo</span><span style="color: #007700">();   </span><span style="color: #FF8000">// 调用命名空间 "B" 中的函数 "foo"<br /><br /></span><span style="color: #0000BB">\B</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">();  </span><span style="color: #FF8000">// 调用全局空间中的类 "B" 的 "foo" 方法<br />            // 如果类 "B" 未找到，则尝试自动装载类 "B"<br /><br />// 当前命名空间中的静态方法或函数<br /><br /></span><span style="color: #0000BB">A\B</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">();   </span><span style="color: #FF8000">// 调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法<br />              // 如果类 "A\A\B" 未找到，则尝试自动装载类 "A\A\B"<br /><br /></span><span style="color: #0000BB">\A\B</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">();  </span><span style="color: #FF8000">// 调用命名空间 "A\B" 中定义的类 "B" 的 "foo" 方法<br />              // 如果类 "A\B" 未找到，则尝试自动装载类 "A\B"<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </div><?php manual_footer($setup); ?>