Jump to content

Help parsing a StdClass Object


darkgr33n

Recommended Posts

Hi

 

I've got a StdClass Object that I need to parse. I can parse specific elements, but not sure how to parse when there is more than one element with the same name.

 

example:

 

 

$foo = array (
  (object) array("Label" => "Street", "Line" => "Stanley Road"),
  (object) array("Label" => "Town", "Line" => "Manchester"),
  (object) array("Label" => "Number of Rules", "Line" => "2"),
  (object) array("Label" => "Rule", "Line" => "X014"),
  (object) array("Label" => "Rule Text", "Line" => "Rule text for X014"),
  (object) array("Label" => "Rule", "Line" => "X015"),
  (object) array("Label" => "Rule Text", "Line" => "Rule text for X015")
  );

/*

this is what $foo contains with print_r

Array ( 
[0] => stdClass Object ( 
  [Label] => Street 
  [Line] => Stanley Road ) 
[1] => stdClass Object ( 
  [Label] => Town 
  [Line] => Manchester ) 
[2] => stdClass Object ( 
  [Label] => Number of Rules 
  [Line] => 2 ) 
[3] => stdClass Object ( 
  [Label] => Rule 
  [Line] => X014 ) 
[4] => stdClass Object ( 
  [Label] => Rule Text 
  [Line] => Rule text for X014 ) 
[5] => stdClass Object ( 
  [Label] => Rule 
  [Line] => X015 ) 
[6] => stdClass Object ( 
  [Label] => Rule Text 
  [Line] => Rule text for X015 ) 
) 

*/

foreach($foo as $foo_data)
{
  $foo_list [$foo_data->Label] = $foo_data->Line;
}

echo ($foo_list["Street"] . "<br>");
echo ($foo_list["Town"] . "<br>");
echo ($foo_list["Number of Rules"] . "<br>");
echo ($foo_list["Rule"] . "<br>");
echo ($foo_list["Rule Text"] . "<br>");
echo ($foo_list["Rule"] . "<br>");
echo ($foo_list["Rule Text"] . "<br>");

/*

this is what is written with the echo's above - two sets of X015

Stanley Road
Manchester
2
X015
Rule text for X015
X015
Rule text for X015

*/

 

There is a "Number of Rules" element which will tell me how many Rule elements I'm expecting.

 

This could be anything between 0 and 10 rule/rule text element pairs, the example above having 2.

 

Any ideas how I would parse the entire array correctly [i'm going to be putting them into separate variables to use in a database, just using echo in the example.

 

I need to see:

 

 

Stanley Road
Manchester
2
X014
Rule text for X014
X015
Rule text for X015

 

Thanks

Link to comment
Share on other sites

You mean like this?

 

<?php

$foo = array (
(object) array("Label" => "Street", "Line" => "Stanley Road"),
(object) array("Label" => "Town", "Line" => "Manchester"),
(object) array("Label" => "Number of Rules", "Line" => "2"),
(object) array("Label" => "Rule", "Line" => "X014"),
(object) array("Label" => "Rule Text", "Line" => "Rule text for X014"),
(object) array("Label" => "Rule", "Line" => "X015"),
(object) array("Label" => "Rule Text", "Line" => "Rule text for X015")
);

foreach ($foo as $bar) {
echo "{$bar->Line}<br />";
}

Link to comment
Share on other sites

You mean like this?

 

<?php

$foo = array (
(object) array("Label" => "Street", "Line" => "Stanley Road"),
(object) array("Label" => "Town", "Line" => "Manchester"),
(object) array("Label" => "Number of Rules", "Line" => "2"),
(object) array("Label" => "Rule", "Line" => "X014"),
(object) array("Label" => "Rule Text", "Line" => "Rule text for X014"),
(object) array("Label" => "Rule", "Line" => "X015"),
(object) array("Label" => "Rule Text", "Line" => "Rule text for X015")
);

foreach ($foo as $bar) {
echo "{$bar->Line}<br />";
}

 

Yes, sort of!

 

But, rather than echoing them out, I need to set a session variable named from the Label, which is why I tried putting them in an array, and when I get to the Rule session variable, I can add a number suffix.

 

Sorry, maybe my initial post wasn't that clear.

 

I really want to achieve being able to set the sessions like this:

 

$_SESSION['Street'] = "Stanley road";
$_SESSION['Town'] = "Manchester";
$_SESSION['Rule1'] = "X014";
$_SESSION['RuleText1'] = "Rule text for X014";
$_SESSION['Rule2'] = "X015";
$_SESSION['RuleText2'] = "Rule text for X015";

 

so, when I come across a Rule or Rule Text Label, I need to add a count suffix to the name, so

 

Rule + 1

Rule + 2

etc

 

Does that make more sense ?

 

Sorry. I've tried a few things, but it starts to get really convoluted, and I'm sure there must be an easier way!

 

Cheers

Link to comment
Share on other sites

This solves your problem, but to be honest, I think you're probably going about this the wrong way.  I don't know enough about what you're doing to say for sure, but this is not really the best way to solve things in PHP.  If you describe the problem in more detail I might be able to guide you towards a more elegant solution.

 

In the mean time:

<?php

$foo = array (
(object) array("Label" => "Street", "Line" => "Stanley Road"),
(object) array("Label" => "Town", "Line" => "Manchester"),
(object) array("Label" => "Number of Rules", "Line" => "2"),
(object) array("Label" => "Rule", "Line" => "X014"),
(object) array("Label" => "Rule Text", "Line" => "Rule text for X014"),
(object) array("Label" => "Rule", "Line" => "X015"),
(object) array("Label" => "Rule Text", "Line" => "Rule text for X015")
);

$rules = array();
$rule_texts = array();
foreach ($foo as $bar) {
if ($bar->Label == "Rule") {
	$rules[] = $bar->Line;
} else if ($bar->Label == "Rule Text") {
	$rule_texts[] = $bar->Line;
} else {
	$_SESSION[$bar->Label] = $bar->Line;
}
}

for ($x = 1; $x <= count($rules); $x++) {
$_SESSION["Rule$x"] = $rules[$x - 1];
$_SESSION["RuleText$x"] = $rule_texts[$x - 1];
}

print_r($_SESSION);
exit;

 

 

*EDIT* fixed a typo

Link to comment
Share on other sites

Thanks for that. I've gone down a similar road, spurred on by your first post:

 


$rule_suffix = 0;
$text_suffix = 0;

foreach($foo as $bar)
{
  	if ($bar->Label == 'Rule')
  	{
	$rule_suffix ++;
	echo ("RULE" . $rule_suffix . " : " . $bar->Line ."<br>");
}
elseif ($bar->Label == 'Rule Text')
  	{
	$text_suffix ++;
	echo ("RULE TEXT" . $text_suffix . " : " . $bar->Line ."<br>");
}
else	
{
	echo ("{$bar->Label} : {$bar->Line}<br>");
}
}

 

But you're right, not sure it is the best way to go, but it works at least, so I am further on than I was.

 

As an overview, I'm receiving a SOAP Reponse, in the format of the $foo object, and just need to parse the object, pull out the variables into Session variables, and then write to a database;

 

Obviously if we didn't have elements of the same name returned, it would be a lot less convoluted, but unfortunately, they're the requirements we're working to.

 

Thanks again for helping me out, I appreciate that. Also encouraged that I came up with something similar, although not as robust as yours.

 

 

Link to comment
Share on other sites

Just remember that you can store arrays in $_SESSION.  Anytime you find yourself with variables like var1, var2, var3 in PHP you are definitely doing things wrong :P

 

Arrays are WIN.

 

lol, thanks for the tip, i like WIN;

being self-taught I've missed some of those fundamental pearls of wisdom - i shall carry it with me always :)

Link to comment
Share on other sites

Ok, I've got it down a little, and am using arrays ;)

 

$foo = array (	(object) array("Label" => "Street", "Line" => "Stanley Road"),	(object) array("Label" => "Town", "Line" => "Manchester"),	(object) array("Label" => "Number of Rules", "Line" => "2"),	(object) array("Label" => "Rule", "Line" => "X014"),	(object) array("Label" => "Rule Text", "Line" => "Rule text for X014"),	(object) array("Label" => "Rule", "Line" => "X015"),	(object) array("Label" => "Rule Text", "Line" => "Rule text for X015"));

$suffix = 0;
$rules = array();

foreach($foo as $bar)
{
  	if ($bar->Label == 'Rule')
  	{
	$suffix ++;
	$rules[] = array($bar->Label.$suffix => $bar->Line);
}
elseif ($bar->Label == 'Rule Text')
  	{
	$rules[] = array($bar->Label.$suffix => $bar->Line);
}
else
{
	echo ("{$bar->Label} : {$bar->Line}<br>");
}
}
print_r ($rules);

 

which returns:

 

Street : Stanley Road
Town : Manchester
Number of Rules : 2
Array ( 
[0] => Array ( [Rule1] => X014 )
[1] => Array ( [Rule Text1] => Rule text for X014 ) 
[2] => Array ( [Rule2] => X015 ) 
[3] => Array ( [Rule Text2] => Rule text for X015 )
) 

 

which I think I can work with. The SOAP Response is always going to be a Rule followed by a Rule Text, so I should be safe ... I think ...

Link to comment
Share on other sites

ok, i've got something now, although still not too happy about two foreach loops for one iteration.

 

foreach($foo as $bar)
{
  	if ($bar->Label != 'Rule' AND $bar->Label != 'Rule Text') 
{
	$_SESSION[$bar->Label] = $bar->Line;
} 
else 
{
	switch ($bar->Label)
	{
		case 'Rule':
		$suffix ++;
		$rules[$bar->Label.$suffix] = $bar->Line;
		break;
		case 'Rule Text':
		$rules[$bar->Label.$suffix] = $bar->Line;
		break;
	}
}
}

foreach ($rules as $key => $value)
{
$_SESSION[$key] = $value;
}

 

which gives the following:

 

var_dump ($_SESSION);

array(7) { 
["Street"]=> string(12) "Stanley Road"
["Town"]=> string(10) "Manchester" 
["Number of Rules"]=> string(1) "2" 
["Rule1"]=> string(4) "X014" 
["Rule Text1"]=> string(18) "Rule text for X014"
["Rule2"]=> string(4) "X015" 
["Rule Text2"]=> string(18) "Rule text for X015" 
} 

 

which is pretty much what I was after, but open to any cleaner suggestions ;)

Link to comment
Share on other sites

Try typecasting the object to an array. E.g.

 


$foo = $ThestdClass;

$bar = (array)$foo;

no that should convert the stdClass into an array

 

Thanks, although not used directly, it did get me looking further, and I've come up with the following, although still seems quite long-winded. Perhaps there's no shorter way. I wish the SOAP return would add a sequential suffix to the tag names, but I don't have control over that :(

 

$foo = array (
  (object) array("Label" => "Street", "Line" => "Stanley Road"),
  (object) array("Label" => "Town", "Line" => "Manchester"),
  (object) array("Label" => "Number of Rules", "Line" => "2"),
  (object) array("Label" => "Rule", "Line" => "X014"),
  (object) array("Label" => "Rule Text", "Line" => "Rule text for X014"),
  (object) array("Label" => "Rule", "Line" => "X015"),
  (object) array("Label" => "Rule Text", "Line" => "Rule text for X015"),
  );

function objectToArray( $object )
    {
        if( !is_object( $object ) && !is_array( $object ) )
        {
            return $object;
        }
        if( is_object( $object ) )
        {
            $object = get_object_vars( $object );
        }
        return array_map( 'objectToArray', $object );
    }

// cast the object 
$array = (array) $foo;

// convert array to object 
$array = (array) objectToArray($foo);

/*

which gives:

Array ( 
[0] => Array ( [Label] => Street [Line] => Stanley Road ) 
[1] => Array ( [Label] => Town [Line] => Manchester ) 
[2] => Array ( [Label] => Number of Rules [Line] => 2 ) 
[3] => Array ( [Label] => Rule [Line] => X014 ) 
[4] => Array ( [Label] => Rule Text [Line] => Rule text for X014 ) 
[5] => Array ( [Label] => Rule [Line] => X015 ) 
[6] => Array ( [Label] => Rule Text [Line] => Rule text for X015 ) )
*/

$suffix = 0;
$array_count = count($array)-1;

for ($i=0;$i<=$array_count ;$i++)
{
if ($array[$i]['Label'] != 'Rule' AND $array[$i]['Label'] != 'Rule Text')
{
$_SESSION[$array[$i]['Label']] = $array[$i]['Line'];
}
else
{
switch ($array[$i]['Label'])		
{			
case 'Rule':			
$suffix ++;			
$_SESSION[$array[$i]['Label'].$suffix] = $array[$i]['Line'];			
break;			

case 'Rule Text':			
$_SESSION[$array[$i]['Label'].$suffix] = $array[$i]['Line'];			
break;		
}
}
}

var_dump($_SESSION);

/*

prints out:

array(7) { 
["Street"]=> string(12) "Stanley Road" 
["Town"]=> string(10) "Manchester" 
["Number of Rules"]=> string(1) "2" 
["Rule1"]=> string(4) "X014" 
["Rule Text1"]=> string(18) "Rule text for X014" 
["Rule2"]=> string(4) "X015" 
["Rule Text2"]=> string(18) "Rule text for X015" 
} 

Link to comment
Share on other sites

I'm not exactly clear precisely what you are trying to achieve (perhaps I haven't read the thread carefully enough) so apologies in advance is this isn't helpful to you. However, the code below takes your array of objects (from SOAP or a hard-coded array for testing) and parses them into a neat array structure.

 

I wasn't going to reply to the thread (not being clear if this is what you want) but the snippet below introduces a different approach to moulding an array of items into some other structure which even if it's not particularly useful to you darkgr33n, may be an idea for others to store for later consideration when doing a task like this.

 

So, onto the snippet which produces the following structure/output from your array of objects (see $foo in above posts).

 

Expected output

array(4) {
  ["Street"]=>
  string(12) "Stanley Road"
  ["Town"]=>
  string(10) "Manchester"
  ["Number of Rules"]=>
  string(1) "2"
  ["Rules"]=>
  array(2) {
    ["X014"]=>
    string(18) "Rule text for X014"
    ["X015"]=>
    string(18) "Rule text for X015"
  }
}

 

The snippet

function parse_foo($result, $value) {
// Stores the last rule id (so its text can be related to it)
static $last;

if ($value->Label == 'Rule') {
	// Add empty rule (its value will come next)
	$last = $value->Line;
	$result['Rules'][$last] = "";
} elseif ($value->Label == 'Rule Text') {
	// Add value to rule
	$result['Rules'][$last] = $value->Line;
} else {
	// Not a rule id or text
	$result[$value->Label] = $value->Line;
}

return $result;
}

// Lets see what parse_foo does
var_dump(array_reduce($foo, 'parse_foo'));

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.