I have an array that can contain multidimensional elements. For populating checkboxes from database in the edit-form, I need to check for specific key-value pairs from this array.
The array ($areastools) can look like this:
array:9 [▼
15 => array:2 [▼
0 => 1
1 => 4
16 => 4
45 => array:2 [▶]
47 => 4
50 => array:2 [▶]
51 => 4
]
The first key is the specific area id ($area->pivot->id), and the values are the tool ids ($tool->id).
Currently I have this check, where the checkbox is checked if
(array_key_exists($area->pivot->id, $areastools) &&
($areastools[$area->pivot->id] == $tool->id))
This works for all elements of the array that are not multidimensional. The correct checkboxes are then checked in the edit-form.
But when two tools are added to the same area, the checkboxes for none of these tools are checked, as the condition does not check the values correct if an area has many tools.
I have been searching and trying, but can not find out how to do this. Can anyone please help me?
I'd make a little function. Not very elegant, but it works.
function areaTools($areaTools, $areaId, $toolId) {
if(array_key_exists($areaId, $areaTools) {
if(is_array($areaTools[$areaId]) {
foreach($areaTools[$areaId] as $tool) {
if($tool == $toolId;) {
return true;
}
}
} else {
return $areaTools[$areaId] == $toolId;
}
}
}
if you only want to know if a certain key-value pair is found, use array_walk_recursive()
$found=0;
function find_key_value($v, $k)
{
global $area,$tool,$found;
if (($k==$area->pivot->id)&&($v==$tool->id))
$found=1;
}
array_walk_recursive($areastools, 'find_key_value');
Related
I need to compare arrays, if element from first or second array has duplicates in another one I need to exclude it. I know it sound simply and I'm sure it is but i cant handle with that problem :(
So i have first array like this:
Array:3 [
6 => blog/something
4 => blog/somethingElse
5 => blog/else
]
Second array almost identical:
Array:3 [
1 => /blog
2 => /comments
3 => /posts
]
And the last array:
(integer on the left is id of elements in second array, in this example
comments and posts)
Array:2 [
0 => array:2 [
'page_id' => 2
'value' => noindex
]
1 => array:2 [
'page_id' => 3
'value' => noindex
]
]
So if I have element in array first or second which exist in array thrid too AND have value = noindex i need to exclude it.
I have tried do this by foreach recursive, by array_walk_recursive but I still can't get satisfied result
First get all the indices you need to exclude and then exclude them:
$excludeIndices = array_column(array_filter($array3, function ($entry) {
return $entry['value'] === 'noindex';
}), 'page_id');
$keepArray1 = array_diff_key($array1, array_flip($excludeIndices));
$keepArray2 = array_diff_key($array2, array_flip($excludeIndices));
Sandbox
You can filter using the first two arrays directly.
$result = array_filter($last, function($item) use ($first, $second) {
return !($item['value'] == 'noindex' &&
(isset($first[$item['page_id']]) || isset($second[$item['page_id']]))
);
});
I'm having a looping mind-breaking issue which I can't seem to solve myself. Currently working on saving a form input in a webshop. The data:
"personalisation" => array:3 [▼
0 => "embroidery"
1 => "printing"
2 => "embroidery"
]
"repeat" => array:2 [▼
0 => "true"
1 => "true"
]
"selectedColors" => array:1 [▼
0 => "3"
]
The problem which I have here: I need to loop through the personalisation array to add to my DB. With the embroidery, the repeat value is linked and for the printing the selectedColors is linked. How can I loop through the personlisation array and match the values from the other array?
I really wouldn't recommend designing forms like this, you're basically just sending a jumbled mess to your backend with no association.
You can "correct" the association by filtering the personalisation array and reindexing it so the keys match the other arrays.
$embroderies = array_values(array_filter($array['personalisation'], function($item) {
return $item === 'embroidery';
}));
foreach($emborderies as $key => $value) {
// get value from $array['repeat'][$key];
}
I can't think of any other way than to use a helper array for example.
It could be
array('embroidery' => 'repeat', 'printing' => 'selectedColors')
And you start looping through personalization, depending on the value you use it as a key in the helper array, then finally get the wanted value from the array.
1st iteration: 0/embroidery -> embroidery/repeat -> repeat/true
2nd iteration: 1/printing -> printing/selectedColors -> selectedColors/
...
this might be a bit of a generic title, but I will try to explain my problem the best way I can.
So I've got this type of associative array:
Array
(
[ICO_0] => checked
[Investment_0] => checked
[Investment_1] => checked
[Marketing_1] => checked
)
What I would like to do is to divide it into multiple arrays based on numbers that are attached to the end of the key ( 0, 1 ... ). Basically I'd like to get a new array to look like this:
Array(
Array(
[ICO_0] => checked
[Investment_0] => checked
[Token Sale_0] => checked
),
Array(
[Investment_1] => checked
[Marketing_1] => checked
)
)
I've tried approaching this issue with array_chunk but couldn't get it to work.
I'll need this output since I want to sort those nested arrays based on items that they're holding, starting from the highest number of items.
Thanks!
You can use several different methods to accomplish this. One method is to loop through and explode the key name if you know there will always be an underscore, grab the last number, and use that as your index:
$results = [
"ICO_0" => "checked",
"Investment_0" => "checked",
"Investment_1" => "checked",
"Marketing_1" => "checked",
"Investment_2" => "checked",
"Marketing_2" => "checked"
];
foreach($results as $key => $value){
$ex = explode('_', $key);
$new_result[end($ex)][$key] = $value;
}
Which for me returns the following:
array:3 [▼
0 => array:2 [▼
"ICO_0" => "checked"
"Investment_0" => "checked"
]
1 => array:2 [▼
"Investment_1" => "checked"
"Marketing_1" => "checked"
]
2 => array:2 [▼
"Investment_2" => "checked"
"Marketing_2" => "checked"
]
]
I'm trying to create a recursive method to fill an array with each new item found.
function getUserUbigeoString($ubigeo_id){
$ubigeoRepository = new \App\Repositories\UbigeoRepository();
$ubigeos = array();
$ubigeo = $ubigeoRepository->getUbigeo($ubigeo_id);
if(!empty($ubigeo)){
if($ubigeo->ubigeo_id == null){
$ubigeos[] = $ubigeo->name;
}
$ubigeos[] = getUserUbigeoString($ubigeo->ubigeo_id);
}
return $ubigeos;
}
The objective of the code is to get an array fill with all the name of the ubigeos.
0 => ubigeo1
1 => ubigeo2
2 => ubigeo3
etc...
As of right now, i have tried placing the return many different locations, but the closest result i have gotten was:
array:1 [▼
0 => array:1 [▼
0 => array:2 [▼
0 => "Port Dusty"
1 => []
]
]
]
==========EDIT============
Structure of database ubigeos:
id name level ubigeo_id
----------------------------
3 ubigeo1 1 null
37 ubigeo2 2 3
55 ubigeo3 3 37
the output would be a simple array like so, which then i could implode into a comma separated string:
array:1 [
0 => 'ubigeo1'
1 => 'ubigeo2'
2 => 'ubigeo3'
]
so assuming that you really want to call this with function with an Ubigeo instance and only get the names from that and from the parent Ubigeo instances (i.e. calling the function with id 55 initially to get the result array), you can try something like this (I didn't want to modify your function call parameters - normally I would include the array as a function parameter instead of instantiating new one in each recursion step):
function getUserUbigeoString($ubigeo_id)
{
$ubigeoRepository = new \App\Repositories\UbigeoRepository();
$ubigeos = array();
$ubigeo = $ubigeoRepository->getUbigeo($ubigeo_id);
if(!empty($ubigeo))
{
if($ubigeo->ubigeo_id != null) {
$ubigeos = getUserUbigeoString($ubigeo->ubigeo_id);
}
$ubigeos[] = $ubigeo->name;
}
return $ubigeos;
}
Use Can do it with lists method in laravel
Ex :
$ubigeoRepository->lists('ubigeo_id','id')->all();
I have a family tree app in laravel, and I want to be able to show an outline view (start with a family from long ago, show its kids, show those kids' families, those families' kids, etc).
So I made this recursive get_descendants function:
public static function get_descendants(Family $family, $results_array, $counter)
{
// start new round with a different temp array, to keep track
$counter++;
$this_array = "array_$counter";
$$this_array = [];
array_push ($$this_array, $family->caption);
$kids = FamilyController::get_kids_of_family($family);
// if family has no kids, return 0;
if (!count($kids))
{
return 0;
}
else // add kids and check for their families
{
foreach ($kids as $kid) {
array_push ($$this_array, $kid->firstname);
// get families made by kid- for each one, call get_descendants
$families_made = FamilyController::get_families_person_made($kid);
foreach ($families_made as $new_family) {
array_push($$this_array, self::get_descendants($new_family, $$this_array, $counter));
}
};
// we've gone through the kids, add this round's array to the general results array
array_push ($results_array, $$this_array);
}
return $results_array;
}
I've confirmed with print statements that the looping through is correct, but there's a problem with the way I'm saving the results. I want to get something like this, where the top family shows once, with children and their families nested:
array:1 [▼
0 => array:4 [▼
0 => "Padme & Anakin"
1 => "Leia"
2 => array:3 [▼
0 => "Leia & Han"
1 => "Kylo Ren"
]
3 => "Luke"
]
]
but I'm getting this (with an extra repeat in the middle):
array:1 [▼
0 => array:4 [▼
0 => "Padme & Anakin"
1 => "Leia"
2 => array:3 [▼
0 => "Padme & Anakin"
1 => "Leia"
2 => array:3 [▼
0 => "Leia & Han"
1 => "Kylo Ren"
]
]
3 => "Luke"
]
]
Can anyone see where my mistake is?
Update: it turns out that it works if I get rid of that final results_array and just use the dynamic one the whole way, like this:
public static function get_descendants(Family $family, $results_array, $counter)
{
// start new round with a different temp array, to keep track
$counter++;
$this_array = "array_$counter";
$$this_array = [];
array_push ($$this_array, $family->caption);
$kids = FamilyController::get_kids_of_family($family);
// if family has no kids, return 0;
if (!count($kids))
{
return 0;
}
else // add kids and check for their families
{
foreach ($kids as $kid) {
array_push ($$this_array, $kid->first);
// get families made by kid- for each one, call get_descendants
$families_made = FamilyController::get_families_person_made($kid);
if (count($families_made))
{
foreach ($families_made as $new_family) {
array_push($$this_array, self::get_descendants($new_family, $$this_array, $counter));
}
}
};
}
return $$this_array;
}
Looks unnecessarily complex, with dynamic arrays, and you keep populating the same array, so that's why Luke appears in the wrong place.
A cleaner solution might be to be very specific about where people are in the array rather than using a dynamic array name. Just a suggestion -
public static function getDescendants(Family $family)
{
$family = [];
$family['name'] = $family->caption;
if ($kids = static::getKidsOfFamily($family)) {
foreach ($kids as $kid) {
$family['children'][] = $kid->firstname;
$subfamilies = static::getFamiliesPersonMade($kid);
foreach ($subfamilies as $subfamily) {
$family['subfamilies'][] = static::getDescendants($subfamily);
}
};
}
return $family;
}
would produce something like
array [
"name" => "Padme & Anakin"
"children" => array [
"Leia",
"Luke"
],
"subfamilies" => array [
array [
"name" => "Leia & Han"
"children" => array [
"Kylo Re"
]
]
]
]