PHPで配列をオブジェクトに変換する方法は?


367

このような配列をオブジェクトに変換するにはどうすればよいですか?

[128] => Array
    (
        [status] => Figure A.
 Facebook's horizontal scrollbars showing up on a 1024x768 screen resolution.
    )

[129] => Array
    (
        [status] => The other day at work, I had some spare time
    )

4
正確にはどのようなオブジェクトを取得したいですか?私が何を意味するか:属性は何であるべきですか?
Pascal MARTIN

ループ内のそれべき両方のステータスが共にprintetされるように一つのデータアレイであるので
streetparade

:いないことを確認すると、これだけの作品から$a = (object)['hello' => 'world'];
Nishchalゴータム

回答:


588

最も単純なケースでは、おそらく配列をオブジェクトとして「キャスト」するだけで十分です。

$object = (object) $array;

別のオプションは、標準クラスを変数としてインスタンス化し、値を再割り当てしながら配列をループすることです。

$object = new stdClass();
foreach ($array as $key => $value)
{
    $object->$key = $value;
}

以下のようエドソンメディナが指摘、本当にきれいな解決策は、ビルトイン使用することですjson_機能を:

$object = json_decode(json_encode($array), FALSE);

これはまた、(再帰的に)すべてのサブ配列をオブジェクトに変換します。残念ながら、ループアプローチに対して2〜3倍のパフォーマンスヒットがあります。

警告!(コメントのUltraに感謝):

さまざまな環境でのjson_decodeは、さまざまな方法でUTF-8データを変換します。私はローカルでは「240.00」、生産では「240」という値を取得します-大規模な災害。変換が失敗した場合のMoroverは、文字列をNULLとして返します。


41
「変数は数字で始めることはできないので」、そうすることができます:$ object-> {3} = 'xyz';
chelmertz 2009

11
「2〜3倍のパフォーマンスヒットがあります」これは不公平な比較です。後者のメソッドは再帰的なオブジェクトを返しますが、(@ streetparadeの回答のように)追加の条件なしのループアプローチは最初のレベルのみを変換します。
feeela 2013年

8
@feeela私はそれが不当だとは思わない。変換を再帰的に行うことは述べた。また、
2〜3倍の

6
警告!さまざまな環境でのjson_decodeは、さまざまな方法でUTF-8データを変換します。私はローカルでは「240.00」、生産では「240」という値を取得します-大規模な災害。Moroverが変換に失敗した場合、文字列はNULLとして返されます
Szymon Toda

1
json_ *関数を使用する場合は注意してください。この場合、元の配列に格納されている参照(他の配列への参照など)が複製されます。x配列のキーが別の配列への参照を保持しているとしましょう。その後$object->x、ワンライナーの実行後は、の複製となり$array['x']、元の配列への参照ではなくなります。これは一部のアプリケーションでは無害である可能性がありますが、大規模な配列の場合、メモリを浪費し、参照が後で使用されている場合は実行が混乱する可能性があります。
Coprolal

153

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

// *convert array to object* Array([id]=> 321313[username]=>shahbaz)
$object = (object) $array_name;

//now it is converted to object and you can access it.
echo $object->username;

107

簡単な方法は

$object = (object)$array;

しかし、それはあなたが望むものではありません。オブジェクトが必要な場合、何かを達成したいのですが、この質問にはそれがありません。オブジェクトを使用するという理由だけでオブジェクトを使用しても意味がありません。


2
動作しません、私がここで質問する前に私はそれをしたので、実行する別の方法があるはずです
ストリートパレード2009

20
なぜオブジェクトを使用したい理由を彼に示さなければならないのですか?それがどのように行われるには関係ないと思います。多分彼はそれらをjson_encodeするか、それらをシリアル化する必要がありますか?これを行う理由はたくさんあります。
zombat 2009

うーん..私はそれがこのオブジェクトのように見えるブラウザ出力を見てみました(stdClass)#150(130){[0] => array(1){["status"] => string(130) "ついにMacとLinuxユーザーはChromeの土地で二流市民のように感じる必要はありません。彼らは公式のベータ版を持っています… "}公式にはオブジェクトですが、これを繰り返して$ obj-> statusのようなステータスにアクセスできるようにする方法?
ストリートパレード2009

zombat、JSONエンコードはオブジェクトを使用する理由にはなりません。オブジェクトを使用するためのjson_encode()へのフラグがあります。シリアライズを使用すると、受信側が予期する特定のオブジェクトタイプが必要になります。そして一般的に私は実際の問題を手助けしようとします。私にとって、この質問は、どこかでアーキテクチャの間違いがあることを意味しています。
ヨハネス2009

問題1、オブジェクトの問題へのlaravel配列の使用
Anthony Kal

105

クイックハック:

// assuming $var is a multidimensional array
$obj = json_decode (json_encode ($var), FALSE);

きれいではありませんが、動作します。


2
私は実際にこのソリューションが大好きです。ユーザー定義の代わりに組み込み関数を使用する方が常に速く、これはうまく機能します。先端をありがとう。
-aknatn

@Oddantこれは上記の問題を解決します(配列をオブジェクトに変換します)。あなたの怒りは私の解決策ではなくメインポストに向けられるべきです。
Edson Medina 2013年

@EdsonMedina私がやった、私の投稿はあまりにもダウンしています。
vdegenne 2013年

1
@ Oddant、@ EdsonMedinaに公平を期するため、元の質問では属性に必要な可視性を指定していません。また、OPは$this後続のコメントでアクセサとして使用されていないため、stdClass出力としてインスタンスを望んでいるのではなく、回答などのユーザー定義クラスが使用します。私はこのソリューションの優雅さに同意しますが、残念ながら、オブジェクトへのキャストが機能しないネストされた配列でこの問題を解決するためにかなり一般的に採用されているパターンです。OPが、配列ではなく入力としてオブジェクトを必要とするインターフェースを使用している可能性もあります。
DeaconDesperado 2013年

3
この方法を使用すると、基本的なタイプ以外はすべて失われることを忘れないでください。DateTimeは、コンバータstdObjectなどになります。
デニスプシェノフ2014年

97

3つの方法は次のとおりです。

  1. 実際のオブジェクトを偽造する:

    class convert
    {
        public $varible;
    
        public function __construct($array)
        {
            $this = $array;
        }
    
        public static function toObject($array)
        {
            $array = new convert($array);
            return $array;
        }
    }
  2. 配列をオブジェクトにキャストして、配列をオブジェクトに変換します。

    $array = array(
        // ...
    );
    $object = (object) $array;
  3. 配列を手動でオブジェクトに変換します。

    $object = object;
    foreach ($arr as $key => $value) {
        $object->{$key} = $value;
    }

2
うーんありがとうございますが、あなたのフェイスクラスは次のエラーを与えます致命的なエラー:/var/www/bot/inc/twitter-bot.phpの10行目の$ thisを再割り当てできません
streetparade 09

1
typcasint @ referenceは、ここで機能しない場合でも、良い考えではありません。T_NEWまたはT_STRINGまたはT_VARIABLEまたは '$'を予期して、予期しないT_OBJECT_CASTを取得しました
streetparade

2
$ array =&(オブジェクト)$ array == nice KISS実装!
mate64

16
なぜ誰もが2)とは異なる方法を使用したいのですか?欠点はありますか?
Yogu 14

7
配列をオブジェクトに型キャストすると、ネストされた配列では機能し
ません

34

簡単な方法として、これは再帰的な配列のオブジェクトも作成します:

$object = json_decode(json_encode((object) $yourArray), FALSE);

4
に渡すfalsejson_decode()、連想配列が返されます。
Rust

3
@ user3284463 toを渡すtruejson_decode、連想配列falseが返されStdClassます。これがデフォルトであり、インスタンスを返します。
エリオットリード

23

必要な場所とオブジェクトへのアクセス方法に応じて、さまざまな方法でアクセスできます。

例:型キャストするだけ

$object =  (object) $yourArray;

ただし、最も互換性のある方法は、タイプを指定する文字列に基づいて(または値を逆参照するだけで無視して)標準のPHPキャストを実装するユーティリティメソッド(まだPHPの一部ではない)を使用することです。

/**
 * dereference a value and optionally setting its type
 *
 * @param mixed $mixed
 * @param null  $type (optional)
 *
 * @return mixed $mixed set as $type
 */
function rettype($mixed, $type = NULL) {
    $type === NULL || settype($mixed, $type);
    return $mixed;
}

あなたのケースでの使用例(オンラインデモ):

$yourArray = Array('status' => 'Figure A. ...');

echo rettype($yourArray, 'object')->status; // prints "Figure A. ..."

17

これは私のために働いた

  function array_to_obj($array, &$obj)
  {
    foreach ($array as $key => $value)
    {
      if (is_array($value))
      {
      $obj->$key = new stdClass();
      array_to_obj($value, $obj->$key);
      }
      else
      {
        $obj->$key = $value;
      }
    }
  return $obj;
  }

function arrayToObject($array)
{
 $object= new stdClass();
 return array_to_obj($array,$object);
}

使用法 :

$myobject = arrayToObject($array);
print_r($myobject);

戻り値 :

    [127] => stdClass Object
        (
            [status] => Have you ever created a really great looking website design
        )

    [128] => stdClass Object
        (
            [status] => Figure A.
 Facebook's horizontal scrollbars showing up on a 1024x768 screen resolution.
        )

    [129] => stdClass Object
        (
            [status] => The other day at work, I had some spare time
        )

通常のように、次のようにループできます。

foreach($myobject as $obj)
{
  echo $obj->status;
}

しかし、これは型キャストよりも約500%遅くなります(テスト済み)。$ obj =(object)$ array;
xZero 2017

@xZeroですが$obj = (object) $array;、多次元配列では機能しません。
Jeff Puckett

15

私の知る限り、組み込みの方法はありませんが、単純なループと同じくらい簡単です。

    $obj= new stdClass();

    foreach ($array as $k=> $v) {
        $obj->{$k} = $v;
    }

オブジェクトを再帰的に構築する必要がある場合は、それについて説明できます。


14

(オブジェクト)関数を使用して、配列をオブジェクトに変換できます。

$arr= [128=> ['status'=>
                 'Figure A. Facebook \'s horizontal scrollbars showing up on a 1024x768 screen resolution.'],
                  129=>['status'=>'The other day at work, I had some spare time']];

            $ArrToObject=(object)$arr;
            var_dump($ArrToObject);

結果は配列を含むオブジェクトになります:

object(stdClass)#1048(2){[128] => array(1){

["status"] => string(87) "図A. Facebookの水平スクロールバーが1024x768の画面解像度で表示されます。" }

[129] => array(1){["status"] => string(44) "先日仕事があり、少し時間があります"}}


9

実際、これを多次元配列で使用したい場合は、再帰を使用する必要があります。

static public function array_to_object(array $array)
{
    foreach($array as $key => $value)
    {
        if(is_array($value))
        {
            $array[$key] = self::array_to_object($value);
        }
    }
    return (object)$array;
}

8

私は間違いなくこのようなきれいな方法で行きます:

<?php

class Person {

  private $name;
  private $age;
  private $sexe;

  function __construct ($payload)
  {
     if (is_array($payload))
          $this->from_array($payload);
  }


  public function from_array($array)
  {
     foreach(get_object_vars($this) as $attrName => $attrValue)
        $this->{$attrName} = $array[$attrName];
  }

  public function say_hi ()
  {
     print "hi my name is {$this->name}";
  }
}

print_r($_POST);
$mike = new Person($_POST);
$mike->say_hi();

?>

あなたが提出した場合:

処方

あなたはこれを得るでしょう:

マイク

私はこれがオブジェクトからの上記の回答を比較するより論理的なものであることを発見しました(カプセル化されたかわいい小さなオブジェクト)。

また、get_object_varsを使用して、操作対象のオブジェクトに追加の属性が作成されないようにします(姓が付いている車や、4つの車輪を振る舞う人は必要ありません)。


$ array [$ attr_name]の代わりに$ attr_valueを使用しないのはなぜですか。yourpublic関数からfrom_array($ array)関数
Sakkeer Hussain

7

たとえば、ArrayObjectを使用することもできます。

<?php
    $arr = array("test",
                 array("one"=>1,"two"=>2,"three"=>3), 
                 array("one"=>1,"two"=>2,"three"=>3)
           );
    $o = new ArrayObject($arr);
    echo $o->offsetGet(2)["two"],"\n";
    foreach ($o as $key=>$val){
        if (is_array($val)) {
            foreach($val as $k => $v) {
               echo $k . ' => ' . $v,"\n";
            }
        }
        else
        {
               echo $val,"\n";
        }
    }
?>

//Output:
  2
  test
  one => 1
  two => 2
  three => 3
  one => 1
  two => 2
  three => 3

1
私の意見では、これが最良の答えになるはずです。詳細情報:php.net/manual/en/arrayobject.construct.php
Julian

7

私が使用するもの(それはクラスのメンバーです):

const MAX_LEVEL = 5; // change it as needed

public function arrayToObject($a, $level=0)
{

    if(!is_array($a)) {
        throw new InvalidArgumentException(sprintf('Type %s cannot be cast, array expected', gettype($a)));
    }

    if($level > self::MAX_LEVEL) {
        throw new OverflowException(sprintf('%s stack overflow: %d exceeds max recursion level', __METHOD__, $level));
    }

    $o = new stdClass();
    foreach($a as $key => $value) {
        if(is_array($value)) { // convert value recursively
            $value = $this->arrayToObject($value, $level+1);
        }
        $o->{$key} = $value;
    }
    return $o;
}

7

少し複雑ですが、簡単に拡張できるテクニック:

配列があるとします

$a = [
     'name' => 'ankit',
     'age' => '33',
     'dob' => '1984-04-12'
];

この配列の属性が多かれ少なかれPersonクラスがあるとします。例えば

class Person 
{
    private $name;
    private $dob;
    private $age;
    private $company;
    private $city;
}

それでも配列を人物オブジェクトに変更したい場合。ArrayIteratorクラスを使用できます。

$arrayIterator = new \ArrayIterator($a); // Pass your array in the argument.

これでイテレータオブジェクトが作成されました。

FilterIteratorクラスを拡張するクラスを作成します。抽象メソッドacceptを定義する必要がある場所。例に従ってください

class PersonIterator extends \FilterIterator
{
    public function accept()
    {
        return property_exists('Person', parent::current());
    }
}

上記の実装は、クラスに存在する場合にのみプロパティをバインドします。

クラスPersonIteratorにメソッドをもう1つ追加します。

public function getObject(Person $object)
{
        foreach ($this as $key => $value)
        {
            $object->{'set' . underscoreToCamelCase($key)}($value);
        }
        return $object;
}

クラスにミューテーターが定義されていることを確認してください。これで、オブジェクトを作成する場所でこれらの関数を呼び出す準備ができました。

$arrayiterator = new \ArrayIterator($a);
$personIterator = new \PersonIterator($arrayiterator);

$personIterator->getObject(); // this will return your Person Object. 

6

再帰はあなたの友達です:

function __toObject(Array $arr) {
    $obj = new stdClass();
    foreach($arr as $key=>$val) {
        if (is_array($val)) {
            $val = __toObject($val);
        }
        $obj->$key = $val;
    }

    return $obj;
}

6

メイン関数内の「innerfunc」をロックするためにラムダ関数を使用することを選択したため、これにはPHP7が必要です。ラムダ関数は再帰的に呼び出されるため、「use(&$ innerfunc)」が必要です。あなたはPHP5でそれをすることができましたがinnerfuncを隠すことができませんでした。

function convertArray2Object($defs) {
    $innerfunc = function ($a) use ( &$innerfunc ) {
       return (is_array($a)) ? (object) array_map($innerfunc, $a) : $a; 
    };
    return (object) array_map($innerfunc, $defs);
}

5

私が作ったこの関数を使用してください:

function buildObject($class,$data){
    $object = new $class;
    foreach($data as $key=>$value){
        if(property_exists($class,$key)){
            $object->{'set'.ucfirst($key)}($value);
        }
    }
    return $object;
}

使用法:

$myObject = buildObject('MyClassName',$myArray);

5

一発ギャグ

$object= json_decode(json_encode($result_array, JSON_FORCE_OBJECT));

1
元の配列に格納されている(他の配列への参照など)は、このワンライナーによって複製されることに注意してください。x配列のキーが別の配列への参照を保持しているとしましょう。そうすると$object->x、ワンライナーの実行後$result_array['x']は、同じ配列ではなくの複製になります。
Coprolal 2018

4

簡単:

$object = json_decode(json_encode($array));

例:

$array = array(
    'key' => array(
        'k' => 'value',
    ),
    'group' => array('a', 'b', 'c')
);

$object = json_decode(json_encode($array));

次に、次のことが当てはまります。

$object->key->k === 'value';
$object->group === array('a', 'b', 'c')

1
これは回避策だと思います。なぜ配列をjsonにエンコードしてからデコードするのですか?それは私にとって最適な決定ではありません。
ジュリアン

1
@Julianは再帰的に動作するため、適切に定義され、十分に信頼できる(「標準」)方法で動作し、ランダムに手動でコーディングされた猿の魔法の優れた代替手段として十分に高速です。
Sz。

3

また、変数の左側に(オブジェクト)を追加して、新しいオブジェクトを作成することもできます。

<?php
$a = Array
    ( 'status' => " text" );
var_dump($a);
$b = (object)$a;
var_dump($b);
var_dump($b->status);

http://codepad.org/9YmD1KsU


1
:多分価値が、これは「キャスティング」または「タイプキャスト」と呼ばれると呼ばれる言及php.net/manual/en/...:及び(オブジェクト)配列の行動()ここでは文書化されてphp.net/manual/en/...
ピート・

2

json_encodeUTF-8以外のデータを処理する方法のため、使用には問題があります。json_encode/ json_encodeメソッドは、連想配列以外の配列も配列として残すことに注意してください。これは必要な場合とそうでない場合があります。私は最近、このソリューションの機能を再作成する必要があるが、関数を使用しない立場にありましたjson_。これが私が思いついたものです:

/**
 * Returns true if the array has only integer keys
 */
function isArrayAssociative(array $array) {
    return (bool)count(array_filter(array_keys($array), 'is_string'));
}

/**
 * Converts an array to an object, but leaves non-associative arrays as arrays. 
 * This is the same logic that `json_decode(json_encode($arr), false)` uses.
 */
function arrayToObject(array $array, $maxDepth = 10) {
    if($maxDepth == 0) {
        return $array;
    }

    if(isArrayAssociative($array)) {
        $newObject = new \stdClass;
        foreach ($array as $key => $value) {
            if(is_array($value)) {
                $newObject->{$key} = arrayToObject($value, $maxDepth - 1);
            } else {
                $newObject->{$key} = $value;
            }
        }
        return $newObject;
    } else {

        $newArray = array();
        foreach ($array as $value) {
            if(is_array($value)) {
                $newArray[] = arrayToObject($value, $maxDepth - 1);
            } else {
                $newArray[] = $value;
            }                
        }
        return $newArray;
    }
}

2

世界最高の方法:)

function arrayToObject($conArray)
{
    if(is_array($conArray)){
        /*
        * Return array converted to object
        * Using __FUNCTION__ (Magic constant)
        * for recursive call
        */
        return (object) array_map(__FUNCTION__, $conArray);
    }else{
        // Return object
        return $conArray;
    }
}

別の方法を使用すると、問題が発生します。これが最良の方法です。あなたは今まで見たことがあります。


2

オブジェクトへの多次元配列。このコードは、Bing検索APIのtryおよびcatchメソッドの変換に使用されます。

try {
        // Perform the Web request and get the JSON response
        $context = stream_context_create($options);
        $results = file_get_contents($url . "?cc=" . $country . "&category=" . $type, false, $context);
        $results = json_decode($results);
        return response()->json($results);
    } catch (\Exception $e) {
        $results = array('value' => array(
                (object) array(
                    "name" => "Unable to Retrive News",
                    "url" => "http://www.sample.com/",
                    "image" => (object) array("thumbnail" => (object) array("contentUrl" => "")),
                    "publishedAt" => "",
                    "description" => "")
            )
        );
        $results = (object) $results;
        return response()->json($results);
    }

2

リフレクションを使用できます。

<?php

$array = ['name'=>'maria','age'=>33];

class Person {

    public $name;
    public $age;

    public function __construct(string $name, string $age){
        $this->name  = $name;
        $this->age = $age;
    }
}

function arrayToObject(array $array, string $class_name){

    $r = new ReflectionClass($class_name);
    $object = $r->newInstanceWithoutConstructor();
    $list = $r->getProperties();
    foreach($list as $prop){
      $prop->setAccessible(true);
      if(isset($array[$prop->name]))
        $prop->setValue($object, $array[$prop->name]);
    } 

    return $object;

}

$pessoa1 = arrayToObject($array, 'Person');
var_dump($pessoa1);

1

CakePHPには、基本的に配列をオブジェクトにマップする再帰的なSet :: mapクラスがあります。オブジェクトを希望どおりに表示するには、配列の外観を変更する必要がある場合があります。

http://api.cakephp.org/view_source/set/#line-158

最悪の場合、この関数からいくつかのアイデアを得ることができるかもしれません。


1

明らかに、他の人々の答えの外挿だけですが、マルチ次元配列をオブジェクトに変換する再帰関数は次のとおりです。

   function convert_array_to_object($array){
      $obj= new stdClass();
      foreach ($array as $k=> $v) {
         if (is_array($v)){
            $v = convert_array_to_object($v);   
         }
         $obj->{strtolower($k)} = $v;
      }
      return $obj;
   }

そして、配列は数字キーを持っていた場合、彼らはまだ使用して生成されるオブジェクトで参照することができることを覚えておいてください{}(例えば:$obj->prop->{4}->prop


1

これらのすべてのコードに触発されて、次の機能をサポートする拡張バージョンを作成しようとしました:特定のクラス名、コンストラクターメソッドの回避、「beans」パターン、厳密モード(既存のプロパティのみを設定):

    class Util {

static function arrayToObject($array, $class = 'stdClass', $strict = false) {
        if (!is_array($array)) {
            return $array;
        }

        //create an instance of an class without calling class's constructor
        $object = unserialize(
                sprintf(
                        'O:%d:"%s":0:{}', strlen($class), $class
                )
        );

        if (is_array($array) && count($array) > 0) {
            foreach ($array as $name => $value) {
                $name = strtolower(trim($name));
                if (!empty($name)) {

                    if(method_exists($object, 'set'.$name)){
                        $object->{'set'.$name}(Util::arrayToObject($value));
                    }else{
                        if(($strict)){

                            if(property_exists($class, $name)){

                                $object->$name = Util::arrayToObject($value); 

                            }

                        }else{
                            $object->$name = Util::arrayToObject($value); 
                        }

                    }

                }
            }
            return $object;
        } else {
            return FALSE;
        }
        }
}

1

コード

この機能はと同じように機能しjson_decode(json_encode($arr), false)ます。

function arrayToObject(array $arr)
{
    $flat = array_keys($arr) === range(0, count($arr) - 1);
    $out = $flat ? [] : new \stdClass();

    foreach ($arr as $key => $value) {
        $temp = is_array($value) ? $this->arrayToObject($value) : $value;

        if ($flat) {
            $out[] = $temp;
        } else {
            $out->{$key} = $temp;
        }
    }

    return $out;
}

テスト中

テスト1:フラットアレイ

$arr = ["a", "b", "c"];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));

出力:

array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
)
array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
)

テスト2:オブジェクトの配列

$arr = [["a" => 1], ["a" => 1], ["a" => 1]];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));

出力:

array(
    0 => stdClass::__set_state(array('a' => 1,)),
    1 => stdClass::__set_state(array('a' => 1,)),
    2 => stdClass::__set_state(array('a' => 1,)),
)
array(
    0 => stdClass::__set_state(array('a' => 1,)),
    1 => stdClass::__set_state(array('a' => 1,)),
    2 => stdClass::__set_state(array('a' => 1,)),
)

テスト3:オブジェクト

$arr = ["a" => 1];
var_export(json_decode($arr));
var_export($this->arrayToObject($arr));

出力:

stdClass::__set_state(array('a' => 1,))
stdClass::__set_state(array('a' => 1,))

0

私は非常に簡単な方法でそれをしました、

    $list_years         = array();
    $object             = new stdClass();

    $object->year_id   = 1 ;
    $object->year_name = 2001 ;
    $list_years[]       = $object;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.