I have a rather simple script which uses a hardcoded array to load employees and their names and emails, then loops through each array element and sets an email address array so that it emails each report to the right person.
The issue is that each employee will have multiple emails, so I need to have the email key consume multiple addresses and then when I loop below it would need to email that report to multiple people
What's the best way to alter this?
$items = array(
array(
"employee" => 5273,
"name" => "Jon Doe",
"email" => "emp1#newSite.com"
),
array(
"employee" => 5274,
"name" => "Jane Doe",
"email" => "emp2#newSite.com"
),
);
foreach($items as $item){
$dealerNum = $item["employee"];
$dealerName = $item["name"];
$emails = config('emails.employees');
if (array_key_exists('email',$item)){
$emails['to'][] = $item['email'];
}
}
Make the email value an array. Then you can append it to $emails['to'].
There's no need to call config('emails.employees') every time through the loop. Call it once before the loop, then add to the emails inside the loop.
$items = array(
array(
"employee" => 5273,
"name" => "Jon Doe",
"email" => ["emp1#newSite.com"]
),
array(
"employee" => 5274,
"name" => "Jane Doe",
"email" => ["emp2#newSite.com", "emp3#newSite.com"]
),
);
$emails = config('emails.employees');
foreach($items as $item){
$dealerNum = $item["employee"];
$dealerName = $item["name"];
if (array_key_exists('email',$item)){
$emails['to'] += $item['email'];
}
$emails['to'] = array_unique($emails['to']); // remove duplicates
}
Related
I am parsing a csv file, and then looping it like so.
foreach ($this->csvData as $dataKey => &$item) {
foreach ($item as $key => $value) {
print_r($item);
}
}
Now if I output item, I can see something like the following
array:12 [
"ID" => "12345"
"CODE" => "AZ6G"
"YEAR" => "2009"
"WEEK" => "13"
"FULL_DATE" => "29/04/2014"
"SALES" => "asdas89.34"
"QUANTITY" => "3"
]
So the above example represents one row in the csv, the key is the header name and then it has a value.
The problem is this, I know which columns I need to keep based on an index value. These values are selected by the user at a previous stage. So in the above example I know I need to keep the ID, FULL_DATE and SALES, so in my database I have 0, 4, 5 which represents their indexes.
Now I need to extract these columns. If I do something like the following
foreach ($this->csvData as $dataKey => &$item) {
foreach ($item as $key => $value) {
print_r($item[4]);
}
}
I will get an undefined index problem as there is no key named 4. If I give it the name of the key, it will work, and show me the value.
So how can I get the value using the key index instead of the name?
Thanks
you could use array_keys and then loop over those keys you said you get from the Database like so:
<?php
$keys = [0, 4, 5];
$data = [
"ID" => "12345",
"CODE" => "AZ6G",
"YEAR" => "2009",
"WEEK" => "13",
"FULL_DATE" => "29/04/2014",
"SALES" => "asdas89.34",
"QUANTITY" => "3"
];
foreach($keys as $key) {
echo $data[array_keys($data)[$key]] . "\n";
}
// outputs:
// 12345
// 29/04/2014
// asdas89.34
Explanation what happens:
array_keys($data)[0]; // is "ID"
// and the "ID" can be used as "key" for the $data array with
$data[array_keys($data)[0]]; // which is $data["ID"]; => "12345"
You can play with it online here: http://sandbox.onlinephpfunctions.com/code/4d6a4d86a6cdceccf4034fca06dcef9e50a89dc8
In laravel, I have a working code block where I loop an array and within it I call an email list. However, there are certain elements in the array that have a specific email that I want to add to it. So I always want the existing email config list to be used no matter what, but if the array element of the person has an email key I want to add that to the emails array, if that makes sense.
Here is the existing code as it:
$items = array(
array(
"employee" => 123,
"name" => "Tom",
"email" => "Tom#sitepoint.com"
),
array(
"employee" => 234,
"name" => "Sally"
),
array(
"employee" => 345,
"name" => "Rob"
),
array(
"employee" => 456,
"name" => "Ed"
"email" => "ed#sitepoint.com"
),
array(
"employee" => 567,
"name" => "Barbara"
)
);
foreach($items as $item){
//if there is an override email in the command
if($this->option('email') != 'default') {
if(!filter_var($this->option('email'), FILTER_VALIDATE_EMAIL)) {
$this->error('invalid email:'.$this->option('email'));
return;
}
$emails = ['to'=>[$this->option('email')],'cc'=>[]];
} else {
//This line works as is but I want a condition so that if the array element has and "email" key, I add that value as well
$emails = config('emails.printouts.employeePrintOuts');
//here I would need to add the array value (if email is set in that element)
}
...
}
The part in question is only in the 'else' block. How can I properly do this so that only certain array elements will have an email key and if they do I add it to the emails array that is always using the config list?
As mentioned in comments, you can use array_key_exist() function to check that $items contain email key.
Also to fullfil $emails['to'] subarray only in case that it doesn't contain current $items['email'] you may use in_array() function.
Solution:
if ( array_key_exist('email', $item) && !in_array($item['email'], $emails['to']) )
{
//TODO validate $item['email'] here
$emails['to'][] = $item['email'];
}
//Result $emails array will be looks like this:
[
'to' => [ "Tom#sitepoint.com", "ed#sitepoint.com" ],
'cc' => []
]
I got the following array:
"task" : {
"author_id" : 150,
"created_at" : somedate,
"status_id" : 2,
"assignee_id" : 100,
"updated_at" : somedate_too
and I got 2 more associative arrays where I store names for IDs in the following way:
"100" => Mike,
"150" => Bob //etc..., the same for statuses
I need to check for the IDs in the first array and replace numbers with names for the corresponding arrays in the most effective way. I tried the following:
if(isset(task['status_id'])){$row = array_merge($row, [$status_ids[
task['status_id']]]);}else{$row = array_merge($row, '');}
if(isset(task['author_id'])){row = array_merge($row, [$users[// note the different array here
task['author_id']]]);}else{$row = array_merge($row, '');}
if(isset(task['assignee_id'])){$row = array_merge($row, [$users[
task['assignee_id']]]);}else{$row = array_merge($row, '');}
In my resulting array ($row) I cannot miss the index and replace it with another value. If there is no value in the first array, I need to insert an empty string to get the following, for example:
['in progress', '', 'Mike']
if there is no author_id in the first array. I believe there should be a better way to do it with foreach loop, but I cant find out how because for different fields I get the data from different arrays. I dont think a separate if clause for every field is the most suitable here.
Any help would be welcome. Thank You.
You could map your special keys to their array counterparts using references and use that mapping when populating $row, like this:
$users = [
"100" => "Mike",
"150" => "Bob",
];
$status_ids = [
1 => "Foo",
2 => "Bar",
];
// Define output format and array mapping
$mapping = [
"author_id" => &$users, // Mapped to $users array
"created_at" => null, // Not mapped, keep $task value
"status_id" => &$status_ids,
"assignee_id" => &$users,
"updated_at" => null,
];
$task = [
"author_id" => 150,
"created_at" => "Some date",
"status_id" => 2,
// "assignee_id" => 99999, // Oops, missing key/value => empty string in $row
"updated_at" => "Some other date",
];
foreach ($mapping as $key => $mappedArray) {
#$row[] = $mappedArray
? $mappedArray[$task[$key]] ?: ''
: $task[$key];
}
print_r($row);
Output:
Array
(
[0] => Bob
[1] => Some date
[2] => Bar
[3] =>
[4] => Some other date
)
It should work (I didn't try it, but it should give you the general idea):
<?php
$fields = array("author_id", "assignee_id", "status_id");
$aliases = array("users", "users", "status_ids");
foreach ($task as $key=>&$value) {
$alias = str_replace($fields, $aliases, ${$key});
if (is_array(${$alias}) {
$value = array_key_exists($value, ${$alias}) ? ${$alias}[$value] : "";
}
}
unset($value);
And then you can fill up your $row as you planned, directly from the $task array.
So I have the following array of data in PHP
$array = array(
"animal" => "panda",
"location" => "San Diego",
"age" => "2",
),
array(
"animal" => "tiger",
"location" => "Bronx",
"age" => "5",
),
array(
"animal" => "panda",
"location" => "Bronx",
"age" => "3",
),
array(
"animal" => "tiger",
"location" => "bronx",
"age" => "3",
),
array(
"animal" => "panda",
"location" => "San Diego",
"age" => "2",
)
)
What I want to do is convert this into an associative array that will contain the count for the animals, locations and age. so if I wanted to see how many pandas are in san diego and are age 2 I would access the new array with $newArray['panda']['San Diego']['2'] and the output would be 2.
My issue is I can easily run a loop and build an array and count the items when it is completely static like so.
foreach($array as $a) {
$newArray[$a['animal']][$a['location']][$a['age']] += 1;
}
However I want to know how to accomplish the same concept when the number of keys is dynamic. for instance what if there are only location and animal in one call and sometimes there might be location, animal, age, and gender in another call.
There are some examples I have found that expound on doing this for associative arrays but not for multidimensional arrays with this particular use case.
Any Thoughts?
The Idea
It looks to me as if you're trying to do too much in one go. Instead of transforming your array to contain all your answers, consider making a function to run queries against it.
The Solution
/**
* #param array $animals The whole animals array
* #param array $query Array containing keys and values you want to filter by
*
* #return array Animals that match $query
*/
function filterAnimals($animals, $query) {
return array_filter($animals, function ($animal) use ($query) {
// Check if $animal has every key and the corresponding value from $query
foreach ($query as $key => $value) {
if (!isset($animal[$key]) || $animal[$key] != $value) {
return false;
}
}
return true;
});
}
filterAnimals() filters your $animals array and returns only the animals that have the common keys and values with the $query array. Searching for all pandas from San Diego would look like this:
$result = filterAnimals($animals, [
'animal' => 'panda',
'location' => 'San Diego'
]);
Then, if you wish, you can count the $result:
$count = count($result);
I have the following array from an API
$arrs = array(
"id" => $ids,
"names" => $names,
"description" => $desc,
"picture_url" => $p_img;
);
The API require this information to work unfortunately I can only have one array per request, so I send this question to the developers:
How can I list multiple item such as:
$arrs= array(
"items1" => array (
"id" => $ids,
"names" => $names,
"description" => $desc,
"picture_url" => $p_img;
)
"items2" => array (
"id" => $ids,
"names" => $names,
"description" => $desc,
"picture_url" => $p_img;
)
"items3" => array (
"id" => $ids,
"names" => $names,
"description" => $desc,
"picture_url" => $p_img;
)
));
And they told me that at the moment is not possible, so, the "important" part of this array is the "names", when it is use with a single item there is no problem I get a single name, done, no problem, but what if I have multiple names? I can send multiple request but that will be seen as a flood or something like... just imaging 300 names = 300 request in one second or so... sure I can put a pause per request but is not efficient...
the API will read something like this...
"id" => 654,
"names" => "John", // <-- Lets look at this...
"description" => "Fancy desc...",
"picture_url" => "http"//domain.com/assets/user/654/av_654_dd.jpg";
So before I output the array I have an SQL Query with a while to display the information...
while ($names = $listnames->fetch_assoc()) {echo $names['names']. ', ';}
This will display... John, Karl, Lisa, Mark... so this same structure I'd love to put it into my array... the thing is I can't put a while after the => ... that would be silly and it wont work...
"id" => 654,
"names" => "John, Karl, Lisa, Mark", // <-- Lets look at this...
"description" => "Fancy desc...",
"picture_url" => "http"//domain.com/assets/user/654/av_654_dd.jpg";
if I need only one name then there is not problem... but in this case I need to put all of the name as a value, so, how can get the result from a WHILE loop.... so that I can use that result elsewhere...
Thank you for taking the time..
while ($names = $listnames->fetch_assoc()) {
$name_array[] = $names['names'];
}
$arrs=array(
"items1" => array (
"id" => $ids,
"names" => implode(', ', $name_array),
"description" => $desc,
"picture_url" => $p_img;
)
);
We don't know how you access to the API.
If this is a REST API, you are able to do only what the developers planned.
If this is a framework or another library, you may edit it.
And you should receive your results like theses:
$arrs = array(
array(
"id" => 1,
"names" => 'MyName',
"description" => 'MyDesc',
"picture_url" => 'MyPic',
),
array(
"id" => 2,
"names" => 'MyName',
"description" => 'MyDesc',
"picture_url" => 'MyPic',
),
);
So if you have full access to the SQL results, to get all results' data, you could do:
$results = array();
while( $row = $listnames->fetch_assoc() ) {
$results[] = $row;
}
If you want to set several possible name in input, the developers should develop that is possible with array of values.
For names, they just have to code: "LIKE '".implode("', LIKE '", $names)."'"
They could also add '%' to allow more values, e.g. 'John' for 'Johnny'.
I think we need more informations to really help you.