<?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 => 'ja',
  ),
  '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' => 'ja',
    '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>非修飾名</dt>
     <dd>
      <p class="para">
       これは名前空間区切り文字を含まない識別子で、<code class="literal">Foo</code> のようなものです。
      </p>
     </dd>
    
    
     <dt>修飾名</dt>
     <dd>
      <p class="para">
       これは名前空間区切り文字を含む識別子で、<code class="literal">Foo\Bar</code> のようなものです。
      </p>
     </dd>
    
    
     <dt>完全修飾名</dt>
     <dd>
      <p class="para">
       これは名前空間区切り文字を含む識別子のうち先頭が名前空間区切り文字で始まるもので、
       <code class="literal">\Foo\Bar</code> のようなものです。名前空間 <code class="literal">\Foo</code>
       も完全修飾名です。
      </p>
     </dd>
    
    
     <dt>相対名</dt>
     <dd>
      <p class="para">
       <code class="literal">namespace\Foo\Bar</code> のように、
       <code class="literal">namespace</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">
      修飾名の場合は、名前の最初の識別子を、
      現在のクラス/名前空間のインポートテーブルに従って翻訳します。
      たとえば、名前空間 <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">
      非修飾名の場合、名前はそれぞれのシンボルタイプの
      現在のインポートテーブルに従って翻訳されます。
      これは、クラスのような名前は、クラス/名前空間のインポートテーブルに従って
      翻訳されるし、関数名は、関数のインポートテーブルに従うし、
      定数は定数のインポートテーブルに従うということになります。
      たとえば、<code class="literal">use A\B\C;</code> の後に、
      <code class="literal">new C()</code> のようなことをすると、
      C は <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">
      非修飾名について、適用すべきインポートルールが存在せず、
      名前がクラスのようなシンボルを参照している場合、
      現在の名前空間が先頭に付加されます。
      たとえば、名前空間 <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" の autoload を試みます<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" の autoload を試みます<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" の autoload を試みます<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" の autoload を試みます<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" の autoload を試みます<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" の autoload を試みます<br /><br />// 別の名前空間から使用するstaticメソッド/関数<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" の autoload を試みます<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" の autoload を試みます<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" の autoload を試みます<br /><br />// 現在の名前空間から使用するstaticメソッド/関数<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" の autoload を試みます<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" のメソッド "foo" をコールします<br />              // クラス "A\B" が見つからない場合はクラス "A\B" の autoload を試みます<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

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