Yii, MongoDB query Subdocuments for insertion in a Mysql Table - php

I'm doing a project using Yii Framework, MySQL and MongoDB. I need to get the data from a collection of the mongo database and insert the records in a mysql table. The document of mongodb has subdocuments and I need to insert a row in mysql for every subdocument in the collection. The code of my project is:
$query = array('year'=>'2014');
$records = Yii::app()->edmsMongoCollection('DocumentosDesgloseER')->find($query);
foreach($records as $data){
$success = false;
$model = new DesgloseAcumulado;
$atributos['Id_Enterprise'] = $data['id_enterprise'];
$atributos['Id_Store'] = $data['id_store'];
$atributos['Month'] = $data['month'];
$atributos['Year'] = $data['year'];
$atributos['Id_Usuario'] = Yii::app()->user->id;
$atributos['Id_RubroER'] = $data['DocumentosDesgloseER'][0]['id_rubroer'];
$i = $i + 1;
$model->attributes = $atributos;
if($model->save()) {
$success = true;
}
}
And the structure of my collection in mongodb is:
{
"_id" : ObjectId("535fe63acac5853943166f5c"),
"DocumentosDesgloseER" : [
{
"elemento" : "VENTAS NETAS",
"id_rubroer" : "45",
"id_documento_consolidados_temp" : "31809",
"abreviatura" : "VN",
"orden" : "1",
"formula" : "(250*CM)",
"tipo_fila" : "1",
"resultado_actual" : "113.628",
"resultado_ant" : "239.851",
"promedio_mensual_actual" : "111.365",
"ppto_mes_actual" : "131.540",
"real_acumulado_actual" : "556.826",
"real_acumulado_ant" : "965.824",
"ppto_acumulado_actual" : "666.805"
},
{
"elemento" : "RUBRO DE PRUEBAS",
"id_rubroer" : "19",
"id_documento_consolidados_temp" : "31810",
"abreviatura" : "RP",
"orden" : "3",
"formula" : "CM/500",
"tipo_fila" : "1",
"resultado_actual" : "71.057",
"resultado_ant" : "281.697",
"promedio_mensual_actual" : "67.090",
"ppto_mes_actual" : "72.347",
"real_acumulado_actual" : "335.448",
"real_acumulado_ant" : "879.719",
"ppto_acumulado_actual" : "366.743"
}
],
"documentoID" : "4DOTA2",
"id_enterprise" : "1",
"id_store" : "24",
"month" : "Importes2",
"year" : "2014",
"lastMonthNumber" : NumberLong(4)
}
This is only one of the documents in the collection. As I said earlier, I need to save a row for every subdocument for each document in the mysql database. My code save only the data of the document and the id_rubroer of the subdocument "0".
Does anyone know how I can make the For Loop for each subdocument rather than for each object (document)?
Thanks

Just for-loop the "sub-documents"... say:
foreach($records['DocumentosDesgloseER'] as $data){
$success = false;
$model = new DesgloseAcumulado;
$atributos['Id_Enterprise'] = $data['id_enterprise'];
$atributos['Id_Store'] = $data['id_store'];
$atributos['Month'] = $data['month'];
$atributos['Year'] = $data['year'];
$atributos['Id_Usuario'] = Yii::app()->user->id;
$atributos['Id_RubroER'] = $data['id_rubroer'];
$i = $i + 1;
$model->attributes = $atributos;
if($model->save()) {
$success = true;
}
}

Related

Finding data in mongodb by column name without a known _id

I want to select id and property_name just like i would on mysql
select property_name,_id from properties from properties
In mongodb that is
> db.properties.find({
...
... },{
... "property_name": 1
... }
... );
{ "_id" : ObjectId("6098e4743569ea6d9d6985b2"), "property_name" : "Aero Club" }
{ "_id" : ObjectId("6098f8e7a3397059ef264932"), "property_name" : "Radisson Blu Hotel" }
>
This is my php code
$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->hotel->properties;
//echo $collection->count();
echo "<pre>";
print_r($collection->find(array(), array("property_name" => 1))).iterator_to_array();
echo "</pre>";
I don't see the array of id and property_name returned anywhere so its hard fro me to loop through the returned object.
After returning the id and property, i wan't to translate this query into mongodb
select * from rooms where (has_sauna = 'yes' OR has_elevator = 'yes' or has_television = 'yes') and (price between "200" and "300" )
How can i fix the php query?.
Have you tried this one?
$collection->find(
{ $and: [
{ $or: [
{has_sauna : 'yes'},
{has_elevator : 'yes'},
{has_television : 'yes'}
]},
{ price: {$gt : 200, $lt : 300} }
]}
);
I can get the id and property name like this
$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->hotel->properties;
$cursor = $collection->find();
foreach ($cursor as $document) {
echo '"_id": '.$document["_id"]."<br />";
echo '"property name": '.$document["property_name"]."<br />";
}
While this works, i would like to know how to specify what columns/fields to find.

How to save multiple items from JSON post in database using Yii

What I'm trying to achieve here is to save multiple items from JSON post data into database whenever there's a new registration.
I've successfully save a single registration. But if I have multiple registrations, it won't save all data passed. It will save only the first item.
Here's the JSON post data captured:
{"id" : "1514358676612-F9RM4",
"accountId" : 128768,
"eventId" : 206218,
"timestamp" : 1514358676612,
"url" : "http://hub.mymagic.my/bizzabo/bizzaboCallback",
"details" : {
"items" : [ {
"contactEmail" : "ikram#mymagic.my",
"created" : "2017-12-27T07:09:21.000+0000",
"ticketPaid" : 0,
"contactFirstName" : "Ikram",
"contactLastName" : "Khasim",
"currency" : "USD",
"validity" : "valid",
"status" : "completed",
"ticketType" : "test",
"ticketId" : 1296403,
"invoice" : false,
"contactName" : "Ikram Khasim",
"paymentStatus" : "completed",
"registrationForm" : {
"type_of_person" : "Experienced Entrepreneur",
"firstName" : "Ikram",
"organisation__instit" : "MaGIC",
"lastName" : "Khasim",
"gender" : "Male | Lelaki",
"age_group" : "22-24",
"mobileNumber" : "0193533005",
"email" : "ikram#mymagic.my",
"how_did_you_hear_abo" : "Word of mouth"
},
"type" : "ticket"
}, {
"contactEmail" : "yasmin#mymagic.my",
"created" : "2017-12-27T07:09:21.000+0000",
"ticketPaid" : 0,
"contactFirstName" : "Ikram",
"contactLastName" : "Khasim",
"currency" : "USD",
"validity" : "valid",
"status" : "completed",
"ticketType" : "test",
"ticketId" : 1296404,
"invoice" : false,
"contactName" : "Ikram Khasim",
"paymentStatus" : "completed",
"registrationForm" : {
"type_of_person" : "Experienced Entrepreneur",
"firstName" : "Ikram",
"organisation__instit" : "MaGIC",
"lastName" : "Khasim",
"gender" : "Male | Lelaki",
"age_group" : "22-24",
"mobileNumber" : "0193533005",
"email" : "yasmin#mymagic.my",
"how_did_you_hear_abo" : "Word of mouth"
},
"type" : "ticket"
} ],
"contactEmail" : "ikram#mymagic.my",
"contactFirstName" : "Ikram",
"contactLastName" : "Khasim",
"currency" : "USD",
"action" : "charge",
"status" : "completed",
"quantity" : 2,
"invoice" : false,
"contactName" : "Ikram Khasim",
"paymentStatus" : "completed",
"amount" : 0,
"orderId" : 651560
},
"type" : "orderCreated"
}
And this is the code to save the JSON post data items into database. It successfully stored the first item into the database, however didn't save the second item.
public function actionBizzaboCallback()
{
$junk = new Junk;
$junk->code = 'bizzabo-bizzaboCallback-'.time();
$junk->content .= serialize($_POST);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// fetch RAW input
$json = file_get_contents('php://input');
// expecting valid json
if (json_last_error() !== JSON_ERROR_NONE) {
$junk = new Junk;
$junk->code = 'bizzabo-getJSONError-'.time();
$junk->content = sprintf('JSON not captured at : %s', Yii::app()->params['masterDomain']);
die(header('HTTP/1.0 415 Unsupported Media Type'));
} else {
// check if registration exist
// decode json
$objects = json_decode($json);
//create new registration
$object = new EventRegistration;
$object->event_code = $objects->eventId;
$tmps = HUB::getEventCode($object->event_code);
$object->event_id = $tmps->id;
$object->event_vendor_code = 'bizzabo';
$object->registration_code = $objects->details->items[0]->ticketId;
$object->full_name = sprintf('%s %s', $objects->details->items[0]->registrationForm->firstName, $objects->details->items[0]->registrationForm->lastName);
$object->first_name = $objects->details->items[0]->registrationForm->firstName;
$object->last_name = $objects->details->items[0]->registrationForm->lastName;
$object->email = $objects->details->items[0]->registrationForm->email;
$object->date_registered = time();
$object->date_payment = time();
$object->json_original = json_decode($json,true);
$object->date_added = time();
$object->date_modified = time();
if($object->save()){
$success = 'successfully insert data into db';
}else{
$fail = $object->errors;
$status = 'failed insert data into db';
}
//create junk
$junk = new Junk;
$junk->code = 'bizzabo-getBizzaboRegistrationIntoDB-'.time();
$junk->content = sprintf('Success(%s) or Fail(%s) with error message (%s). With first name is %s and last name is %s. JSON Captured: %s', $success, $status, $fail, $object->first_name, $object->last_name, $json);
}
}
$junk->save();
}
you should iterate over the items content for save the related values eg:
} else {
// check if registration exist
// decode json
$objects = json_decode($json);
foreach( $object->details->items as $key = $value){
//create new registration
$object = new EventRegistration;
$object->event_code = $objects->eventId;
$tmps = HUB::getEventCode($object->event_code);
$object->event_id = $tmps->id;
$object->event_vendor_code = 'bizzabo';
// apply the actual item value
$object->registration_code = $value->ticketId;
$object->full_name = sprintf('%s %s',
$value->registrationForm->firstName,
$value->registrationForm->lastName);
.......
......
}

how to access json file fields [duplicate]

This question already has answers here:
How to loop through PHP object with dynamic keys [duplicate]
(16 answers)
Closed 5 years ago.
{
"took" : 363,
"timed_out" : false,
"num_reduce_phases" : 15,
"_shards" : {
"total" : 7195,
"successful" : 7195,
"failed" : 0
},
"hits" : {
"total" : 35672,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"2" : {
"doc_count_error_upper_bound" : 54,
"sum_other_doc_count" : 1463,
"buckets" : [
{
"key" : "ふるさと納税",
"doc_count" : 30376
}
]
}
}
}
This is the json file . I need to access the doc_count field.
I am trying to do it like this
$trend_words = json_decode($file);
$aggregations = $trend_words->aggregations;
$buckets = $aggregations->{2}->buckets->{0};
But its not working.
Can someone help.
$trend_words = json_decode($file,true);
$aggregations = $trend_words['aggregations']['2']['buckets'][0]['doc_count'];
print_r($aggregations)
You should use ,true otherwise you will get an stdclass object and not an array you want.
try this
<?php
$sJson = '
{
"took" : 363,
"timed_out" : false,
"num_reduce_phases" : 15,
"_shards" : {
"total" : 7195,
"successful" : 7195,
"failed" : 0
},
"hits" : {
"total" : 35672,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"2" : {
"doc_count_error_upper_bound" : 54,
"sum_other_doc_count" : 1463,
"buckets" : [
{
"key" : "ふるさと納税",
"doc_count" : 30376
}
]
}
}
}
';
$aJson = json_decode($sJson, true);
echo $aJson['aggregations'][2]['buckets'][0]['doc_count'];
https://3v4l.org/kHfdo
Here is the answer, As the buckets increases you need to have a loop through to read all the buckets
$trend_words = json_decode($file, true);
$aggregations = $trend_words['aggregations'][2];
$buckets = array();
foreach($aggregations as $element)
$buckets[] = $element['buckets'];
print_r($buckets);
Make Json to array and try
$trend_words = json_decode($file, true);
$aggregations = $trend_words['aggregations'];
$buckets =$aggregations[2]['buckets'][0];

Sync phonebook using php

I am working on web-service to sync contacts using yii2 framework. where i am having whole phone-book (in json array) from mobile end and i have to check which phone numbers are there in my database.
Request params would be something like this
{
"user_id": "4",
"user_details": [{
"first_name": "A",
"last_name": "A"
}, {
"first_name": "B",
"last_name": "B"
,
"mobile_number": ["(888) 888-888", "(777) 777-777"]
}, {
"first_name": "C",
"last_name": "C",
"mobile_number": ["+918000584123", "(666) 666-6666", "(555) 555-5555", "(444) 444-4444"]
}]
}
To achieve the functionality i have done following code.
public function actionSyncPhoneBook()
{
$amResponse = $amResponseData = [];
$snUserId = $this->amData['user_id'];// Here i will get user_id
if (!empty($this->omUser))
{
$userDetails = $this->amData['user_details'];//Here i will get array of user_details
$amAppContacts =[];
$amNonAppContacts = [];
//I have loop here of user details to scan mobile number array
foreach ($userDetails as $userKeys)
{
//In case if mobile number array is not given
if(!empty($userKeys["mobile_number"]))
{
// Loop for scanning mobile numbers
foreach ($userKeys["mobile_number"] as $key => $mobileNumber)
{
//regex for matching mobile number.
$phone = preg_replace('/[^a-zA-Z0-9+]/', '', $mobileNumber);
$oModelUser = Users::find()
->where(['phone' => $phone])
->one();
//Check if conttact is exists or not using exist method
$checkContactExists = Users::find()->where(['phone' => $phone])->exists();
if($checkContactExists == 1)
{
$oModelFriends = Friends::find()->where(["from_user_id"=>$snUserId,"to_user_id"=>$oModelUser->id])->asArray()->one();
$amCheckPhoneNumber['user_id'] = !empty((string)$oModelUser->id) ? (string)$oModelUser->id : '';
$amCheckPhoneNumber['first_name'] = !empty($oModelUser->first_name) ? $oModelUser->first_name : '';
$amCheckPhoneNumber['last_name'] = !empty($oModelUser->last_name) ? $oModelUser->last_name : '';
$amCheckPhoneNumber['email'] = !empty($oModelUser->email) ? $oModelUser->email : '';
$amCheckPhoneNumber['phone'] = !empty($oModelUser->phone) ? $oModelUser->phone : '';
$amCheckPhoneNumber['status'] = !empty((string)$oModelUser->status) ? (string)$oModelUser->status : '';
$amCheckPhoneNumber['relationship_status'] = !empty($oModelUser->relationship_status) ? $oModelUser->relationship_status : '';
$amCheckPhoneNumber['mobile_verified'] = !empty((string)$oModelUser->mobile_verified) ? (string)$oModelUser->mobile_verified : '';
$amCheckPhoneNumber['email_verified'] = !empty($oModelUser->email_verified) ? $oModelUser->email_verified : '';
$amCheckPhoneNumber['latitude'] = !empty($oModelUser->latitude) ? $oModelUser->latitude : "0";
$amCheckPhoneNumber['longitude'] = !empty($oModelUser->longitude) ? $oModelUser->longitude : "0";
if($oModelFriends["is_friend"] == 1)
{
$amCheckPhoneNumber['is_friend'] = "friends";
}
else
{
$amCheckPhoneNumber['is_friend'] = "no_friends";
}
//User Image
if(!empty($oModelUser->user_image))
{
if (filter_var($oModelUser->user_image, FILTER_VALIDATE_URL))
{
if(!empty($oModelUser->user_image))
{
$ssEventDetailsUserImage = $oModelUser->user_image;
}
else
{
$ssEventDetailsUserImage = Yii::$app->params['aws_cover_image_path'];
}
}
else
{
$ssEventDetailsUserImage =Yii::$app->params['aws_cover_image_path'];
}
}
else
{
$ssEventDetailsUserImage = Yii::$app->params['aws_cover_image_path'];
}
//Cover Image
if(!empty($oModelUser->cover_image))
{
if (filter_var($oModelUser->cover_image, FILTER_VALIDATE_URL))
{
if(!empty($oModelUser->cover_image))
{
$ssCoverImage = $oModelUser->cover_image;
}
else
{
$ssCoverImage = Yii::$app->params['aws_cover_image_path'];
}
}
else
{
$ssCoverImage =Yii::$app->params['aws_cover_image_path'];
}
}
else
{
$ssCoverImage = Yii::$app->params['aws_cover_image_path'];
}
$amCheckPhoneNumber['cover_image'] = !empty($ssCoverImage) ? $ssCoverImage : '';
$amCheckPhoneNumber['user_image'] = !empty($ssEventDetailsUserImage) ? $ssEventDetailsUserImage : '';
$amCheckPhoneNumber['app_user'] = "1";
//Final Response of users those who are using application
$amAppContacts[] = $amCheckPhoneNumber;
}
else
{
//Users who does not use application.
$otherUsers['user_id'] = !empty($userKeys['id']) ? $userKeys['id'] : '';
$otherUsers['first_name'] = !empty($userKeys['first_name']) ? $userKeys['first_name'] : '';
$otherUsers['last_name'] = !empty($userKeys['last_name']) ? $userKeys['last_name'] : '';
$otherUsers['email'] = !empty($userKeys['email']) ? $userKeys['email'] : '';
$otherUsers['phone'] = !empty($mobileNumber) ? $mobileNumber : '';
$otherUsers['status'] = !empty($userKeys['status']) ? $userKeys['status'] : '';
$otherUsers['relationship_status'] = !empty($userKeys['relationship_status']) ? $userKeys['relationship_status'] : '';
$otherUsers['user_image'] = Yii::$app->params['aws_cover_image_path'];
$otherUsers['cover_image'] = Yii::$app->params['aws_cover_image_path'];
$otherUsers['mobile_verified'] = !empty($userKeys['mobile_verified']) ? $userKeys['mobile_verified'] : '';
$otherUsers['email_verified'] = !empty($userKeys['email_verified']) ? $userKeys['email_verified'] : '';
$otherUsers['latitude'] = !empty($userKeys["latitude"]) ? $userKeys["latitude"] : "0";
$otherUsers['longitude'] = !empty($userKeys["longitude"]) ? $userKeys["longitude"] : "0";
$otherUsers['is_friend'] = "";
$otherUsers['app_user'] = "0";
//Final Response of users those who are not using app.
$amNonAppContacts[] = $otherUsers;
}
}
}
}
//Merging the app users and non-app users together.
$amResponseData = array_merge($amAppContacts,$amNonAppContacts);
$amResponse = Common:: successResponse("Sync your phonebook.",$amResponseData);
Common::encodeResponseJSON($amResponse);
}
}
From above code i am checking if mobile number is exist in the database than it will push into app users and rests will be in non-app users.
In my database mobile numbers are stored in the format of +(countryCode)(mobileNumber)
Example +918000584123
But it should also work if i don't pass +91 or any country codes.
It should work if mobile number array would be like
"mobile_number": ["(888) 888-888", "(777) 777-777"]
or it should be like
"mobile_number": ["+918000584123","+91 8000584123","8000584123", "(666) 666-6666", "(555) 555-5555", "(444) 444-4444"]
How to achieve this functionality?
Any help would be appreciated.
Thanks in advance.
dont need regex like this
$phone = preg_replace('/[^a-zA-Z0-9+]/', '', $mobileNumber);
Instead you can use
$phone = preg_replace('/[^0-9]/', '', $mobileNumber);
and change your where condition like this below. You should use LIKE condition
$oModelUser = Users::find()->where("phone LIKE'%".$phone."'")->one();
$checkContactExists = Users::find()->where("phone LIKE '%".$phone."'")->exists();
You tagged it with mysql, so I am answering from that angle.
The various phone number should be in a separate table, together with an id of the person they belong to. That way, there can be an arbitrary number of numbers for any person. I suggest 1:many, not many:many, and simply let the occasional shared phone be a dup number in the new table.
The table would have a non-unique index on number, thereby making it 'trivial' in SQL to locate the person(s) with a given number (or set of numbers, using IN).

Mongodb Nested array value is empty always

Mongodb gives the following:
{
"_id" : ObjectId("55d1d8ea464498a8338b4567"),
"appuserfirstname" : "Bhatti",
"appuserlastname" : "Singh",
"appusermiddlename" : "Tripatpal",
"appuseremail" : "tripat.90#gmail.com",
"appusergoogleid" : [
{ "id" : "APA91bFPqNjK5bWdTe6bAniDV8ZlmG5vL3Q1qRz_WGAasOMu_WBbzoorWI2uCU7yC4IS-yggNGQvL7oUp5YhiejOC1TB4bFQspKj4AUZ05-IEL9DJiI2oNwIl5YwW5zyBVqrTMNWFF2B" }
],
"usercreationdate" : ISODate("2015-08-17T18:21:54Z"),
"status" : "0",
"userfollows" : [
{ "following" : ObjectId("55cd8dae46449867738b4567") }
]
}
I want the ids that are in following. but it always gives me empty string
<?php
$appuserid = '123456789';
$appuserscollection = $this->database->createCollection("appusers");
$followers = array('_id' => new MongoId($appuserid));
$s = "";
$result = $appuserscollection->find($followers);
foreach($result as $document) {
$s.=$document['userfollows'];
}
echo $s;
?>
With
$appuserscollection = $this->database->createCollection("appusers");
you create a new collection. And a new collection is always empty
you could try
$collection = new MongoCollection($this->database, 'appusers');

Categories