web-dev-qa-db-ja.com

いつstdClassを使用する必要があり、いつphp ooコードで配列を使用する必要がありますか?

仕事で大きなリファクタリングの期間の真っ只中、関数からデータを返す方法としてstdClass *****を導入したいと思います。私の決定をサポートするために主観的でない引数を見つけようとしています。

どちらか一方を使用するのが最善の状況はありますか?

配列の代わりにstdClassを使用するとどのような利点がありますか?


1つの値を返すことができるように、関数は小さくて具体的である必要があると言う人もいます。stdClassを使用するという私の決定は、長期的に各プロセスに適切な値オブジェクトを見つけることを望んでいるため、一時的です。

68
JonG

通常のアプローチは

  • 固定ブランチで定義されたデータ構造を返すときにオブジェクトを使用します。

     $person
       -> name = "John"
       -> surname = "Miller"
       -> address = "123 Fake St"
    
  • リストを返すときに配列を使用します。

      "John Miller"
      "Peter Miller"
      "Josh Swanson"
      "Harry Miller"
    
  • 構造化情報のリストを返すときにオブジェクトの配列を使用します。

      $person[0]
        -> name = "John"
        -> surname = "Miller"
        -> address = "123 Fake St"
    
      $person[1]
        -> name = "Peter"
        -> surname = "Miller"
        -> address = "345 High St"
    

オブジェクトは、それらに対処するためのキーが常に必要になるため、データのリストを保持するのには適していません。配列は両方の機能を実行できます-任意のリストとデータ構造を保持します。

したがって、必要に応じて、最初の例と3番目の例のオブジェクトに対して連想配列を使用できます。それは本当にスタイルと好みの問題だと思います。

@Decezeは、オブジェクトをいつ使用するか(検証、型チェック、およびfutureメソッド)について多くの優れた点を示しています。

60
Pekka 웃

stdClassを使用して配列と同じ機能を実現することはIMHOとしてはあまり役に立ちませんが、オブジェクトのオーバーヘッドを追加するだけで、実際にメリットはありません。また、多くの便利な配列関数(array_intersectなど)もありません。型チェックを有効にするには、少なくとも独自のクラスを作成するか、オブジェクトを使用する価値があるようにオブジェクトにメソッドを追加する必要があります。

41
deceze

あなたの唯一の意図が関数呼び出しから複数の任意のデータ型を返すことである限り、配列よりもstdClassを使用することの合理的な利点はないと思います

技術的に複数の値をネイティブに返すことはできないため、PHPで使用可能な他のすべてのデータ型を保持できるコンテナを使用する必要があります。それはオブジェクトまたは配列のいずれかです。

function fn1() { return array(1,2); }
function fn2() { return array('one' => 1, 'two' => 2); }
function fn3() { return (object) array(1,2); }
function fn4() { return (object) array('one' => 1, 'two' => 2); }

上記のすべてが機能します。配列は、無視できるごくわずかな分数であり、入力する手間が少なくて済みます。また、汎用のstdClassとは対照的に、明確に定義された目的があります(少し意地悪ですが、そうではありません)。どちらも暗黙的なインターフェースしかないため、ドキュメントまたは関数本体を調べて、それらに何が含まれるかを知る必要があります。

任意のコストでオブジェクトを使用する場合は、 ArrayObject または SplFixedArray を使用できますが、それらのAPIを見ると、単純なタスクの機能が必要であると言えますランダムな複数の値を返しますか?私はそうは思いません。ただし、誤解しないでください。stdClassを使用する場合は、それを使用してください。それは何かを壊すようなものではありません。しかし、あなたも何も得ません。少なくともいくつかの利点を追加するには、このためにReturnValuesという名前の別のクラスを作成できます。

単純なタグ付けクラスである可能性があります

class ReturnValues {}

またはより機能的なもの

class ReturnValues implements Countable
{
    protected $values;
    public function __construct() { $this->values = func_get_args(); }
    public function __get($key) return $this->values[$key]; }
    public function count() { return count($this->values); }
}

確かに、それはあまり機能せず、値を取得することは暗黙のインターフェイスを通じて行われますが、少なくともクラスには、より明確に定義された責任があります。このクラスから拡張して、特定の操作のReturnValueオブジェクトを作成し、それらに明示的なインターフェースを与えることができます。

class FooReturnValues extends ReturnValues
{
    public function getFoo() { return $this->values['foo']; }
    public function getBar() { return $this->values['foo']; }
}

開発者はAPIを調べて、foo()が返す複数の値を知る必要があります。もちろん、複数の値を返す可能性のあるすべての操作に対して具体的なReturnValueクラスを記述する必要があると、すぐに退屈な作業になる可能性があります。そして個人的に、私はこれが最初の目的のために過度に設計されていると思います。

とにかく、それが理にかなっていることを願っています。

18
Gordon

まあ、3つの違いがあります。

  • 彼らはアイデンティティを持っています。これが、配列引数を渡すデフォルトが値による呼び出しであり、オブジェクトのデフォルトが共有による呼び出しである理由です。
  • 意味の違いがあります。オブジェクトを使用する場合、コードを読んだ人なら誰でも、その値はモデルがある種のエンティティを表すことを理解しますが、配列はコレクションまたはマップとして機能することになっています
  • そして最後に重要なことですが、リファクタリングが大幅に容易になります。 stdClassではなく具象クラスを使用する場合は、別のクラスをインスタンス化するだけで済みます。また、メソッドを追加することもできます。

greetz
back2dos

4
back2dos

私が見つけることができる唯一の客観的な信頼の票は:

json_decodeはデフォルトでstdClassを使用するため、ユーザーランドの私たちが同様の状況でstdClassを使用する必要があります。

2

コードを簡潔にして、文のように読みやすくする必要がある場合は、配列上のstdClassオブジェクトが便利です。たとえば、一連のプロパティを返す関数getProperties()を例にとります。たとえば、人に関するデータ(名前、年齢、性別)です。 getProperties()が連想配列を返す場合、返されたプロパティの1つを使用するときは、2つの命令を記述します。

_$data = getProperties();
echo $data['name'];
_

一方、getProperties()がstdClassを返す場合は、1つの命令でそれを記述できます。

_echo getProperties()->name;
_
1

配列と標準クラスのテストでは、phpが動的プロパティを処理する方法は、連想配列よりも遅くなります。マイクロ最適化を主張するためにこれを言っているのではなく、これを行う場合は、メソッドのないデータクラスを定義し、パブリックプロパティを設定する方がよいでしょう。 php 5.4以降を使用している場合は特に。内部的に定義されたプロパティは、ハッシュテーブルのないc配列に直接マップされます。動的なものはハッシュテーブルを使用する必要があるためです。

これには、後で主要なインターフェイスを作り直すことなく、完全なクラスになるという追加のボーナスがあります。

1
bgrohs