Get perfect match array using different variables in php - php

I have three variables
$region ='APJ';
$sub_region = 'India';
$country = 'India'
and i have multiple arrays like
Array
(
[0] => Array
(
[region] => APJ
[subregion] => India
[country] =>
)
[1] => Array
(
[region] => APJ
[subregion] =>china
[country] =>
)
[2] => Array
(
[region] => WW
[subregion] =>france
[country] => France
)
[3] => Array
(
[region] => EMEA
[subregion] =>mema
[country] => France
)
)
I need to find the perfect match array for using these three variables.
In the above example we have 4 arrays with different values.
First array matching region and sub region level also.
Second array only region level is matching.
All other are not matching even one value also.
So i choose the first array as result.
So using php how i find the perfect matching array in this kind of scenario?

Concept: "Ranking"
Create a comparison array with the same structure as the definiton arrays
Loop through all definitions and …
Count matches (rank) for each definition (loop through comparison array).
Store the mathing level (rank) in the definition array itself (additional key: _level).
Keep the index of the highest ranked definition array.
Result: The index of the definition array with the highest rank ($highestlevel).(= The first definition with the highest ranking)
Code
<?php
$defs = array ( // Definitions
array(
'region' => 'APJ', // to be compared
'country' => '', // to be compared
'typeofrec' => 1,
'TotalAllocations' => 0,
'TotalTransfersOut' => 0,
'subregion' => 'India', // to be compared
'TotalTransfersIn' => 0,
'StartOfAllocation' => 0,
'ApprovedActivities' => 10,
'AvailableBalance' => -10,
'Exposure' => 0,
),
array(
'region' => 'APJ',
'subregion' => 'china ',
'country' => '',
),
array(
'region' => 'WW',
'subregion' => 'france',
'country' => 'France',
),
array(
'region' => 'EMEA',
'subregion' => 'mema',
'country' => 'France',
),
);
// Comparison array
// Instead of ...
// $region ='APJ';
// $sub_region = 'India';
// $country = 'India'
$testarray = array( // Comparison array
'region' => 'APJ',
'subregion' => 'India',
'country' => 'India',
);
// --------------------------------------------------------------------------
$highestlevel = 0; // Index of highest ranked definition
foreach ($defs as $ix => $def) { // Loop through all definitions
$defs[$ix]['_level'] = 0; // Add new entry to array
foreach($testarray as $key => $value) { // Loop throug comparison values
// Increment ranking level if matched
if (trim($def[$key]) == trim($value)) $defs[$ix]['_level']++;
// Variant "case ignored":
// if (strtolower(trim($def[$key])) == strtolower(trim($value))) $defs[$ix]['_level']++;
}
// Keep index of highest ranked
if (!isset($defs[$highestlevel]['_level']) || $defs[$highestlevel]['_level'] < $defs[$ix]['_level']) $highestlevel = $ix;
}
// --------------------------------------------------------------------------
// Display the result
echo '<h3>Result</h3><pre>'; var_dump($defs[$highestlevel]); echo '</pre>';
Main advantages:
Flexibility:The code only assumes array structures. Neither key names nor element types nor fixed array lengths are assumed. So it Works with different values and array lengths.
Compactness.
Result
array(12) {
["region"]=> string(3) "APJ"
["country"]=> string(0) ""
["typeofrec"]=> int(1)
["TotalAllocations"]=> int(0)
["TotalTransfersOut"]=> int(0)
["subregion"]=> string(5) "India"
["TotalTransfersIn"]=> int(0)
["StartOfAllocation"]=> int(0)
["ApprovedActivities"]=> int(10)
["AvailableBalance"]=> int(-10)
["Exposure"]=> int(0)
["_level"]=> int(2)
}

Please try this
$region ='APJ';
$sub_region = 'India';
$country = 'India'
$ret ="";
foreach($yourarr as $key=> $subArr){
/* If region,subregion & country values matches given data return mached array value */
if($subArr['region'] == $region && $subArr['subregion'] == $sub_region && $subArr['country'] == $country){
$matArr = $arr[$key];
break;
}
/* Else If any of the 2 matches with given data return the specific array value */
else if(
($subArr['region'] == $region && $subArr['subregion']) ||
($subArr['subregion'] == $sub_region && $subArr['country'] == $country ) ||
($subArr['region'] == $region && $subArr['country'] == $country )
){
$matArr = $arr[$key];
break;
}
/* Else any of the value matches return the specific array value*/
else if($subArr['region'] == $region || $subArr['subregion'] == $sub_region || $subArr['country'] == $country){
$matArr = $arr[$key];
break;
}
}
echo "Matching Array Is:";
print_r($matArr);

for($i=0;$i<count($arr);$i++)
{
if(($arr[$i]['region']==$region) && ($arr[$i]['subregion']==$sub_region) && ($arr[$i]['country']==$country) )
{
echo "3"."index".$i;
}
elseif( (($arr[$i]['region']==$region) && ($arr[$i]['subregion']==$sub_region)) || ( ($arr[$i]['subregion']==$sub_region) && ($arr[$i]['country']==$country) ) || ( ($arr[$i]['region']==$region) && ($arr[$i]['country']==$country) ) )
{
echo "2"."index".$i;
}
elseif(($arr[$i]['region']==$region) || ($arr[$i]['subregion']==$sub_region) || ($arr[$i]['country']==$country))
{
echo "1"."index".$i;
}
else
{
echo "not found";
}
}
$arr is your array.
in above code it first search for perfect match means all case are matche
in second case it match for two
in third case it match for atleast one
3 is the top priority and get the index value

Related

Efficient way of searching an index with 2 criterias on a multidimensional array in php

I need to find the index of a multidimensional array given two values, one of the values is repeated several times since it is a list of states and cities, here's an example
array(
99773000 => array('State' => 'ANTIOQUIA', 'City' => 'CUMARIBO'),
99624000 => array('State' => 'ANTIOQUIA', 'City' => 'SANTA ROSALIA'),
99524000 => array('State' => 'VICHADA', 'City' => 'LA PRIMAVERA'),
99001000 => array('State' => 'VICHADA', 'City' => 'PUERTO CARREÑO'),
.....
xxxxxxxx => array('State') => etc......
);
Now, I receive in the function a state and a city and I need to return the index, this is how Im doing it right now:
foreach ( $array as $index => $state_and_city ) {
$current_state = $state_and_city['State'];
$current_city = $state_and_city['City'];
if( $current_state == $state && $current_city == $city) {
return $index;
}
}
return '';
I would like to know if there's a more efficient approach of doing it?
Here you just need to get the keys from the inner array and that can be achieved by array_search function.
foreach ($array as $index => $state_and_city ) {
$current_state = $state_and_city['State'];
$current_city = $state_and_city['City'];
$state_key = array_search($current_state,$index);
$city_key = array_search($current_city,$index);
if($state_key == $state && $city_key == $city) {
return $index;
}
}
return '';

Print next array after matching array

I have an array of arrays that contain array key with the value, here the example :
$text = [
[
'Hotel' => 'N',
'Jayakarta' => 'NE',
'Jaya' => 'NE',
'sangat' => 'ADV',
'nyaman' => 'ADJ',
'ditempati' => 'V.'
]
,
[
'Andi' => 'NOB',
'menginap' => 'V',
'di' => 'PREP',
'Hotel' => 'N',
'Neo' => 'NE',
'Malioboro => 'NE',
'selama' => 'N',
'satu' => 'NUM',
'minggu' => 'N.'
]
];
And I have array prefix that contain :
$prefix = [ [0] => Hotel [1] => Hostel [2] => Losmen [3] => Motel [4] => Penginapan [5] => Pesanggrahan [6] => Pondok [7] => Wisma ]
If $prefix elements are in $text array then I will check next array value of text. If array value is N or NE then I will make an output from prefix text until the end of array that contain value N or NE.
Here's what I am doing for the moment:
foreach($text as $index => $tok){
foreach ($tok as $tokkey => $tokvalue) {
if(in_array($tokkey, $prefix)){
echo $tokkey;
$next = next($tok);
if($tokvalue == "N" or $tokvalue == "NE"){
echo key($tok);
}
}
}
}
The output I got :
Hotel Jayakarta, Hotel menginap
The expected output should be:
- Hotel Jayakarta Jaya
- Hotel Neo Malioboro selama
Any help is much appreciated, Thank you.
Below are the steps I followed to get the desired out put.
1) If tokkey present in prefix array, call a function.
2) Create a new array starting from the element which matches with prefix array.
3) Loop the new array and check for next value to be either 'N' or 'NE'
4) Display those keys from array.
foreach($text as $index => $tok){
foreach ($tok as $tokkey => $tokvalue) {
if(in_array($tokkey, $prefix)){
getKeys($tokkey,$tok);
echo "<br/>";
}
}
}
function getKeys($tokkey,$tok){
$flag = 0;
echo $tokkey.' ';
foreach($tok as $k=>$v){
if($k==$tokkey){
$flag = 1;
}
if($flag){
$new_array[$k]=$v;
}
}
foreach($new_array as $k=>$v){
$ff = next($new_array);
if(($ff == 'NE' || $ff == 'N')){
echo key($new_array).' ';
}
}
}
Out Put:
Hotel Jayakarta Jaya Hotel Neo Malioboro selama
http://sandbox.onlinephpfunctions.com/code/2777d3ab3d34c941c23886d42e537cde7fff2351
From what I understand from your text, you need to replace your if() that only runs once, for a while() that runs while the next() string is NE or N.
foreach($text as $index => $tok){
foreach ($tok as $tokkey => $tokvalue) {
if(in_array($tokkey, $prefix)){
echo $tokkey;
next($tok);
while($tokvalue == "N" || $tokvalue == "NE")
{ echo key($tok);
next($tok);
$tokvalue = current($tok);
}
}
}
echo "\n";
}
}

How to group an array into subarrays using its keys?

I am looking to group an array into subarrays based on its keys.
Sample Array
Array
(
[0] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 1
[b_name] => B1
[c_id] => 1
[c_name] => C1
)
[1] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 1
[b_name] => B1
[c_id] => 2
[c_name] => C2
)
[2] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 2
[b_name] => B2
[c_id] => 3
[c_name] => C3
)
[3] => Array
(
[a_id] => 2
[a_name] => A2
[b_id] => 3
[b_name] => B3
[c_id] => 4
[c_name] => C4
)
)
I need this sample array to be converted into a JSON array of the following format:
Expected Output
[{
"a_id": 1,
"a_name": "A1",
"b_list": [{
"b_id": 1,
"b_name": "B1",
"c_list": [{
"c_id": 1,
"c_name": "C1"
}, {
"c_id": 2,
"c_name": "C2"
}]
}, {
"b_id": 2,
"b_name": "B2",
"c_list": [{
"c_id": 3,
"c_name": "C3"
}]
}]
}, {
"a_id": 2,
"a_name": "A2",
"b_list": [{
"b_id": 3,
"b_name": "B3",
"c_list": [{
"c_id": 4,
"c_name": "C4"
}]
}]
}]
I was able to group by a key using the code below.
$array = array(
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "1","c_name" => "C1"),
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "2","c_name" => "C2"),
array("a_id" => "1","a_name" => "A1","b_id" => "2","b_name" => "B2","c_id" => "3","c_name" => "C3"),
array("a_id" => "2","a_name" => "A2","b_id" => "3","b_name" => "B3","c_id" => "4","c_name" => "C4")
);
$return = array();
foreach($array as $val) {
$return[$val["a_id"]][] = $val;
}
print_r($return);
But my actual scenario involves grouping into sub arrays didn't worked.
Looking forward to see if there is an optimized way or useful function to get into my expected JSON response.
Note: I am looking into a generalized use case here . For example : a_list as countries,b_list as states and c_list as cities.
Man that is very specific use case for arrays. Well here is your solution.
$array = <YOUR SAMPLE ARRAY>
$output = [];
/*
* Nesting array based on a_id, b_id
*/
foreach ($array as $item) {
$aid = $item['a_id'];
$bid = $item['b_id'];
$cid = $item['c_id'];
if(!isset($output[$aid])){
$output[$aid] = [
'a_id' => $item['a_id'],
'a_name' => $item['a_name'],
'b_list' => [
$bid => [
'b_id' => $item['b_id'],
'b_name' => $item['b_name'],
'c_list' => [
$cid = [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
]
]
]
]
];
} else if (!isset($output[$aid]['b_list'][$bid])){
$output[$aid]['b_list'][$bid] = [
'b_id' => $item['b_id'],
'b_name' => $item['b_name'],
'c_list' => [
$cid => [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
]
]
];
} else if(!isset($output[$aid]['b_list'][$bid]['c_list'][$cid])) {
$output[$aid]['b_list'][$bid]['c_list'][$cid] = [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
];
} else {
// Do/Dont overrider
}
}
/*
* Removing the associativity from the b_list and c_list
*/
function indexed($input){
$output = [];
foreach ($input as $key => $item) {
if(is_array($item)){
if($key == 'b_list' || $key == 'c_list'){
$output[$key] = indexed($item);
} else {
$output[] = indexed($item);
}
} else {
$output[$key] = $item;
}
}
return $output;
}
$indexed = indexed($output);
print_r(json_encode($indexed, 128));
Interesting requirement there.
Here is my generalized solution that is also extendable.
function transform($array, $group=[
['a_id','a_name','b_list'],
['b_id','b_name','c_list'],
['c_id','c_name'],
]){
foreach($array as $a){
$r = &$result;
foreach($group as $g){
$x = &$r[$a[$g[0]]];
$x[$g[0]] = $a[$g[0]];
$x[$g[1]] = $a[$g[1]];
if(isset($g[2])) $r = &$x[$g[2]]; else break;
}
}
return transformResult($result);
}
function transformResult($result){
foreach($result as &$a)
foreach($a as &$b)
if(is_array($b)) $b = transformResult($b);
return array_values($result);
}
To extend this solution, all you have to do is modify the $group parameter,
either directly in the function declaration or by passing an appropriate value as the 2nd parameter.
Usage example:
echo json_encode(transform($array), JSON_PRETTY_PRINT);
This will return the same output assuming the same $array input in your example.
Now here is the code that works best in the given situation. I have created a similar situation and then explained the solution in detail.
Situation
The Order Form is multipage depending on the number of days served based on the package selected. Details of each package are stored in the database with the following fields:
package_id (Unique Field)
package_name (Name of the Package, e.g. Package A)
servings_count (Total Servings in a Day)
days_served (Number of Days Served in a Month)
In order to carry forward the selection of meals for each day and serving of that day to store as an Order in the database, I required a Multidimensional Array of PHP that can be defined/populated dynamically.
Expected output is something like:
Array
(
[Day 1] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
[Day 2] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
This above array has been created 100% dynamically based on the explained structure and number of servings and days. Below is the code with some explanation.
First, we have to declare two PHP Arrays.
$total_meals_array = []; //Primary, Multidimension Array
$meals_selected_array = []; //Meals Details Array to be used as primary array's key value.
After doing this, run MySQL query to read packages from the database. Now based on the result, do the following:
$total_meals_array = []; //Primary, Multidimension Array
$meals_selected_array = []; //Meals Details Array to be used as primary array's key value.
if( $num_row_packages >= 1 ) {
while($row_packages = mysqli_fetch_array ($result_packages)) {
$package_id = $row_packages['package_id'];
$package_name = $row_packages['package_name'];
$servings_count = $row_packages['servings_count'];
$days_served = $row_packages['days_served'];
//this for loop is to repeat the code inside `$days_served` number of times. This will be defining our primary and main Multidimensional Array `$total_meals_array`.
for ($y = 1; $y <= $days_served; $y++) {
//once inside the code, now is the time to define/populate our secondary array that will be used as primary array's key value. `$i`, which is the meal count of each day, will be added to the key name to make it easier to read it later. This will be repeated `$meals_count` times.
for ($i = 1; $i <= $meals_count; $i++) {
$meals_selected_array["meal_id_" . $i] = "Unique ID";
$meals_selected_array["meal_code_" . $i] = "Meal Name";
$meals_selected_array["meal_type_" . $i] = "Meal";
}
//once our secondary array, which will be used as the primary array's key value, is ready, we will start defining/populating our Primary Multidimensional Array with Keys Named based on `$days_served`.
$total_meals_array["Day " . $y] = $meals_selected_array;
}
}
}
That's it! Our dynamic Multidimensional Array is ready and can be viewed by simply the below code:
print "<pre>";
print_r($total_meals_array);
print "</pre>";
Thank you everyone, specially #yarwest for being kind enough to answer my question.
Here is the code, you can use it for index from a_ to y_ deep. The innerest element is null, if you don't want it. Terminate the for loop before last element, then process last element seperately. You also can do some improvement on this code. Hope this helps.
<?php
$array = array(
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "1","c_name" => "C1"),
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "2","c_name" => "C2"),
array("a_id" => "1","a_name" => "A1","b_id" => "2","b_name" => "B2","c_id" => "3","c_name" => "C3"),
array("a_id" => "2","a_name" => "A2","b_id" => "3","b_name" => "B3","c_id" => "4","c_name" => "C4")
);
$arrays = array_map(function($v){return array_chunk($v, 2, true);}, $array);
$result = [];
foreach($arrays as $value)
{
$ref = &$result;
$len = count($value);
$index = 0;
for(; $index < $len; $index++)
{
$arr = $value[$index];
$char = key($arr)[0];
$charAdd = chr(ord($char)+1);
$key = $arr[$char.'_id'].$arr[$char.'_name'];
$listKey = $charAdd.'_list';
foreach($arr as $k => $v)
{
$ref[$key][$k] = $v;
}
$ref = &$ref[$key][$listKey];
}
}
var_dump($result);
Output: the online live demo
ei#localhost:~$ php test.php
array(2) {
["1A1"]=>
array(3) {
["a_id"]=>
string(1) "1"
["a_name"]=>
string(2) "A1"
["b_list"]=>
array(2) {
["1B1"]=>
array(3) {
["b_id"]=>
string(1) "1"
["b_name"]=>
string(2) "B1"
["c_list"]=>
array(2) {
["1C1"]=>
array(3) {
["c_id"]=>
string(1) "1"
["c_name"]=>
string(2) "C1"
["d_list"]=>
NULL
}
["2C2"]=>
array(3) {
["c_id"]=>
string(1) "2"
["c_name"]=>
string(2) "C2"
["d_list"]=>
NULL
}
}
}
["2B2"]=>
array(3) {
["b_id"]=>
string(1) "2"
["b_name"]=>
string(2) "B2"
["c_list"]=>
array(1) {
["3C3"]=>
array(3) {
["c_id"]=>
string(1) "3"
["c_name"]=>
string(2) "C3"
["d_list"]=>
NULL
}
}
}
}
}
["2A2"]=>
array(3) {
["a_id"]=>
string(1) "2"
["a_name"]=>
string(2) "A2"
["b_list"]=>
array(1) {
["3B3"]=>
array(3) {
["b_id"]=>
string(1) "3"
["b_name"]=>
string(2) "B3"
["c_list"]=>
array(1) {
["4C4"]=>
array(3) {
["c_id"]=>
string(1) "4"
["c_name"]=>
string(2) "C4"
["d_list"]=>
&NULL
}
}
}
}
}
}
This is rather interesting. As far as I can tell, you are trying to transform a flat array into a multidimensional array, as well as transforming the keys into a multidimensional representation.
The top level difference seems to reside in the part before the underscore of the a_* keys.
Then, for each of these keys, every other *_ letters should induce it's own list.
This recursive function does the trick without hardcoding, will work with whatever number of levels, letters (or whatever else) and right identifiers.
It seems to return exactly the json you show in the sample ($array being the array as defined in your question)
$multidimension = multidimensionalify($array, ['a', 'b', 'c'], ['name']);
var_dump(json_encode($multidimension, JSON_PRETTY_PRINT));
function multidimensionalify(
array $input,
array $topLevelLetters,
array $rightHandIdentifiers,
$level = 0,
$parentId = null,
$uniqueString = 'id'
)
{
$thisDimension = [];
$thisLetter = $topLevelLetters[$level];
foreach ($input as $entry)
{
$thisId = $entry["{$thisLetter}_{$uniqueString}"];
$condition = true;
if ($parentId !== null)
{
$parentLetter = $topLevelLetters[$level - 1];
$condition = $entry["{$parentLetter}_{$uniqueString}"] === $parentId;
}
if (!isset($thisDimension[$thisId]) && $condition)
{
$thisObject = new stdClass;
$thisObject->{"{$thisLetter}_{$uniqueString}"} = $thisId;
foreach ($rightHandIdentifiers as $identifier)
{
$thisObject->{"{$thisLetter}_{$identifier}"} = $entry["{$thisLetter}_{$identifier}"];
}
if (isset($topLevelLetters[$level + 1])) {
$nextLetter = $topLevelLetters[$level + 1];
$thisObject->{"{$nextLetter}_list"} = multidimensionalify($input, $topLevelLetters, $rightHandIdentifiers, $level + 1, $thisId, $uniqueString);
}
$thisDimension[$thisId] = $thisObject;
}
}
return array_values($thisDimension);
}
Try this function just pass your array and key name for grouping and then convert to json.
public function _group_by($array, $key) {
$return = array();
foreach ($array as $val) {
$return[$val[$key]][] = $val;
}
return $return;
}

PHP - processing array values

I have an array that contains DNS records and looks like this
Array ( [domain] => xxxx.com [record_id_+++711753] => 711753 [host_+++711753] => # [type_+++711753] => A [priority_+++711753] => [value_+++711753] => 80.82.72.12 [record_id_+++711752] => 711752 [host_+++711752] => www [type_+++711752] => A [priority_+++711752] => [value_+++711752] => 80.82.72.12 [record_id_+++711754] => 711754 [host_+++711754] => # [type_+++711754] => MX [priority_+++711754] => 20 [value_+++711754] => fallback.denit.net [record_id_+++711755] => 711755 [host_+++711755] => # [type_+++711755] => MX [priority_+++711755] => 10 [value_+++711755] => ms.denit.net [record_id_+++711756] => 711756 [host_+++711756] => mail [type_+++711756] => A [priority_+++711756] => [value_+++711756] => 62.148.185.22 [record_id_+++711757] => 711757 [host_+++711757] => autodiscover [type_+++711757] => CNAME [priority_+++711757] => [value_+++711757] => autoredirect.mshex.nl [record_id_+++1148031] => 1148031 [host_+++1148031] => webmail [type_+++1148031] => CNAME [priority_+++1148031] => [value_+++1148031] => webmail.mshex.nl )
_+++ is a delimiter between the record_id and the type of DNS value.
I need to talk to an API to update records. It works like this (example);
$mdr->addParam( "command", "dns_record_modify" );
$mdr->addParam( "domein", "xxx" );
$mdr->addParam( "tld", "com" );
$mdr->addParam( "record_id", "461741" );
$mdr->addParam( "host", "#" );
$mdr->addParam( "address", "mail2.xxx.com" );
$mdr->addParam( "priority", "20" );
I know that I can use explode to fill the API values, domain and TLD.
However I cant seem to find a way to group the array values by record_id and fire a request per record_id that combines multiple values like host, type and priority.
How should I achieve this?
You're correct about using the explode() method. IMO this is the best approach to the solution. I updated the answer because of the slight typo error and also added a working version. See it here.
# loop each entry
foreach($array as $key => $value)
{
# [0] - record_id
# [1] / $value - 711753
# check that the key isn't domain since it doesn't contain _++
if($key != 'domain')
{
$mdr->addParam(explode('_+++', $key)[0], $value);
}
else
{
$mdr->addParam($key,$value);
}
}
The above code snippet explodes the _+++ out of the key to find the callback value. The $value then holds the corresponding data callback and then each is passed through your instanced object in the method addParam().
Since the callback domain in your array keys does not contain the _+++ brace, I did a check before using the explode() method.
To group the array values by record_ids, you could create a new, multidimensional array and use the record IDs as top-level keys. Here's an example:
$data = array();
$data['domain'] = 'xxxx.com';
$data['record_id_+++711753'] = 711753;
$data['host_+++711753'] = '#';
$data['type_+++711753'] = 'A';
$data['type_+++1148031'] = 'CNAME';
$data['host_+++1148031'] = 'webmail';
$sorted_data = [];
foreach($data as $key=>$val){
$key_info = explode('_+++', $key);
if (count($key_info) > 1){
$record_id = $key_info[1];
$key_name = $key_info[0];
$sorted_data[$record_id][$key_name] = $val;
}
}
var_dump($sorted_data);
You could transform your data to another structure, and then produce the $mdr->addParam calls from that:
$domain = $data["domain"]; // "xxx.com"
$tld = end(explode(".", $domain)) "com"
$domain = substr($domain, count($domain)-count($tld)-1); // "xxx"
$updates = [];
foreach ($data as $key => $value) {
$parts = explode("_+++", $key);
if (count($parts) != 2) continue;
list($key, $rec) = $parts;
if ($key == "value") $key = "address";
$updates[$rec][$key] = $value;
}
$updates will be something like this:
Array(
[711753] => Array (
[record_id] => 711753
[host] => #
[type] => A
[priority] =>
[address] => 80.82.72.12
),
[711752] => Array (
[record_id] => 711752
[host] => www
[type] => A
[priority] =>
[address] => 80.82.72.12
),
...
Then from that, you continue:
foreach($updates as $update) {
$mdr = new .... // some code to create new instance
$mdr->addParam( "command", "dns_record_modify");
$mdr->addParam( "domein", $domain);
$mdr->addParam( "tld", $tld);
foreach($update as $key => $value) {
$mdr->addParam($key, $value);
}
// execute mdr ...
}

Create array of hierarchical directories in PHP

I have the following code (I know that this code is not optimized but it's not for discussion):
function select_categories($cat_id)
{
$this->db = ORM::factory('category')
->where('parent', '=', $cat_id)
->find_all();
foreach ($this->db as $num => $category)
{
if($category->parent == 0)
{
$this->tmp[$category->parent][$category->id] = array();
}
else {
$this->tmp[$category->parent][$category->id] = array();
}
$this->select_categories($category->id);
}
return $this->tmp;
}
Function returns this array:
array(3) (
0 => array(2) (
1 => array(0)
2 => array(0)
)
2 => array(1) (
3 => array(0)
)
3 => array(2) (
4 => array(0)
5 => array(0)
)
)
But how should I change the code
else {
$this->tmp[$category->parent][$category->id] = array();
// ^^^^^^^^^^^^^^^^^^^^^^ (this bit)
}
To merge array[3] to array[2][3] for example (because array[3] is a subdirectory of array[2] and array[2] is a subdirectory of array[0][2]), so, I need to make this (when I don't know the level of subdirectories):
array (
0 => array (
1 => array
2 => array (
3 => array (
4 => array
5 => array
)
)
)
)
A long time ago I wrote some code to do this in PHP. It takes a list of entities (in your case, categories) and returns a structure where those entities are arranged in a tree. However, it uses associative arrays instead of objects; it assumes that the “parent” ID is stored in one of the associative array entries. I’m sure that you can adapt this to your needs.
function make_tree_structure ($nontree, $parent_field)
{
$parent_to_children = array();
$root_elements = array();
foreach ($nontree as $id => $elem) {
if (array_key_exists ($elem[$parent_field], $nontree))
$parent_to_children [ $elem[$parent_field] ][] = $id;
else
$root_elements[] = $id;
}
$result = array();
while (count ($root_elements)) {
$id = array_shift ($root_elements);
$result [ $id ] = make_tree_structure_recurse ($id, $parent_to_children, $nontree);
}
return $result;
}
function make_tree_structure_recurse ($id, &$parent_to_children, &$nontree)
{
$ret = $nontree [ $id ];
if (array_key_exists ($id, $parent_to_children)) {
$list_of_children = $parent_to_children [ $id ];
unset ($parent_to_children[$id]);
while (count ($list_of_children)) {
$child = array_shift ($list_of_children);
$ret['children'][$child] = make_tree_structure_recurse ($child, $parent_to_children, $nontree);
}
}
return $ret;
}
To see what this does, first try running it on a structure like this:
var $data = array (
0 => array('Name' => 'Kenny'),
1 => array('Name' => 'Lilo', 'Parent' => 0),
2 => array('Name' => 'Adrian', 'Parent' => 1)
3 => array('Name' => 'Mark', 'Parent' => 1)
);
var $tree = make_tree_structure($data, 'Parent');
If I’m not mistaken, you should get something like this out: (the “Parent” key would still be there, but I’m leaving it out for clarity)
array (
0 => array('Name' => 'Kenny', 'children' => array (
1 => array('Name' => 'Lilo', 'children' => array (
2 => array('Name' => 'Adrian')
3 => array('Name' => 'Mark')
)
)
)
Examine the code to see how it does this. Once you understand how this works, you can tweak it to work with your particular data.
Assuming you dont want any data/children tags in your array:
foreach ($this->db as $num => $category)
{
// save the data to the array
$this->tmp[$category->id] = array();
// save a reference to this item in the parent array
$this->tmp[$category->parent][$category->id] = &$this->tmp[$category->id];
$this->select_categories($category->id);
}
// the tree is at index $cat_id
return $this->tmp[$cat_id];
If you just need to retrieve the full tree out of the database, you can even simplify your query (get all records at once) and remove the recursive call in this function. You will need an extra check that will only set the $this->tmp[$catagory->id] when it does not exist and else it should merge the data with the existing data.

Categories