making sure a generated array key is unique - php

I have this array
$array = array(
"one" => "bar",
"two" => "21",
"three" => "22",
"four" => "25",
"five" => array(
"xxxxxxxxxxxxxxxxxx" => array(
"ar1" => "food",
"ar2" => "dr",
"ar3" => "ch",
"ar4" => "ju"
),
"yyyyyyyyyyyyyyyyyyyy" => array(
"ar1" => "food",
"ar2" => "dr",
"ar3" => "ch",
"ar4" => "ju"
)),
"six" => "et",
"seven" => "op",
"eight" => "hjs",
"nine" => array(
"1" => array(
"ar5" => "food",
"ar87" => "dr",
"ar21" => "ch",
"ar443" => "ju"
),
"2" => array(
"73" => "food",
"82" => "dr",
"90" => "ch",
"2123" => "ju"
)),
"ten" => "bar",
"eleven" => "bar",
"twelve" => "bar"
);
and i want to make sure that every new array added must have a unique array key.To do that,i first get all the keys of the others i.e $array['nine'] in my case then run a function until a unique key is found.
To add a new array to $array['nine'] and to get all the keys in nine
$keyedd = array_keys($array['nine']);
$appendThis[''.unique_array_key($keyedd).''] = array(
"73" => "nitrous",
"82" => "oxide",
"90" => "laughing",
"2123" => "gas"
);
$array['nine'] = $array['nine'] + $appendThis;
This is the function
function unique_array_key($the_array){
$r = rand();
if (array_key_exists("$r", $the_array)) {
unique_array_key($the_array);
}
else if(!array_key_exists("$r", $the_array)) {
echo $r;
}
}
Once i run this
[nine] => Array
(
[1] => Array
(
[ar5] => food
[ar87] => dr
[ar21] => ch
[ar443] => ju
)
[2] => Array
(
[73] => food
[82] => dr
[90] => ch
[2123] => ju
)
[] => Array
(
[73] => nitrous
[82] => oxide
[90] => laughing
[2123] => gas
)
)
the newly added array do not have an array key.However,unique_array_key($keyedd); on its own seems to work fine.Why is the function not adding a unique key?.

I would prefer internal PHP functionality for unique key generation:
$appendThis[uniqid()] = array(
"73" => "nitrous",
"82" => "oxide",
"90" => "laughing",
"2123" => "gas"
);
No needs to reinvent wheel. Check documentation for uniqid() function.
Update
If you have web-cluster running your application simultaneously on several hosts with shared data storage, and more than 10000 ID generations in one second just use:
uniqid(php_uname('n'), true)
for ID generation. Your solution with rand() ID generation have only mt_getrandmax() variations. Usually it is 2147483647. With 10000 ID generations in sec you'll get exceed available ID's limit in 2.4 days, and your code will run in infinite loop because every key check in array will have true result and recursively call new ID generation again and again.
Also, your solution make the application performance dependent on data amount. Than more data you'll have, than higher chance of additional loops for ID generation because of duplicates. For example, if you'll have N already stored arrays with unique ID's, there is a chance next ID will be generated for N+1 cycles.
If your project not highload, will be enough uniqid() or uniqid('', true) if you need additional entropy.

Replace echo $r; with return $r;:
function unique_array_key($the_array){
$r = rand();
if (array_key_exists("$r", $the_array)) {
return unique_array_key($the_array);
} else {
return $r;
}
}
}

Related

check for matching key value in multidimensional array if exists in new array update key value by adding the the number

So I have an array that has multiple entries based on the same order (soId). what I need to do is combine the totals of all the orders that have the same soId into a new array. Here is an example of my array:
array:3738 [▼
0 => array:8 [▼
"A" => "1/3/2021"
"B" => 10556
"C" => 6963
"E" => "AMAZON - D"
"K" => "0.00"
"L" => "15.00"
"M" => "-15.00"
"Q" => "111-327***"
]
1 => array:8 [▼
"A" => "1/3/2021"
"B" => 10556
"C" => 6963
"E" => "AMAZON - D"
"K" => "218.98"
"L" => "47.06"
"M" => "171.92"
"Q" => "111-327***"
]
2 => array:8 [▼
"A" => "1/3/2021"
"soId" => 10556
"C" => 6963
"E" => "AMAZON - D"
"K" => "0.00"
"L" => "6.99"
"M" => "-6.99"
"Q" => "111-32707***"
]
3 => array:8 [▼
"A" => "1/3/2021"
"B" => 10556
"C" => 6963
"E" => "AMAZON - D"
"K" => "0.00"
"L" => "25.00"
"M" => "-25.00"
"Q" => "111-3270792-5031461"
]
So that the matching soID rows would be combined in the new array and would look like this:
array:3738 [▼
0 => array:8 [▼
"invoice" => "1/3/2021"
"soId" => 10556
"invoiceId" => 6963
"client" => "AMAZON - D"
"salePrice" => "218.98"
"unitCost" => "94.05"
"margin" => "124.93"
"extInvoice" => "111-327***"
]
Here is what I was trying but I cannot seem to detect the soId in the new array.
$sheetData = array();
foreach ($sheet as $row) {
//check for matching key value in multidimensional array
if (isset($sheetData['soId'])) { // This is not working skips to else
// This occurence found in the new array
// add+ the salePrice to the new array salePrice.
// add+ the unitCost to the new array unitCost.
// add+ the margin to the new array margin.
}
else {
// first occurence of soId
$sheetData[] = array(
'invoice' => $row['A'],
'soId' => $row['B'],
'invoiceId' => $row['C'],
'client' => $row['E'],
'salePrice' => $row['K'],
'unitCost' => $row['L'],
'margin' => $row['M'],
'extInvoice' => $row['Q']
);
}
}
I am not sure how to accomplish both identifying the multiple occurrences of the soId in the new array (sheetData) or how I could if found combine the total of the three rows: salePrice, unitCost, and margin on the matching soId rom in the new array.
The reason for the conditional statement evaluating to false has to do with the fact that you simply push a new array into $sheetData.
$sheetData looks something like the following in the process:
$sheetData = [
0 => [
'invoice' => 'some_value',
'soId' => '1234',
....
]
];
Thus whenever the test for isset($sheetData['soId']) is evaluated, it evaluates to false. Because 'soId' is not directly set on $sheetData but on one of the nested arrays (in the example index 0).
So, what I personally would do or recommend is to create a small mapping. This mapping will be used to relate the unique identifier soId to an array index.
Whenever we first encounter a new soId we will thus push it onto the result array, followed by mapping the soId to its index.
This allows us to access the array index in constant time and to update the respective sums as such.
Please see the following example:
$map = [];
$sheetData = [];
foreach ($sheet as $row) {
$soId = $row['B'];
// Since there seemed to be presence of thousand separated numbers
// we remove the separation symbol and convert it to a floatval first.
$salePrice = floatval(str_replace(',', '', $row['K']));
$unitCost = floatval(str_replace(',', '', $row['L']));
$margin = floatval(str_replace(',', '', $row['M']));
if (!key_exists($soId, $map)) {
// For simplicity let's rename the fields the first
// time we encounter the soId.
$row = array(
'invoice' => $row['A'],
'soId' => $soId,
'invoiceId' => $row['C'],
'client' => $row['E'],
'salePrice' => $salePrice,
'unitCost' => $unitCost,
'margin' => $margin,
'extInvoice' => $row['Q']
);
// Array push gives us back the number of items,
// hence - 1 is the index in the result array.
$index = array_push($sheetData, $row) - 1;
// For constant time access we track where we
// stored the soId in the sheetData array.
$map[$soId] = $index;
continue;
}
// Otherwise we just add the values to the running totals.
$sheetData[$map[$soId]]['salePrice'] += $salePrice;
$sheetData[$map[$soId]]['unitCost'] += $unitCost;
$sheetData[$map[$soId]]['margin'] += $margin;
}
echo '<pre>';
print_r($sheetData);
echo '</pre>';
The output:
Array
(
[0] => Array
(
[invoice] => 1/3/2021
[soId] => 10556
[invoiceId] => 6963
[client] => AMAZON - D
[salePrice] => 218.98
[unitCost] => 94.05
[margin] => 124.93
[extInvoice] => 111-327***
)
)
Create your result indexed on the soId (index B) and add the subsequent ones:
foreach($sheet as $row) {
if(!isset($result[$row['B']])) {
$result[$row['B']] = array(
'invoice' => $row['A'],
'soId' => $row['B'],
'invoiceId' => $row['C'],
'client' => $row['E'],
'salePrice' => $row['K'],
'unitCost' => $row['L'],
'margin' => $row['M'],
'extInvoice' => $row['Q']);
} else {
$result[$row['B']]['salePrice'] += $row['K'];
$result[$row['B']]['unitCost'] += $row['L'];
$result[$row['B']]['margin'] += $row['M'];
}
}
Not necessary but if you want to re-index it then:
$result = array_values($result);

Displaying one string from a list of multiple strings

I'm trying to grab data from this array, but when I do var_dump($ArrayedLevels['Attack']); it returns NULL, I know for a fact that it was able to grab the data from the SQL database, I think it has something to do with my array. Any help would be greatly appreciated.
include("highscoresconfig.php");
$GrabXP = $database2->prepare("SELECT * FROM `skills` WHERE `playerName` = ?");
$GrabXP->execute(array($playerName));
$MainResult = $GrabXP->fetchAll();
$ArrayedLevels = $array = [
"Attack" => $MainResult['Attacklvl'],
"Defence" => $MainResult['Defencelvl'],
"Strength" => $MainResult['Strengthlvl'],
"Hitpoints" => $MainResult['Hitpointslvl'],
"Ranged" => $MainResult['Rangelvl'],
"Prayer" => $MainResult['Prayerlvl'],
"Magic" => $MainResult['Magiclvl'],
"Cooking" => $MainResult['Cookinglvl'],
"Woodcutting" => $MainResult['Woodcuttinglvl'],
"Fletching" => $MainResult['Fletchinglvl'],
"Fishing" => $MainResult['Fishinglvl'],
"Firemaking" => $MainResult['Firemakinglvl'],
"Crafting" => $MainResult['Craftinglvl'],
"Smithing" => $MainResult['Smithinglvl'],
"Mining" => $MainResult['Mininglvl'],
"Herblore" => $MainResult['Herblorelvl'],
"Agility" => $MainResult['Agilitylvl'],
"Thieving" => $MainResult['Thievinglvl'],
"Slayer" => $MainResult['Slayerlvl'],
"Farming" => $MainResult['Farminglvl'],
"Runecrafting" => $MainResult['Runecraftlvl'],
"Hunter" => $MainResult['Hunterlvl'],
"Construction" => $MainResult['Constructionlvl'],
"Summoning" => $MainResult['Summoninglvl'],
"Dungeoneering" => $MainResult['Dungeoneeringlvl'],
];
var_dump($ArrayedLevels["Attack"]);
Problem might be because the fetchAll() returns all the rows of your query.
if($GrabXP->execute(array($playerName))){
//Success
$MainResult = $GrabXP->fetchAll();
/*
This will give you all the rows. Use a foreach loop to iterate through all the rows.
If you want only the first row, add this-
*/
$MainResult = $MainResult[0];
//The rest of your code.
$ArrayedLevels = $array = Array(
"Attack" => $MainResult['Attacklvl'],
...
);
var_dump($ArrayedLevels["Attack"]);
}
else{
//Failure
}
The brackets don't work in PHP when creating a new array, use array() to create one.
Actually: as of PHP 5.4 they do work, see here: http://nl3.php.net/manual/en/language.types.array.php
Try var_dump($MainResult);
if all good, try create your array like this:
$ArrayedLevels = array(
"Attack" => $MainResult['Attacklvl'],
"Defence" => $MainResult['Defencelvl'],
"Strength" => $MainResult['Strengthlvl'],
"Hitpoints" => $MainResult['Hitpointslvl'],
"Ranged" => $MainResult['Rangelvl'],
"Prayer" => $MainResult['Prayerlvl'],
"Magic" => $MainResult['Magiclvl'],
"Cooking" => $MainResult['Cookinglvl'],
"Woodcutting" => $MainResult['Woodcuttinglvl'],
"Fletching" => $MainResult['Fletchinglvl'],
"Fishing" => $MainResult['Fishinglvl'],
"Firemaking" => $MainResult['Firemakinglvl'],
"Crafting" => $MainResult['Craftinglvl'],
"Smithing" => $MainResult['Smithinglvl'],
"Mining" => $MainResult['Mininglvl'],
"Herblore" => $MainResult['Herblorelvl'],
"Agility" => $MainResult['Agilitylvl'],
"Thieving" => $MainResult['Thievinglvl'],
"Slayer" => $MainResult['Slayerlvl'],
"Farming" => $MainResult['Farminglvl'],
"Runecrafting" => $MainResult['Runecraftlvl'],
"Hunter" => $MainResult['Hunterlvl'],
"Construction" => $MainResult['Constructionlvl'],
"Summoning" => $MainResult['Summoninglvl'],
"Dungeoneering" => $MainResult['Dungeoneeringlvl'],
);
first of all try to print the structure of the variable $MainResult:
var_dump($MainResult);
FetchAll return an array with all restuls like
resutl = [
[0] => ['first row'],
[1] => ['sec. row']
]
you will See The variable $MainResult looks like:
MailResult => [
[0] => ['Attacklvl' => 'foo'],
[1] => ['Defencelvl' => 'bar']
]

Looping through an Multidimentinal/Associative Array

Looking for some help with looping through a multidimensional/associative array in PHP. Essentially, I need to loop through and output the certain key values in a table. Not having much luck.
Here is a sample of my array.
$myarray = array(
"body" => array(
"0" => array(
"machine" => array(
"id" => "1",
"name" => "macbookpro",
"description" => "laptop machine",
"state" => "reserved",
"state_since" => "2013-08-28 12:05:00",
"queue_snapshot" => array(
"time" => "2013-08-01 12:00:00",
"jobs" => "450",
"jobs_available" => "90",
"cputime_running" => "00:01:00",
"cputime_eligible" => "00:90:00",
"cputime_block" => " 90:00:00",
)
)
),
"1" => array(
"machine" => array(
"id" => "2",
"name" => "ipad",
"description" => "tablet machine",
"state" => "available",
"state_since" => "2013-08-28 12:05:00",
"queue_snapshot" => array(
"time" => "2013-08-01 12:00:00",
"jobs" => "50",
"jobs_available" => "20",
"cputime_running" => "00:05:00",
"cputime_eligible" => "00:12:00",
"cputime_block" => " 00:10:00",
)
)
)
));
I have some values in this array that will need to be accessed later so I only need to be able to access particular values in order to create this table. Needs to output like this....
Machine Name | Description | State | Jobs | Jobs Available |
macbookpro laptop machine reserved 450 90
ipad tablet machine available 50 20
Untestet on the fly
<?php
if(isset($myarray['body']) && is_array($myarray['body']))
foreach($myarray['body'] as $id=>$arr) {
$name = $arr['name'];
$description = $arr['description'];
$jobs = $arr['queue_snapshot']['jobs'];
$jobs_available = $arr['queue_snapshot']['jobs_available'];
echo "<br>$name $description $jobs $jobs_available";
}
?>

Adding Docusign Template array into REST Header

So I'm back again. My problem is this:
I have an array of Docusign Templates from checkboxes in a Codeigniter view:
<?php
echo form_open('create_envelope');
foreach ($response["envelopeTemplates"] as $envelopeTemplate) { ?>
<li><?php echo form_checkbox('templatearray[]', $envelopeTemplate["templateId"], FALSE), $envelopeTemplate["name"]; ?></li>
<?php } ?>
What I'm trying to do is add the templates to our REST Header request:
$data = array(
"accountId" => $accountId,
"emailSubject" => "Hello World!",
"emailBlurb" => "This comes from PHP",
"templateId" => "ID from template array here",
"templateRoles" => array(
array(
"tabs" => array(
"textTabs" => array (
array (
"tabLabel" => "lic_num",
"value" => "$license_number"
),
array (
"tabLabel" => "ubi_num",
"value" => "$ubi_number"
),
array (
"tabLabel" => "tra_nam",
"value" => "$trade_name"
)
)
),
"email" => "$applicant_email",
"name" => "$applicant_name",
"roleName" => "Applicant"
)
),
"status" => "sent"
);
Is this possible?
EDIT: So I got it to work using loops to get my data in the request, but I'm running into an interesting problem. If I put one or two templates in the envelope, it sends fine. If I put more than two in, it duplicates the templates. Here is my code for the complicated loops:
$compTempArray = array();
$applicant_name = $this->input->post("applicant_name");
$applicant_email = $this->input->post("applicant_email");
$license_number = $this->input->post("license_number");
$ubi_number = $this->input->post("ubi_number");
$trade_name = $this->input->post("trade_name");
foreach($hello as $key => $value) {
if(sizeof($hello) > 1) {
for($i = 1; $i < sizeof($hello); $i++) {
$compTempArray[] = array("serverTemplates" => array(
array(
"sequence" => $i,
"templateId" => $value
)
),
"inlineTemplates" => array(
array(
"sequence" => $i,
"recipients" => array(
"signers" => array(
array(
"tabs" => array(
"textTabs" => array (
array ("tabLabel" => "lic_num", "value" => $license_number),
array ("tabLabel" => "ubi_num", "value" => $ubi_number),
array ("tabLabel" => "tra_nam", "value" => $trade_name)
)
),
"email" => "*********#*****.com",
"name" => $applicant_name,
"recipientId" => "1",
"roleName" => "Applicant"
),
)
)
)
));
}
$data = array("accountId" => $accountId,
"emailSubject" => "Hello World!",
"emailBlurb" => "This comes from PHP",
"compositeTemplates" => $compTempArray,
"status" => "sent");
} else {
$data = array("accountId" => $accountId,
"emailSubject" => "Hello World!",
"emailBlurb" => "This comes from PHP",
"templateId" => "$value",
"templateRoles" => array(
array(
"tabs" => array(
"textTabs" => array (
array ("tabLabel" => "lic_num", "value" => $license_number),
array ("tabLabel" => "ubi_num", "value" => $ubi_number),
array ("tabLabel" => "tra_nam", "value" => $trade_name)
)
),
"email" => "*********#*****.com",
"name" => $applicant_name,
"roleName" => "Applicant"
)
),
"status" => "sent");
}
}
Any idea why it would do this?
NEW EDIT: Update on this weirdness: one to two - one copy of each template, three - it doubles the amount of each template, four - it triples the amount, five - it quadruples the amount.
NEWEST EDIT: So as it turns out, it was the for loop that I was using to try and increment the sequence. I got rid of the loop and hardcoded the sequence to 1. That fixed it.
To apply multiple templates to a single envelope you'll need to use the compositeTemplates structure.
compositeTemplates can get complex very quickly but they do allow for great flexibility and functionality for your envelopes. The API documentation is the best place to read about compositeTemplates but as previously mentioned the April 2012 Templates Webinar is also a good resource. The third example provides a basic use of compositeTemplates in that it shows you how to combine two server templates into one single envelope. You can use that as a base for your JSON.
To apply 2 server templates to a single envelope it uses the following JSON:
{
"emailSubject": "DocuSign Templates Webinar - Example 3",
"emailBlurb": "Example #3 - Composite Templates",
"status": "sent",
"compositeTemplates": [
{
"serverTemplates": [
{
"sequence": "1",
"templateId": "55A80182-2E9F-435D-9B16-FD1E1C0F9D74"
}
],
"inlineTemplates": [
{
"sequence": "1",
"recipients": {
"signers": [
{
"email": "firstrecipient#gmail.com",
"name": "John Doe",
"recipientId": "1",
"roleName": "RoleOne"
}
]
}
}
]
},
{
"serverTemplates": [
{
"sequence": "2",
"templateId": "44D9E888-3D86-4186-8EE9-7071BC87A0DA"
}
],
"inlineTemplates": [
{
"sequence": "2",
"recipients": {
"signers": [
{
"email": "secondrecipient#gmail.com",
"name": "Jane Doe",
"recipientId": "1",
"roleName": "RoleOne"
}
]
}
}
]
}
]
}
Note that the sequence value for each template determines the order of template application to the envelope. So in other words, the sequence value determines the document order, but since the templates might have matching/conflicting info (in terms of template roles for instance) the sequence value might also affect the end result of the envelope.

PHP return array of matching KEY NAMES and there values

I'm having a terrible time trying to pull out some values out of an array. Here is a slimmed down version of the array.
$properties = array( array( PropertyID => 2845,
Address_1 => "1234 Any street",
MEDIA_IMAGE_00 => "23428.jpg",
MEDIA_IMAGE_TEXT_00 => "Front of House",
MEDIA_IMAGE_01 => "29872.jpg",
MEDIA_IMAGE_TEXT_01 => "Master Bedroom",
MEDIA_IMAGE_02 => "29834.jpg"
),
array( PropertyID => 2845,
Address_1 => "555 This street",
MEDIA_IMAGE_00 => "234234.jpg",
MEDIA_IMAGE_TEXT_00 => "Front of House",
MEDIA_IMAGE_01 => "298724.jpg",
MEDIA_IMAGE_TEXT_01 => "Second Bedroom",
MEDIA_IMAGE_02 => "298346.jpg"
),
array( PropertyID => 2845,
Address_1 => "333 Main street",
MEDIA_IMAGE_00 => "2342845.jpg",
MEDIA_IMAGE_TEXT_00 => "Lounge",
MEDIA_IMAGE_01 => "2987246.jpg",
MEDIA_IMAGE_TEXT_01 => "Front of House",
MEDIA_IMAGE_02 => "2983434.jpg"
),
);
There is a massive amount of data in each sub array I've trimmed it down for length...
I'm inserting this data into a MySQL database, however, I'm inserting the images into a separate table [PropertyID, Image, ImageText] because some properties may have more images than others.
So now that the background is out of the way.
How do I pull just the keys of the array that match and there info into another array? So that I would end up with an array from the above that would end up with something similar to:
$property_images = array( array( PropertyID => 2845,
IMAGE => "23428.jpg",
IMAGE_TEXT => "Front of House"),
array( PropertyID => 2845,
IMAGE => "29872.jpg",
IMAGE_TEXT => "Master Bedroom",
array( PropertyID => 2845,
MEDIA_IMAGE_02 => "29834.jpg"
IMAGE_TEXT => "Living Room"
I've tried sscanf to no avail and fiddle around with array_keys but haven't managed to figure out how to target the key names rather than the key values...
Thanks for your help in advance!
Edit:
foreach( $properties as $v ) {
foreach( $v as $k => $m ) {
if( strpos($k, 'MEDIA_IMAGE_TEXT_') !== FALSE ) {
$new_array[] = array('PropertyID' => $v['PropertyID'], 'IMAGE'=>$prev, 'IMAGE_TEXT'=>$m );
}
if( strpos($k, 'MEDIA_IMAGE_') !== FALSE ) {
$prev = $m; //var_dump($prev);
}
}
}

Categories