<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/language.enumerations.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ja',
  ),
  'this' => 
  array (
    0 => 'language.enumerations.backed.php',
    1 => '値に依存した列挙型(Backed Enum)',
    2 => '値に依存した列挙型(Backed Enum)',
  ),
  'up' => 
  array (
    0 => 'language.enumerations.php',
    1 => '列挙型(Enum)',
  ),
  'prev' => 
  array (
    0 => 'language.enumerations.basics.php',
    1 => '列挙型の基礎',
  ),
  'next' => 
  array (
    0 => 'language.enumerations.methods.php',
    1 => '列挙型とメソッド',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    'path' => 'language/enumerations.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.enumerations.backed" class="sect1">
  <h2 class="title">値に依存した列挙型(Backed Enum)</h2>

  <p class="para">
   デフォルトでは、列挙型はスカラー値の情報を持っていません。
   単なるシングルトンオブジェクトです。
   しかし、列挙型の case をデータベースや、
   類似のデータストアで読み書きする必要があるケースが多くあります。
   よって、ビルトインの (容易にシリアライズできる)
   スカラー値を列挙型の中で定義すると便利です。
  </p>

  <p class="para">
   列挙型にスカラー値を定義するには、以下のようにします:
  </p>

  <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">enum </span><span style="color: #0000BB">Suit</span><span style="color: #007700">: </span><span style="color: #0000BB">string<br /></span><span style="color: #007700">{<br />    case </span><span style="color: #0000BB">Hearts </span><span style="color: #007700">= </span><span style="color: #DD0000">'H'</span><span style="color: #007700">;<br />    case </span><span style="color: #0000BB">Diamonds </span><span style="color: #007700">= </span><span style="color: #DD0000">'D'</span><span style="color: #007700">;<br />    case </span><span style="color: #0000BB">Clubs </span><span style="color: #007700">= </span><span style="color: #DD0000">'C'</span><span style="color: #007700">;<br />    case </span><span style="color: #0000BB">Spades </span><span style="color: #007700">= </span><span style="color: #DD0000">'S'</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
  </div>


  <p class="para">
   スカラー値を持つ case を、&quot;Backed Case&quot; と呼びます。
   なぜなら、オブジェクトよりもシンプルな値に依存して(Backed)いるからです。
   全ての case が Backed Case である列挙型を &quot;Backed Enum&quot; と呼びます。
   Backed Enum には Backed Case のみを含めることができます。
   Pure Enum には Pure Case だけを含めることができます。
  </p>

  <p class="para">
   Backed Enum は、整数、または文字列の値を持つことができます。
   そして、単一の列挙型が一度に持つことの出来る型はひとつだけです
   (つまり、<code class="literal">int|string</code> のような union
   型はサポートしていないということです)。
   列挙型がスカラー情報を持つとマークすると、
   全ての case はユニークなスカラーの値を明示的に定義しなければいけません。
   自動生成されるスカラー値 (例: 整数の連番) は存在しません。
   Backed Enum の case の値は、全てユニークでなければいけません。
   つまり、ふたつの Backed Enum の case は、
   同じスカラー値を持ってはいけないということです。
   しかし、定数は case を参照していても構わないので、
   別名を作成することはできます。
   <a href="language.enumerations.constants.php" class="link">列挙型と定数</a>
   も参照ください。
  </p>

  <p class="para">
   スカラー値は、定数のスカラー式でなければいけません。
   PHP 8.2.0 より前のバージョンでは、
   スカラー値はリテラルか、リテラルを表す式でなければいけませんでした。
   これは、定数や定数式はサポートされていなかったことを意味します。
   つまり、<code class="literal">1 + 1</code> は許されますが、
   <code class="literal">1 + SOME_CONST</code> は許されていませんでした。
  </p>

  <p class="para">
   Backed Enum の case は、追加の読み取り専用のプロパティ
   <code class="literal">value</code> を持っています。
   これは、Backed Enum の定義で指定された値です。
  </p>

  <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">print </span><span style="color: #0000BB">Suit</span><span style="color: #007700">::</span><span style="color: #0000BB">Clubs</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">value</span><span style="color: #007700">;<br /></span><span style="color: #FF8000">// "C" と表示<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
  </div>


  <p class="para">
   <code class="literal">value</code> プロパティを強制的に読み取り専用にするため、
   そのリファレンスを変数には代入できません。
   つまり、以下のようなコードはエラーになります:
  </p>

  <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />$suit </span><span style="color: #007700">= </span><span style="color: #0000BB">Suit</span><span style="color: #007700">::</span><span style="color: #0000BB">Clubs</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$ref </span><span style="color: #007700">= &amp;</span><span style="color: #0000BB">$suit</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">value</span><span style="color: #007700">;<br /></span><span style="color: #FF8000">// Error: Cannot acquire reference to property Suit::$value<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
  </div>


  <p class="para">
   Backed Enum は内部的に
   <span class="interfacename"><a href="class.backedenum.php" class="interfacename">BackedEnum</a></span> インターフェイスを実装しています。
   このメソッドは、以下の2つのメソッドを公開しています:
  </p>

  <ul class="simplelist">
   <li>
    <code class="literal">from(int|string): self</code>
    スカラー値を受け取り、対応する Enum の case を返します。
    対応する case がない場合は、
    <span class="classname"><a href="class.valueerror.php" class="classname">ValueError</a></span>
    がスローされます。
    このメソッドは、入力のスカラー値が信頼でき、
    存在しない enum
    の値はアプリケーションを停止すべきエラーとみなせる場合に役立ちます。
   </li>
   <li>
    <code class="literal">tryFrom(int|string): ?self</code>
    スカラー値を受け取り、対応する Enum の case を返します。
    対応する case がない場合は、<strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong> を返します。
    このメソッドは、入力のスカラー値が信頼できない場合で、
    呼び出し側が独自のエラーハンドリングや、
    デフォルト値のロジックを実装したい場合に役立ちます。
   </li>
  </ul>

  <p class="para">
   <code class="literal">from()</code> と <code class="literal">tryFrom()</code> 
   メソッドは、標準の 弱い/強い 型付けのルールに従います。
   弱い型付けのルールでは、整数または文字列を受け入れ、
   システムは値をそれに従って自動変換します。
   厳密な型付けモードの場合、文字列型の Backed Enum に整数値を渡す
   (またはその逆をする) と、<span class="classname"><a href="class.typeerror.php" class="classname">TypeError</a></span> が発生します。
   float についても、全ての場合に同じ型付けのルールに従います。
   それ以外の型については、どちらのモードでも TypeError が発生します。
  </p>

  <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />$record </span><span style="color: #007700">= </span><span style="color: #0000BB">get_stuff_from_database</span><span style="color: #007700">(</span><span style="color: #0000BB">$id</span><span style="color: #007700">);<br />print </span><span style="color: #0000BB">$record</span><span style="color: #007700">[</span><span style="color: #DD0000">'suit'</span><span style="color: #007700">];<br /><br /></span><span style="color: #0000BB">$suit </span><span style="color: #007700">=  </span><span style="color: #0000BB">Suit</span><span style="color: #007700">::</span><span style="color: #0000BB">from</span><span style="color: #007700">(</span><span style="color: #0000BB">$record</span><span style="color: #007700">[</span><span style="color: #DD0000">'suit'</span><span style="color: #007700">]);<br /></span><span style="color: #FF8000">// 不正なデータを渡すと、次のようなエラーが発生 -&gt; ValueError: "X" is not a valid scalar value for enum "Suit"<br /></span><span style="color: #007700">print </span><span style="color: #0000BB">$suit</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">value</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$suit </span><span style="color: #007700">= </span><span style="color: #0000BB">Suit</span><span style="color: #007700">::</span><span style="color: #0000BB">tryFrom</span><span style="color: #007700">(</span><span style="color: #DD0000">'A'</span><span style="color: #007700">) ?? </span><span style="color: #0000BB">Suit</span><span style="color: #007700">::</span><span style="color: #0000BB">Spades</span><span style="color: #007700">;<br /></span><span style="color: #FF8000">// 不正なデータに対しては null を返すので、Suit::Spades が代わりに使われます。<br /></span><span style="color: #007700">print </span><span style="color: #0000BB">$suit</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">value</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
  </div>


  <p class="para">
   Backed Enum において、手動で <code class="literal">from()</code> や
   <code class="literal">tryFrom()</code> メソッドを定義すると、
   致命的なエラーが発生します。
  </p>

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