mirror of
https://github.com/php/doc-ja.git
synced 2026-03-23 22:52:11 +01:00
396 lines
12 KiB
XML
396 lines
12 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<!-- EN-Revision: 0f14761ba340c6e49797706ac3f0cf1147d97253 Maintainer: mumumu Status: ready -->
|
|
|
|
<chapter xml:id="language.attributes" xmlns="http://docbook.org/ns/docbook">
|
|
<title>アトリビュート</title>
|
|
<sect1 xml:id="language.attributes.overview">
|
|
<title>アトリビュートの概要</title>
|
|
<?phpdoc print-version-for="attributes"?>
|
|
|
|
<para>
|
|
PHP のアトリビュートは、クラス、メソッド、関数、パラメータ、プロパティ、定数に、
|
|
構造化され、かつマシンが読み取り可能なメタデータを提供します。
|
|
これらは <link linkend="book.reflection">リフレクション API</link> を介して実行時に検査でき、
|
|
コードを変更することなく動的な振る舞いを可能にします。
|
|
アトリビュートは、宣言的な方法でコードにメタデータの注釈を付ける方法を提供します。
|
|
</para>
|
|
|
|
<para>
|
|
アトリビュートは、機能の実装と利用を分離できるようにします。
|
|
インターフェイスがメソッドを強制することで構造を定義するのに対し、
|
|
アトリビュートはメソッド、関数、プロパティ、定数を含む、
|
|
複数の要素にわたってメタデータを提供します。
|
|
インターフェイスがメソッドの実装を強制するのとは異なり、
|
|
アトリビュートはコードの構造を変更することなく注釈を付けます。
|
|
</para>
|
|
|
|
<para>
|
|
アトリビュートは、強制された構造の代わりにメタデータを提供することで、
|
|
オプションのインターフェイスメソッドを補完または置き換えることができます。
|
|
アプリケーションでの操作を表す <literal>ActionHandler</literal> インターフェイスを考えてみましょう。
|
|
一部の実装ではセットアップ手順が必要な場合がありますが、必要ない場合もあります。
|
|
<literal>ActionHandler</literal> を実装するすべてのクラスに
|
|
<literal>setUp()</literal> メソッドの定義を強制する代わりに、
|
|
アトリビュートを使用してセットアップ要件を示すことができます。
|
|
このアプローチは柔軟性を高め、必要に応じてアトリビュートを複数回適用できます。
|
|
</para>
|
|
|
|
<example>
|
|
<title>アトリビュートを使い、インターフェイスのオプションのメソッドを実装する</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
interface ActionHandler
|
|
{
|
|
public function execute();
|
|
}
|
|
|
|
#[Attribute]
|
|
class SetUp {}
|
|
|
|
class CopyFile implements ActionHandler
|
|
{
|
|
public string $fileName;
|
|
public string $targetDirectory;
|
|
|
|
#[SetUp]
|
|
public function fileExists()
|
|
{
|
|
if (!file_exists($this->fileName)) {
|
|
throw new RuntimeException("File does not exist");
|
|
}
|
|
}
|
|
|
|
#[SetUp]
|
|
public function targetDirectoryExists()
|
|
{
|
|
if (!file_exists($this->targetDirectory)) {
|
|
mkdir($this->targetDirectory);
|
|
} elseif (!is_dir($this->targetDirectory)) {
|
|
throw new RuntimeException("Target directory $this->targetDirectory is not a directory");
|
|
}
|
|
}
|
|
|
|
public function execute()
|
|
{
|
|
copy($this->fileName, $this->targetDirectory . '/' . basename($this->fileName));
|
|
}
|
|
}
|
|
|
|
function executeAction(ActionHandler $actionHandler)
|
|
{
|
|
$reflection = new ReflectionObject($actionHandler);
|
|
|
|
foreach ($reflection->getMethods() as $method) {
|
|
$attributes = $method->getAttributes(SetUp::class);
|
|
|
|
if (count($attributes) > 0) {
|
|
$methodName = $method->getName();
|
|
|
|
$actionHandler->$methodName();
|
|
}
|
|
}
|
|
|
|
$actionHandler->execute();
|
|
}
|
|
|
|
$copyAction = new CopyFile();
|
|
$copyAction->fileName = "/tmp/foo.jpg";
|
|
$copyAction->targetDirectory = "/home/user";
|
|
|
|
executeAction($copyAction);
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.attributes.syntax">
|
|
<title>アトリビュートの文法</title>
|
|
|
|
<para>
|
|
アトリビュートの文法は、いくつかの重要な要素で構成されています。
|
|
アトリビュートの宣言は <literal>#[</literal> で始まり、<literal>]</literal> で終わります。
|
|
その内部には、1つ以上のアトリビュートをカンマで区切って並べることができます。
|
|
アトリビュート名は、<link linkend="language.namespaces.basics">名前空間の基礎</link> で説明されているように、
|
|
非修飾名、修飾名、または完全修飾名にすることができます。
|
|
アトリビュートへの引数はオプションで、括弧 <literal>()</literal> で囲みます。
|
|
引数にはリテラル値または定数式のみを指定できます。
|
|
位置引数と名前付き引数の両方の構文がサポートされています。
|
|
</para>
|
|
|
|
<para>
|
|
アトリビュート名とその引数はクラスに解決され、
|
|
リフレクション API を介してアトリビュートのインスタンスが要求されると、
|
|
引数がそのコンストラクタに渡されます。
|
|
したがって、各アトリビュートに対してクラスを導入することをお勧めします。
|
|
</para>
|
|
|
|
<example>
|
|
<title>アトリビュートの文法</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// a.php
|
|
namespace MyExample;
|
|
|
|
use Attribute;
|
|
|
|
#[Attribute]
|
|
class MyAttribute
|
|
{
|
|
const VALUE = 'value';
|
|
|
|
private $value;
|
|
|
|
public function __construct($value = null)
|
|
{
|
|
$this->value = $value;
|
|
}
|
|
}
|
|
|
|
// b.php
|
|
|
|
namespace Another;
|
|
|
|
use MyExample\MyAttribute;
|
|
|
|
#[MyAttribute]
|
|
#[\MyExample\MyAttribute]
|
|
#[MyAttribute(1234)]
|
|
#[MyAttribute(value: 1234)]
|
|
#[MyAttribute(MyAttribute::VALUE)]
|
|
#[MyAttribute(array("key" => "value"))]
|
|
#[MyAttribute(100 + 200)]
|
|
class Thing
|
|
{
|
|
}
|
|
|
|
#[MyAttribute(1234), MyAttribute(5678)]
|
|
class AnotherThing
|
|
{
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect1>
|
|
|
|
|
|
<sect1 xml:id="language.attributes.reflection">
|
|
<title>リフレクションAPI を使ってアトリビュートを読み取る</title>
|
|
|
|
<para>
|
|
クラス、メソッド、関数、パラメータ、プロパティ、クラス定数からアトリビュートにアクセスするには、
|
|
リフレクション API が提供する <function>getAttributes</function> メソッドを使用します。
|
|
このメソッドは <classname>ReflectionAttribute</classname> インスタンスの配列を返します。
|
|
これらのインスタンスは、アトリビュート名、引数を問い合わせることができ、
|
|
表現されたアトリビュートのインスタンスをインスタンス化するために使用できます。
|
|
</para>
|
|
|
|
<para>
|
|
リフレクションされたアトリビュートの表現を実際のインスタンスから分離することで、
|
|
存在しないアトリビュートクラス、型指定ミス、値の不足など、
|
|
エラー処理をより詳細に制御できます。
|
|
アトリビュートクラスのオブジェクトは <function>ReflectionAttribute::newInstance</function>
|
|
を呼び出した後にのみインスタンス化され、その時点で引数の検証が行われます。
|
|
</para>
|
|
|
|
<example>
|
|
<title>リフレクションAPIを使い、アトリビュートを読み取る</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
#[Attribute]
|
|
class MyAttribute
|
|
{
|
|
public $value;
|
|
|
|
public function __construct($value)
|
|
{
|
|
$this->value = $value;
|
|
}
|
|
}
|
|
|
|
#[MyAttribute(value: 1234)]
|
|
class Thing
|
|
{
|
|
}
|
|
|
|
function dumpAttributeData($reflection) {
|
|
$attributes = $reflection->getAttributes();
|
|
|
|
foreach ($attributes as $attribute) {
|
|
var_dump($attribute->getName());
|
|
var_dump($attribute->getArguments());
|
|
var_dump($attribute->newInstance());
|
|
}
|
|
}
|
|
|
|
dumpAttributeData(new ReflectionClass(Thing::class));
|
|
/*
|
|
string(11) "MyAttribute"
|
|
array(1) {
|
|
["value"]=>
|
|
int(1234)
|
|
}
|
|
object(MyAttribute)#3 (1) {
|
|
["value"]=>
|
|
int(1234)
|
|
}
|
|
*/
|
|
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
リフレクションインスタンスのすべてのアトリビュートをループする代わりに、
|
|
アトリビュートクラス名を引数として渡すことで、
|
|
特定のアトリビュートのクラスだけを取得できます。
|
|
</para>
|
|
|
|
<example>
|
|
<title>リフレクションAPIを使い、特定のアトリビュートを読み取る</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
function dumpMyAttributeData($reflection) {
|
|
$attributes = $reflection->getAttributes(MyAttribute::class);
|
|
|
|
foreach ($attributes as $attribute) {
|
|
var_dump($attribute->getName());
|
|
var_dump($attribute->getArguments());
|
|
var_dump($attribute->newInstance());
|
|
}
|
|
}
|
|
|
|
dumpMyAttributeData(new ReflectionClass(Thing::class));
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="language.attributes.classes">
|
|
<title>アトリビュートクラスを宣言する</title>
|
|
|
|
<para>
|
|
アトリビュートごとに個別のクラスを定義することをお勧めします。
|
|
最も単純なケースでは、<literal>#[Attribute]</literal> 宣言を持つ空のクラスで十分です。
|
|
このアトリビュートは、<literal>use</literal> 文を使用してグローバル名前空間からインポートできます。
|
|
</para>
|
|
|
|
<example>
|
|
<title>単純なアトリビュートクラスの例</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
namespace Example;
|
|
|
|
use Attribute;
|
|
|
|
#[Attribute]
|
|
class MyAttribute
|
|
{
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<para>
|
|
アトリビュートを適用できる宣言の種類を制限するには、
|
|
<literal>#[Attribute]</literal> 宣言の最初の引数としてビットマスクを渡します。
|
|
</para>
|
|
|
|
<example>
|
|
<title>アトリビュートを使える場所を限定するために、ターゲットとなるクラスを作る</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
namespace Example;
|
|
|
|
use Attribute;
|
|
|
|
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION)]
|
|
class MyAttribute
|
|
{
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
|
|
<para>
|
|
<classname>MyAttribute</classname> を別の型で宣言すると、
|
|
<function>ReflectionAttribute::newInstance</function> の呼び出し時に例外がスローされます。
|
|
</para>
|
|
</example>
|
|
|
|
<para>ビットマスクには、以下が指定できます:</para>
|
|
|
|
<simplelist>
|
|
<member><constant>Attribute::TARGET_CLASS</constant></member>
|
|
<member><constant>Attribute::TARGET_FUNCTION</constant></member>
|
|
<member><constant>Attribute::TARGET_METHOD</constant></member>
|
|
<member><constant>Attribute::TARGET_PROPERTY</constant></member>
|
|
<member><constant>Attribute::TARGET_CLASS_CONSTANT</constant></member>
|
|
<member><constant>Attribute::TARGET_PARAMETER</constant></member>
|
|
<member><constant>Attribute::TARGET_ALL</constant></member>
|
|
</simplelist>
|
|
|
|
<para>
|
|
デフォルトでは、アトリビュートは宣言ごとに1回しか使用できません。
|
|
アトリビュートを繰り返し可能にするには、
|
|
<literal>#[Attribute]</literal> 宣言のビットマスクで
|
|
<constant>Attribute::IS_REPEATABLE</constant> フラグを指定します。
|
|
</para>
|
|
|
|
<example>
|
|
<title>宣言時にアトリビュートを複数回使えるように、IS_REPEATABLE を使う</title>
|
|
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
namespace Example;
|
|
|
|
use Attribute;
|
|
|
|
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION | Attribute::IS_REPEATABLE)]
|
|
class MyAttribute
|
|
{
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
|
|
</example>
|
|
</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
|
|
-->
|