我想简单地从mysql
创建一个多级类别层次结构分类表:
________________________________________________________________________
| id | parent_id | name
————————————————————————————————————————————————————————————————————————
| 1 | 0 | Root
| 2 | 1 | Sub category of root
| 3 | 0 | category 1
| 4 | 3 | sub category of category 1
| 5 | 4 | sub category of first sub category of category 1
————————————————————————————————————————————————————————————————————————
PHP
public function getCategoryTree($level = 0) {
$rows = $this->db
->select(‘id,parent_id,name’)
->where(‘parent_id’, $level)
->get(‘categories’)
->result();
if (count($rows) > 0) {
foreach ($rows as $row) {
$rows = $this->getCategoryTree($row->id);
}
}
//return $rows;
}
echo $rows;
// output will be show as string so i have to return this string in a variable
Root
—Sub category of root
category 1
—sub category of category 1
——sub category of first sub category of category 1
答案 0 :(得分:6)
您的代码中最大的问题是您在foreach循环中覆盖了$rows
。
此外,使用递归解决方案,就像你已经去过的那样,跟踪从函数/方法的内部调用返回的内容非常重要。
另外,我添加了一个订单,以确保首先显示根类别。
protected function getCategoryTree($level = 0, $prefix = '') {
$rows = $this->db
->select('id,parent_id,name')
->where('parent_id', $level)
->order_by('id','asc')
->get('categories')
->result();
$category = '';
if (count($rows) > 0) {
foreach ($rows as $row) {
$category .= $prefix . $row->name . "\n";
// Append subcategories
$category .= $this->getCategoryTree($row->id, $prefix . '-');
}
}
return $category;
}
public function printCategoryTree() {
echo $this->getCategoryTree();
}
答案 1 :(得分:0)
试试以下......
<?php
$sql = "SELECT id, name, parent_id FROM category ORDER BY parent_id, id";
$results = mysqli_query($con,$sql) or die(mysqli_error()) ;
if($results)
{
while($result = mysqli_fetch_array($results))
{
$category['categories'][$result['id']] = $result;
$category['parent_cats'][$result['parent_id']][] = $result['id'];
}
}
?>
<?php
function getCategories($parent, $category)
{
$html = "";
if (isset($category['parent_cats'][$parent]))
{
$html .= "<ul>\n";
foreach ($category['parent_cats'][$parent] as $cat_id)
{
if (!isset($category['parent_cats'][$cat_id]))
{
$html .= "<li>".$category['categories'][$cat_id]['name']."</li> \n";
}
if (isset($category['parent_cats'][$cat_id]))
{
$html .= "<li>". $category['categories'][$cat_id]['name'] . " \n";
$html .= getCategories($cat_id, $category);
$html .= "</li> \n";
}
}
$html .= "</ul> \n";
}
return $html;
}
?>
现在调用Recursive函数来显示层次结构中的所有类别:
<?php echo $data['category'] = getCategories(0, $category);?>
详情info
答案 2 :(得分:0)
<?php
$servername = "localhost";
$username = "root";
$password = "";
$conn = new mysqli($servername, $username, $password,'test');
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
function getCategoryTree($level = 0, $prefix = '') {
$category = '';
$sql = "SELECT * FROM category WHERE parent_id = $level ORDER BY id asc";
$result = $GLOBALS['conn']->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$category .= $prefix . $row['name'] . "<br/>";
$category .= getCategoryTree($row['id'], $prefix . '-');
}
}
return $category;
}
function printCategoryTree() {
echo getCategoryTree();
}
printCategoryTree();
?>
答案 3 :(得分:0)
此表:
CREATE TABLE `categories` (
`id` int(11) NOT NULL,
`parent_id` int(11) NOT NULL DEFAULT '0',
`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
首先创建config.php。
<?php
$servername = "localhost";
$username = "root";
$password = "";
$db = new mysqli($servername, $username, $password,'test');
if ($db->connect_error) {
die("Connection failed: " . $db->connect_error);
}
?>
然后创建category.php。
<?php
require 'config.php';
if(isset($_POST['submit']))
{
$parent_id=$_POST['parent_id'];
$name=$_POST['name'];
global $db;
$db->query("INSERT INTO categories (name,parent_id) VALUES('$name','$parent_id') ") or die(mysql_error());
}
function categoryTree($parent_id = 0, $sub_mark = ''){
global $db;
$query = $db->query("SELECT * FROM categories WHERE parent_id = '$parent_id' ORDER BY name ASC ");
if($query->num_rows > 0){
while($row = $query->fetch_assoc()){
echo '<option value="'.$row['id'].'">'.$sub_mark.$row['name'].'</option>';
categoryTree($row['id'], $sub_mark.'---');
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form action="" method="POST"><select name="parent_id">
<option value="0">Select Category</option><?php categoryTree(); ?>
</select>
Category : <input name="name" type="text" />
<input name="submit" type="submit" value="Submit" /></form>
</body>
</html>
答案 4 :(得分:0)
Create a file add.php
<script type="text/javascript" src="<?=$this->config->item('js_path')?>jquery-3.2.1.js"></script>
<script type="text/javascript" src="<?=$this->config->item('js_path')?>jquery.validate.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.2.0/jquery-confirm.min.css" rel="stylesheet" type="text/css" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.0.2/js/toastr.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.2.0/jquery-confirm.min.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="<?=$this->config->item('css_path')?>bootstrap.min.css">
<html>
<head>
<div id="myDropdown" class="dropdown-content">
<a href="<?php echo base_url('Category/add') ?>">Category Form</a>
<a href="<?php echo base_url('Category/index') ?>">User Listing</a>
</div>
<div align="center"><h3>Category Form</h3></div>
</head>
<body>
<form id="signup_form" method="post" action="" enctype="multipart/form-data" >
<table border="1" align="center" width="450">
<tr>
<td>Category Name</td>
<td>
<input type="text" id="category_name" name="category_name" onkeypress="return isChar(event)" value="<?php echo !empty($editRecord[0]->category_name) ? $editRecord[0]->category_name :'' ?>" class="form-control" placeholder="Category Name">
</td>
</tr>
<tr>
<td>Category</td>
<td>
<select class="form-control" id="parent_id" name="parent_id">
<option value="">Select Category</option>
<?php if(!empty($result)){ ?>
<?php foreach($result as $category){ ?>
<option value="<?php echo $category['id'] ?>"><?php echo $category['category_name']; ?></option>
<?php
if(!empty($category['subs'])) {
foreach ($category['subs'] as $sub) {
?>
<option value="<?php echo $category['id'] ?>"><?php echo '--' . $sub['category_name'] ?></option>
<?php
}
}
?>
<?php } }else{
echo '<li><a href="javascript:void();" style="color:red;">Sorry no category found.</a></li>';
} ?>
</select>
</td>
</tr>
<tr collspan="2">
<td align="center">
<input type="submit" name="submit" value="submit">
</td>
</tr>
</table>
<input type="hidden" name="id" id="id" value="<?= !empty($editRecord[0]->id)?$editRecord[0]->id:'';?>" >
</form>
</body>
</html>
<script type="text/javascript">
$("#signup_form").validate({
onkeyup: false,
rules:{
category_name: {
required: true
},
},
messages:{
category_name:{
required: "Category Name cannot be blank.",
},
},
});
function isChar(evt)
{
evt = (evt) ? evt : window.event;
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode >=48 && charCode <= 57) {
return false;
}
return true;
}
$('#signup_form').submit(function(e) {
/* Populate data to state dropdown */
var form = $(this);
e.preventDefault();
$.ajax({
type: "POST",
url: "<?php echo base_url('Category/insert_record/');?>",
data: form.serialize(),
success:function(data){
//console.log(data);
$('#parent_id').html('<option value="">Select Category</option>');
var dataObj = jQuery.parseJSON(data);
if(dataObj){
$(dataObj).each(function(){
var option = $('<option />');
option.attr('value', this.id).text(this.category_name);
$('#parent_id').append(option);
});
}
toastr.success('Category Added Successfully.', 'Success Alert', {timeOut: 5000});
$('#signup_form').trigger("reset");
},
error: function() { toastr.danger('Something went worng.', 'Danger Alert', {timeOut: 5000}); }
});
});
</script>
创建文件列表。php
<link rel="stylesheet" type="text/css" href="<?=$this->config->item('css_path')?>bootstrap.min.css">
<script type="text/javascript" src="<?=$this->config->item('js_path')?>jquery-3.2.1.js"></script>
<html>
<body>
<table border="2" align="center">
<tr>
<td width="30">#</td>
<td>Product Name</td>
<td>Price</td>
<td>Category Name</td>
<td>Sub_Category Name</td>
<td>Image</td>
<td>Action</td>
</tr>
<?php
foreach($products as $product)
{
?>
<tr>
<td><?php echo $product->id;?></td>
<td><?php echo $product->product_name;?></td>
<td><?php echo $product->price;?></td>
<td><?php echo $product->category_name;?></td>
<td><?php echo $product->subcategory_name;?></td>
<td><img style="width: 50px;height: 40px;" src="<?php echo base_url('uploads/'. $product->image);?>" /></td>
<td>
<a href="<?php echo base_url('Category/edit_record/')?><?php echo $product->id?>">Edit</a>
<span class='delete' id='del_<?php echo $product->id; ?>'>Delete</span>
</td>
</tr>
<?php
}
?>
<tr>
<td colspan="2"><a href="<?php echo base_url('Category/add')?>">Add new</a></td>
</tr>
</table>
</body>
</html>
<script type="text/javascript">
$(document).ready(function(){
$('.delete').click(function(){
var el = this;
var id = this.id;
var splitid = id.split("_");
// Delete id
var deleteid = splitid[1];
// AJAX Request
$.ajax({
url: "<?php echo base_url('Category/delete/');?>",
type: 'POST',
data: { id:deleteid },
success: function(response){
// Removing row from HTML Table
$(el).closest('tr').css('background','tomato');
$(el).closest('tr').fadeOut(800, function(){
$(this).remove();
});
}
});
});
});
</script>
<style type="text/css">
.panel-heading a{float: right;}
#importFrm{margin-bottom: 20px;display: none;}
#importFrm input[type=file] {display: inline;}
</style>
现在创建category_model
class Category_model extends CI_Model
{
function ordered_menu($array,$parent_id = 0)
{
$temp_array = array();
foreach($array as $element)
{
if($element['parent_id']==$parent_id)
{
$element['subs'] = $this->ordered_menu($array,$element['id']);
$temp_array[] = $element;
}
}
return $temp_array;
}
public function get_categories()
{
$this->db->select('id,category_name');
$result = $this->db->get('categories');
return $result->result();
}
public function get_category(){
$this->db->select('id,category_name');
$this->db->where('parent_id',0);
$result = $this->db->get('categories');
return $result->result();
}
function getSubs($params = array())
{
$this->db->select('id, category_name,parent_id');
$this->db->from('categories');
if(array_key_exists("conditions",$params)){
foreach ($params['conditions'] as $key => $value) {
if(strpos($key,'.') !== false){
$this->db->where($key,$value);
}else{
$this->db->where('categories.'.$key,$value);
}
}
}
$query = $this->db->get();
$result = ($query->num_rows() > 0)?$query->result_array():FALSE;
return $result;
}
public function get_products()
{
$this->db->select('products.id,category_name,parent_id,product_name,price,subcategory_name,image');
$this->db->from('categories');
$this->db->join('products','products.category_id = categories.parent_id');
$this->db->join('sub_categories','sub_categories.cat_id = categories.id');
$result=$this->db->get();
return $result->result();
}
public function get_detail($id){
$this->db->select('*');
$this->db->where('id',$id);
$result = $this->db->get('products');
return $result->result();
}
}
?>
创建类别控制器。
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Category extends CI_Controller {
public function __construct()
{
parent:: __construct();
$this->load->model('category_model');
$this->load->model('Common_model');
}
public function index()
{
$data['products'] = $this->category_model->get_products();
$this->load->view('category/list',$data);
}
public function add()
{
$data['categories']=$this->db->get('categories')->result_array();
$data['result']=$this->category_model->ordered_menu( $data['categories'],0);
$this->load->view('category/add',$data);
}
public function insert_record()
{
$this->load->library('form_validation');
if($this->input->server('REQUEST_METHOD') == 'POST')
{
$this->form_validation->set_rules('category_name','Category Name','trim|required');
if($this->form_validation->run() == FALSE)
{
$this->load->view('category/add');
}
else
{
$post_array = $this->input->post();
if($post_array['parent_id'] == '')
{
$data = array(
'category_name' => $post_array['category_name'],
'parent_id' => 0,
);
}else{
$data = array(
'category_name' => $post_array['category_name'],
'parent_id' => $post_array['parent_id'],
);
}
$inser_data = $this->Common_model->insert('categories',$data);
if(!empty($inser_data))
{
$allcategory = $this->category_model->get_categories();
foreach ($allcategory as $value) {
$cat[] = $value;
}
echo json_encode($cat);
}
}
}
}
public function add_product()
{
$data['categories']=$this->category_model->get_category();
$this->load->view('category/add_product',$data);
}
public function get_subcatries(){
$subcat = array();
$category= $this->input->post('parent_id');
if($category){
$con['conditions'] = array('parent_id'=>$category);
$subcat = $this->category_model->getSubs($con);
}
echo json_encode($subcat);
}
public function insert()
{
$config['upload_path'] = 'uploads/';
$config['allowed_types'] = '*';
$config['max_filename'] = '255';
$config['encrypt_name'] = TRUE;
$config['max_size'] = '1024'; //1 MB
if (isset($_FILES['file']['name']))
{
if (0 < $_FILES['file']['error'])
{
echo 'Error during file upload' . $_FILES['file']['error'];
} else
{
if (file_exists('uploads/' . $_FILES['file']['name']))
{
echo 'File already exists : uploads/' . $_FILES['file']['name'];
}
else
{
$this->load->library('upload', $config);
if (!$this->upload->do_upload('file')) {
echo $this->upload->display_errors();
} else {
$photo = $_FILES['file']['name'];
}
}
}
} else {
echo 'Please choose a file';
}
$this->load->library('form_validation');
if($this->input->server('REQUEST_METHOD') == 'POST')
{
$this->form_validation->set_rules('product_name','Product Name','trim|required');
$this->form_validation->set_rules('price','Price','trim|required');
$this->form_validation->set_rules('category_id','Category Name','trim|required');
if($this->form_validation->run() == FALSE)
{
$this->load->view('category/add');
}
else
{
$post_array = $this->input->post();
if($post_array['subcat_id'] == '')
{
$data = array(
'product_name' => $post_array['product_name'],
'price' => $post_array['price'],
'category_id' => $post_array['category_id'],
'image' => $photo,
'subcat_id' => 0,
);
}else{
$data = array(
'product_name' => $post_array['product_name'],
'price' => $post_array['price'],
'category_id' => $post_array['category_id'],
'image' => $photo,
'subcat_id' => $post_array['subcat_id'],
);
}
$inser_data = $this->Common_model->insert('products',$data);
if(!empty($inser_data))
{
echo '1';
}else{
echo '0';
}
}
}
}
public function edit_record()
{
$id = $this->uri->segment(3);
$result = $this->category_model->get_detail($id);
if(empty($result))
{
redirect('Category/');
}
$data['editRecord'] = $result;
$this->load->view('category/add_product',$data);
}
}
?>
此创建用于添加类别的产品。
<script type="text/javascript" src="<?=$this->config->item('js_path')?>jquery-3.2.1.js"></script>
<script type="text/javascript" src="<?=$this->config->item('js_path')?>jquery.validate.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.2.0/jquery-confirm.min.css" rel="stylesheet" type="text/css" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.0.2/js/toastr.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.2.0/jquery-confirm.min.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="<?=$this->config->item('css_path')?>bootstrap.min.css">
<html>
<head>
<div id="myDropdown" class="dropdown-content">
<a href="<?php echo base_url('Category/add') ?>">Category Form</a>
<a href="<?php echo base_url('Category/index') ?>">Product Listing</a>
</div>
<div align="center"><h3>Product Form</h3></div>
</head>
<body>
<form id="product_form" method="post" action="" enctype="multipart/form-data" >
<table border="1" align="center" width="450">
<tr>
<td>Product Name</td>
<td>
<input type="text" id="product_name" name="product_name" onkeypress="return isChar(event)" value="<?php echo !empty($editRecord[0]->product_name) ? $editRecord[0]->product_name :'' ?>" class="form-control" placeholder="Product Name">
</td>
</tr>
<tr>
<td>Price</td>
<td>
<input type="text" id="price" name="price" onkeypress="return isNumber(event)" value="<?php echo !empty($editRecord[0]->price) ? $editRecord[0]->price :'' ?>" class="form-control" placeholder="Price">
</td>
</tr>
<tr>
<td>Category</td>
<td>
<select class="form-control" id="category_id" name="category_id">
<option value="">Select Category</option>
<?php if(!empty($categories)){ ?>
<?php foreach($categories as $category){ ?>
<option value="<?php echo $category->id ?>"><?php echo $category->category_name; ?></option>
<?php } }else{
echo '<li><a href="javascript:void();" style="color:red;">Sorry no category found.</a></li>';
} ?>
</select>
</td>
</tr>
<tr>
<td>Sub Category</td>
<td>
<select class="form-control" id="subcat_id" name="subcat_id">
<option value="">Select Sub Category</option>
</select>
</td>
</tr>
<tr>
<td>Image</td>
<td>
<input type="file" name="file" id="file" value="<?php echo !empty($editRecord[0]->file) ? $editRecord[0]->file :'' ?>">
</td>
</tr>
<tr collspan="2">
<td align="center">
<input type="submit" name="submit" value="submit">
</td>
</tr>
</table>
<input type="hidden" name="id" id="id" value="<?= !empty($editRecord[0]->id)?$editRecord[0]->id:'';?>" >
</form>
</body>
</html>
<script type="text/javascript">
$("#product_form").validate({
onkeyup: false,
rules:{
product_name: {
required: true,
},
price: {
required: true,
},
category_id:{
required: true,
}
},
messages:{
product_name:{
required: "Product Name cannot be blank.",
},
price:{
required: "Price cannot be blank.",
},
category_id:{
required: "Category Name cannot be blank.",
}
},
});
function isChar(evt)
{
evt = (evt) ? evt : window.event;
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode >=48 && charCode <= 57) {
return false;
}
return true;
}
function isNumber(evt)
{
evt = (evt) ? evt : window.event;
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode > 32 && (charCode < 48 || charCode > 57)) {
return false;
}
return true;
}
$(document).ready(function(){
$('#category_id').on('change',function(){
var category_id = $(this).val();
if(category_id){
$.ajax({
type:'POST',
url:'<?php echo base_url('Category/get_subcatries'); ?>',
data:'parent_id='+category_id,
success:function(data){
$('#subcat_id').html('<option value="">Select Subcategory</option>');
var dataObj = $.parseJSON(data);
if(dataObj){
$(dataObj).each(function(){
var option = $('<option />');
option.attr('value', this.id).text(this.category_name);
$('#subcat_id').append(option);
});
}else{
$('#subcat_id').html('<option value="">Subcategory not available</option>');
}
}
});
}else{
$('#subcat_id').html('<option value="">Select Category first</option>');
}
});
$('#product_form').submit(function(e) {
var id = $('#id').val();
e.preventDefault();
if(id == '')
{
url = "<?php echo base_url('Category/insert/');?>" + $("#id").val();
$.ajax({
url:url,
type:"post",
data:new FormData(this),
processData:false,
contentType:false,
cache:false,
async:false,
success: function(data){
if (data == 1) {
//setTimeout(function(){document.location.href = "index"},500);
toastr.success('Recored Added Successfully.', 'Success Alert', {timeOut: 5000});
}
$('#product_form').trigger("reset");
},
error: function() { alert("Error posting feed."); }
});
}
else
{
url = "<?php echo base_url('Category/update/');?>" + $("#id").val();
$.ajax({
url:url,
type:"post",
data:new FormData(this),
processData:false,
contentType:false,
cache:false,
async:false,
success: function(data){
if (data == 1) {
toastr.success('Recored Updated Successfully.', 'Success Alert', {timeOut: 5000});
setTimeout(function(){document.location.href = "index"},5000);
}
//$('#signup_form').trigger("reset");
},
error: function() { alert("Error posting feed."); }
});
}
});
});
</script>