nested foreach codeigniter - php

In codeigniter 1.73 i'm trying to display books by category. so if i have a category called cars, i should see a list of books within cars. so i tried a nested foreach loop to accomplish this but can't seem to get it to work.
<?php
class Book_model extends Model {
function books_by_category()
{
$this->db->select('*');
$this->db->from('categories');
$this->db->join('books', 'books.category_id = categories.id');
$query = $this->db->get();
return $query->result();
}
}
then in the view:
foreach($data as $category) {
if (sizeof($category['books']))
{
foreach($category['books'] as $book)
{
<li>$book->book_number anchor("book/chapters/$book->id", $book->book_title)</li>
}
} else {
// show 'no books'
}
}
controller:
function index() {
$data = array();
if($query = $this->book_model->books_by_category())
{
$data['books_by_category'] = $query;
foreach($query as $row)
{
if (!isset($data[$row['id']]))
{
$data[$row['id']] = $row;
$data[$row['id']]['books'] = array();
}
$data[$row['id']]['books'][] = $row;
}
$data['main_content'] = 'books_view';
$this->load->view('includes/template', $data);
}
}

Foreach does not have an "else" clause, as you've used.
foreach($category['books'] as $book)
{
// show books
} else {
// show 'no books'
}
Instead, you could do this: (my PHP is rusty)
if(count($category['books']) <= 0)
{
//No books
}
else
{
foreach($category['books'] as $book)
{
//You have books
}
}

A couple of points
function books_by_category()
{
$this->db->select('*');
$this->db->from('categories');
$this->db->join('books', 'books.category_id = categories.id');
$query = $this->db->get();
return $query->result();
}
This code returns all columns for categories and books that have a category set, is this really what you are trying to do? The function name 'books_by_category' would suggest to me that you are only interested in books for one specific category, from looking at your question I'm guessing this isn't the case.
Presuming you are trying to get all books but group them by category I would do the following:
model
function get_books()
{
$this->db->select('*');
$this->db->from('books');
$this->db->join('categories', 'categories.id = books.category_id');
$query = $this->db->get();
if($query->num_rows() == 0)
{
#no books
return false;
}
return $query->result();
}
controller
function index() {
$data = array();
$book_list = $this->book_model->get_books();
if($book_list)
{
$categories = array();
$books_by_category = array();
foreach($book_list as $book)
{
$category_id = $book['category.id'];
$category_name = $book['category.name'];
if(array_key_exists($category_id, $categories))
{
$categories[$category_id] = $category_name;
}
if(array_key_exists($category_id, $books_by_category))
{
$books_by_category[$category_id] = array();
}
$books_by_category[$category_id][] = $book;
}
$data['categories'] = $categories;
$data['books_by_category'] = $books_by_category;
}
$data['main_content'] = 'books_view';
$this->load->view('includes/template', $data);
}
and the view
<?php if(isSet($books_by_category)) : ?>
<?php foreach($books_by_category as $category => $book_list): ?>
<p>Category: <?php echo $categories[$category]; ?></p>
<ul>
<?php foreach($book_list as $book) : ?>
<li><?php echo $book->book_number; ?>. <?php echo anchor('bible/chapters/' . $book->id, $book->book_title); ?></li>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
<?php else: ?>
<p>Sorry dude, no books.</p>
<?php endif; ?>

There are a few errors in the code which might be causing this.
You have an extra closing bracket before the end of the foreach loop in your controller.
In your view, you are looping through the books category as $book but then you are trying to work with the $row object inside the loop. Try changing this to $book.
Also in your view, you trying to output some HTML without closing out of your PHP tags. The <li> tags in your code are inside your PHP block and then you try to open up a new PHP block again without ever closing the first one.

I came across this and tried to follow along with the example #mattumotu posted and it was really helpful, but I think it might have some errors - specifically with the way the array is being indexed and then looped through. If you are using a number as an id value, and your ids do not start from zero and increase in numerical order from 0 to x, then you will get unknown index orders in your view when you attempt to loop through the array (at least I did). So I modified the example as follows (note I changed the variable names slightly for my own use):
Model:
public function get_imagery_by_category(){
$this->db->select('extra_imagery.*', FALSE); //MH - not sure what FALSE does here
$this->db->select('extra_image_categories.id as cat_id, extra_image_categories.name as cat_name', FALSE); //MH alias the category id and name as they are the same column names as the imagery name and id
$this->db->from('extra_imagery');
$this->db->join('extra_image_categories', 'extra_image_categories.id = extra_imagery.cat'); //get all images where the image cat matches category id
$this->db->order_by('extra_image_categories.id');
$query = $this->db->get();
if($query->num_rows() == 0){
return false;
} else {
return $query->result_array();
}
}
Here we're just sorting all of our items by the category ID, to ensure we are moving through all of our items in numerical order by their category ID, essentially listing items out by category.
Controller:
$imagery_list = $this->imagery_model->get_imagery_by_category();
if($imagery_list){
$categories = array();
$imagery_by_category = array();
$curCatIndex = -1;
$curCatID = NULL;
foreach($imagery_list as $i=>$image){
$category_id = $image['cat_id'];
$category_name = $image['cat_name'];
if ($curCatID != $category_id){
$curCatIndex+=1;
$categories[$curCatIndex] = $category_name;
$curCatID = $category_id;
}
$imagery_by_category[$curCatIndex][] = $image;
}
//print_r($imagery_by_category);
$data['categories'] = $categories;
$data['imagery_by_category'] = $imagery_by_category;
}
Here we're setting an array to hold our categoriesand an array to hold our items. The $imagery_by_category will be a multidimensional array, such that all items in the first category end up in the first array, all items in the second category are in the second array, etc. Like this:
$imagery_by_category[0][0] = category0, item0
$imagery_by_category[0][1] = category0, item1
$imagery_by_category[1][0] = category1, item0
We're setting a counter ($curCatIndex) that will keep track of each time we hit a new category id, and a variable for the category ID to check if our category id has changed ($curCatID). If we hit a new category ID, we know we've collected all the items for that category, so we increment the curCatIndex counter:
$curCatIndex+=1;
Because our $curCatID starts out as NULL when we begin our loop, we increment the $curCatIndex so that our array will start out at index 0.
Whenever we hit a new category id, we push the name of that category to our $categories array:
$categories[$curCatIndex] = $category_name;
and set the $curCatID equal to our new id:
$curCatID = $category_id;
Then, regardless of whether we are in a new category or not, we push the item to the proper place in the multidimensional array:
$imagery_by_category[$curCatIndex][] = $image;
and lastly we just make these arrays available to our view:
$data['categories'] = $categories;
$data['imagery_by_category'] = $imagery_by_category;
Then, in our view:
<?php if(isSet($imagery_by_category)) : ?>
<?php foreach($categories as $i=>$category_item): ?>
<p><?php echo $category_item ?></p>
<?php foreach($imagery_by_category[$i] as $image_item) : ?>
<?php
echo $image_item['id'];
?>
<?php endforeach; ?>
<?php endforeach; ?>
<?php else: ?>
<p>No imagery</p>
<?php endif; ?>
We have a nested loop. The outer loop loops through our categories:
<?php foreach($categories as $i=>$category_item): ?>
Notice that we've added a variable $i to keep track of the loop index (i.e. array index)
Then we print out the name of the category:
<p><?php echo $category_item ?></p>
and then the inner loop loops through the items in that category:
<?php foreach($imagery_by_category[$i] as $image_item) : ?>
Notice we're using the $i variable here to make sure we select the right dimension from our item array.
Then inside this loop you can do whatever you want. Here I'm just printing out the unique id of my item:
echo $image_item['id'];
Probably a more elegant way to do this, but hope it helps someone. I banged my head against the wall on this for awhile. Thanks to mattumotu for getting me on the right track. I've posted a clearer code example here:
http://mikeheavers.com/main/code-item/order_items_in_one_database_table_by_categories_from_another_database_table

Related

variables within controller foreach returns NULL inside view

I have a web application built using codeigniter. What I'm trying to do is show a summary of results on my view. In my controller I have the below code
function index() {
$data['summery'] = $this->Main_model->get_summery();
foreach ($data['summery'] as $d) {
$data['total_week'] = $this->Main_model->get_total_week($d['i_id']);
$data['total_month'] = $this->Main_model->get_total_month($d['i_id']);
}
}
The problem that im having is each summery record has total weekly count and a monthly count based on the i_id
in my view i loop through the summery and it display the summery but when i echo $total_week or echo $total_month its always returns NULL
$data['total_week'] = $this->Main_model->get_total_week($d['i_id']);
$data['total_month'] = $this->Main_model->get_total_month($d['i_id']);
When i do a var_dump on the above variables it shows the number, but when i try to echo it on the view it returns NULL
I hope I under stood correct Try something like this
function index() {
$this->load->model('main_model');
$data['summery'] = array();
$summery = $this->main_model->get_summery();
foreach ($summery as $d) {
$data['summery'][] = array(
'total_week' => $this->main_model->get_total_week($d['i_id']),
'total_month' => $this->main_model->get_total_month($d['i_id'])
);
}
$this->load->view('the_view', $data);
}
View
<?php foreach ($summery as $something) {?>
<?php echo $something['total_week'];?>
<?php echo $something['total_month'];?>
<?php }?>

push array data in every index of an array using codeigniter php

I have two tables sport_tbl, match_tbl. In sport_tbl, i defined sport_name such as cricket. In match_tbl, I have match_name,match_date,sport_id.
I want to show match_date of every sport_name (ex. i am showing match_date list for cricket sport and i want to show every date has match_name list).
I want to show one distinct match_date.
Image
my controller code:-
$url = 'cricket' // for example first sport_name
$data['getSportMatch'] = $this->user_model->getSportMatch($url);
my model code:-
public function getSportMatch($sport)
{
$query = $this->db->get_where('match_tbl',array('sport_name' => $sport));
if($query->num_rows > 0)
{
foreach($query->result() as $item){
$data[] = $item;
}
return $data;
}
}
my code in view:-
<div><?php foreach($getSport as $item): ?><h4><?= $item->sport_name; ?></h4><div><?= foreach($getSportMatch as $item): ?>
match_date)) ?>here i want to show list match_name of every match_date
My table structure images
1) sport_tbl
2) match_tbl
3) another match_tbl
you can solve this in model easily. if i did not understand wrong . you need 2 function in model.
1. will get sport names
2. will get matches of given sport name
//model functions
function get_sports(){
$data = array();
$sports = $this->db->select('sport_name')->from('sport_tbl')->get()->result();
if($sports)
{
foreach($sports as $sport){
$data[$sport->sport_name] = $this->get_matches($sport->sport_name);
}
return $data;
}
}
function get_matches($sport_name){
$matches = $this->db->select('*')->from('match_tbl')->where('sport_name',$sport_name)->get()->result();
return $matches;
}
so in view data will be something like this
$data => array(
'cricket'=> array(0 => array(
'match_id' => 11,
'sport_id' = 2 .....
)))
Try this coding ...
public function getSportMatch($sport)
{
$query = $this->db->query("SELECT * FROM sport_tbl as st INNER JOIN match_tbl as mt ON st.sport_id = mt.sport_id WHERE st.sport_name ='".$sport."'");
if($query->num_rows > 0)
{
$query_result = $query->result_array();
$final_result = array();
foreach($query_result as $result ) {
$date = $result['match_date'];
$final_result[$date][] = $result;
}
return $final_result;
}
}
View Coding :-
if(isset($final_result)) {
foreach($final_result as $result) {
echo $result['match_date']; // First display match date
if(isset($result['match_date'])) {
foreach($result['match_date'] as $match) {
echo $match['match_name']; // Second listout the match name
}
}
}
}

How can I get category name of post in news module from category module in CodeIgniter HMVC

I want to get category name for news post. I can easily get category id but I want to get category name using category Id or other method. How should I do that?
This is how I displayed my blog post in controller
function post($slug = FALSE)
{
if (isset($slug)) {
$data['query'] = $this->mdl_blogs->get_where_slug($slug);
$data['view_file'] = "blog_view";
$this->load->module('template');
$this->template->public_one_col($data);
}
}
in model
function get_where_slug($slug){
$table = $this->get_table();
$this->db->where('news_slug', $slug);
$query=$this->db->get($table);
return $query;
}
in view
<?php
foreach ($query->result() as $row) {
$data['news_title'] = $row->news_title;
$news_body = $row->news_body;
$news_slug = $row->news_slug;
$category_id = $row->category_id;
//$data['category_name'] = $row->category_name;
//$news_category = $row->news_category;
?>
<h2><a href="<?php echo (base_url().'blogs/post/'.$news_slug) ;?>">
<?php echo $data['news_title'];?></a></h2>
<p><?php echo $news_body;?></p>
<p><?php echo $category_id;?></p>
<?php
}
?>
<?php
//echo Modules::run('comments');
?>
Here I also want to display category name. I want to get it from categories table
Here are my tables
in News table
news_id
category_id
news_slug
......
in categories
category_id
category_name
category_slug
You need to join your category table in your model
function get_where_slug($slug){
$table = $this->get_table();
$query=$this->db
->select('n.*,c.category_name,c.category_slug')
->from($table.' n')
->join('category c','n.category_id=c.category_id','LEFT')
->where('n.news_slug', $slug)
->get();
return $query;
}
And in your view you can have you category name in foreach loop as
$category_name = $row->category_name;
same for category_slugif you want this too

Printing the Categories and Sub Categories Alone

function build_list($id=0,$collapsed="") //return an array with the categories ordered by position
{
$RootPos = "";
$this->c_list = array();
if($id != 0){
$this_category = $this->fetch($id);
$positions = explode(">",$this_category['position']);
$RootPos = $positions[0];
}
// lets fetch the root categories
$sql = "SELECT *
FROM ".$this->table_name."
WHERE position RLIKE '^([0-9]+>){1,1}$' AND c_group = '".$this->Group."'
ORDER BY c_name";
$res = mysql_query($sql) or die(trigger_error("<br><storng><u>MySQL Error:</u></strong><br>".mysql_error()."<br><br><storng><u>Query Used:</u></strong><br>".$sql."<br><br><storng><u>Info:</u></strong><br>",E_USER_ERROR));
while($root = mysql_fetch_array($res)){
$root["prefix"] = $this->get_prefix($root['position']);
$this->c_list[$root['id']] = $root;
if($RootPos == $root['id'] AND $id != 0 AND $collapsed != ""){
$this->list_by_id($id);
continue;
}else{
// lets check if there is sub-categories
if($collapsed == "" AND $id==0){
$has_children = $this->has_children($root['position']);
if($has_children == TRUE) $this->get_children($root['position'],0);
}}}
return $this->c_list;
}
// He is the Author of the code...
Categories Class
Author: Shadi Ali
Now I want to just return the Categories and Sub Categories from the above code.
function browse() {
$categories = new categories;
$categories_list = $categories->build_list();
foreach($categories_list as $c)
{
return $c->$id;
}
}
The above code is not working.... can anyone help me out.
Here are two problems with the browse() function:
The return statement is inside the foreach loop. The statement will return one value for one of the items in the $categories-list (at most), and not continue to loop over the rest of the $categories-list.
The $id variable is never declared or initialised in return $c->$id, perhaps you meant to use $c['id'] or $c->id

Populating accordion with database results help

I am building a system in which the user can build thre own navigation menu from a selection of catergories, the way it works is that is they click on 'Blog' they they can get an accordion titled 'Blog' and on expanding this they see all the blog titles, however as the moment, my application creates multiple accordions if there are multiple blog entries, so at the moment i have two blog entries and when the user slects 'Blog' they get to accordions, where as they should get one with all the titles in
Controller:
public function category($content_id) {
//$this->output->enable_profiler(TRUE);
if (intval($this->uri->segments[4])){
$content_id = $this->uri->segments[4];
} else {
$content_id = $this->uri->segments[7];
}
$data['content'] = $this->site_model->get_content($content_id);
$this->load->view("call", $data);
}
Model:
public function get_content($content_id) {
$this->db->select('*');
$this->db->from ('content');
$this->db->join('categories', 'categories.category_id = content.categories_category_id', 'left');
$this->db->where ('categories_category_id', $content_id);
$query = $this->db->get();
return $query->result_array();
}
View:
<?php
if(isset($content)) {
// var_dump($content);
foreach($content as $row) {
echo "<h2 class='$row[category_name]'><a href='#'>$row[category_name]</a></h2>";
echo "<div class='$row[category_name]'><a href='index.php/home/get_content/$row[content_id]' class='contentlink'>$row[content_title]</a></div>";
}
}
?>
How can I alter my code so for category the user selects only one accordion gets built put all the categories realted content is placed in that accordion?
Hope this makes sense.
If I understand correctly you should move the creation of the header out of your loop:
<?php
if(isset($content)) {
echo "<h2 class='$category_name'><a href='#'>$category_name</a></h2>";
foreach($content as $row) {
echo "<div class='$row[category_name]'><a href='index.php/home/get_content/$row[content_id]' class='contentlink'>$row[content_title]</a></div>";
}
}
?>
If you don't know the category name you could try something like this:
<?php
$first = true;
if(isset($content)) {
echo "<h2 class='$category_name'><a href='#'>$category_name</a></h2>";
foreach($content as $row) {
if ($first) {
echo "<h2 class='$row[category_name]'><a href='#'>$row[category_name]</a></h2>";
$first = false;
}
echo "<div class='$row[category_name]'><a href='index.php/home/get_content/$row[content_id]' class='contentlink'>$row[content_title]</a></div>";
}
}
?>

Categories