Create associative array using foreach with object as value - php

I am using XMLRPC to build an XML structure that passes across product information to a 3rd party system. I need to build an associative array of the product custom options and I don't know what syntax to use as the value in each case is an object.
I can't debug and play about with it as I normally would as believe it or not I've had to do this on a live site so I've been emailing myself the array to make sure it looks alright, then when it does I've applied it to the site, XMLRPC throws an error saying it can't serialize the object I've built, then I quickly switch it back out again.
If I hardcode it like this it works fine.
$item_array = array(
"product_id" => new xmlrpcval($item->getSku()),
"name" => new xmlrpcval($item->getName()),
"price" => new xmlrpcval($item->getBaseCalculationPrice(), 'double'),
"vat_inclusive" => new xmlrpcval(0,'int'),
"quantity" => new xmlrpcval($item->getQty(),'int'),
"option_text" => new xmlrpcval(
array(
"option_1" => new xmlrpcval("Colour: Military Black"),
"option_2" => new xmlrpcval("Sizes: L")
),
"struct")
);
It's the folowing section I need to generate, specifically the array in a foreach loop as I don't know how many options there will be;
"option_text" => new xmlrpcval(
array(
"option_1" => new xmlrpcval("Colour: Military Black"),
"option_2" => new xmlrpcval("Sizes: L")
),
"struct")
If I do it like below then it comes out fine, but the value is a string rather than an object, which XMLRPC can't serialize;
$optioncount = 1;
$attList = array();
foreach ( $attributes as $attribute => $value ) {
$attpair = implode(": ", $value);
$attList['option_'. $optioncount] = 'new xmlrpcval("'.$attpair.'")';
$optioncount++;
}
If I var_dump($attList) I get;
array(2) {
["option_1"]=>
string(39) "new xmlrpcval("Colour: Military Black")"
["option_2"]=>
string(25) "new xmlrpcval("Sizes: L")"
}
Any other way seems to turn $attList into a total mess - I know this should be very basic but for the life of my I can't get this working. Thanks for any pointers.
If I var_dump($attList) when I use new xmlrpcval($attpair); I get;
array(2) {
["option_1"]=>
object(xmlrpcval)#469 (3) {
["me"]=>
array(1) {
["string"]=>
string(22) "Colour: Military Black"
}
["mytype"]=>
int(1)
["_php_class"]=>
NULL
}
["option_2"]=>
object(xmlrpcval)#433 (3) {
["me"]=>
array(1) {
["string"]=>
string(8) "Sizes: L"
}
["mytype"]=>
int(1)
["_php_class"]=>
NULL
}
}

Building your array must look like:
$optioncount = 1;
$attList = array();
foreach ( $attributes as $attribute => $value ) {
$attpair = implode(": ", $value);
$attList['option_'. $optioncount] = new xmlrpcval($attpair);
$optioncount++;
}
And then:
"option_text" => new xmlrpcval(
$attList,
"struct")

Related

MongoDb SearchQuery Issue

I have a database and a table user. when i perform below code i got output as below.
$searchQuery = array('userID' => '2');
$collection = $db->mydatabase->users;
$cursor = $collection->find()->limit(2);
foreach ($cursor as $doc) {
var_dump($doc);
}
Output:
array(4) {
'_id' =>
class MongoId#8 (1) {
public $$id =>
string(24) "56c8216d7f8b9a0e148b4567"
}
'userID' =>
int(7)
'lastTimeOnline' =>
string(19) "2016-02-20 01:48:53"
'displayName' =>
string(0) ""
}
array(4) {
'_id' =>
class MongoId#9 (1) {
public $$id =>
string(24) "56c8216d7f8b9a0e148b4568"
}
'userID' =>
int(2)
'lastTimeOnline' =>
string(19) "2016-02-20 01:48:53"
'displayName' =>
string(0) ""
}
Now i need to find only those records whose userID is 2, so i change the code as below.
$searchQuery = array('userID' => '2');
$collection = $db->mydatabase->users;
$cursor = $collection->find($searchQuery)->limit(2);
foreach ($cursor as $doc) {
var_dump($doc);
}
but now the output is blank :-(
I have two doubts.
A) why 2nd code to fetch userId=2 is not working
B)why on both cases var_dump($cursor) is giving below output and why not detail of $doc
class MongoCursor#5 (0) {
}
Seems like the userID in database is saved as Integer and your are trying to query using a string parameter, try to change the query array to the following:
$searchQuery = array('userID' => 2);
You are storing the userId as an integer and in the query you are using a string due to which you are find nothing so instead of writing 2 like this '2' write it like this 2

Php array foreach

I am trying to fetch some data from an API and put it into an array and then to MySQL.
My Code:
$find_sql = "SELECT * FROM `scrape`";
$users_to_scrape = $app['db']->fetchAll($find_sql);
$instagram = $app['instagram'];
$oauth = json_decode(file_get_contents($app['oauth_path']));
$instagram->setAccessToken($oauth);
foreach($users_to_scrape as $user_to_scrape) {
printf("Getting info for %s <%s>\n", $user_to_scrape['instagram_id'], $user_to_scrape['user_name']);
$follows = $instagram->getUser($user_to_scrape['instagram_id'], 999);
foreach($follows->data as $follow) {
echo var_dump($follows);
$data = array(
'instagram_id' => $follow->id,
'followed_by_instgram_id' => $user_to_scrape['instagram_id'],
'user_name' => $follow->username,
'full_name' => iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($follow->full_name)),
'profile_picture' => $follow->profile_picture,
'followers' => $follow->counts->followed_by,
'follows' => $follow->counts->follows
);
printf("+ %s <%s>\n", $data['instagram_id'], $data['user_name']);
//skapa tabell med follows (instagram_id,
if ($follow->counts->followed_by >= "30000") {
$app['db']->insert('follows', $data);
}
}
}
The Vardump returns this:
object(stdClass)#111 (2) {
["meta"]=>
object(stdClass)#112 (1) {
["code"]=>
int(200)
}
["data"]=>
object(stdClass)#113 (7) {
["username"]=>
string(9) "Dimbos"
["bio"]=>
string(97) "•Have fun in life Contact: info#skogen.com"
["website"]=>
string(24) "http://www.life.com"
["profile_picture"]=>
string(106) "https://xxertt.com/hphotos-ak-xaf1/t51.2885-19/11311351_362556250614181_543_a.jpg"
["full_name"]=>
string(10) "Dimbo"
["counts"]=>
object(stdClass)#114 (3) {
["media"]=>
int(113)
["followed_by"]=>
int(256673)
["follows"]=>
int(345)
}
["id"]=>
string(8) "38353560"
}
}
And the error I receive is this:
Notice: Trying to get property of non-object in /var/www/script.php on line 40
On line 40 we have this:
'instagram_id' => $follow->id,
I also get error on the following set arrays.
Can't really figure it out.
Because $follows->data is a stdClass object, iterating it with foreach will loop over each of its properties individually, returning the value of each property. This means that though id is present in the loop, it is merely the last data element of the loop, inaccessible by its property name.
Using the foreach, the iterator value of $follow results directly in the values rather than properties, as in:
// Value of $follow on each loop iteration:
"Dimbos"
"•Have fun in life Contact: info#skogen.com"
"http://www.life.com"
// etc...
You don't need the foreach loop. Instead, access each element of $follows->data directly:
// Remove the foreach loop
$data = array(
// Each property is directly accessible in $follows->data
'instagram_id' => $follows->data->id,
'followed_by_instgram_id' => $user_to_scrape['instagram_id'],
'user_name' => $follows->data->username,
'full_name' => iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($follows->data->full_name)),
'profile_picture' => $follows->data->profile_picture,
'followers' => $follows->data->counts->followed_by,
'follows' => $follows->data->counts->follows
);
printf("+ %s <%s>\n", $data['instagram_id'], $data['user_name']);
//skapa tabell med follows (instagram_id,
if ($follows->data->counts->followed_by >= "30000") {
$app['db']->insert('follows', $data);
}
You could create a variable that references the data property, allowing you to access those inner properties with less code, but I don't see it as necessary.
// Refer to data in $follow
$follow = $follows->data;
echo $follow->id;
echo $follow->counts->followed_by;
// etc...

Multi level array assignment

Here is the example PHP array representation
array(
"test1" => array(
"test1subtest1" => array(..)
),
"test2" => array(
"test2subtest1" => array(..)
)
)
So, here is the question: is there any tool in PHP which can be used to assign values to multidimensional array with random depth and index names? It suppose to look like this:
$valuetoassing = "TESTVALUE";
$testarray = array();
array_assign_multidimensional($testarray, $valuetoassing, array("test1", "test1subtest1", "test1subtest1subtest1"));
Problem is that I do not know what depth the array will have, so I can not code it. Index names are also generated at the run time.
EDIT: I figured that my particular case can be solved using some kind of linked list (stored as array with items that contain actual data and pointer to the index of the next element), but I'm sure I'll meet this problem again in the future so I will not close the question right now.
This is pretty easy to do using references.
function array_assign_multidimensional(&$input_array, $value, $list){
$assignee = &$input_array;
foreach($list as $key){
$assignee = &$assignee[$key];
}
$assignee = $value;
}
$input = array(
'firstLayer' => array(
'secondLayer' => array(
'test' => 'old'
)
),
'randomOutlyingValue' => ''
);
array_assign_multidimensional($input, 'new', array('firstLayer', 'secondLayer', 'test'));
var_dump($input);
/*
array(2) {
["firstLayer"]=>
array(1) {
["secondLayer"]=>
array(1) {
["test"]=>
string(3) "new"
}
}
["randomOutlyingValue"]=>
string(0) ""
}
*/

Authorize.Net-XML - Adding line items

First off thanks for writing this class. It has made life much easier for me in building applications.
I have CIM set up and I have no problem adding users, processing payments, etc. However I am stuck on adding line items. The examples on github use static population of the array used to create the XML request EX:
'lineItems' => array(
'itemId' => 'ITEM00001',
'name' => 'name of item sold',
'description' => 'Description of item sold',
'quantity' => '1',
'unitPrice' => '6.95',
'taxable' => 'true'
),
'lineItems' => array(
'itemId' => 'ITEM00002',
'name' => 'other name of item sold',
'description' => 'Description of other item sold',
'quantity' => '1',
'unitPrice' => '1.00',
'taxable' => 'true'
),
This works great if you are manually creating things but I am dynamically creating these line items based on user input. Unfortunately, I am unable do add multiple line items to the array due to the fact that the key ('lineItems') gets overwritten and I end up with one line item.
I have tried creating an array of lineItems and then merging it with no luck. Hopefully I am just missing a simple fix for this.
Thanks for responding John! Once again, great work on this class it has made my life much easier.
Here is what I ended up doing for simplicity. I am sure this can be expounded upon if necessary, but for me this worked perfect. Instead of passing multiple line items on the same level of the array I created line items as their own array and then modified setParamaters() to iterate through that array.
private function setParameters($xml, $array)
{
if (is_array($array))
{
foreach ($array as $key => $value)
{
if (is_array($value))
{
if($key == 'lineItems'){
foreach($value as $lineitems){
$line_item = $xml->addChild('lineItems');
foreach($lineitems as $itemkey => $itemvalue) {
$line_item->addChild($itemkey, $itemvalue);
}
}
}
else
{
$xml->addChild($key);
$this->setParameters($xml->$key, $value);
}
}
else
{
$xml->$key = $value;
}
}
}
}
This suited my needs perfectly and made it so I did not have to change anything on the front end except nesting the lineItems array. So the array I am sending looks more like this:
["lineItems"]=>
array(2) {
[0]=>
array(6) {
["itemId"]=>
string(9) "ITEM00010"
["name"]=>
string(21) "Blah Blah"
["description"]=>
string(21) "Blah Blah Description"
["quantity"]=>
string(1) "1"
["unitPrice"]=>
string(4) "100"
["taxable"]=>
string(5) "false"
}
[1]=>
array(6) {
["itemId"]=>
string(9) "ITEM00011"
["name"]=>
string(25) "Thing Thing"
["description"]=>
string(25) "Thing Thing Description"
["quantity"]=>
string(1) "2"
["unitPrice"]=>
string(3) "50"
["taxable"]=>
string(5) "false"
}
}
Also, for anyone out there looking to build the arrays for the line items I did this:
foreach ($services as $key => $service){
$line_items["lineItems"][] = array(
'itemId' => 'ITEM000'.$key,
'name' => $service->name,
'description' => $service->name,
'quantity' => $service_count[$key],
'unitPrice' => $service->price,
'taxable' => 'false'
);
}
And then just added it to the transaction_array that I passed to the AuthnetXML instance.
Thanks again!
Joel
I am the author of that class. The AuthnetXML class currently has a bug in it that results in the results you saw. You would need to make a change to core class to work around this.
I received an email from a user who offered a solution which I have not had a chance to review yet. I'll give you the same information they gave me and hopefully it helps you:
The problem is that you can't have duplicate keys at the same level in an array. If you do the last one entered wins and the rest are overwritten.
So you need a way to represent repeating items from XML in and array. I decide to use the JSON methods to keep it simple. A quick wat to convert Simple XML to and array is to pass it through JSON.
$array = json_decode( json_encode( $simpleXML), true);
That will convert XML like this:
<transactionSettings>
<setting>
<settingName>allowPartialAuth</settingName>
<settingValue>false</settingValue>
</setting>
<setting>
<settingName>duplicateWindow</settingName>
<settingValue>0</settingValue>
</setting>
<setting>
<settingName>emailCustomer</settingName>
<settingValue>false</settingValue>
</setting>
<setting>
<settingName>recurringBilling</settingName>
<settingValue>false</settingValue>
</setting>
<setting>
<settingName>testRequest</settingName>
<settingValue>false</settingValue>
</setting>
</transactionSettings>
To an array like this:
array(
'transactionSettings' => array(
'setting' => array(
0 => array('settingName' =>'allowPartialAuth' , 'settingValue' => 'false',),
1 => array('settingName' => 'duplicateWindow', 'settingValue' => '0', ),
2 => array('settingName' => 'emailCustomer', 'settingValue' => 'false', ),
3 => array('settingName' => 'recurringBilling', 'settingValue' => 'false',),
4 => array( 'settingName' => 'testRequest', false, ),
)
);
So you need to modify AuthNetXML.class to recognize this format. Just replace your setParameters() method with:
private function setParameters($xml, $array)
{
if (is_array($array))
{
$first = true;
foreach ($array as $key => $value)
{
if (is_array($value)) {
if( is_numeric($key) ) {
if($first){
$xmlx = $xml;
$first = false;
} else {
$parent = $xml->xpath('parent::*');
$xmlx = $parent[0]->addChild($xml->getName());
}
} else {
$xmlx = $xml->addChild($key);
}
$this->setParameters($xmlx, $value);
}
else
{
$xml->$key = $value;
}
}
}
}
UPDATE 2012-08-21
This bug has been fixed. Sample code has been updated.
EDIT: I've solved this issue. The lineItems key must be passed in like so:
'lineItems' => array(
'itemId' => '13',
'name' => 'hello',
'description' => 'hello description',
'quantity' => '1',
'unitPrice' => '55.00'
),
Note this differs from what's provided the samples over at the Authorize.net-XML repo. I'm going to head over there now and submit a fix.
ORIGINAL QUESTION:
I'm running into a similar problem involving the Authorize.net-XML class; when executing the createCustomerProfileTransactionRequest() method I receive the following error:
The element 'lineItems' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has
invalid child element 'lineItem' in namespace
'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.
List of possible elements expected: 'itemId' in namespace
'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.' (length=272)
I've even gone so far as to paste in the sample input provided here, but receive the identical error? The class is otherwise working just fine; I use the createTransactionRequest() and createCustomerProfileRequest() methods to process AIM transactions and create CIM profiles without problem.
To reiterate, I'm even attempting to use identical sample input as that found on GitHub.
Any ideas?
Thanks so much!
Jason

mongo php find $in issue with _id's

I'm fairly new to Mongo and PHP. I've been fine with the relatively simple stuff but I've hit a snag performing a php find within a mongo collection conditionally limited by an array of _id's.
Here's a walkthrough...
// "characters" collection
{ "_id":{"$id":"3f177b70df1e69fe5c000001"}, "firstname":"Bugs", "lastname":"Bunny" }
{ "_id":{"$id":"3f2872eb43ca8d4704000002"}, "firstname":"Elmer", "lastname":"Fudd" }
{ "_id":{"$id":"3f287bb543ca8de106000003"}, "firstname":"Daffy", "lastname":"Duck" }
// "items" collection
{ "_id":{"$id":"4f177b70df1e69fe5c000001"}, "mdl":"carrot", "mfg":"Wild Hare Farms ltd.", "ownerid":{"$id":"3f177b70df1e69fe5c000001"} }
{ "_id":{"$id":"4f2872eb43ca8d4704000002"}, "mdl":"hat", "mfg":"Acme Inc.", "ownerid":{"$id":"3f2872eb43ca8d4704000002"} }
{ "_id":{"$id":"4f287bb543ca8de106000003"}, "mdl":"spaceship", "mfg":"Acme Inc.", "ownerid":{"$id":"3f287bb543ca8de106000003"} }
// Let's say I do a find on the item collection for a specific manufacturer...
$itemOwners = $db->items->find(array("mfg" => "Acme Inc."), array("ownerid"));
// The result looks something like this...
[
"4f2872eb43ca8d4704000002":{"_id":{"$id":"4f2872eb43ca8d4704000002"},"ownerid":{"$id":"3f2872eb43ca8d4704000002"}},
"4f287bb543ca8de106000003":{"_id":{"$id":"4f287bb543ca8de106000003"},"ownerid":{"$id":"3f287bb543ca8de106000003"}}
]
// I'd now like to perform a find on the character collection and get the corresponding owner documents.
// To do that I need to build the $in array from the previous find results...
foreach ($itemOwners as $doc)
$itemOwnersTemp[] = $doc["ownerid"];
$itemOwners = $itemOwnersTemp;
// The resulting array looks like this. I've read that the ids need to be in MongoId format. Seems like they are?
[
{"$id":"3f2872eb43ca8d4704000002"},
{"$id":"3f287bb543ca8de106000003"}
]
// and (finally) the conditional find. The result set is always empty. What am I tripping up on?
$characterDocs = $db->characters->find(array("_id" => array('$in' => $itemOwners));
I've just tried this with slightly modified code:
<?php
$m = new Mongo('localhost:13000', array( 'replicaSet' => 'a' ) );
$db = $m->demo;
$db->authenticate('derick', 'xxx');
// "characters" collection
$c = $db->characters;
$c->insert(array( '_id' => new MongoID("3f177b70df1e69fe5c000001"), 'firstname' => 'Bugs', 'lastname' => 'Bunny' ));
$c->insert(array( '_id' => new MongoID("3f2872eb43ca8d4704000002"), 'firstname' => 'Elmer', 'lastname' => 'Fudd' ));
$c->insert(array( '_id' => new MongoID("3f287bb543ca8de106000003"), 'firstname' => 'Daffy', 'lastname' => 'Duck' ));
// "items" collection
$c = $db->items;
$c->insert(array( '_id' => new MongoId("4f177b70df1e69fe5c000001"), 'mdl' => 'carrot', 'ownerid' => new MongoID('3f177b70df1e69fe5c000001')));
$c->insert(array( '_id' => new MongoId("4f2872eb43ca8d4704000002"), 'mdl' => 'hat', 'ownerid' => new MongoID('3f2872eb43ca8d4704000002')));
$c->insert(array( '_id' => new MongoId("4f287bb543ca8de106000003"), 'mdl' => 'space', 'ownerid' => new MongoID('3f287bb543ca8de106000003')));
// Let's say I do a find on the item collection for a specific manufacturer...
$itemOwners = $db->items->find(array("mdl" => "hat"), array("ownerid"));
// The result looks something like this...
/*[
"4f2872eb43ca8d4704000002":{"_id":{"$id":"4f2872eb43ca8d4704000002"},"ownerid":{"$id":"3f2872eb43ca8d4704000002"}},
"4f287bb543ca8de106000003":{"_id":{"$id":"4f287bb543ca8de106000003"},"ownerid":{"$id":"3f287bb543ca8de106000003"}}
]*/
// I'd now like to perform a find on the character collection and get the corresponding owner documents.
// To do that I need to build the $in array from the previous find results...
foreach ($itemOwners as $doc) {
$itemOwnersTemp[] = $doc["ownerid"];
}
$itemOwners = $itemOwnersTemp;
// The resulting array looks like this. I've read that the ids need to be in MongoId format. Seems like they are?
/*
[
{"$id":"3f2872eb43ca8d4704000002"},
{"$id":"3f287bb543ca8de106000003"}
]
*/
// and (finally) the conditional find. The result set is always empty. What am I tripping up on?
$characterDocs = $db->characters->find(array("_id" => array('$in' => $itemOwners)));
var_dump( iterator_to_array( $characterDocs ) );
?>
And it provides the output that I expect:
array(1) {
["3f2872eb43ca8d4704000002"]=>
array(3) {
["_id"]=>
object(MongoId)#3 (1) {
["$id"]=>
string(24) "3f2872eb43ca8d4704000002"
}
["firstname"]=>
string(5) "Elmer"
["lastname"]=>
string(4) "Fudd"
}
}
Somewhere, I think you're doing a wrong conversion but it's difficult to tell as you don't show the output of PHP.
Instead of this:
$itemOwnersTemp[] = $doc["ownerid"];
Try this:
$itemOwnersTemp[] = new MongoID($doc["ownerid"]);

Categories