How can I make this function simpler? Unknown array depth - php

I am back with another question.
I am trying to go through an array and list all the items that match the parent ID of the category and subcategory then list the items in the inventory for the subcategory.
I need to show all items from the category when a button is clicked.
I have a tree view like this
When you click on M8 or 316SS it'll either show the items in M8 or it'll show all the items in the 316SS category.
I need to do this but on every level as well however the code I am currently using doesn't work for it.
Which is this
<?php
include 'classLoader.php';
if (isset($_GET['id']) && !empty($_GET['id'])) {
$items = DB::query("SELECT * FROM inventory WHERE parent=:parent", array(":parent" => $_GET['id']));
if (!empty($items)) {
$data = array();
foreach ($items as $item_key => $item) {
$data["data"][] = array('<i class="icon material-icons">open_in_new</i><a class="link icon-only"><i class="icon material-icons">edit</i></a>', $item['item'], $item['supplier_product_code'], $item['price_per_unit'], $item['current_stock'], $item['category'], '<a class="link icon-only"><i class="icon material-icons">delete</i></a>');
}
header("Content-Type: application/json");
echo json_encode($data, JSON_PRETTY_PRINT);
} else {
$categories = DB::query("SELECT * FROM categories WHERE parent=:id", array(":id" => $_GET['id']));
$data = array();
foreach ($categories as $cat_key => $cat) {
$items = DB::query("SELECT * FROM inventory WHERE parent=:parent", array(":parent" => $cat['id']));
foreach ($items as $item_key => $item) {
$data["data"][] = array('<i class="icon material-icons">open_in_new</i><a class="link icon-only"><i class="icon material-icons">edit</i></a>', $item['item'], $item['supplier_product_code'], $item['price_per_unit'], $item['current_stock'], $item['category'], '<a class="link icon-only"><i class="icon material-icons">delete</i></a>');
}
}
header("Content-Type: application/json");
echo json_encode($data, JSON_PRETTY_PRINT);
}
}
?>
When that didn't work I tried the following code (Cut down but it is pretty much duplicated like 10 times). This code works however it is resource intensive and only goes so many deep. I need one that will continue following it until its got nowhere else to go.
<?php
include 'classLoader.php';
if (isset($_GET['id']) && !empty($_GET['id'])) {
$items = DB::query("SELECT * FROM categories WHERE parent=:id", array(":id" => $_GET['id']));
$d = array();
if (!empty($items)) {
foreach ($items as $item_key => $item) {
$d[] = $item['category_name'];
$subItems = DB::query("SELECT * FROM categories WHERE parent=:catID", array(":catID" => $item['id']));
foreach ($subItems as $item_key => $item) {
$d[] = $item['category_name'];
$subItems = DB::query("SELECT * FROM categories WHERE parent=:catID", array(":catID" => $item['id']));
foreach ($subItems as $item_key => $item) {
$d[] = $item['category_name'];
$subItems = DB::query("SELECT * FROM categories WHERE parent=:catID", array(":catID" => $item['id']));
foreach ($subItems as $item_key => $item) {
$d[] = $item['category_name'];
$subItems = DB::query("SELECT * FROM categories WHERE parent=:catID", array(":catID" => $item['id']));
foreach ($subItems as $item_key => $item) {
$d[] = $item['category_name'];
$subItems = DB::query("SELECT * FROM inventory WHERE parent=:catID", array(":catID" => $item['id']));
}
}
}
}
}
}
header("Content-Type: application/json");
echo json_encode($d, JSON_PRETTY_PRINT);
}
?>
Is there a way to make this function "recursive" in a sense? The database is like this
# categories
| category_name | parent |
| Fasteners | 0 |
| Bolts | 1 |
| 316SS | 2 |
| M8 | 3 |
# inventory
| item | parent |
| 20 | 0 |
| 30 | 1 |
These tables both have over 3000 unique items in them.
Sorry for the very low quality question.

Solved.
I used the following code.
$cats = DB::query("SELECT * FROM categories");
$r = fetch_recursive($cats, $_GET['id']);
foreach ($r as $cat_key => $cat) {
$items = DB::query("SELECT * FROM inventory WHERE parent=:parent", array(":parent" => $cat['id']));
foreach ($items as $item_key => $item) {
$data["data"][] = array('<i class="icon material-icons">open_in_new</i><a class="link icon-only"><i class="icon material-icons">edit</i></a>', $item['item'], $item['supplier_product_code'], $item['price_per_unit'], $item['current_stock'], $item['category'], '<a class="link icon-only"><i class="icon material-icons">delete</i></a>');
}
}
function fetch_recursive($src_arr, $id, $parentfound = false, $cats = array())
{
foreach($src_arr as $row)
{
if((!$parentfound && $row['id'] == $id) || $row['parent'] == $id)
{
$rowdata = array();
foreach($row as $k => $v)
$rowdata[$k] = $v;
$cats[] = $rowdata;
if($row['parent'] == $id)
$cats = array_merge($cats, fetch_recursive($src_arr, $row['id'], true));
}
}
return $cats;
}

Related

How to write category and subcategory with foreach?

I have a database category table , With 3 fields id,name,cate . And I put it into array
$select = $this->db->get_where('cate',array('cate >'=> 0))->result_array();
I want to write a foreach that
if (cate == 1) : This is the main menu
else if (cate == main menu id) : this is subcategory
Here is what I have tried
foreach ($select as $key => $value) {
$id = $value['id'];
$name = $value['name'];
$cate = $value['cate'];
}
I'm sorry for my poor English
it's my solution:
$categoriesHierchy = [];
foreach ($categories as $mainCategory) {
$childNode = [
'id' => $mainCategory->getID(),
'polishName' => $mainCategory->getPolishName(),
'children' => findChildrenOfCategory($mainCategory)
];
array_push($categoriesHierchy, $childNode);
}
public function findChildrenOfCategory($category)
{
$children = [];
if (count($category->getChildren()) > 0) {
foreach ($category->getChildren() as $child) {
$childCategories = findChildrenOfCategory($child);
$childNode = [
'id' => $child->getID(),
'polishName' => $child->getPolishName(),
'children' => $childCategories
];
array_push($children, $childNode);
}
}
return $children;
}
foreach ($select as $value) { //selecting each row/element
$cate = $value['cate']; //grabbing column values
$name = $value['name'];
If($cate == 1){ //no need of cate == main cate id
echo $name." is a main";
}else{
echo $name." is a sub";
}
}

2 foreach loops with arrays

What I am trying to do is get my "$ages" array to display a value once per player in order of the array..
However every time I add the extra for loop with that array, it duplicates each player 20 times, with each array value once. I want 20 players, with the 20 different values of the array one each.
Here's the current output, that is duplicating each player 20 times.
http://freerdarts.com/test.php
Here's the code
<link rel="stylesheet" href="https://freerdarts.com/assets/css/main.css" />
<?php
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML(file_get_contents('https://www.leagueleader.net/sharedreport.php?operatorid=98&code=1166aea7-6e0e-4864-8074-8ebd93311041'));
$doc->strictErrorChecking = false;
$pre = [];
$keys = ['name', 'team', 'ppd', 'games', 'wins', 'hats', '3bd', 'ton80','hton','lton','6do','7do','8do','9do'];
$keys2 = ['name', 'mpr', 'games', 'wins','assists', 'hats','whorse','5mr','6mr','7mr','8mr','9mr'];
foreach ($doc->getElementsByTagName('table') as $k => $table) {
if (strpos($table->getAttribute('class'), 'report') === false) {
continue;
}
foreach ($table->getElementsByTagName('tr') as $i => $tr) {
if ($tr->parentNode->nodeName === 'thead') continue; // skip headers
$row_values = [];
foreach ($tr->childNodes as $td) {
$text = trim($td->nodeValue);
if ($text === '') continue;
$row_values[] = $text;
}
if($k == 1 ){
$row_values = array_combine($keys, $row_values);
}else if($k == 2 ){
unset($row_values[1]);
$row_values = array_combine($keys2, $row_values);
}
$pre[$row_values['name']][] = $row_values;
}
}
$combined = [];
foreach($pre as $name => $row){
$combined[$name] = [
"name"=> $name,
"team"=> $row[0]['team'],
"ppd_01" => $row[0]['ppd'],
"games_01" => $row[0]['games'],
"wins_01" => $row[0]['wins'],
"hats_01" => $row[0]['hats'],
"3bd" => $row[0]['3bd'],
"ton80" => $row[0]['ton80'],
"hton" => $row[0]['hton'],
"lton" => $row[0]['lton'],
"6do" => $row[0]['6do'],
"7do" => $row[0]['7do'],
"8do" => $row[0]['8do'],
"9do" => $row[0]['9do'],
"mpr_crk" => $row[1]['mpr'],
"games_crk" => $row[1]['games'],
"wins_crk" => $row[1]['wins'],
"assists_crk" => $row[1]['assists'],
"hats_crk" => $row[1]['hats'],
"whorse" => $row[1]['whorse'],
"5mr" => $row[1]['5mr'],
"6mr" => $row[1]['6mr'],
"7mr" => $row[1]['7mr'],
"8mr" => $row[1]['8mr'],
"9mr" => $row[1]['9mr']
];
}
//echo '<pre>'.json_encode($combined, JSON_PRETTY_PRINT).'</pre>';
//echo $combined['Ronnie Otto']['ppd_01'];
?>
<?php
// Players Ages
$ages = array(one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen,twenty);
sort($combined);
foreach($combined as $row) {
foreach($ages as $age) {
// Name Corrections
if($row['name'] == 'Scott Sandburg'){ $row['name'] = 'Scott Sandberg'; }
// Profile Images
$profile_image = $row['name'];
$profile_image = str_replace(' ', '_', $profile_image);
?>
<div class="profile">
<span class="profile_ext"> <img src="../images/profiles/<?=$profile_image?>.jpg" />
<span class="name"><?=$row['name'];?></span>
<span class="age"><?=$age;?></span>
<span class="gamesplayed"><?=$row['games_01']+$row['games_crk'];?></span>
<span class="blank"></span>
<!-- Cricket Stats -->
<span class="cricketmpr"><?=$row['mpr_crk'];?></span>
<span class="cricket_5mr"><?=$row['5mr'];?></span>
<span class="cricket_6mr"><?=$row['6mr'];?></span>
<span class="cricket_7mr"><?=$row['7mr'];?></span>
<span class="cricket_8mr"><?=$row['8mr'];?></span>
<span class="cricket_9mr"><?=$row['9mr'];?></span>
<span class="cricket_whorse"><?=$row['whorse'];?></span>
<span class="blank"></span>
<!-- 01 Stats -->
<span class="o1ppd"><?=$row['ppd_01'];?></span>
<span class="o1_lton"><?=$row['lton'];?></span>
<span class="o1_hats"><?=$row['hats_01'];?></span>
<span class="o1_hton"><?=$row['hton'];?></span>
</span>
</div>
<?php } } ?>
The problem is that you have an inner foreach() in your display part...
foreach($ages as $age) {
this doesn't seem in any way connected to the data you are displaying as there doesn't seem to be an age in the data.
You should also be getting some warnings as
$ages = array(one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen,twenty);
will show
Warning: Use of undefined constant one - assumed 'one' (this will
throw an Error in a future version of PHP)
You should have quotes round the values...
$ages = array('one',...
If you just want the players listed with the corresponding age, you first need to change
foreach($combined as $key => $row) {
// Remove next foreach
// foreach($ages as $age) {
Then to display the age, use the $key from the foreach() to index the $ages array...
<span class="age"><?=$ages[$key];?></span>

php : csv import to multiple table is taking too long

i am using csv importer library to load bulk of products into mysql database with codeigniter. csv file has some column names from one table like name, price and some column names from another table like categories. it inserts name and price to first table and categories will be inserted after we got id from first table, so category will go with id of the product. but this is taking too long to process the csv file (1000 entries = 2 minutes). the code i have put is
$csv_file_data = $this->csvimport->get_array($_FILES['csv']['tmp_name']);
foreach ($csv_file_data as $csv_data) {
$required = array(
'name' => $csv_data['name'],
'price' => $csv_data['price']
);
foreach ($required as $key => $value) {
$this->db->set($key, $value);
}
$categories= array();
foreach ($csv_data as $key => $value) {
if(strstr($key, 'categories')) {
$category = explode('|', $value);
for($i = 0; $i < sizeof($category); $i++) {
array_push($categories, $category[$i]);
}
}
}
$this->db->insert('first_table');
$id = $this->db->insert_id();
foreach ($categories as $metatag) {
$this->db->set('productid', $id);
$this->db->set('category', $metatag);
$this->db->insert('second_table');
}
}
but it is taking too long to process only 1000 entries, how to optimize this to process 5000 entries in less than 20-30 seconds ?
I believe this is what you're after ...
$csv_file_data = $this->csvimport->get_array($_FILES['csv']['tmp_name']);
foreach ($csv_file_data as $csv_data) {
$required = array(
'name' => $csv_data['name'],
'price' => $csv_data['price']
);
$this->db->set($required);
$categories = array();
foreach ($csv_data as $key => $value) {
if (strstr($key, 'categories')) {
$category = explode('|', $value);
for ($i = 0; $i < sizeof($category); $i++) {
$categories[] = $category[$i];
}
}
}
$this->db->insert('first_table');
$bulk = array();
$id = $this->db->insert_id();
foreach ($categories as $metatag) {
$bulk[] = array(
'category' => $metatag,
'productid' => $id,
);
}
$this->db->insert_batch('table2', $bulk);
}
Note the use of insert_batch which will dramatically improve your speed and also you can give set() an array.
Can you try a version like this and tell me if this is working and return me the time for 100 rows ?
$bulk = [];
$csv_file_data = $this->csvimport->get_array($_FILES['csv']['tmp_name']);
$required = [];
foreach ($csv_file_data as $csv_data) {
$bulk = [];
$id = $this->db->insert_id();
$required[] = [
'name' => $csv_data['name'],
'price' => $csv_data['price'],
];
foreach ($csv_data as $key => $value) {
if (false !== strpos($key, 'categories')) {
$category = explode('|', $value);
foreach ($category as $metatag) {
$bulk[] = [
'category' => $metatag,
'productid' => $id,
];
}
}
}
}
$this->db->insert_batch('first_table', $required);
$this->db->insert_batch('second_table', $bulk);

PHP: For each different key value, group together

I have this mysql sample table:
+----+---------------+-------+
| id | company | value |
+----+---------------+-------+
| 1 | google | 50 |
+----+---------------+-------+
| 2 | microsoft | 24 |
+----+---------------+-------+
| 3 | google | 12 |
+----+---------------+-------+
| 4 | microsoft | 89 |
+----+---------------+-------+
| 5 | stackoverflow | 45 |
+----+---------------+-------+
And I want to print it as such so that they are grouped by company:
<ul class="google">
<li>50</li>
<li>12</li>
</ul>
<ul class="microsoft">
<li>24</li>
<li>89</li>
</ul>
<ul class="stackoveflow">
<li>45</li>
</ul>
This is my current code:
$resultx = mysql_query();
$temp=0;
$p = array();
while ($row = mysql_fetch_array($resultx)) {
$p[$temp]['id']=$row['id'];
$p[$temp]['company']=$row['company'];
$p[$temp]['value']=$row['value'];
$temp++;
}
foreach ($p as $obj) {
echo '<ul class="'.$obj["company"].'"><li>'.$obj["value"].'</li></ul>';
};
But my code prints all the company together.
EDIT:
I want to group the company in different UL's.
I would assume that I would have to use another foreach inside my foreach.
When building your array, make the key of the array be the company name or company id. Since I don't see a company id in your query, I will go with name. Now have it be a multidemsional array, with the inner array beging the values.
$resultx = mysql_query();
$p = array();
while ($row = mysql_fetch_array($resultx)) {
$p[$row['company']]['id']=$row['id'];
$p[$row['company']]['company']=$row['company'];
$p[$row['company']]['values'][]=$row['value'];
}
foreach ($p as $obj) {
echo '<ul class="'.htmlspecialchars($obj["company"]).'">';
foreach ($obj['values'] as $value) {
echo '<li>'.htmlspecialchars($value).'</ul>';
}
echo '</ul>';
};
Let us begin:
SELECT * FROM `yourTableName` ORDER BY `company`
Then you do this:
for($i = 0; $i<sizeOf($p); $i++)
{
if ($p[$i] == 0 || $p[$i]['company'] != $p[$i-1]['company'])
echo '<ul class="'.$obj["company"].'">';
ecoh '<li>'.$obj["value"].'</li>';
if ($p[$i] == 0 || $p[$i]['company'] != $p[$i-1]['company'])
echo '</ul>';
}
$resultx = mysql_query();
$temp=0;
$companies = array();
while ($row = mysql_fetch_array($resultx)) {
$companies[$row['company']][]=$row;
}
foreach ($companies as $company=>$values) {
echo '<ul class="'.$company.'">';
foreach($values as $value){
echo '<li>'.$value["value"].'</li>';
}
echo'</ul>';
}
There are of course other ways to do it, to make it simple I used 2 different loops.
$companies = array();
//One array that will have companies' names as keys
// and the value would be an array of values.
$resultx = mysql_query();
while ($row = mysql_fetch_array($resultx)) {
$companies[ $row['company'] ][] = $row['value'];
}
foreach ($companies as $company => $values) { //Loop the companies
echo '<ul class="'.$company.'">';
foreach($values as $value) //Loop the values of that company
{
echo '<li>'.$value.'</li>';
}
echo '</ul>';
}
** Haven't tested it.
I hope that this will solve your problem
$p = array(array());
while ($row = mysql_fetch_array($resultx)) {
$p[$row['company']][] = $row['value'];
}
foreach ($p as $key => $obj) {
echo '<ul class="'.$key.'">';
foreach ($obj as $val) {
echo '<li>'.$val.'</li>';
}
echo '</ul>';
};

Creating list in categorised form from MySQL database for shopping cart?

I have created database looking like this
cat_id cat_parent_id cat_name cat_decs
11 0 Men for men
12 0 Women for women
13 11 Men clothing 123
14 12 Women cloth 434
and i want to print this way
Men
Men clothing
Women
Women cloth
either in my menubar or in combobox i have tried to find the solution but all gone in vein
i have used this function but it is printing like this
Men
Women
Men clothing
Women cloth
function buildCategoryOptions($catId = 0)
{
//die();
$sql = "SELECT cat_id, cat_parent_id, cat_name
FROM tbl_category
ORDER BY cat_id";
$result = mysql_query($sql) or die('Cannot get Product. ' . mysql_error());
$categories = array();
while($row = mysql_fetch_array($result)) {
list($id, $parentId, $name) = $row;
//echo $id, $parentId, $name;
if ($parentId == 0) {
// we create a new array for each top level categories
$categories[$id] = array('name' => $name, 'children' => array());
}
else {
// the child categories are put int the parent category's array
$categories[$parentId]['children'][] = array('id'=> $id, 'name'=> $name);
}
}
echo ($categories[28]['children'][0]['name']);
// build combo box options
$list = '';
foreach ($categories as $key => $value) {
$name= #$value['name'];
//print_r($value['name']);
$children = $value['children'];
$list .= "<optgroup label=\"$name\">";
foreach ($children as $child) {
$list .= "<option value=\"{$child['id']}\"";
if ($child['id'] == $catId) {
$list.= " selected";
}
$list .= ">{$child['name']}</option>\r\n";
}
$list .= "</optgroup>";
//die();
}
//die();
return $list;
}

Categories