I'm using PHP, and in order to feed some data to an API using Curl, I need to format some strings and have been using json_encode. It works just fine for simpler bits, but this I can't figure out:
The API expects this:
{
"id": "string",
"startTime": "2017-04-18T08:04:23.167Z",
"endTime": "2017-04-18T08:04:23.167Z",
"contacts": [
{
"id": "string",
"displayName": "string"
}
My code so far:
$data_set_pre = array(
"id" => "",
"startTime" => "2017-04-14T07:47:59.028Z",
"endTime" => "2017-04-15T07:47:59.028Z",
"contacts" => array("id" => "ahashofsomenumbersandletters", "displayName" => "John Doe"),
);
$data_set = json_encode($data_set_pre);
Unfortunately, this produces:
{"id":"","startTime":"2017-04-14T07:47:59.028Z","endTime":"2017-04-15T07:47:59.028Z","contacts":{"id":"ahashofsomenumbersandletters","displayName":"John Doe"}}
I've been researching, and I'm getting the impression that json_encode will encode everything BUT an unbroken sequential array starting from 0 as an object, and I don't now how to work around this.
(No, I can't change what the API requires, it's provided by a 3rd-party).
<?php
$data_set_pre = array(
"id" => "12",
"startTime" => "2017-04-14T07:47:59.028Z",
"endTime" => "2017-04-15T07:47:59.028Z",
"contacts" => array(
array(
"id" => "ahashofsomenumbersandletters", "displayName" => "John Doe"
)
)
);
$data_set = json_encode($data_set_pre);
Change the following line:
"contacts" => array("id" => "ahashofsomenumbersandletters", "displayName" => "John Doe"),
to
"contacts" => array(array("id" => "ahashofsomenumbersandletters", "displayName" => "John Doe")),
It will give:
{"id":"","startTime":"2017-04-14T07:47:59.028Z","endTime":"2017-04-15T07:47:59.028Z","contacts":[{"id":"ahashofsomenumbersandletters","displayName":"John Doe"}]}
here [{"id":"ahashofsomenumbersandletters","displayName":"John Doe"}] is a multi-dimension array
Related
This is the first problem:
I have two Associative Arrays, one containing sales persons and one containing clients.
$salesPersons = array(
array(
"id" => "1",
"name" => "Mr Smith",
"email" => "mrsmith#email.com",
"clients" => array()
),
array(
"id" => "2",
"name" => "James Bond",
"email" => "jamesbond#email.com",
"clients" => array()
)
);
$clients = array(
array(
"id" => "1",
"name" => "Lucifer Enterprises",
"salesPersonId" => "1"
),
array(
"id" => "2",
"name" => "Charlies Chocolate Factory",
"salesPersonId" => "1"
),
array(
"id" => "3",
"name" => "Geckos Investments",
"salesPersonId" => "2"
),
);
I want to map $salesPersons['id'] to clients['salesPersonId'] by ID and return a multidimensional associative array like this:
$result_i_want = array(
array(
"id" => "1",
"name" => "Mr Smith",
"email" => "mrsmith#email.com",
"clients" => array(
array(
"id" => "1",
"name" => "Lucifer Enterprises",
),
array(
"id" => "2",
"name" => "Charlies Chocolate Factory",
),
)
),
array(
"id" => "2",
"name" => "James Bond",
"email" => "jamesbond#email.com",
"clients" => array(
array(
"id" => "3",
"name" => "Geckos Investments",
),
)
)
);
My solution to the first problem
I have solved it using nested foreach-loops and array_push
$result = array();
foreach ($clients as $c_record) {
foreach ($salesPersons as $s_record) {
if ($c_record['salesPersonId'] == $s_record['id']) {
array_push($s_record['clients'], array(
"id" => $c_record['id'],
"name" => $c_record['name']
));
array_push($result, $s_record);
}
}
}
The remaining problem
This solution doesn't seem to be very efficient.
For each client record I check all sales persons to see if there is a match. I think the number of computations are:
no. of clients * no. of sales persons
I have a huge database and also need to add even more dimensions by mapping projects to the clients and deliverables to the projects. I think this could pose a problem.
Question
Is there a more efficient way to get the same result?
Build an index :
you need to access your salesPerson entries by id, you can start by creating an associative array id => salesPerson, and then use this associative array in your loop.
$salesById = array();
foreach ($salesPersons as $s_record) {
$salesById[ $s_record['id'] ] = $s_record;
}
$result = array();
foreach ($clients as $c_record) {
$s_record = $salesById[ $c_record['salesPersonId'] ];
if ($s_record == null) {
// you may want to handle invalid ids in the client array
// one way is to simply ignore this client record :
continue;
}
array_push($s_record['clients'], array(
"id" => $c_record['id'],
"name" => $c_record['name']
));
array_push($result, $s_record);
}
Notes
There may be a problem in the way you create your $result array :
if a sales person has n clients, the $result array will reference that sales person n times.
Look closer into what result you actually want, you may simply want to return $salesPersons, or $salesById.
As LeGEC said:
you need to access your salesPerson entries by id, you can start by creating an associative array id => salesPerson, and then use this associative array in your loop.
You need to set the index of your arrays with the id:
<?php
$salesPersons = array(
1 => array(
"id" => "1",
"name" => "Mr Smith",
"email" => "mrsmith#email.com",
"clients" => array()
),
2 => array(
"id" => "2",
"name" => "James Bond",
"email" => "jamesbond#email.com",
"clients" => array()
)
);
$clients = array(
1 => array(
"id" => "1",
"name" => "Lucifer Enterprises",
"salesPersonId" => "1"
),
2 => array(
"id" => "2",
"name" => "Charlies Chocolate Factory",
"salesPersonId" => "1"
),
3 => array(
"id" => "3",
"name" => "Geckos Investments",
"salesPersonId" => "2"
),
);
Then:
$result = array();
foreach ($clients as $id => $c_record) {
if (isset($salesPersons[$id])) {
$result[] = array_merge($clients[$id], $salesPersons[$id]);
} else {
$result[] = $clients[$id];
}
}
var_dump($result);
Result here: http://sandbox.onlinephpfunctions.com/code/e590bdb5aaea2794fc5a04ee60f61db766129664
PS:
My code works with your use case, but it will not work if the size of the $salesPersons array is bigger than the $clients array
I'm having some issues with the Laravel Collection class.
What I'm trying to do:
I have a multisite solution in which a site has "facilitators". Sometimes one facilitator appears on multiple sites, and not just one.
I want to list all the facilitators and the website they're on the main page, but I don't want multiple users.
So what I currently do is:
Get the Facilitators.
Use Collection to collect the facilitators and use unique('name').
This gives me unique facilitators, but only picks the first one it detects and then deletes the other ones.
So lets say I have this collection:
Collection {
#items: array:3 [
0 => array:2 [
"name" => "John"
"site" => "Example"
]
1 => array:2 [
"name" => "Martin"
"site" => "Another"
]
2 => array:2 [
"name" => "John"
"site" => "Another"
]
]
}
With unique() I would get:
Collection {
#items: array:3 [
0 => array:2 [
"name" => "John"
"site" => "Example"
]
1 => array:2 [
"name" => "Martin"
"site" => "Another"
]
]
}
And this is what I want to get:
Collection {
#items: array:3 [
0 => array:2 [
"name" => "John"
"site" => ["Example", "Another"]
]
1 => array:2 [
"name" => "Martin"
"site" => "Another"
]
]
}
Does anyone have an idea how I could accomplish this with Laravel's collection class?
When stuck with collections always remember reduce is a powerful tool in your arsenal.
Building on Sam's answer which I couldn't get to work, I think using reduce alongside groupBy should work...
$sites = collect([
["name" => "John", "site" => "Example"],
["name" => "Martin", "site" => "Another"],
["name" => "John", "site" => "Another"],
]);
$sites->groupBy('name')->reduce(function ($result, $item) {
$result[] = [
'name' => $item->first()['name'],
'sites' => $item->pluck('site')->toArray()
];
return $result;
}, collect([]))->toArray();
And from the console...
λ php artisan tinker
Psy Shell v0.8.2 (PHP 7.0.10 ÔÇö cli) by Justin Hileman
>>> $sites = collect([
... ["name" => "John", "site" => "Example"],
... ["name" => "Martin", "site" => "Another"],
... ["name" => "John", "site" => "Another"],
... ]);
=> Illuminate\Support\Collection {#698
all: [
[
"name" => "John",
"site" => "Example",
],
[
"name" => "Martin",
"site" => "Another",
],
[
"name" => "John",
"site" => "Another",
],
],
}
>>> $sites->groupBy('name')->reduce(function ($result, $item) {
... $result[] = ['name' => $item->first()['name'], 'sites' => $item->pluck('site')->toArray()];
...
... return $result;
... }, collect([]))->toArray();
=> [
[
"name" => "John",
"sites" => [
"Example",
"Another",
],
],
[
"name" => "Martin",
"sites" => [
"Another",
],
],
]
One thing to note is that you specified in your question that the sites should return a single string if there's only one site and an array if there's many.The above solution does not provide this! I think this is inconsistent and you should always return an array for the sites key, even if it only has one value as it will make it more difficult to read and manipulate later on.
However, if this is something important, you could instead check if there are many sites when using pluck to set an array and if not you could set it as a single string, like this:
$sites->groupBy('name')->reduce(function ($result, $item) {
$result[] = [
'name' => $item->first()['name'],
'sites' => $item->pluck('site')->count() > 1 ? $item->pluck('site') : $item->first()['site']
];
return $result;
}, collect([]))->toArray();
which would produce...
[
[
"name" => "John",
"sites" => [
"Example",
"Another",
],
],
[
"name" => "Martin",
"sites" => "Another",
],
]
you can do it by chaining to get exactly what you want, assuming $collection is the main collection
$collection->groupBy('name')->map(function($facilitators) {
return ['name' => $facilitators->first()['name'], 'site' => $facilitators->pluck('site')->toArray()];
})->values()->toArray();
first we group by name so it will give 2 dimensional array inside collection, then iterate to that and name will be common so get it from first element, then from all the element pluck site and convert it to array, using flatMap will make it single level nested.
I have the following script that returns a json response.
$response["customer_creds"] =array(array('customer_names'=>$user['name'], 'customer_email' => $user['email'], 'customer_id' => $user['customer_id'], 'customer_type' => $user['customer_type'], 'rating' => $user['rating']));
The above script returns:
"customer_creds": [
{
"customer_names": "John Doe",
"customer_email": "example#example.com",
"customer_id": "123456",
"customer_type": "1",
"rating": "4"
}
],
Now I want my json to return the customer_type as an object.("customer_type": [1],
I have tried json decoding and encoding on the same script but nothing seems to work. Any workarounds on this? At a later stage I'll want to have my json to return multiple customer types. The final response should be something like this:
"customer_creds": [
{
"customer_names": "John Doe",
"customer_email": "example#example.com",
"customer_id": "123456",
"customer_type": [1,2,3],
"rating": "4"
}
],
Any suggestion would be highly appreciated. Thanks
You just want the customer_type to be an array of values, instead of just one value?
$response["customer_creds"] = array(
array(
'customer_names' => $user['name'],
'customer_email' => $user['email'],
'customer_id' => $user['customer_id'],
'customer_type' => array($user['customer_type']), // Just wrap it with array()
'rating' => $user['rating']
)
);
i am trying to pass an array to an API, the API takes array in following format when i run it in POSTMAN (raw form),
{
"records": [
{
"content": "50.150.50.55",
"type": "A",
"name": "test.mauqe.com",
"prio": null,
"ttl": 3600
}
]
}
while am trying to pass the array in my code in this format,
$data = array(
"content" => "50.150.50.55",
"type" => "A",
"name" => "gulpanra.mauqe.com",
"prio" => "null",
"ttl" => "3600"
);
i don't understand, whats the problem. response said error (Data sending format error). plz help
The API expects an array of maps. The following is an array of maps.
[
{
"content": "50.150.50.55",
"type": "A",
"name": "test.mauqe.com",
"prio": null,
"ttl": 3600
},
{},
{},
...
]
What you are passing is not the same. You're passing in a single map
{
"content" => "50.150.50.55",
"type" => "A",
"name" => "gulpanra.mauqe.com",
"prio" => "null",
"ttl" => "3600"
}
Try amending $data to:
$data = array();
array_push($data['records'], array(
"content" => "50.150.50.55",
"type" => "A",
"name" => "gulpanra.mauqe.com",
"prio" => "null",
"ttl" => "3600"
));
<?php
$data = array('records' => array());
$data['records'][] = array(
"content" => "50.150.50.55",
"type" => "A",
"name" => "gulpanra.mauqe.com",
"prio" => null,
"ttl" => 3600
);
$json_output = json_encode( $data );
echo $json_output;
?>
This will give the following as output:
{"records":[{"content":"50.150.50.55","type":"A","name":"gulpanra.mauqe.com","prio":null,"ttl":3600}]}
Use json_encode to convert your array in json format and then pass it to the api.
The Api you are using is expecting data in json format.
$data = json_encode($data);
You will need to convert array into json format in order to pass it to the api. use json_encode(). Use the code below
$array = array( "content" => "50.150.50.55", "type" => "A", "name" => "gulpanra.mauqe.com", "prio" => "null", "ttl" => "3600" );
$data = json_encode($data); // Pass this to API
Hope this helps you
you have to make array outside for example
you are using this type of array to encode
$data['records'] = array(
'content' => '50.150.50.55',
and so on
);
change this array to this
$data = array(
'content' => '50.150.50.55',
and so on
);
this will help
I want to compare the 2 arrays below and find the differences. The values for keys "lead owner" and "company" are different, but when I compare these arrays, it says only "company" values are different. But when I create 2 new arrays with only one key/value pair for "lead owner" it works properly. Am I making some mistake?
<?php
$arr1 = Array
(
"leadid" => "418176000000069007",
"smownerid" => "418176000000047003",
"lead owner" => "Amit Patil",
"company" => "SAM",
"first name" => "Test",
"last name" =>"Lead1",
"designation" => "call",
"email" => "",
"phone" => "958",
"fax" => "",
"mobile" => "",
"website" => "www.infosys.con",
"lead source" => "Cold Call",
"lead status" => "Contact in Future",
"industry" => "None",
"no of employees" => "45000",
"annual revenue" => "0",
"rating" => "Active",
"smcreatorid" => "418176000000047003",
"created by" => "Amit Patil",
"modifiedby" => "418176000000047003",
"modified by" => "Amit Patil",
"created time" => "2012-04-05 19:58:00",
"modified time" => "2012-05-02 08:51:08",
"street" => "",
"city" => "",
"state" => "",
"zip code" => "",
"country" => "",
"description" => "",
"skype id" => "",
"email opt out" => "false",
"salutation" => "Mr.",
"secondary email" => ""
);
$arr2 = Array
(
"leadid" => "418176000000069007",
"smownerid" => "418176000000047003",
"lead owner" => "Amit aaa",
"company" => "SAM A",
"first name" => "Test",
"last name" => "Lead1",
"designation" => "call",
"email" => "",
"phone" => "958",
"fax" => "",
"mobile" => "",
"website" => "www.infosys.con",
"lead_source" => "Cold Call",
"lead_status" => "Contact in Future",
"industry" => "None",
"no_of_employees" => "45000",
"annual_revenue" => "0",
"rating" => "Active",
"smcreatorid" => "418176000000047003",
"created_by" => "Amit Patil",
"modifiedby" => "418176000000047003",
"modified_by" => "Amit Patil",
"created_time" => "2012-04-05 19:58:00",
"modified_time" => "2012-05-02 08:51:08",
"street" => "",
"city" => "",
"state" => "",
"zip_code" => "0",
"country" => "",
"description" => "",
"skype_id" => "",
"email_opt_out" => "false",
"salutation" => "Mr.",
"secondary_email" => ""
);
$arr3 = array("lead owner" => "Amit Patil");
$arr4 = array("lead owner" => "Amit aaa");
print_r(array_diff($arr1,$arr2));
echo "<br>";
print_r(array_diff($arr3,$arr4));
?>
Output is as below
Array ( [company] => SAM )
Array ( [lead owner] => Amit Patil )
If you want to diff between associative arrays so that the key-value pairs matter, not just the values, use array_diff_assoc, not array_diff.
You are understanding it wrongly.
The documentation page of array_diff says
Returns an array containing all the entries from array1 that are not
present in any of the other arrays.
But the Amit Patil is present in the second array hence it is returning only one value which is SAM and It is only one value which is not present in second array.
array_diff() returns complementary values. So you can do it like this:
array_diff(array_merge($arr1, $arr2), array_intersect($arr1, $arr2));
This way it will work.
It happens because the "array_diff" function returns the values that occurs for any key in the first array and do not occurs for none of the keys in the second array.
The lead_owner "Amit Patil" is not equal to the second array lead_owner, but is equal to the created_by and modified_by keys of the second one.
You should use "array_diff_assoc" for this purpose.
try this and see, this should work
print_r(array_diff_assoc($arr1,$arr2));
echo "<br>";
print_r(array_diff_assoc($arr3,$arr4));