3

したがって、以下のような構造のオブジェクトがあり、それらはすべてstdClassオブジェクトとして返されます

$person->contact->phone;
$person->contact->email;
$person->contact->address->line_1;
$person->contact->address->line_2;
$person->dob->day;
$person->dob->month;
$person->dob->year;
$album->name;
$album->image->height;
$album->image->width;
$album->artist->name;
$album->artist->id;

など... (これらの例は互いにリンクされていないことに注意してください)。

contact->phoneの直接プロパティとして呼び出す変数変数を使用することは可能$personですか?

例えば:

$property = 'contact->phone';
echo $person->$property;

これはそのままでは機能せず、スローされるE_NOTICEため、これを達成するための別の方法を考えようとしています。

何か案は?

プロキシメソッドに関する回答への回答:

そして、このオブジェクトがライブラリからのものであり、それを使用して次のように新しいオブジェクトに配列マップを設定していることを除いて:

array(
  'contactPhone' => 'contact->phone', 
  'contactEmail' => 'contact->email'
);

次に、マップを foreach して新しいオブジェクトを設定します。代わりにマッパーを巻き込むことができると思います...

4

14 に答える 14

4

私があなたなら->property();、返す単純なメソッドを作成します$this->contact->phone

于 2011-03-21T09:41:39.600 に答える
3

可変変数を使用して contact->phone を $person の直接プロパティとして呼び出すことは可能ですか?

式を変数変数名として使用することはできません。

しかし、いつでもごまかすことができます:

class xyz {

    function __get($name) {

        if (strpos($name, "->")) {
            foreach (explode("->", $name) as $name) {
                $var = isset($var) ? $var->$name : $this->$name;
            }
            return $var;
        }
        else return $this->$name;
    }
}
于 2011-03-21T10:04:41.770 に答える
2

合法であるからといって、それが道徳的であるとは限りません。そして、これが PHP の主な問題です。はい、考えられることはほとんど何でもできますが、それでは正しくありません。デメテルの法則を見てみましょう。

デメテルの法則

本当にやりたい場合は、これを試してください: json_decode(json_encode($person),true);

オブジェクトではなく配列として解析できますが、設定ではなく取得のために仕事をします。

編集:

class Adapter {

  public static function adapt($data,$type) {

  $vars = get_class_vars($type);

  if(class_exists($type)) {
     $adaptedData = new $type();
  } else {
    print_R($data);
    throw new Exception("Class ".$type." does not exist for data ".$data);
  }

  $vars = array_keys($vars);

  foreach($vars as $v) {

    if($v) {        
      if(is_object($data->$v)) {
          // I store the $type inside the object
          $adaptedData->$v = Adapter::adapt($data->$v,$data->$v->type);
      } else {
          $adaptedData->$v =  $data->$v;
      }
    }
  }
  return $adaptedData;

  }

}

于 2011-03-21T10:19:02.063 に答える
2

読めないコードにつながるため、これは悪いことだと思いますが、他のレベルでも明らかに間違っていますが、一般に、オブジェクト構文に変数を含める必要がある場合は、最初に解析されるように中括弧で囲む必要があります。

例えば:

$property = 'contact->phone';
echo $person->{$property};

SimpleXML オブジェクトで定期的に発生する可能性のある、名前に許可されていない文字を含むオブジェクトにアクセスする必要がある場合も、同じことが当てはまります。

$xml->{a-disallowed-field}
于 2011-03-21T10:04:11.180 に答える
0

型キャストを使用して、オブジェクトを配列に変更できます。

$person = (array) $person;

echo $person['contact']['phone'];
于 2011-03-21T09:57:39.223 に答える
0

言いたくないのですが、 eval を実行できます。

foreach ($properties as $property) {
     echo eval("return \$person->$property;");
}
于 2011-03-21T10:19:25.950 に答える
0

作成に加えてfunction getPhone(){return $this->contact->phone;}、要求されたフィールドの内部オブジェクトを調べる魔法のメソッドを作成できます。ただし、魔法の方法はやや遅いことを覚えておいてください。

class Person {
    private $fields = array();

    //...

    public function __get($name) {
        if (empty($this->fields)) {
            $this->fields = get_class_vars(__CLASS__);
        }
        //Cycle through properties and see if one of them contains requested field:
        foreach ($this->fields as $propName => $default) {
            if (is_object($this->$propName) && isset($this->$propName->$name)) {
                return $this->$propName->$name;
            }
        }
        return NULL;
        //Or any other error handling
    }
}
于 2011-03-21T10:19:26.450 に答える
0

オブジェクトを構造体のような方法で使用する場合、要求されたノードへの「パス」を明示的にモデル化できます。その後、同じ取得コードでオブジェクトを「装飾」できます。

「取得のみ」の装飾コードの例:

function retrieve( $obj, $path ) {
    $element=$obj;
    foreach( $path as $step ) { 
       $element=$element[$step];
    }
    return $element;
}

function decorate( $decos, &$object ) {
   foreach( $decos as $name=>$path ) {
      $object[$name]=retrieve($object,$path);
   }
}

$o=array( 
  "id"=>array("name"=>"Ben","surname"=>"Taylor"),
  "contact"=>array( "phone"=>"0101010" )
);

$decorations=array(
  "phone"=>array("contact","phone"),
  "name"=>array("id","name")  
);

// this is where the action is
decorate( $decorations, &$o);
print $o->name;
print $o->phone;

(コードパッドで見つけてください

于 2011-03-21T10:46:16.743 に答える
0

内部オブジェクトをネストしているほとんどの場合、データ構造を再評価するのに適した時期かもしれません。

上記の例では、personにはcontactdobがあります。連絡先にはaddressも含まれます。複雑なデータベース アプリケーションを作成する場合、最上位レベルからデータにアクセスしようとすることは珍しくありません。ただし、これに対する最善の解決策は、本質的に内部オブジェクトに「マイニング」しようとするのではなく、データをpersonクラスに統合することです。

于 2011-03-21T10:12:59.377 に答える
0

私は、このアプローチ全体を廃止し、より長い道のりですが、よりクリーンで、おそらくより効率的な方法を採用することにしました。そもそも私はこのアイデアにあまり熱心ではありませんでしたが、大多数がここで私のために決心するように話してくれました. ご回答ありがとうございます。

編集:

もし興味があれば:

public function __construct($data)
{
  $this->_raw = $data;
}

public function getContactPhone()
{
  return $this->contact->phone;
}

public function __get($name) 
{
  if (isset($this->$name)) {
    return $this->$name;
  }

  if (isset($this->_raw->$name)) {
    return $this->_raw->$name;
  }

  return null;
}
于 2011-03-21T10:36:05.600 に答える
0

2 つの関数の名前を知っていれば、これを実行できますか? (未検証)

$a = [
    'contactPhone' => 'contact->phone', 
    'contactEmail' => 'contact->email'
];

foreach ($a as $name => $chain) {
    $std = new stdClass();
    list($f1, $f2) = explode('->', $chain);
    echo $std->{$f1}()->{$f2}(); // This works
}

常に 2 つの機能ではない場合は、さらにハックして機能させることができます。ポイントは、ブラケット形式を使用している限り、可変変数を使用して連鎖関数を呼び出すことができるということです。

于 2016-08-16T20:49:28.377 に答える