Adding rows spanning multiple rows in Symfony Console - php

I am currently developing a CLI using Symfony Console and I have run into a problem regarding adding a row spanning multiple rows.
My code is
$table = new Table($output);
$table->setHeaders(['Elements','Properties']);
foreach($elements as $key => $element) {
if ($key != 'templates') {
//process element
$rowcount = 0;
foreach($element as $name => $component){
if(is_string($component)){
$strings[] = $name.' = '.($component == '' ? 'empty' : $component);
$rowcount++;
}
}
//creating row
$count = 0;
foreach ($strings as $string) {
if ($count == 0) {
$frow[] = new TableCell($key, ['rowspan' => $rowcount]);
$frow[] = $string;
} else {
$row[] = $string;
}
$count++;
}
$rows = [$frow,$row];
var_dump($rows);
$table->addRows($rows);
unset($frow,$row,$strings);
}
}
$table->setStyle('borderless');
$table->render();
The var_dump at this point creates this result
array(2) {
[0]=>
array(2) {
[0]=>
object(Symfony\Component\Console\Helper\TableCell)#63 (2) {
["value":"Symfony\Component\Console\Helper\TableCell":private]=>
string(5) "forms"
["options":"Symfony\Component\Console\Helper\TableCell":private]=>
array(2) {
["rowspan"]=>
int(4)
["colspan"]=>
int(1)
}
}
[1]=>
string(12) "name = forms"
}
[1]=>
array(3) {
[0]=>
string(18) "path = admin/forms"
[1]=>
string(14) "scope = system"
[2]=>
string(16) "attachto = empty"
}
}
The CLI should appear like this
============= ===================
Elements Properties
============= ===================
forms name = forms
path = admin/forms
scope = system
attachto = empty
I don't know if this is too much but the problem is the alignment of the second column is completely disjointed.The scope=system section moves to a 3rd column.

Related

PHP duplicates in nested multidimensional array to combine certain value

The desired output is to have:
{"userId":1,"email":"example#email.com","first":"Tyler","last":"Kanz","groups":[{"groupId":"1","groupName":"GROUP A","groupRoles":["1", "3"]},{"groupId":"2","groupName":"GROUP B","groupRoles":["2"]}]}
Which would compare the Group IDs and combine duplicates with their Group Roles.
I have tried using,
foreach ($groups as $group) {
if ($group['groupId'] == $group_id) {
array_push($group['groupRoles'], $group_role);
//And then unsetting the array
}
It is just adding all of the Groups/Roles into the Group array onto the Groups Array.
array(3) { ["groupId"]=> string(1) "1" ["groupName"]=> string(5)
"GROUP A" ["groupRoles"]=> array(1) { [0]=> string(1) "1" } } array(3) {
["groupId"]=> string(1) "2" ["groupName"]=> string(10) "GROUP B"
["groupRoles"]=> array(1) { [0]=> string(1) "2" } } array(3) {
["groupId"]=> string(1) "1" ["groupName"]=> string(5) "GROUP A"
["groupRoles"]=> array(1) { [0]=> string(1) "3" } }
{"userId":1,"email":"example#email.com","first":"Tyler","last":"Kanz","groups":[{"groupId":"1","groupName":"IRISS","groupRoles":["1"]},{"groupId":"2","groupName":"GROUP B","groupRoles":["2"]},{"groupId":"1","groupName":"GROUP A","groupRoles":["3"]}]}
foreach ($groupmeta as $value) {
$group_roles = array();
$array = unserialize($value['property_value']);
if ($array[0] == $user_ID) {
//Gets Group ID and Role
$group_id = $value['group_id'];
$group_role = $array[1];
$exists = false;
$group_name_q= json_decode(json_encode($wpdb->get_results($wpdb->prepare('SELECT group_name FROM groups WHERE id=%s', $group_id))), true);
$group_name = $group_name_q[0]['group_name'];
echo $group_role;
echo '<br>';
$group_roles[] = $group_role;
$group_info = array(
'groupId'=>$group_id,
'groupName'=>$group_name,
'groupRoles'=>$group_roles,
);
$groups[] = $group_info;
}
}
$sorted_groups = array();
echo '<br>';
}
$return_arr = array(
"userId"=>$user_ID,
"email"=>$user_email,
"first"=>$user_first,
"last"=>$user_last,
"groups"=>$groups
);
echo json_encode($return_arr);
//var_dump($groupmeta_value);
}
Found an answer, FOREACH runs as a cloned object.
Instead I used the following FOR loop and got the desired results.
$found_group = false;
for ($i = 0; $i < count($groups); $i++) {
if ($groups[$i]['groupId'] == $group_id) {
array_push($groups[$i]['groupRoles'], $group_role);
$found_group = true;
}
}
if (!$found_group) {
//Group Name
$group_name_q= json_decode(json_encode($wpdb->get_results($wpdb->prepare('SELECT group_name FROM groups WHERE id=%s', $group_id))), true);
$group_name = $group_name_q[0]['group_name'];
$group_roles[] = $group_role;
$group_info = array(
'groupId'=>$group_id,
'groupName'=>$group_name,
'groupRoles'=>$group_roles,
);
$groups[] = $group_info;
}

PHP find similar ID's (EAN codes) and show if excist

I have a database with different kind of products that have similar ID's (EAN codes). I'm trying to print a list of all similar codes so I can import them and connect them to the same product.
Example:
Product Y has ID 190198001795 and 0190198001795
Product X has ID 190198001780, 0190198001780 and 00190198001780
What I'm trying to achieve:
190198001795 - 0190198001795
190198001795 - 0190198001780 - 00190198001780
What did I try:
Create a foreach to 'group' the similar ID's, but eventually this may corrupt the correct groups.
<?
// GET ALL PRODUCT ID's
$sql = "SELECT * FROM `products`";
$result = $mysqli->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
// Total Downloads - Thousand sperator
$shopID = $row["id"];
$EAN = $row["ean"];
$sqlDouble = "SELECT * FROM `products` WHERE `EAN` IN ('$EAN','0$EAN','00$EAN','000$EAN') LIMIT 200";
$resultDouble = $mysqli->query($sqlDouble);
if ($resultDouble->num_rows > 1) {
// output data of each row
while($row = $resultDouble->fetch_assoc()) {
$EAN = $row["ean"];
$shopID = $row["id"];
$children[] = $EAN;
}
}
}
}
foreach (array_chunk($children, 2, true) as $array) {
echo '<div>';
foreach($array as $kicks) {
echo $kicks." ";
}
echo '</div>';
}
?>
Is there another way to parse trough my rows and check / combine similar ID's?
Try this. See comments for explanation. Outputs:
array(2) {
[190198001780]=>
array(2) {
[2]=>
string(13) "0190198001780"
[8]=>
string(14) "00190198001780"
}
[1234]=>
array(2) {
[5]=>
string(5) "01234"
[6]=>
string(6) "001234"
}
}
Code:
<?php
$eans = ['190198001780', '8715839583923', '0190198001780', '015839583923', '1234', '01234', '001234', '001235', '00190198001780'];
foreach ($eans as $ean)
{
// For all EANs that do not have a leading zero, try to find
// similar ones by looking for the same code with one or more leading
// zeroes.
if ($ean[0] !== '0' && ctype_digit($ean))
{
// Look for any occurrences of this EAN with one or more (+) leading zeroes.
// If no similar EANs found, then don't record any.
if ($matches = preg_grep('/[0]+' . $ean . '/', $eans))
$children[$ean] = $matches;
}
}
var_dump($children);
/*
array(2) {
[190198001780]=>
array(2) {
[2]=>
string(13) "0190198001780"
[8]=>
string(14) "00190198001780"
}
[1234]=>
array(2) {
[5]=>
string(5) "01234"
[6]=>
string(6) "001234"
}
}
*/

Generate multi dimensional array from list string

I'd like to generate a multi-dimensional array in PHP from the following -
- Item 1
-- Item 1.1
-- Item 1.2
--- Item 1.2.1
--- Item 1.2.2
---- Item 1.2.2.1
- Item 2
- Item 3
- Item 4
-- Item 4.1
-- Item 4.2
My eventual aim is to convert this string into an unordered list.
I'd imagine the best way to do this would be to create a recursive function. On a good day I'm sure I could work this out but I'm having a bit of a mind blank!
The array structure should be something like the below dump -
array(6) {
[0]=>
string(6) "Item 1"
[1]=>
array(3) {
[0]=>
string(8) "Item 1.1"
[1]=>
string(8) "Item 1.2"
[2]=>
array(3) {
[0]=>
string(10) "Item 1.2.1"
[1]=>
string(10) "Item 1.2.2"
[2]=>
array(1) {
[0]=>
string(12) "Item 1.2.2.1"
}
}
}
[2]=>
string(6) "Item 2"
[3]=>
string(6) "Item 3"
[4]=>
string(6) "Item 4"
[5]=>
array(2) {
[0]=>
string(8) "Item 4.1"
[1]=>
string(8) "Item 4.2"
}
}
Hope you can help.
The following will convert straight into HTML without recursion:
$text = array();
$text[] = '- Item 1';
$text[] = '-- Item 1.1';
$text[] = '-- Item 1.2';
$text[] = '--- Item 1.2.1';
$text[] = '--- Item 1.2.2';
$text[] = '---- Item 1.2.2.1';
$text[] = '- Item 2';
$text[] = '- Item 3';
$text[] = '- Item 4';
$text[] = '-- Item 4.1';
$text[] = '-- Item 4.2';
$previous_dash_count = 0; // topmost parent
foreach ($text as $line) {
if (preg_match('/(^\-+)(.*)/', $line, $matches, PREG_OFFSET_CAPTURE)===1) {
$dash_count = strlen($matches[1][0]);
$title = $matches[2][0];
if ($dash_count == $previous_dash_count) {
echo "<li>$title</li>\n";
} elseif ($dash_count > $previous_dash_count) {
echo str_repeat("<ul>\n", $dash_count - $previous_dash_count);
echo "<li>$title</li>\n";
} else {
echo str_repeat("</ul>\n",$previous_dash_count-$dash_count+1);
echo "<ul>\n";
echo "<li>$title</li>\n";
}
$previous_dash_count = $dash_count;
}
}
echo str_repeat("</ul>\n",$previous_dash_count);
I make several assumptions. That the input text always behaves well and doesn't contain randomness. Also I don't assume UTF-8 text, but you're safe with dashes.
Here is the array version in all its gory glory:
$stack = array();
$previous_dash_count = 0;
$parent_node = array();
foreach ($text as $line) {
if (preg_match('/(^\-+)(.*)/', $line, $matches, PREG_OFFSET_CAPTURE)===1) {
$dash_count = strlen($matches[1][0]);
$title = $matches[2][0];
if ($dash_count == $previous_dash_count) {
$parent_node[] = $title;
} elseif ($dash_count > $previous_dash_count) {
for ($push_count = $previous_dash_count; $push_count<$dash_count; $push_count++) {
array_push($stack, $parent_node); // remember node
$new_child = array();
$new_child[] = $title;
$parent_node[] = $new_child;
$parent_node = $new_child;
}
} else {
for ($pop_count = $previous_dash_count; $pop_count >$dash_count; $pop_count--) {
$old_child = $parent_node;
$parent_node = array_pop($stack);
$parent_node[] = $old_child;
}
$parent_node[] = $title;
}
$previous_dash_count = $dash_count;
}
}
for ($pop_count = $previous_dash_count; $pop_count > 0; $pop_count--) {
$old_child = $parent_node;
$parent_node = array_pop($stack);
$parent_node[] = $old_child;
}
print_r($parent_node);
We keep a stack of array nodes, so we have a link between a child and its parent. Note the structure of this code is identical to that for the straight HTML version.

Combine varied number of dynamically named arrays

I have seen the following: array_merge() How can I add a 'range' of an array name and the answers don't work for me.
I have an array that I am looping through in order to slice and convert certain currency strings to float numbers. I then have to array_merge them back together in order to work with the array and have been dynamically naming them so that I don't overwrite the previous array_merge. After doing so, I then need to combine all of the dynamically named arrays into one array.
Initially I had the following code, which worked great when I only had 3 nested arrays in the $order['product'] array. However, this number varies, and the code needs to do so as well.
$nr = 1;
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
${"final_product" . $nr} = array_merge($product, $product_total);
$nr++;
};
$arrays = array($final_product1, $final_product2, $final_product3);
var_dump($arrays);
This results in the following array:
array(3) {
[0]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(18) }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(17) }
[2]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(2.75) } }
How do I implement a varied number of dynamically named arrays in the line:
$arrays = array($final_product1, $final_product2, $final_product3);
I attempted the following, but the array is nested incorrectly. Feel free to fix this code or come up with a better solution.
$nr = 1;
$i = 1;
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
${"final_product" . $nr} = array_merge($product, $product_total);
if ($nr > 0) {
$arrays = $final_product1;
for ($i = 2; $i <= $nr; $i++) {
$arrays = array_merge($arrays, ${"final_product" . $nr});
}
} else {
echo "There are no products in this order";
}
$nr++;
};
var_dump($arrays);
This results in the incorrectly nested array:
array(2) {
[0]=> array(2) {
[0]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(18) }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(17) } }
[1]=> array(2) {
["source_code"]=> string(10) "408000-025"
["total"]=> float(2.75) } }
Simply replace your dynamically single-named variables with an array:
$final_product = array();
foreach ($order['product'] as $product) {
$product_total = array_slice($product, 1);
array_walk($product_total, "convertCurrencyStringtoNumber");
$final_product[] = array_merge($product, $product_total);
};
var_dump($final_product);
Unless I'm missing something here... this should be as easy and simple as:
$final_array=[];
foreach ($order['product'] as $product) {
$final_array[]['total'] = (float) $product['whatever value 1 is...'];
$final_array[]['source_code'] = $product['source_code'];
}
var_dump($final_array);
If you need to apply convertCurrencyStringtoNumberbecause it does something weird to the variable then changethe seccond line to:
$final_array[]['total'] = convertCurrencyStringtoNumber(array_slice($product, 1));

find / select specified ID in array php

i have array with database, and have to select only this items what have "tid" = 1
array(3) {
[1]=>
array(4) {
["tid"]=> "1"
["title"]=> "Google"
["url"]=> "http://google.com/"
["description"]=> "A very efficient search engine."
}
[2]=>
array(4) {
["tid"]=> "2"
["title"]=> "Facebook"
["url"]=> "http://facebook.com/"
["description"]=> "Trade securities, currently supports nearly 1000 stocks and ETFs"
}
[3]=>
array(4) {
["tid"]=> "1"
["title"]=> "Yandex"
["url"]=> "http://yandex.ru/"
["description"]=> "Another efficient search engine popular in Russia"
}
}
how can i select only this items from array what have "tid" = 1?
<?php
$final_arr = array();
foreach($tid_arrs as $tid_arr){
if($tid_arr['tid'] == 1){
$final_arr[] = $tid_arr;
}
}
print_r($final_arr);
?>
$filteredArray = array();
for($i = 0, $end = count($array);$i < $end;i++)
{
if($array[$i]["tid"] === "1")
{
$filderedArray[] = $array[$i];
}
}
That way $filteredArray will contain solely the items with tid 1;
Try array_filter function: http://php.net/manual/en/function.array-filter.php this should help.
print_r(array_filter($array, "filter_function"));
function filter_function($element){
return (int)$element['tid'] === 1;
}
let's say you starting array is $arr.
$result = array();
foreach ($arr as $arrItem) {
if ((array_key_exists('tid', $arrItem)) && ($arrItem['tid'] == "1")){
$result[] = $arrItem;
}
}
$result should be what you are excepted.

Categories