Sort the Multi Dimensional array in key sequence - php

Basically, I am building html form inputs that have dynamic inputs For example In below example if user want to increase the unit_type then user can add the new input from front end and send it to store
Note: If user will add the unit_type then all others keys will automatically added. Like if user try to increase the unit_type then unit_address and all other inputs increase accordingly.
Right Now I have the array like this
array:7 [
"unit_type" => array:2 [
0 => null
1 => null
]
"unit_address" => array:2 [
0 => null
1 => null
]
"unit_phone" => array:2 [
0 => null
1 => null
]
"fax" => array:2 [
0 => null
1 => null
]
"installed_capacity" => array:2 [
0 => null
1 => null
]
"production_capacity" => array:2 [
0 => null
1 => null
]
"unit_email" => array:2 [
0 => null
1 => null
]
]
Expected Result
[
[
//Here all keys contain the first values of all arrays
'unit_type'=>'first_value',
'unit_address'=>'first_value',
'unit_phone'=>'first_value',
'fax'=>'first_value',
'installed_capacity'=>'first_value',
'production_capacity'=>'first_value',
'unit_email'=>'first_value'
],
[
//Here all keys contain the second values of all arrays
'unit_type'=>'second_value',
'unit_address'=>'second_value',
'unit_phone'=>'second_value',
'fax'=>'second_value',
'installed_capacity'=>'second_value',
'production_capacity'=>'second_value',
'unit_email'=>'second_value'
]
]

Loop through the existing return data and build the new array like so:
$input_array = []; //your data received from the front end
$return_array = []; //structured data return
foreach($input_array as $field => $fieldData){
foreach ($fieldData as $key => $data){
$return_array[$key][$field] = $data;
}
}

Related

Filter Array based on if contains php

My aim here is to remove the whole object from the array if "record_type" is null. I should then only be left with data that has a record_type set in the array.
I've looked into the array filter not sure how I target the data within the array "record_type". My only other thought is to import to a database and then SQL query what I want then delete data I've had which is much more overkill.
<pre>
array:36 [▼
0 => array:3 [▼
"type" => "comment"
"line_index" => 0
"text_b64" => "OyBjUGFuZWwgZmlyc3Q6ODguMC4xMiAodXBkYXRlX3RpbWUpOjE2MTg1NDYxNDIgQ3BhbmVsOjpab25lRmlsZTo6VkVSU0lPTjoxLjMgaG9zdG5hbWU6cjExOC5sb24yLm15c2VjdXJlY2xvdWRob3N0LmNvbSBs ▶"
]
1 => array:3 [▼
"line_index" => 1
"text_b64" => "OyBab25lIGZpbGUgZm9yIG9ha3RyZWVkZW50YWxtb3J0aW1lci5jby51aw=="
"type" => "comment"
]
2 => array:3 [▼
"text_b64" => "JFRUTCAxNDQwMA=="
"line_index" => 2
"type" => "control"
]
3 => array:6 [▼
"line_index" => 3
"dname_b64" => "b2FrdHJlZWRlbnRhbG1vcnRpbWVyLmNvLnVrLg=="
"record_type" => "SOA"
"ttl" => 30
"type" => "record"
"data_b64" => array:7 [▶]
]
4 => array:6 [▼
"dname_b64" => "b2FrdHJlZWRlbnRhbG1vcnRpbWVyLmNvLnVrLg=="
"line_index" => 10
"record_type" => "NS"
"ttl" => 30
"type" => "record"
"data_b64" => array:1 [▶]
]
5 => array:6 [▼
"ttl" => 30
"dname_b64" => "b2FrdHJlZWRlbnRhbG1vcnRpbWVyLmNvLnVrLg=="
"line_index" => 11
"record_type" => "NS"
"data_b64" => array:1 [▶]
"type" => "record"
]
</pre>
Goal: only be left with data that has a 'record_type' set (not null) in the array
Solution: use array_filter() on your source array ($arr) and filter for records with 'record_type' != "NS" (assuming "NS" is what you refer to as null, or not set).
<?php
$result = array_filter(
$arr,
function (array $record) {
if (isset($record['record_type'])) {
return $record['record_type'] != "NS";
} return null;
}
);
working demo
EDIT
If you want to filter for only those records that are of a certain type, e.g. type 'record', following should help:
<?php
$result = array_filter(
$arr,
function (array $record) {
if ($record['type'] == 'record') {
return true;
} return false;
}
);
working demo
If your Goal is to filter array to remove any inner-array that hasn't a record_type, So use array_filter with a callback function fn to check that record_type exist with isset function.
array_filter($arr, fn($el)=>isset($el["record_type"]));

PHP array_slice or equivalent on array of arrays that are keyed by ID

I have a multi-dimensional array that is keyed by uuid's and need to slice/pop/unset an element by uuid (i.e., if I had a410463e-7fe2-4fba-8733-a812c0ee8c54 and wanted to remove that item by that uuid) so that the result is essentially the same minus the one item that was removed:
array:5 [
"5fc29794-9e08-4944-ba6d-4a5fcde5c88b" => array:3 [
"id" => "5fc29794-9e08-4944-ba6d-4a5fcde5c88b"
"name" => "fuga"
"value" => 0
]
"a410463e-7fe2-4fba-8733-a812c0ee8c54" => array:3 [
"id" => "a410463e-7fe2-4fba-8733-a812c0ee8c54"
"name" => "nihil"
"value" => 0
]
"c141d973-91fe-4227-8985-04bd0665f4a8" => array:3 [
"id" => "c141d973-91fe-4227-8985-04bd0665f4a8"
"name" => "eaque"
"value" => 0
]
"17030897-1aa9-487d-a4be-d574dd0c9d9b" => array:3 [
"id" => "17030897-1aa9-487d-a4be-d574dd0c9d9b"
"name" => "eveniet"
"value" => 3
]
"901d9f8f-573f-444f-8562-0cdf5888ba6e" => array:3 [
"id" => "901d9f8f-573f-444f-8562-0cdf5888ba6e"
"name" => "in"
"value" => 6
]
]
I know how to slice by index, but am having trouble finding resources on how this might be achieved. This is for a phpunit test. I've tried unset, but can't seem to store that in a variable or just call it in an assertion:
unset($array1[$id]);
unset($array2[$id]);
Does not persist the change.
$newUnchanged = unset($array1[$id]);
$oldUnchanged = unset($array2[$id]);
Throws syntax error, unexpected 'unset' error. Ultimately I want to assert that all of the unchanged items remained the same as prior to a single item being updated. I've also tried this ugly business which is removing a single item, but not the correct one:
$keyOne = array_search($id, array_keys($array1), true);
$oldUnchanged = array_slice($array1, $keyOne, null, true);
$keyTwo = array_search($id, array_keys($array2), true);
$newUnchanged = array_slice($array2, $keyTwo, null, true);
// Shows that the item that I wanted to slice still exists in both arrays
dd($id, $oldUnchanged, $newUnchanged);
// ^ Causes this test to fail
$this->assertEquals($oldUnchanged, $newUnchaged);
I figured out I have to clone the arrays before I can unset them
$oldUnchanged = $array1;
unset($oldUnchanged[$id]);
$newUnchanged = $array2;
unset($newUnchanged[$id]);

sending 2 values in 1 array in laravel

I have 2 arrays of data and i need to join the results of this two arrays.
I can use array_combine but there is 2 issues:
my first array is coming from check boxes and send data of checked check-box only
my second array coming from input fields and sending all my inputs
the issue here is my first array have (for example) 3 values while my second array has 7 values
This kind of combine will return the error of:
array_combine(): Both parameters should have an equal number of elements
Data
this is my dd results:
"optionID" => array:3 [▼ //check-box values
0 => "1"
1 => "2"
2 => "11"
]
"optionPRICE" => array:8 [▼ //input values
0 => "98"
1 => null
2 => null
3 => null
4 => null
5 => null
6 => null
7 => null
]
what I want
what i'm looking for is to get values of my inputs from checked check-boxes and not the rest of them.
example i check data 1,2,3 i get value 1,2,3 whether is null of filled and not getting 4,5,6,7 as you see in my dd data above.
code
this is what my html looks like
<tr>
<td class="text-center" width="50">
<label class="switch switch-small">
<input type="checkbox" name="optionID[]" value="11"> //checkbox arrays
<span></span>
</label>
</td>
<td>
CDN
</td>
<td class="text-center">
//input arrays
<input class="form-control" type="number" name="optionPRICE[]">
</td>
</tr>
I'm looking to get my data in any of this 2 kinds
this
"optionID" => array:3 [▼ //check-box values
0 => "1"
1 => "2"
2 => "11"
]
"optionPRICE" => array:8 [▼ //input values
0 => "98"
1 => null
2 => null
]
or this
"optionID" => array:3 [▼
"array" => array:2 [
0 => "1",
1 => "98",
],
"array" => array:2 [
0 => "2",
1 => null,
],
"array" => array:2[
0 => "11",
1 => null,
],
]
any idea?
Update
Based on answers if i use mapping function to return data as my second sample desire it would be confusing to naming data and relate them to my model column, so I share my model names and explain which data has to go in which column in order to be save in right place.
Schema
Schema::create('product_options', function (Blueprint $table) {
$table->increments('id');
$table->integer('product_id')->nullable()->unsigned();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->integer('option_id')->nullable()->unsigned();
$table->foreign('option_id')->references('id')->on('options')->onDelete('cascade');
$table->string('price')->nullable();
});
optionID data has to go in option_id column and optionPRICE data to price column.
For product_id column as this data will save after my product is saved so i just simply get the id by $product->id that column is out of issue.
Update 2
I tried many different conditions to see how data will send here is a serious issue based on the answers I've got.
When I pass data from 1 selected option, e.g. select colors and fill some data to send it works as it supposed to.
But when I select second option e.g. select sizes for this option only checkbox id's will send and data of optionPRICE will not send, this issue applies for next options as well (option 3,4,5,6....)
Here is a sample:
array:3 [▼
0 => array:3 [▼ //this is from colors (included price)
"option_id" => "4"
"price" => "768"
"product_id" => 50
]
1 => array:3 [▼ //this is also from colors (included price)
"option_id" => "5"
"price" => "5467"
"product_id" => 50
]
2 => array:3 [▼ //this one is from sizes (not included price, while i filled the price!)
"option_id" => "10"
"price" => null
"product_id" => 50
]
]
Update 3
OK, I worked around and tested some ways to fix the issue, here is what i figured and what i achieved:
Th issue of returning my third price null (update 2) was because we were counting prices array and not inputs of checked check-boxes. that was why 3rd option was null while my actual filled option was 11. (refer to my data dd top of my question)
I can get now actual filled optionPRICE fields and not by counting them but with the values.
Here is what I did so far:
$options = $request->input('optionID');
$prices = $request->input('optionPRICE');
$collection = array_filter($prices, function($value) {
return !is_null($value);
});
$toInsert = array_merge([$options, $collection]);
dd($toInsert);
code above returns this:
array:2 [▼
0 => array:3 [▼
0 => "4"
1 => "5"
2 => "10"
]
1 => array:3 [▼
0 => "768"
1 => "5467"
5 => "5465496"
]
]
but if i fill price for only 2 of my check-boxes will be like:
array:2 [▼
0 => array:3 [▼
0 => "4"
1 => "5"
2 => "10"
]
1 => array:2 [▼
0 => "768"
1 => "5467"
]
]
This is good to get only input data without needs of counting array elements just pure values.
After this I need to join this 2 array of mine and return null in case of second case happens (3 check-box, 2 price).
Any help on that?
This should get you your first desired solution using array_slice:
// Get the length of the smaller array
$minLength = min(count($arr1), count($arr2));
$result = [
'optionID' => array_slice($arr1, 0, $minLength),
'optionPRICE' => array_slice($arr2, 0, $minLength),
];
For your second desired solution, you could try something like this (if I understood correctly):
$checkboxes = [1, 2, 11];
$inputs = [98, null, null];
$result = collect($checkboxes)->map(function ($item, $key) use($inputs) {
return [$item, $inputs[$key] ?? null];
})->toArray();
dd($result);
// array:3 [
// 0 => array:2 [
// 0 => 1
// 1 => 98
// ]
// 1 => array:2 [
// 0 => 2
// 1 => null
// ]
// 2 => array:2 [
// 0 => 11
// 1 => null
// ]
// ]

Updating array keys inside of an array

My goal is to be able to update a key value inside of an array inside of an array and I'm don't know if I'm using the right php array function.
BEFORE:
array:2 [
"week_number" => 1
"games" => array:1 [
0 => array:3 [
"game_number" => 1
"umpires" => []
"teams" => []
]
]
]
AFTER:
array:2 [
"week_number" => 1
"games" => array:1 [
0 => array:3 [
"game_number" => 1
"umpires" => []
"teams" => [1,2]
]
]
]
Test Class:
private function validParams($overrides = [])
{
return array_merge_recursive([
'week_number' => 1,
'games' => [[
'game_number' => 1,
'umpires' => [],
'teams' => [],
]]
], $overrides);
}
$response = $this->actingAs($this->authorizedUser)
->post(route('games.store', ['week' => $this->week->id]), $this->validParams([
'games' => [][
[
'teams' => [1,2]
]
]
]));
If you want to update the keys... typing $array['new_key'] = $array['old_key'] will duplicate the value with 2 sets of keys.
You have a few options here. Either you create a new array and just set your desired keys or work with array_keys and array_values and mix them up... your choice
http://php.net/manual/en/ref.array.php
See the list above, there are a lot of array functions you can use... see the two above and array_map... there is virtually a great number of ways you can do this. See how your problem is best handled after reviewing the documentation.
Good luck!
This is the moment where you need unset(): Adding a value with a different key will not update or overwrite the old value but simply add another key-value pair.
Hence, add the new value fist, then unset the old one. We can use To array_walk to itterate over the array:
array_walk($array, function (& $item) {
$item['new_key'] = $item['old_key'];
unset($item['old_key']);
});
Take note of the & reference operator in the lambda function: it ensures we are working on the original array and not a copy of it.
I found this as a solution.
private function validParams($overrides = [])
{
return array_replace_recursive([
'week_number' => 1,
'games' => [
0 => [
'game_number' => 1,
'umpires' => [],
'teams' => [],
]
]
], $overrides);
}
->post(route('games.store', ['week' => $this->week->id]), $this->validParams([
'games' => [
0 => [
'teams' => [1,2]
]
]
]));

Laravel: Create Array

I have a multi questions with multi answers on the same page and I want to display all data so I create a new array to pass it to the view the new array will contain all question with the answers if the question has no answer then the value will be null and if it has answer the value should be as the value that stored on the database.the problem that the new array stores the last question data only.
$exist_data = RatingDatum::where($check_data)->get(); /*get all the previous data I have to answers here for the two questions only the third question have no answer */
$datum = array();
] foreach ($question_angles as $index => $angle) {
if (!empty($exist_data)){
foreach ($exist_data as $row) {
if ( $row['question_angle_id'] == $angle->id) {
$datum[$index]['question_angle_id'] = $angle->id;
$datum[$index]['answer_id'] = $row['answer_id'];
$datum[$index]['comment'] = $row['comment'];
$datum[$index]['reference'] = $row['reference'];
} else {
$datum[$index]['question_angle_id'] = $row['question_angle_id'];
$datum[$index]['answer_id'] = $row['answer_id'];
$datum[$index]['comment'] = null;
$datum[$index]['reference'] = null;
}
}
}
}
dd($datum);
array:3 [▼
0 => array:4 [▼
"question_angle_id" => 2
"customize_question_id" => null
"comment" => null
"reference" => null
]
1 => array:4 [▼
"question_angle_id" => 2
"customize_question_id" => 7666
"comment" => "test"
"reference" => "test"
]
2 => array:4 [▼
"question_angle_id" => 2
"customize_question_id" => null
"comment" => null
"reference" => null
]
]
the data should look like this the first two question have answers but the last question not have answer so the values is null:
array:3 [▼
0 => array:4 [▼
"question_angle_id" => 1
"answer_id" =>2
"comment" => null
"reference" => null
]
1 => array:4 [▼
"question_angle_id" => 2
"answer_id" => 6
"comment" => "test"
"reference" => "test"
]
2 => array:4 [▼
"question_angle_id" => 3
"answer_id" => null
"comment" => null
"reference" => null
]
]

Categories