How to convert MongoDB BSONDocument to valid JSON in PHP? - php

I am using MongoDB with the PHP Library. I inserted a valid JSON document inside MongoDB using PHP. I am now retrieving the document using findOne and am getting a MongoDB\Model\BSONDocument object as a result. How do I get back my JSON document easily? Is there any inbuilt function or will I have to write logic to convert the BSONDocument to JSON?

I didn't see any answers here and I was having the same issue. I did some research and it appears that when you create a document of MongoDB\Model\BSONDocument there is a bsonSerialize() method. This method will return a stdClass Object which is really the PHP Array Class. According to documentation one can then convert from PHP to BSON and then to JSON.
This is crazy looking, but it works. Here is my example $accountResultDoc is of MongoDB\Model\BSONDocument type.
$json = MongoDB\BSON\toJSON(MongoDB\BSON\fromPHP($accountResultDoc))
Results
{
"_id": {
"$oid": "56e1d8c31d41c849fb292184"
},
"accountName": "Michael's Test Company",
"accountType": "Partner",
"subsidiary_id": {
"$oid": "563c3ffbaca6f518d80303ce"
},
"salesforceId": "WERWERWEr2",
"netsuiteExternalId": "56e1d8c31d41c849fb292184",
"suspendBilling": false,
"testAccount": false,
"serviceOrder_ids": null,
"invoice_ids": null
}

The BSONDocument object has a jsonSerialize method. Use that:
Example
{"_id" : 12345,
"filename" : "myfile",
"header" : {
"version" : 2,
"registry" : "test",
"serial" : 20080215,
"records" : 17806,
"startDate" : 19850701,
"endDate" : 20080214
},
}
$connect = new MongoDB\Client('mongodb://yourconnection');
$db = $connect->YourDB;
$collection = $db->YourCollection;
$test = $collection->findOne(array("_id"=>12345));
$data = $test->jsonSerialize();
echo $data->_id;
echo $data->filename;
Will output this:
12345
myfile

Another way would be:
json_encode( $bsonDoc->getArrayCopy() );

I had the same problem and this is how I accessed the values inside. This works with find.
foreach ($result as $entry) {
echo $entry['_id'], $entry['val1'], ['val2'];
}
Hope this helps someone.

Related

MongoDB simply merge two unknown Documents

Is there a way in PHP Mongodb to write an object in an already existing document and only overwrite or add the values contained in the object.
The object structure is not known to me.
Here is a sample:
existing document:
{
"package": {
"parameter": "value",
"one": "two"
}
}
php object or array:
$obj[package][parameter] = "value2"
$obj[package][new] = "test"`
result schould be
{
"package": {
"parameter": "value2",
"one": "two",
"new": "test"
}
}
I need something like array_merge()
I tried the $merge aggerator but it does not seem to work.
Unknown modifier: $merge. Expected a valid update modifier or pipeline-style update specified as an array
$merge is used to insert/update document to collection, like the UPSERT command in SQL. Have a look at $mergeObjects. Use it in combination with $replaceWith (or $replaceRoot which is just an alias)
Would be something like
{ $replaceWith: { $mergeObjects: [ "$$ROOT", {"new" : "test"} ] } }
$$ROOT is the existing object. If the existing object has any fields with the same name as your new object, then it will be overwritten with new field values. If you like to prefer the existing fields, then flip the arguments in the array.
The sample data you provided is not valid JSON, thus I cannot provide a full solution.

how to append information to a document in mongo?

Background Information
I have the following data in my mongo database:
{ "_id" :
ObjectId("581c97b573df465d63af53ae"),
"ph" : "+17771111234",
"fax" : false,
"city" : "abd",
"department" : "",
"description" : "a test"
}
I am now writing a script that will loop through a CSV file that contains data that I need to append to the document. For example, the data might look like this:
+17771111234, 10:15, 12:15, test#yahoo.com
+17771111234, 1:00, 9:00, anothertest#yahoo.com
Ultimately I want to end up with a mongo document that looks like this:
{ "_id" :
ObjectId("581c97b573df465d63af53ae"),
"ph" : "+17771111234",
"fax" : false,
"city" : "abd",
"department" : "",
"description" : "a test",
"contact_locations": [
{
"stime": "10:15",
"etime": "12:15",
"email": "test#yahoo.com"
},
{
"stime": "1:00",
"etime": "9:00",
"email": "anothertest#yahoo.com"
},
]
}
Problem
The code I've written is actually creating new documents instead of appending to the existing ones. And actually, it's not even creating a new document per row in the CSV file... which I haven't debugged enough yet to really understand why.
Code
For each row in the csv file, I'm running the following logic
while(!$csv->eof() && ($row = $csv->fgetcsv()) && $row[0] !== null) {
//code that massages the $row into the way I need it to look.
$data_to_submit = array('contact_locations' => $row);
echo "proving that the record already exists...: <BR>";
$cursor = $contact_collection->find(array('phnum'=>$row[0]));
var_dump(iterator_to_array($cursor));
echo "now attempting to update it....<BR>";
// $cursor = $contact_collection->update(array('phnum'=>$row[0]), $data_to_submit, array('upsert'=>true));
$cursor = $contact_collection->insert(array('phnum'=>$row[0]), $data_to_submit);
echo "AFTER UPDATE <BR><BR>";
$cursor = $contact_collection->find(array('phnum'=>$row[0]));
var_dump(iterator_to_array($cursor));
}
}
Questions
Is there a way to "append" to documents? Or do I need to grab the existing document, save as an array, merge my contact locations array with the main document and then resave?
how can I query to see if the "contact_locations" object already exists inside a document?
Hi yes you can do it !
1st you need to find your document and push the new value you need :
use findAndModify and $addToSet :
$cursor = $contact_collection->findAndModify(
array("ph" => "+17771111234"),
array('$addToSet' =>
array(
"contact_locations" => array(
"stime"=> "10:15",
"etime"=> "12:15",
"email"=> "test#yahoo.com"
)
)
)
);
The best part is $addToSet wont add 2 time the same stuff so you will not have twice the same value :)
Here the docs https://docs.mongodb.com/manual/reference/operator/update/addToSet/
I'm not sure the exact syntax in PHP as I've never done it before but I'm currently doing the same thing in JS with MongoDB and $push is the method you're looking for. Also if I may be a bit nitpicky I recommend changing $contact_collection to $contact_locations as a variable name. Array variable names are usually plural and being more descriptive is always better. Also make sure you find the array in the MongoDB first that you want to append to and that you use the MongoDb "update" command

How to get all children in firebase php?

What I'm trying to do is to get the all the child or users from firebase. Here is the JSON Data:
{
"users":{
"USER1":{
"data1": "123",
"data2": "123"
},
"USER2":{
"data1" : "456",
"data2" : "456"
}
}
}
Does anyone know how to get the child using firebasephp? I am using https://github.com/ktamas77/firebase-php this firebase php.
I'm not a PHP developer so this may not be 100% valid php but looking at the code you would do something possibly like this
$firebase = new Firebase('http://myfirebasename.firebaseio.com', TOKEN);
$users = $firebase->get('/users');
This should return you an array of the data at that endpoint.

PHP JSON object nested loop data syntax

I'm trying to loop through some JSON data and pull out specific values. Here is the JSON data and the partially working code.
$jsondata = '
[
{
"id" : "421356",
"trip_update" : {
"trip" : {
"trip_id" : "421356",
"start_time" : "12:05:00",
"start_date" : "20130926",
"route_id" : "15"
},
"stop_time_update" : {
"stop_sequence" :70,
"departure" : {
"delay" : 240,
"time" : 1380215057
},
"stop_id" : "6090"
},
"stop_time_update" : {
"stop_sequence" :71,
"departure" : {
"delay" : 240,
"time" : 1380215075
},
"stop_id" : "6095"
}
}
}]';
$result = json_decode($jsondata);
foreach($result as $value) {
echo "trip_id: ".$value->trip_update->trip->trip_id;
if (gettype($value->trip_update ) == "object") {
foreach($value->trip_update as $item) {
echo " - stop_sequence: ".$item->stop_sequence;
}
}
}
I can get the first level of data under 'trip_update->trip'. But there can be any number of 'stop_time_update' data within 'trip_update' as well. Since this data relates to the trip_update data, I need to loop through it and correlate it.
The end goal is to save this data to a database (not shown in the code), so for clarity, this would be the simplified 2 rows of DB data I would like to save in this example:
trip_id,stop_sequence
421356,70
421356,71
There can be any number of stop_sequences in the source data.
Here is an interactive link to the code for you to edit or mess with:
http://sandbox.onlinephpfunctions.com/code/f21ca8928da7de3e9fb351edb075d0a446906937
You might get better results if you write your own parser or use a stream-parser with callbacks. Here's a PHP implementation of such a parser that works with callbacks. So instead of reading the whole JSON data into memory, the parser will read the data in chunks and notify your "listener-class" whenever a new object starts or a property was read in etc. By doing this, you should get separate callback events for each stop_time_update property instead of just one value in the parsed array.
Very similar to what SAX is for XML.
Hi maybe you can change the name.
function next_update($coincidencias){
$replace=$coincidencias[0].$GLOBALS["json_stop_time_update"]++;
return $replace;
}
$result= preg_replace_callback("/stop_time_update/","next_update",$jsondata);
$result = json_decode($result);
You should rework your JSON - you have multiple keys with the same name, try to do print_r($result) to see what I am talking about - PHP will override the "stop_time_update" key time after time and you will be able to access only the last entry. Instead, you should organize your JSON like that:
[
{
"id" : "421356",
"trip_update" : {
"trip" : {
"trip_id" : "421356",
"start_time" : "12:05:00",
"start_date" : "20130926",
"route_id" : "15"
},
"stop_time_update" : [{
"stop_sequence" :70,
"departure" : {
"delay" : 240,
"time" : 1380215057
},
"stop_id" : "6090"
}, {
"stop_sequence" :71,
"departure" : {
"delay" : 240,
"time" : 1380215075
},
"stop_id" : "6095"
}]
}
}]
then you will be able to iterate through your data like this:
foreach($result[0]->trip_update->stop_time_update as $update)
{
$time = $update->departure->time;
...
}
If you cannot change the data structure, then what probably could help you is a PULL parser - one that does not return parsed data structure, but allows you to use a data stream instead - this way you could iterate over each node. The only one I managed to find is an extension to PHP:
https://github.com/shevron/ext-jsonreader
Check the usage section.
This JSON response is invalid because it contains duplicate keys but JSON doesn't allow duplicate keys.
You should contact the service you're trying to request this response from.
If you have a valid JSON response then you can decode it using the json_decode function which returns an object or an array (depends on the second parameter);
You cannot use a JSON parser for this as it will always overwrite the first element due to the same keys. The only proper solution would be asking whoever creates that "JSON" to fix his code to either use an array or an object with unique keys.
Another option is to write your own decoder function for parse it

Store Array thats Located Inside Object

I have the following JSON:
"list": {
"list_id": "2kA",
"title": "Social Media",
"description": "Trending",
"image": [
"http://cdn.socialmediaexaminer.com/wp-content/uploads/2012/11/br-campaign-report.png?9d7bd4",
"http://cdn.socialmediaexaminer.com/wp-content/uploads/2012/11/br-campaign-report.png?9d7bd"
],
"views": 65
}
How can I store a serialized version of the image array in the database? Doing any of the following returns an error:
$images = $item->list->image;
$images = $item->list->image->[0];
$images = $item->list->['image'];
Thanks guys!
In your DB, data is in JSON, literally it means its a formatted string like:
"something here...."
You cannot access it by "->" as it is not an object.
So,
Convert your string(JSON) to Object to access like these:
$x['list']['image']
It can be achieved by json decoding your string which will convert your string to object
There was a bad error in code too. This one : $item->list->image->[0];
you cannot access an element of an array like this image->[0] --> it should be
$item->list->image[0]
you can access to your images like this:
foreach($item->list->image as $your_image) {
//do what you want
}
or use a associated array like this
$x = json_decode('{"list": {
"list_id": "2kA",
"title": "Social Media",
"description": "Trending",
"image": [
"a",
"b"
],
"views": 65
}}', true);
foreach($x['list']['image'] as $your_image) {
//do what you want
}
to save it to your db use json_encode (and escape), as example of a mysqli connection
$query = 'INSERT INTO your_table (...)
VALUES (\''.mysqli_real_escape_string($dblink, json_encode($your_array)).'\')';
on select you can use json_decode!

Categories