I am trying to display categories stored in my database:
http://dl.dropbox.com/u/16459516/Screen%20shot%202012-05-05%20at%2015.59.40.png
My idea was to get all data out of the database within my model and the reconstruct the array within my function:
function get_all_categories() {
$query = $this->db->query('SELECT * FROM categories');
//code to reconstruct my array like:
//foreach($query->result_array() as $row) {
//$categories[$row['niveau_1']] = array[]
//}
return $categories;
}
and output some array like:
[0] => Array
(
[niveau_1] => main category name
[niveau_2] => Array(
...children here and children of these childs
)
)
Does anyone know how to do this? Im stuck here and dont know how to create the array... i know how to display it in my views but getting them in the array seems hard for me.
Thanks in advance!
This is an idea:
foreach category (except level 4) check if it is present into the result array($c)
if it is not then create an array using a label the category's name
once controlle categories 2 and 3 you can insert the last one inside the generated array
$query = $this->db->query('SELECT * FROM categories');
$raw_categories = $query->result_array();
$c = array();
foreach($raw_categories AS $row)
{
if(!array_key_exists($row['niveau_2'],$c) && !empty($row['niveau_2']))
{
$c[$row['niveau_2']] = array();
}
if(!array_key_exists($row['niveau_3'],$c[$row['niveau_2']]) &&
!empty($row['niveau_3']))
{
$c[$row['niveau_2']]['niveau_3'] = array();
}
$c[$row['niveau_2']]['niveau_3'][] = $row['niveau_4'];
}
this is not tested but you can use it as an idea
I think your database is wrong. As I understand it's a "table of content" or similar (category, sub-category, sub-sub-category, etc.). "1. Visie, Beleid..." appears many-many times.
If I'd do I change the database:
table niveau_1
id_1 - primary key
title - string
table niveau_2
id_2 - primary key
id_1 - connect to niveau_1 (which niveau_1 is its 'parent')
title - string
table niveau_3
id_3 - primary key
id_2 - connect to niveau_2 (which niveau_2 is its parent)
title - string
In this case in your database will not duplicated elements and I think your desired query will be simplier:
SELECT
niveau_1.title AS title_1,
GROUP_CONCAT(niveau_2.title,"#") AS title_2,
GROUP_CONCAT(niveau_3.title,"#") AS title_3
FROM niveau_1
LEFT JOIN niveau_2 ON niveau_2.id_1=niveau_1.id_1
LEFT JOIN niveau_3 ON niveau_3.id_2=niveau_2.id_2
GROUP BY niveau_2.id_2
This query is only a half-solution, it isn't perfect for you but you can start from here.
// your model using activerecord
public function getCategories(){
$q = $this->db->get('categories');
if($q->num_rows > 0){
return $q->result();
}else{
return false;
}
}
//your controller
$this->load->model('category_model');
$data['results'] = $this->category_model->getCategories();
foreach($data['results'] as $c){
//iterate through categories, match them to points.
//match category_id in results with category_id in the other table results
//setup a multi dimensional array to build up what you need.
}
Related
Product Table
where i want to fetch only featured product. I have defined a column in database product_type in which four types of products(hot deals, newly listed, deals of the day and featured product)strong text can be listed which is optional.
Blockquote
Here is my model|query code in codeigniter
public function featured_product()
{
$arrResult = array();
$this->db->select('*');
$this->db->from('product');
$this->db->where("product_type","featured");
$result = $this->db->get()->result_array();
if(!empty($result))
{
$arrResult['result'] = $result;
}
else
{
$arrResult['result'] = '';
}
return $arrResult ;
}
When i try to fetch whole product list in api i get the result but i want to show only featured product.
You could try and use find_in_set:
https://dev.mysql.com/doc/refman/8.0/en/string-functions.html#function_find-in-set
I don’t know codeigniter, but I think, this looks useful:
https://forum.codeigniter.com/thread-71337.html
I propose a different approach.
This is not an answer to your question, but I hope it will allow you to rethink your table structure.
Instead of storing all the product_types in a single column use a pivot table (also known as a junction table).
You'll want to store all the data that you currently have in product_types column in a separate table(the pivot, lets call it product_to_type) and reference the id of product_table and product_type in the pivot table.
Something like this:
Here's a nice db-fiddle to play around with if you want.
This has multiple advantages:
You have a atomic tables
You can add data to either table without causing trouble in other tables
Foreign key ensure data consistency(you can probably do a better job with that. The keys are used are decent but not great)
You can extract any sort of data with the correct use of joins
You can add indexes to make the query buttery smooth
I'm sure there are other advantages too.
As I have changed my database to separate table with product_id matching with product_type. Still I find the solution to my question with a function FIND_IN_SET().
Here is my updated modal query:
public function featured_product()
{
$arrResponse = array();
$data = 'featured';
$this->db->select('*');
$this->db->where('find_in_set("'.$data.'", product_type) <> 0');
$this->db->from('product');
$result = $this->db->get()->result_array();
if(!empty($result))
{
$arrResponse['result'] = $result;
}
else
{
$arrResponse['result'] = '';
}
return $arrResponse ;
}
I am using Academy LMS Source code is in Github
it's a Learning Management system and it is designed to have one category per course
I want to add multiple categories to one course
In /controllers/API.php I have
// Fetch all the categories
public function categories_get($category_id = "") {
$categories = array();
$categories = $this->api_model->categories_get($category_id);
$this->set_response($categories, REST_Controller::HTTP_OK);
}
// Fetch all the courses belong to a certain category
public function category_wise_course_get() {
$category_id = $_GET['category_id'];
$courses = $this->api_model->category_wise_course_get($category_id);
$this->set_response($courses, REST_Controller::HTTP_OK);
}
then in /models/Api_model.php, I have
// Get categories
public function categories_get($category_id)
{
if ($category_id != "") {
$this->db->where('id', $category_id);
}
$this->db->where('parent', 0);
$categories = $this->db->get('category')->result_array();
foreach ($categories as $key => $category) {
$categories[$key]['thumbnail'] = $this->get_image('category_thumbnail', $category['thumbnail']);
$categories[$key]['number_of_courses'] = $this->crud_model->get_category_wise_courses($category['id'])->num_rows();
}
return $categories;
}
// Get category wise courses
public function category_wise_course_get($category_id)
{
$category_details = $this->crud_model->get_category_details_by_id($category_id)->row_array();
if ($category_details['parent'] > 0) {
$this->db->where('sub_category_id', $category_id);
} else {
$this->db->where('category_id', $category_id);
}
$this->db->where('status', 'active');
$courses = $this->db->get('course')->result_array();
// This block of codes return the required data of courses
$result = array();
$result = $this->course_data($courses);
return $result;
}
then in /model/Crud_model.php, I got
public function get_category_details_by_id($id)
{
return $this->db->get_where('category', array('id' => $id));
}
function get_category_wise_courses($category_id = "")
{
$category_details = $this->get_category_details_by_id($category_id)->row_array();
if ($category_details['parent'] > 0) {
$this->db->where('sub_category_id', $category_id);
} else {
$this->db->where('category_id', $category_id);
}
$this->db->where('status', 'active');
return $this->db->get('course');
}
in SQL course table has a column named category_id int(11) which stores one category per course I've changed it to TEXT format and put comma-separated values like 1,2,3 and used the ways like
$this->db->where_in('category_id',$category_id)
and
$this->db->like('category_id',$category_id)
and
$this->db->where("FIND_IN_SET(".$category_id.",category_id) >", 0);
and got no result I just need courses to have comma-separated values in the category_id column
Simply, I want courses to have multiple categories
DB tables
https://pasteboard.co/JNSxO2kz.png
course table
https://pasteboard.co/JNSy7g0.png
category table
https://pasteboard.co/JNSyhlk.png
category_id table (Mapping Table suggested by #micheal-la-ferla )
https://pasteboard.co/JNSyGGn.png
anybody could help?
The way Academy-LMS is designed, it lets you only add 1 category per course. It limits the user and it can be frustrating.
One workaround which could work is to create a new mapping table with 3 columns as follows:
Field Name | Data Type
------------+------------------
ID | int(11)
Course ID | int(11)
Category ID | int(11)
Obviously you need to have the permission to create new tables to use this workaround. Not sure if this is possible for your implementation of Academy-LMS.
The step above will essentially create a one to many relationship between the course and the category, so that 1 course can then be part of multiple categories. (In reality, this would be a many to many relationship since I am assuming that a category may obviously belong to multiple courses).
Therefore the database design will be similar to the one I created here.
If you implement this change, you would then need to make the following changes to the code you have:
// Get categories
public function categories_get($category_id)
{
if ($category_id != "") {
$this->db->where('category_id', $category_id);
}
$this->db->where('parent', 0);
$categories = $this->db->get('course_id')->result_array();
foreach ($categories as $key => $category) {
$categories[$key]['thumbnail'] = $this->get_image('category_thumbnail', $category['thumbnail']);
$categories[$key]['number_of_courses'] = $this->crud_model->get_category_wise_courses($category['id'])->num_rows();
}
return $categories;
}
Essentially, what I did here was replace the parent in the categories with category_id and category with course_id. Not sure if these are correct. You will need to review these when reading from the database as I never used CodeIgniter.
I have table menu with column: id, value, id_parent.
And have multilevel menu:
Item0
Item1
Item2
Item3
I want to delete Item1 and I have his id.
How I can delete Item2 and Item3 when I delete Item1?
I select from table:
public function searchChildren($id)
{
$sql = "SELECT id FROM menu WHERE id_parent = '{$id}'";
return $this->db->query($sql);
}
I can find id the first child:
$idChild = $this->model->search_children_id($id);
How can I find the rest children using a cycle or recursion?
I would create a variable function that i pass to itself by reference, probably better ways to do this, but i created a tree navigator using this method and it works perfectly
I would simply check if there is child under that id, if there is loop though them til there is no more childs, Once there then delete the id
this is non-tested code and sort of pseudo-code, but you will get the idea
$DeleteIdAndChilds= function($Id) use( &$DeleteIdAndChilds){
while($ChildId = $this->model->search_children_id($Id) != null){
$DeleteIdAndChilds($ChildId);
}
//once we are here there is no more child lets delete the $Id
}
cuz you have an id, just make function delete. examp:
function delete_menu($id){
$this->db->where('id_parent', $id);
$this->db->delete('menu');
}
I recommend a recursive function to find all of his children. What do you want to happen if there are multiple children at the same level?
UPDATE: My bad, I didn't mean to leave you hanging... Here is some code for a recursive function. It is essentially the same I use to display my menu except stripped down and refactored for your purpose.
I use pk_ID, Menu_Item, and Menu_Parent for the data columns.
I really hope this helps you.
Call the recursive function which will return a string of itself and all child Items.
Convert to an array.
Loop through the array to delete what you want.
$menu = rtrim(($this->getMenu(0)), ",");
$menu = explode(",", $menu);
public function getMenu($p_parentID=0) {
$output = "";
$data = $this->db->order_by("Menu_Parent, Menu_Item", "ASC")->get_where("my_menu", array(
"Menu_Parent" => $p_parentID,
));
foreach ($data->result() as $row) {
$output .= "{$row->Menu_Item}<br>";
if ($this->hasChildren($row->pk_ID)) {
$output .= $this->getMenu($row->pk_ID);
}
}
return $output;
} # END FUNCTION getMenu
public function hasChildren($p_value=0) {
$data = $this->db->get_where("my_menu", array(
"Menu_Parent" => $p_value
));
$result = $data->num_rows();
return $result;
} # END FUNCTION hasChildren
I'm building a codeigniter site and I have a database table of books - one record for each book with title, author, etc etc fields. I know how to get the db table contents and pass an object to the view and then do a foreach loop to get the values. I could print a table of all the data. However I then get a bit muddled. The page has areas for each book and the data for a book will be one row of the data array. So what I want to do is, if the author is 'this' value, find the correct row in which the author appears and then get the other fields. How can I do a foreach loop that finds the one row with the author's name?
I can't think how to do it - I seem to go round and round in circles.
Help!
Edit: Code:
OK so here's the controller method:
public function index()
{
$books = $this->Books_model->getbooks();
$data = array(
'body_id'=>'home',
'main'=>'home_view',
'books'=>$books
);
$this->load->view('templates/template_main_view', $data);
}
and here's the model method:
function getbooks(){
$query = $this->db->get('books');
return $query->result();
}
so I end up with the variable $books (which is of course an object, not an array) in the view and a var_dump() shows that it has all the data. So far so good. I can then use a foreach loop to get values.
Now I want to extract a single row/record conditional on the fact that it has a given value for 'author' and assign each field of that row to a variable that I can use them in the view. And then I want to repeat that for the other rows. I can't seem to work out how to do that.
Afternote:
I found a way of doing this but not sure if it's the best or neatest:
I do this:
if(isset($books)){
foreach($books as $row){
if($row->author == 'authorname'){
$title = $row->title;
}
}
}
it works but seems a bit clumsy/overkill??
How about creating a specific function for getting the book/s that matches the author name?
For example:
In your controller you can do something like this:
public function index()
{
$data['books'] = $this->Books_model->get_each_book();
$data = array(
'body_id'=>'home',
'main'=>'home_view',
'books'=>$books
);
$this->load->view('templates/template_main_view', $data);
}
The in your model, do something like this:
function get_each_book(){
$this->db->where('author','authorname');
$query = $this->db->get('books');
return $query->result_array();
}
This way, you are gonna filter the results in the model already.
Then in your view, access the variable 'books' through a foreach loop:
Example:
foreach($books as $row)
{
$title = $row['title'];
echo $title;
}
I'm trying to populate a multiselect in my view with the results from a query to the database. Sorry if this is a very basic question—I'm a bit new to CodeIgniter and MVC.
My model simply gets all records from a table:
function getAll() {
$query = $this->db->get('example');
return $query->result_array();
}
I then hope to pass the results to my view to populate a multiselect form element. However, the associative array that is returned does not provide the results I'd like.
What I get:
[0] Array
(
[id] => 6
[name] => Bob
What I'd like to get:
[0] Array
(
[6] => Bob
[7] => Linda
Am I missing something with my query that would achieve my desired results? Should I just use a foreach to create a new array that will be formatted the way I would like? If so would this foreach belong in my controller or view.
Thank you for your help.
Try this:
function getAll()
{
$items = $this->db->get('example')->result_array();
if(empty($items))
return array();
$res = array();
$i = 0;
while($i < count($items))
{
$res[$items[$i]['id']] = $items[$i]['name'];
++$i;
}
return array($res);
}
The most efficient way would be to use active record, because it just gets the data from the column 'name' in your table)
$this->db->select('name')
->from('example');
return $this->db->get()->result();
If you were going to use a foreach loop, if you process the results in the controller you would have to process them again in the view, so you may as well send the entire result array to the view and process them in the view. This is useful if you need to use most of the columns of one particular table in your view.