PHPのArrayAccessインターフェースとは?オブジェクトを配列のように操作する方法
はじめに
PHPには、オブジェクトに対して配列のようなアクセスを可能にするための仕組みとして、ArrayAccessインターフェースが用意されています。このインターフェースを実装したクラスでは、内部に持つ配列型のプロパティを、オブジェクト生成時に外部へ公開することなく、$obj["key"] のような配列構文で直接読み書きできるようになります。
ArrayAccessインターフェースは、以下の4つの抽象メソッドを定義しています。
構文(Syntax)
ArrayAccess {
/* メソッド */
abstract public offsetExists ( mixed $offset ) : bool
abstract public offsetGet ( mixed $offset ) : mixed
abstract public offsetSet ( mixed $offset , mixed $value ) : void
abstract public offsetUnset ( mixed $offset ) : void
}メソッド一覧
- ArrayAccess::offsetExists — 指定したオフセット(キー)が存在するかどうかを判定します。isset() が呼ばれたときに実行されます。
- ArrayAccess::offsetGet — 指定したオフセットの値を取得します。$obj["key"] の読み取り時に実行されます。
- ArrayAccess::offsetSet — 指定したオフセットに値を代入します。$obj["key"] = value の書き込み時に実行されます。
- ArrayAccess::offsetUnset — 指定したオフセットを削除(unset)します。
連想配列を使ったArrayAccessの例
次の例では、連想配列をクラスのprivateプロパティとして保持しています。配列のキーがそのままオフセットとして機能し、要素の設定・取得・削除を配列構文で行えます。なお、offsetSet() をオフセットなしで呼び出した場合($obj[] = value の形式)、新しい値は次に利用可能な整数インデックスへ追加されます。
コード例
<?php
class myclass implements ArrayAccess {
private $arr = array();
public function __construct() {
$this->arr = array(
"Mumbai" => "Maharashtra",
"Hyderabad" => "A.P.",
"Patna" => "Bihar",
);
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->arr[] = $value;
} else {
$this->arr[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->arr[$offset]);
}
public function offsetUnset($offset) {
unset($this->arr[$offset]);
}
public function offsetGet($offset) {
return isset($this->arr[$offset]) ? $this->arr[$offset] : null;
}
}
$obj = new myclass();
var_dump(isset($obj["Mumbai"]));
var_dump($obj["Mumbai"]);
unset($obj["Mumbai"]);
var_dump(isset($obj["Mumbai"]));
$obj["Bombay"] = "Maharashtra";
var_dump($obj["Bombay"]);
$obj["Chennai"] = 'Tamilnadu';
$obj[] = 'New State';
$obj["Hyderabad"] = 'Telangana';
print_r($obj);
?>出力結果
上記プログラムを実行すると、次の出力が得られます。
bool(true) string(11) "Maharashtra" bool(false) string(11) "Maharashtra" myclass Object( [arr:myclass:private] => Array( [Hyderabad] => Telangana [Patna] => Bihar [Bombay] => Maharashtra [Chennai] => Tamilnadu [0] => New State ) )
このように、isset() や unset() といった通常の配列操作が、そのままオブジェクトに対して機能していることがわかります。
インデックス配列の場合
クラスの内部プロパティは連想配列だけでなく、通常のインデックス配列でも構いません。その場合、要素のインデックス(0から始まる整数)がオフセットとして扱われます。offsetSet() をオフセット引数なしで呼び出すと、配列のインデックスは次に利用可能な整数へ自動的に増加します。
コード例
<?php
class myclass implements ArrayAccess {
private $arr = array();
public function __construct() {
$this->arr = array("Mumbai", "Hyderabad", "Patna");
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->arr[] = $value;
} else {
$this->arr[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->arr[$offset]);
}
public function offsetUnset($offset) {
unset($this->arr[$offset]);
}
public function offsetGet($offset) {
return isset($this->arr[$offset]) ? $this->arr[$offset] : null;
}
}
$obj = new myclass();
var_dump(isset($obj[0]));
var_dump($obj[0]);
unset($obj[0]);
var_dump(isset($obj[0]));
$obj[3] = "Pune";
var_dump($obj[3]);
$obj[4] = 'Chennai';
$obj[] = 'NewDelhi';
$obj[2] = 'Bengaluru';
print_r($obj);
?>出力結果
上記プログラムを実行すると、次の出力が得られます。
bool(true) string(6) "Mumbai" bool(false) string(4) "Pune" myclass Object( [arr:myclass:private] => Array( [1] => Hyderabad [2] => Bengaluru [3] => Pune [4] => Chennai [5] => NewDelhi ) )
まとめ
ArrayAccessインターフェースを実装すると、クラスの内部データを外部に公開することなく、配列と同じ直感的な構文でアクセスできるようになります。コレクションクラスや設定管理クラスなどを作成する際に非常に便利な機能なので、ぜひ活用してみてください。
-
PHPのポリモーフィズムとは?インターフェースを使った実装例で解説
ポリモーフィズムとは何か ポリモーフィズム(Polymorphism)は、ギリシャ語の「Poly(多数の)」と「morphism(形)」に由来する言葉で、直訳すると「多くの形」という意味になります。 オブジェクト指向プログラミングにおけるポリモーフィズムとは、異なるクラスに属していても、似たような処理を行うメソッドには同じ名前を付けるべきだという設計原則のことです。これはOOP(オブジェクト指向プログラミング)の基本的なパターンの一つであり、機能の異なる複数のクラスが共通のインターフェースを実行・共有することを可能にします。 この原則の大きな利点は、コードがどのクラスに属しているかを呼び出し側
-
PHPのinterface_exists()関数とは?使い方とサンプルコードを解説
interface_exists()関数は、指定したインターフェースがすでに定義されているかどうかを確認するためのPHP組み込み関数です。name_of_interfaceで指定されたインターフェースが定義済みであればTRUEを返し、未定義であればFALSEを返します。 基本構文 interface_exists(name_of_interface, autoload) パラメータ name_of_interface − 存在を確認したいインターフェース名(文字列で指定)。 autoload − __autoload(またはSPLオートローダー)を呼び出すかどうか。デフォルトはtrueです。