3

I have an array that consists of many stdClasses after doing a json_decode on a json string.

It looks like this:

product: array(3)
0: stdClass
   PropertyAbc: "Product 1|Product 5"
1: stdClass
   PropertyXyz: "Product 2|Product 9|Product 10"
2: stdClass
   PropertyEfg: "Product 3|Product 12"

I need to turn this into a pipe delimited string of all values in the following format: PropertyName>Value as my end result:

PropertyAbc>Product 1|PropertyAbc>Product 5|PropertyXyz>Product 2|PropertyXyz>Product 9|PropertyXyz>Product 10|PropertyEfg>Product 3|PropertyEfg>Product 12

Here is how I attempted to do it, but cant figure out how to get the value and name of the first property when looping through the stdClasses (note: there will always be only one property for each stdClass):

foreach ($json->products as $product) {
    // Put all products in an array
    $arr = explode('|', $NEED-VALUE-OF-FIRST-PROP);

    // Loop through array and combine values
    foreach ($arr as $key => $value) {
        $arr[$key] = $NEED-NAME-OF-FIRST-PROP . ">" . $value;
    }
}
Blake Rivell
  • 13,105
  • 31
  • 115
  • 231
  • When iterating over an object using `foreach ($arr as $key => $value)` then `$key` will hold the properties name. – feeela Mar 12 '18 at 15:41

4 Answers4

5

get_object_vars is useful to get the object properties as an array and work from there.

 $p1 = new StdClass();
 $p1->PropertyAbc = "Product 1|Product 5";

 $p2 = new StdClass();
 $p2->PropertyXyz = "Product 2|Product 9|Product 10";

 $p3 = new StdClass();
 $p3->PropertyEfg = "Product 3|Product 12";

 $products = [ $p1, $p2, $p3 ];
 foreach ($products as $product) {
    $productArray = get_object_vars($product);
    $productPropName = array_keys($productArray)[0];
    $productPropsValues = explode('|', array_values($productArray)[0]);
    foreach ($productPropsValues as $productPropsValue) {
        $result[] = $productPropName . '>' . $productPropsValue;
    }
}

var_dump(implode('|', $result));

string(155) "PropertyAbc>Product 1|PropertyAbc>Product 5|PropertyXyz>Product 2|PropertyXyz>Product 9|PropertyXyz>Product 10|PropertyEfg>Product 3|PropertyEfg>Product 12"

William J.
  • 1,574
  • 15
  • 26
3

Simply convert it to the array by

$products=json_decode(json_encode($json), true);

And then you can operate with it like with a simple array.

Implementation:

<?php
$p1 = new StdClass();
$p1->PropertyAbc = "Product 1|Product 5";

$p2 = new StdClass();
$p2->PropertyXyz = "Product 2|Product 9|Product 10";

$p3 = new StdClass();
$p3->PropertyEfg = "Product 3|Product 12";

$products_orig = [ $p1, $p2, $p3 ];
$products=json_decode(json_encode($products_orig), true);

?>
<pre><?= print_r($products, true) ?></pre>
<?php
$s='';
foreach($products as $a){
    foreach($a as $key=>$b){
        $c=explode('|', $b);
        foreach($c as $d){
            $s.=(($s==='')?'':'|').$key.'>'.$d;
        }
    }
}
echo $s;

?>
Kancho Iliev
  • 701
  • 5
  • 13
  • will only work if class is json_serializable with no side effects – YvesLeBorg Mar 12 '18 at 15:48
  • @Kancholliev I did what you said and now I have an array with 3 arrays within it rather than 3 stdClasses. How can this help me from here? Just curious what the advantage is. How do I get the property name? – Blake Rivell Mar 12 '18 at 16:20
  • @Kancholliev What I am trying to say is I now have something like Array(1) PropertyXyz:"Product 1 | Product 2". How do I get the PropertyXyz portion of it in my code? Key ends up being 0 and value ends up being the entire string: PropertyXyz:"Product 1 | Product 2 – Blake Rivell Mar 12 '18 at 16:31
  • By the way, I think your question is because you've done mistake and missed second parameter (true) for json_decode – Kancho Iliev Mar 12 '18 at 17:49
2

You can use reflection to get the properties of the objects (see http://php.net/manual/de/reflectionclass.getproperties.php):

class Foo {
    public    $foo  = 1;
    protected $bar  = 2;
    private   $baz  = 3;
}

$foo = new Foo();

$reflect = new ReflectionClass($foo);
$props   = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED);

foreach ($props as $prop) {
    print $prop->getName() . "\n";
}

var_dump($props);

results in:

foo
bar
array(2) {
  [0]=>
  object(ReflectionProperty)#3 (2) {
    ["name"]=>
    string(3) "foo"
    ["class"]=>
    string(3) "Foo"
  }
  [1]=>
  object(ReflectionProperty)#4 (2) {
    ["name"]=>
    string(3) "bar"
    ["class"]=>
    string(3) "Foo"
  }
}

The rest of the splitting and concatenating should be straight forward!

Update: Some more clarification. Once you have the property name you can use a dynamic accessor to get the value of the property:

$class = <stdClassObject>;
$reflectionClass = new ReflectionClass($class);
$properties = $reflectionClass->getProperties();

foreach($properties as $p){
  $value = $class->$p;

  // do some concatination here
}
FMK
  • 1,062
  • 1
  • 14
  • 25
0

You may also make the get_object_vars approach a one-liner:

$obj->{array_keys(get_object_vars($obj))[0]};
Anse
  • 1,573
  • 12
  • 27