Access nested objects and arrays - php

I am working with the Mailgun API. I have a variable with some objects and arrays inside that looks like this:
$result =
stdClass::__set_state(array(
'http_response_body' =>
stdClass::__set_state(array(
'items' =>
array (
0 =>
stdClass::__set_state(array(
'geolocation' =>
stdClass::__set_state(array(
'country' => 'UK',
'region' => '72',
'city' => 'London',
)),
'tags' =>
array (
),
'mailing-list' =>
stdClass::__set_state(array(
'list-id' => 'email#address.com',
'address' => 'email#address.com',
'sid' => '123456',
)),
'ip' => '123.456.789',
'log-level' => 'info',
'id' => 'ABCA',
'campaigns' =>
array (
0 =>
stdClass::__set_state(array(
'name' => 'TEST',
'id' => 'test123',
)),
),
)),
),
'http_response_code' => 200,
));
?>
I need to access every single information inside (e.g. the IP, the country, the region), . I tried multiple solutions, including using a foreach.
foreach ($result as $row) {
echo $row->items->ip;
}
However I keep getting
Catchable fatal error: Object of class stdClass could not be converted to string
I know I am not accessing the data the right way. Could you advice?

I think that you mean to be looping over $result->http_response_body->items. What you are actually doing is looping over $result->items which doesn't seem to exist.
foreach($result->http_response_body->items as $item) {
echo $item->ip;
}

Related

getting value from stdclass object/array

ive been trying for a while now trying to get a value from this std object
stdClass::__set_state(array(
'regions' =>
array (
0 =>
stdClass::__set_state(array(
'id' => 1,
'name' => 'Canada',
'image_url' => 'https://s3-us-west-2.amazonaws.com/staticimageskiind/flags/CA#3x.png',
)),
1 =>
stdClass::__set_state(array(
'id' => 2,
'name' => 'USA',
'image_url' => 'https://s3-us-west-2.amazonaws.com/staticimageskiind/flags/US#3x.png',
)),
2 =>
stdClass::__set_state(array(
'id' => 3,
'name' => 'Global',
'image_url' => 'https://s3-us-west-2.amazonaws.com/staticimageskiind/flags/GLBL#3x.png',
)),
3 =>
stdClass::__set_state(array(
'id' => 4,
'name' => 'Australia',
'image_url' => 'https://s3-us-west-2.amazonaws.com/staticimageskiind/flags/AU#3x.png',
)),
),
'info' =>
stdClass::__set_state(array(
'code' => 'INFO_MARKETPLACE_RETRIEVED_REGIONS',
'name' => 'Marketplace Regions Retrieved',
'message' => 'A list of marketplace regions has been retrieved.',
)),
));
but i can't seem to get a value from this object, help would be appreciated, ive searched online but couldnt find out a solution
Did you try:
echo $object->regions[0]->name;
For example?
i have managed to get the correct output i wanted by
$abc = $result->regions;
echo $abc[1]->name;
hope this helps anyone in need

How to access this array

array (
'_attributes' =>
array (
'name' => 'Rothco Product API - Variations',
),
'item_variations' =>
array (
0 =>
stdclass::__set_state(array(
'item_variation_id' => 2,
'item_index' => 3146,
'rothco_item_no' => '10002',
'upc' => '023063601212',
'inventory' => 99,
'created_date' => '2014-11-28 10:06:45.000',
'weight' => '.4000',
'image_filename' => '10002-A.jpg',
'catalog_page_no' => 183,
'msrp' => '20.9900',
'map' => '.0000',
'diameter' => '',
'price' => '8.100000',
'case_price' => NULL,
'case_quantity' => NULL,
'statuses' => '',
)),
),
)
This is my array $list.
I want to access 'item_variations' value from this array,
but if I try $list['item_variations'], or $list->['item_variations']
it is not working
If you want to reach just item_variations then
echo $list['item_variations'];
is sufficient. Things get more tricky if you would like to i.e. get value if created_date from your sample data as you got mix of arrays and objects so that require different access:
echo $list['item_variations'][0]->created_date;
which would output
2014-11-28 10:06:45.000

Extract value from Stripe object

How do I get the value of 'name'?
I've been trying various methods, including array($charge) and __toArray.
First works, second does not:
$charge_id = $charge->id;
echo $charge_id;
$name=$charge->_values->name;
echo $name;
Here is portion of the object returned by Stripe (up to the name I want to extract):
Stripe\Charge::__set_state(array(
'_opts' =>
Stripe\Util\RequestOptions::__set_state(array(
'headers' =>
array (
),
'apiKey' => 'sk_test_...',
)),
'_values' =>
array (
'id' => 'ch_73JaKii01nmbpZ',
'object' => 'charge',
'created' => 1443251926,
'livemode' => false,
'paid' => true,
'status' => 'succeeded',
'amount' => 1000,
'currency' => 'usd',
'refunded' => false,
'source' =>
Stripe\Card::__set_state(array(
'_opts' =>
Stripe\Util\RequestOptions::__set_state(array(
'headers' =>
array (
),
'apiKey' => 'sk_test_...',
)),
'_values' =>
array (
'id' => 'card_73JZrJCDzl877J',
'object' => 'card',
'last4' => '1111',
'brand' => 'Visa',
'funding' => 'unknown',
'exp_month' => 12,
'exp_year' => 2021,
'fingerprint' => 'hhzQQZIXaAVDNMPP',
'country' => 'US',
'name' => 'Steve Veltkamp',
according to this:
https://github.com/stripe/stripe-php/blob/master/lib/Charge.php
you may try to play with retrieve method:
$charge::retrieve($charge->id);
or ( https://github.com/stripe/stripe-php/blob/master/lib/StripeObject.php ):
$chargeArr = $charge->__toArray(true);
add true as argument for recursion
(Note: you should edit your question to remove your secret key and replace it with e.g. 'sk_test_...'. Even if it's just a test key, secret keys are not meant to be shared.)
The property you're trying to access is the cardholder's name. The source attribute of a charge object is actually a card object:
php > echo get_class($charge);
Stripe\Charge
php > echo get_class($charge->source);
Stripe\Card
So to get the cardholder's name, all you have to do is:
$name = $charge->source->name;
Note that name is an optional attribute for cards, so it's possible that you'll get NULL, an empty string, an email address, etc.

Optimizing algorithm to avoid exaggerated script execution time

Yesterday I ask here Append array values to another array by keys comparison and I have tried a few things without success. I have two arrays $result and $result1. count($result) is 204640 and count($result1) is 129849 so they are huge. The arrays is the result of a PDO statement execution as shown in code below. This is an example for $result array:
'00180000015oGSWAA2' =>
array (
'accountId' => '00180000015oGSWAA2',
'npi' => '1053576223',
'firstname' => 'Jack',
'lastname' => 'Cheng',
'title' => '',
'accountLastModifiedDate' => '2014-09-09 17:37:15',
'suffix' => '',
'fax' => '',
'address1' => '853 N CHURCH ST',
'city' => 'SPARTANBURG',
'stateLicensedId' => '31191',
'state' => 'SC',
'phone' => '',
'zip' => '29303',
'address2' => '',
'addressLastModifiedDate' => '2014-09-04 08:44:17',
),
'00180000015oGeXAAU' =>
array (
'accountId' => '00180000015oGeXAAU',
'npi' => '1629067301',
'firstname' => 'Fred',
'lastname' => 'Thaler',
'title' => '',
'accountLastModifiedDate' => '2014-09-09 17:36:41',
'suffix' => '',
'fax' => '',
'address1' => '1 PEARL ST',
'city' => 'BROCKTON',
'stateLicensedId' => '58249',
'state' => 'MA',
'phone' => '',
'zip' => '2301',
'address2' => '',
'addressLastModifiedDate' => '2014-09-04 04:25:44',
)
And this is an example for $result1 array:
'001S000000nBvryIAC' =>
array (
'tid' => '04T800000008zySEAQ',
'acsLastModifiedDate' => '2015-01-06 17:19:48',
),
'00180000015oGeXAAU' =>
array (
'tid' => '04T800000008zzgEAA',
'acsLastModifiedDate' => '2015-01-07 04:06:40',
),
'001S000000nYWcYIAW' =>
array (
'tid' => '04T800000008zySEAQ',
'acsLastModifiedDate' => '2015-02-25 15:45:01',
),
As you can see $result[1] and $result1[1] shares the same keys, right? Ok, then what I need is to push the content of $result1[1] on the end of $result[1] and getting something like:
'00180000015oGeXAAU' =>
array (
'accountId' => '00180000015oGeXAAU',
'npi' => '1629067301',
'firstname' => 'Fred',
'lastname' => 'Thaler',
'title' => '',
'accountLastModifiedDate' => '2014-09-09 17:36:41',
'suffix' => '',
'fax' => '',
'address1' => '1 PEARL ST',
'city' => 'BROCKTON',
'stateLicensedId' => '58249',
'state' => 'MA',
'phone' => '',
'zip' => '2301',
'address2' => '',
'addressLastModifiedDate' => '2014-09-04 04:25:44',
'tid' => '04T800000008zzgEAA',
'acsLastModifiedDate' => '2015-01-07 04:06:40',
)
Meaning when keys are equal in both arrays then merge or append values from the second one into the first one. Right now my best approach is the following:
// PDO statement
$result = $stmt->fetchAll();
// PDO statement
$result1 = $stmt->fetchAll();
foreach ($result as $key => $row) {
foreach ($result1 as $key1 => $row1) {
if ($key === $key1) {
array_push($row, array_shift($row1));
}
}
}
var_dump($row);
But it takes an eternity due to arrays length, so any advice in how to speedup this?
UPDATE: almost a solution
Based on #decese solution I have rewrite this a bit so my apologies in first and take a look to this. Now I called arrays as $oneArr and $twoArr and also I write a small output examples (don't kill me just yet):
// var_export($oneArr)
'00180000015oGSWAA2' =>
array (
'target_id' => '00180000015oGSWAA2',
'firstname' => 'Jack',
),
'00180000015oGeXAAU' =>
array (
'target_id' => '00180000015oGeXAAU',
'firstname' => 'Fred',
)
// var_export($twoArr)
'001S000000nBvryIAC' =>
array (
'tid' => '04T800000008zySEAQ',
'acsLastModifiedDate' => '2015-01-06 17:19:48',
),
'00180000015oGeXAAU' =>
array (
'tid' => '04T800000008zzgEAA',
'acsLastModifiedDate' => '2015-01-07 04:06:40',
)
This is the ouput I want to achieve, meaning when keys are equal in both arrays then merge or append values from the second one into the first one:
'00180000015oGeXAAU' =>
array (
'target_id' => '00180000015oGeXAAU',
'firstname' => 'Fred',
'tid' => '04T800000008zzgEAA',
'acsLastModifiedDate' => '2015-01-07 04:06:40',
)
I have this done, again based on first answer which I thanks a lot for clear a bit things to me, with the following code:
// Fetch results from first SQL query
$result = $stmt->fetchAll();
// Fetch only two keys from the entire and put them on $oneArr
foreach ($result as $row) {
$oneArr[$row['target_id']] = [
'target_id' => $row['target_id'],
'firstname' => $row['firstname']
];
}
// Fetch results from second SQL query
// yes, var names are the same not matter, I will only use one time
$result = $stmt->fetchAll();
// Fetch only two keys from the entire and put them on $twoArr
foreach ($result as $row) {
$twoArr[$row['target_id']] = [
'tid' => $row['tid'],
'acslmd' => $row['acslmd']
];
}
$i = 0;
foreach ($oneArr as $keyOneArr => $valueOneArr) {
if (array_key_exists($keyOneArr, $twoArr)) {
array_push($oneArr[$keyOneArr], $twoArr[$keyOneArr]);
$i++;
}
}
var_export($oneArr);
But result is not the same as I want since I got this:
'00180000015oGeXAAU' =>
array (
'target_id' => '00180000015oGeXAAU',
'firstname' => 'Fred',
0 =>
array (
'tid' => '04T800000008zzgEAA',
'acslmd' => '2015-01-07 04:06:40',
),
),
How I can avoid the extra array on the result array?
PS: Times looks good now: Call time was 00:01:34
Looks like your arrays are actually indexed by the ids, so do this:
foreach ($result1 as $key => $value) {
if (isset($result[$key])) {
$result[$key] += $value;
}
}
Of course, doing all this work in the database using a JOIN would make the most sense to begin with, if possible.
You could use array_merge_recursive
See my working example: http://3v4l.org/hQERW
Note: in the provided data, only 00180000015oGeXAAU is common to both arrays, so it only merges the values for that key
Basically, just call
$result = array_merge_recursive($result, $result1);
PHP.net says:
array_merge_recursive() merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.
If the input arrays have the same string keys, then the values for these keys are merged together into an array, and this is done recursively, so that if one of the values is an array itself, the function will merge it with a corresponding entry in another array too. If, however, the arrays have the same numeric key, the later value will not overwrite the original value, but will be appended.

List posts that a user likes in CakePHP app

I have two tables: Posts and Likes
And I'm trying to list the posts that the current logged in user likes. The method looks like the following:
$following = $this->Follower->listFollowing($this->Auth->user('id'));
$this->paginate = array('limit'=>20,'conditions'=>array('Post.id'=>array($following['Follower']['post_id']),'Post.status'=>array(1,2)),'order'=>array('Post.datetime'=>'desc'),
'contain'=>array('User','Answer'=>array('User'),'Tag'));
$this->set('posts',$this->paginate());
So basically what I'm trying to do is first query the following (likes) table for all matching rows to the user and then use this array of post ids in my find query to list posts that were in the query.
The listFollowing method in the Follower model looks like:
public function listFollowing($user_id)
{
return $this->find('all', array(
'conditions' => array('Follower.user_id'=>$user_id)
));
}
I'm currently getting an error like: Undefined index: Follower [APP/Controller/PostsController.php, line 94] So gonna presume that the way I'm trying to pass the list of post ids from the following in the find query is incorrect.
Can anyone help? Thanks
Edit: Doing a debug on $following gives:
array(
(int) 0 => array(
'Follower' => array(
'id' => '4',
'user_id' => '6',
'post_id' => '136'
),
'User' => array(
'password' => '*****',
'id' => '6',
'username' => 'driz',
'email' => '######'
),
'Post' => array(
'id' => '136',
'user_id' => '8',
'datetime' => '2012-09-11 15:49:52',
'modified' => '2012-09-16 15:31:38',
'title' => 'Test Content',
'slug' => 'Test_content',
'content' => 'Test Content',
'status' => '1'
)
),
(int) 1 => array(
'Follower' => array(
'id' => '5',
'user_id' => '6',
'post_id' => '133'
),
'User' => array(
'password' => '*****',
'id' => '6',
'username' => 'driz',
'email' => '######'
),
'Post' => array(
'id' => '134',
'user_id' => '8',
'datetime' => '2012-09-11 15:49:52',
'modified' => '2012-09-16 15:31:38',
'title' => 'Test Content 2',
'slug' => 'Test_content_2',
'content' => 'Test Content 2',
'status' => '1'
)
)
)
Couple of questions:
Did you checked what query is being executed? If it's executed then probably the method is correct.
is $following being populated? what happens if you debug it?
if you are retreiving with 'all' then the result will look like this:
Array(
[0] => Array
(
[ModelName] => Array
(
[id] => 83
[field1] => value1
[field2] => value2
[field3] => value3
)
[AssociatedModelName] => Array
(
[id] => 1
[field1] => value1
[field2] => value2
[field3] => value3
)
)
)
So you'll never be able to find something at $following['Follower']. Check Cake's documentation for this
Based on you comments, if you need a list of id's try this inside your method:
public function listFollowing($user_id)
{
return $this->find('list', array(
'conditions' => array('Follower.user_id'=>$user_id)
'fields' => array('Follower.user_id'),
'recursive' => 0);
}
The 'list' retrieve mode does exactlye that.
It is hard to guess the error with this limited information but I'm guessing that it's a PHP error related with your $following array.
Can you try putting debug($following) after your listFollowing() function call? So in the end, it should look like this:
$following = $this->Follower->listFollowing($this->Auth->user('id'));
debug($following);
$this->paginate = array('limit'=>20,'conditions'=>array('Post.id'=>array($following['Follower']['post_id']),'Post.status'=>array(1,2)),'order'=>array('Post.datetime'=>'desc'),
'contain'=>array('User','Answer'=>array('User'),'Tag'));
$this->set('posts',$this->paginate());
You will see what is returned from listFollowing() that is causing an index error. You can further debug it with that information. I can no longer help as there is no database schema, full code, the variables/situation that causes this problem, etc :)

Categories