So basically what I am trying to do is retrieving a list of categories from the database and placing it in a variable called $data['categories'].
In the view I am listing this up by simply using a foreach() statement. So far so good.
Though, some categories have subcategories (not all of them). Now, I added a row in the database saying 'is_direct' (has subcategories or not) which displays whether the category has subcategories or not.
Now, I want to list up those subcategories in case they exist.
Here the method to display the header (where the categories and subcategories will be listed) (Don't mind the private, it should be that).
private function show_header($template='default',$page_name='default')
{
// Get the categories.
$data['categories'] = $this->CI->ws_category->get_categories();
// Display the header.
$this->CI->load->view("templates/".$template."/template/header",$data);
}
This method calls for the method get_categories(), that's the one below (simple Active Record).
public function get_categories()
{
// Prepare the SQL query.
$this->db->select('*');
$this->db->from(APP_PREFIX.'categories');
$this->db->order_by('name_clean');
// Execute the query.
$query = $this->db->get();
// Get the results from the query.
$result = $query->result_array();
// Return the array with data.
return $result;
}
And below the view, you can see where the submenu would go.
<?php
// Loop through all the categories.
foreach ($categories as $item):
?>
<li class='nav_link <?php ($item['is_direct'] == '1' ? 'nav_subcats' : ''); ?>'>
<a href='<?php echo base_url().'category/'.$item['category_id'].'-'.$item['name_clean'].'.html';?>' class='nav_main_link'><?php echo $item['name']; ?></a>
<?php
// In case subcategories are present.
if ($item['is_direct'] != '1')
{
?>
<div class='nav_submenu'>
<ul>
<li><a href='#' class='nav_sub_link'>submenu item</a></li>
</ul>
</div>
<?php
}
?>
</li>
<?php
// End the loop.
endforeach;
?>
Can somebody help me?
Thank you.
The approach I would take would be to build out more complete data in your model (or controller) so that you can simply loop through it in the view (like you are currently doing). Below I have written a possible solution. I have modified your get_categories() method to query for subcategories as well. Then, in the view, we check to see if a category has any subcategories and outputs them as necessary.
public function get_categories_and_subcategories()
{
// Prepare the SQL query.
$this->db->select('*');
$this->db->from(APP_PREFIX.'categories');
$this->db->order_by('name_clean');
// Execute the query.
$query = $this->db->get();
// Get the results from the query.
$result = $query->result_array();
// Get subcategories
for ($i = 0; $i < count($result); $i++) {
// Check if subcategory
if ($result[$i]['is_direct']) {
// Query for subcategories - made up for demonstrational purposes
$query = $this->db->query("SELECT * FROM subcategories WHERE parent_id='".$result[$i]['id']."'");
// Add subcategories to category item
$result[$i]['subcategories'] = $query->result_array();
} else {
$result[$i]['subcategories'] = array();
}
}
// Return the array with data.
return $result;
}
Then in the view:
<li class='nav_link <?php ($item['is_direct'] == '1' ? 'nav_subcats' : ''); ?>'>
<a href='<?php echo base_url().'category/'.$item['category_id'].' '.$item['name_clean'].'.html';?>' class='nav_main_link'><?php echo $item['name']; ?></a>
<?php if (count($item['subcategories']) > 0): ?>
<div class='nav_submenu'>
<ul>
<foreach ($item['subcategories'] as $subcategory): ?>
<li><a href='<?php echo $subcategory['url']; ?>' class='nav_sub_link'><?php echo $subcategory['name']; ?></a></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
</li>
Keep in mind I haven't tested this code but you should be able to adopt the general idea to your application.
Related
I have a blog page. I want that when a user Clicks on "All Posts", it should show all posts from Blog. And when someone clicks on a category like "Catering", it should show the posts from "Catering" category only.
Here is what i have did so far
<div class="blog-nav">
<ul class="nav">
<li><a>All Posts</a></li>
<?php
$SelectBlogcats = mysqli_query($con, "SELECT * FROM blog GROUP BY cat_blog");
while($row = mysqli_fetch_assoc($SelectBlogcats)){
$Cat_query = mysqli_query($con,"SELECT * FROM cat_blog WHERE
id=".$row['cat_blog']);
$main_cat = mysqli_fetch_assoc($Cat_query);
?>
<li><a><?php echo $main_cat['bcat_name'];?></a></li>
<?php } ?>
</ul>
</div>
Tested and working answer
<?php
$cat_id=0;
$condition="";
if(isset($_GET['cat'])){
$cat_id=$_GET['cat'];
$condition="where cat_blog=$cat_id";
}
$SelectBlogcats = mysqli_query($con, "SELECT * FROM blog GROUP BY cat_blog");
while($row = mysqli_fetch_assoc($SelectBlogcats)){
$Cat_query = mysqli_query($con,"SELECT * FROM cat_blog WHERE
id=".$row['cat_blog']);
$main_cat = mysqli_fetch_assoc($Cat_query);
?>
<li>
<h2><?php echo $main_cat['bcat_name'];?></h2>
</li>
<?php } ?>
Some semi-pseudo code which might help you accomplish your goals - wholly untested however.
The nested sql queries you have is not very efficient and it is highly likely that a simple join between the tables is what you really need.
Each hyperlink used to select a new / different category to display needs to set ( in this example ) a querystring parameter which can be used to filter records from the entire recordset.
<?php
/*
Hopefully a single query should suffice
joining the two tables rather than querying
separately.
Store the result of the query and use that to build
the nav menu and also display the content late
*/
$cat=!empty( $_GET['category'] ) ? $_GET['category'] : 'all';
# without seeing the schema this is a guess!
$sql='SELECT * FROM `blog` b
JOIN `cat_blog` cb on cb.`id`=b.`cat_blog`
GROUP BY b.`cat_blog`';
$res=$con->query( $sql );
$rs=$res->fetch_all( MYSQLI_ASSOC );
?>
With the data stored in an associative array you can proceed to generate the hyperlink menu where each link has a querystring variable set; ie: ?category=X
<div class="blog-nav">
<ul class="nav">
<li><a href='?category=all'>All Posts</a></li>
<?php
foreach( $rs as $row ){
$active = $cat==$row['bcat_name'] ? ' class="active"' : '';
printf( '
<li%2$s>
%1$s
</li>
',
$row['bcat_name'],
$active
);
}
?>
</ul>
</div>
The recordset can then be processed again to output the actual blog content paying attention to the variable $cat to dictate which records are to be displayed.
<!-- blog display - ALL records or the filtered subset -->
<div class="blog-content">
<?php
if( !empty( $rs )){
foreach( $rs as $row ){
// display only the filtered category or ALL records
if( $cat==$row['cat_name'] or $cat=='all' ){
/* output your blog content ..... */
}
}
}else{
echo 'There was an error fetching database records.';
}
$res->close();
?>
</div>
I am building software where a Choir Leader can run multiple Choirs.
I am trying to return all members associated with a specific Choir Group. So when the Choir leader selects a specific Choir Location, they see all members asssociated with that location.
I have a aauth_users table and a choir_locations_to_users table in the MySQL Database.
the aauth_users table holds all the data regarding each choir member:
the choir_locations_to_users table is a seperate table that lists the user ID and the ID of the choir location.
I am performing a query to grab the necessary data I need to display all the members. such as member name, avatar etc to display on the Choir Location page.
The $id parameter in the function is the Choir Location ID.
public function get_choirlocation_members($id) {
// $query = 'SELECT aauth_users.full_name, aauth_users.avatar, aauth_users.last_login, choir_location_to_users.location_id FROM aauth_users, choir_location_to_users WHERE aauth_users.id = choir_location_to_users.user_id ';
$this->db->select('aauth_users.full_name, aauth_users.avatar, aauth_users.last_login, aauth_users.id, choir_location_to_users.location_id');
$this->db->from('aauth_users, choir_location_to_users');
$this->db->where('aauth_users.id = choir_location_to_users.user_id');
$this->db->order_by('aauth_users.last_login', 'DESC');
$members = $this->db->get();
foreach ($members->result() as $row) {
if($row->location_id == $id){
return $members;
}
}
}
The query above returns the following results:
The problem is in the function after the query it seems to be returning all of the members and not just the members related to this location. as when I do another foreach in my View File with the result I still see all members.
foreach ($members->result() as $row): ?>
<li>
<img class="profile-user-img img-responsive img-circle" src="<?php echo BASE_URL.'uploads/user/'.$row->avatar ?>" alt="User Image">
<a class="users-list-name" href="#"><?php echo $row->full_name ?></a>
<span class="users-list-date">Last Login: <?php echo date ( "d.m.Y " , strtotime ($row->last_login )); ?></span>
</li>
<?php endforeach; ?>
I would really appreciate any help to point out where I may be going wrong in trying to filter out the query results to show only members associated with a specific Choir location based on the location id.
UPDATE Anwser from #Dinesh Ali not working here is what I have:
I tested the new Join Query you suggested in phpMyAdmin and this is the result:
As you see it is returning the correct data in a result table, which is good, so I added the function you suggested like so:
public function get_choirlocation_members($id) {
$this->db->select('aauth_users.full_name, aauth_users.avatar, aauth_users.last_login, aauth_users.id, choir_location_to_users.location_id');
$this->db->from('aauth_users');
$this->db->join('choir_location_to_users', 'aauth_users.id = choir_location_to_users.user_id');
$this->db->where('aauth_users.id = choir_location_to_users.user_id');
$this->db->order_by('aauth_users.last_login', 'DESC');
$members = $this->db->get()->result();
if(isset($members) && count($members) > 0){
return $members;
}else{
return false;
}
}
Then in my view File I am using the following to show each user as a LI list item:
foreach ($members as $row): ?>
<li>
<img class="profile-user-img img-responsive img-circle" src="<?php echo BASE_URL.'uploads/user/'.$row->avatar ?>" alt="User Image">
<a class="users-list-name" href="<?php echo BASE_URL.'administrator/user/view/'.$row->id ?>"><?php echo $row->full_name ?></a>
<span class="users-list-date">Last Login: <?php echo date ( "d.m.Y " , strtotime ($row->last_login )); ?></span>
</li>
<?php endforeach; ?>
But every user is still showing I have 3 users and I only have one user associated with each location, so I expect to see just one result in the view?
You can't get data from two table in way that you are trying to do.
You need to use join() for this read more
public function get_choirlocation_members($id) {
$this->db->select('aauth_users.full_name, aauth_users.avatar, aauth_users.last_login, aauth_users.id, choir_location_to_users.location_id');
$this->db->from('aauth_users');
$this->db->join('choir_location_to_users', 'aauth_users.id = choir_location_to_users.user_id');
$this->db->where('aauth_users.id = choir_location_to_users.user_id');
$this->db->order_by('aauth_users.last_login', 'DESC');
$members = $this->db->get()->result();
When you are using join() no need to check location with loop and condition because join() is doing this job for you
Now first check $members is empty or not
if(isset($members) && count($members) > 0){
return $members;
}else{
return false;
}
}
Try This,
public function get_choirlocation_members($id) {
// $query = 'SELECT aauth_users.full_name, aauth_users.avatar, aauth_users.last_login, choir_location_to_users.location_id FROM aauth_users, choir_location_to_users WHERE aauth_users.id = choir_location_to_users.user_id ';
$this->db->select('aauth_users.full_name, aauth_users.avatar, aauth_users.last_login, aauth_users.id, choir_location_to_users.location_id');
$this->db->from('aauth_users');
$this->db->join('choir_location_to_users','aauth_users.id = choir_location_to_users.user_id','inner');
//$this->db->where('aauth_users.id = choir_location_to_users.user_id');
$this->db->order_by('aauth_users.last_login', 'DESC');
$members = $this->db->get();
foreach ($members->result() as $row) {
if ($row->location_id == $id) {
return $members;
}
}
}
I have what is probably a ridiculously simple problem to solve in PHP, but my brain will not engage.
I have products divided into categories. I have performed a successful query which gives me an array containing the products joined to their respective categories. Now I want to display them by category, splitting each category up into its own div. I have the following code:
$current_category = 0;
do
{
if($current_category != $row['category_id']){
echo '<div class="block">
<div class="menu">
<h4>'.$row['category_name'].'</h4>
<ul>';
do
{
echo '<li><a>'.$row['product_name'].'</a></li>';
}
while ($row['category_id'] == $current_category);
$current_category++;
//close list and divs
echo '</ul>
</div>
</div>';
}
}
while ($row = $stmt->fetch(PDO::FETCH_ASSOC));
But this only outputs the first product in each category, rather than outputting them all then moving on to the next. What am I doing wrong?
You need to get the next row in the inner loop, not in the outer one:
do {
// no need to check we're in the right category - we always are
$current_category = $row['category_id'];
echo '<div class="block">
<div class="menu">
<h4>'.$row['category_name'].'</h4>
<ul>';
do {
echo '<li><a>'.$row['product_name'].'</a></li>';
// !!! get the next row here
$row = $stmt->fetch(PDO::FETCH_ASSOC);
}
while ($row['category_id'] == $current_category);
//close list and divs
echo '</ul>
</div>
</div>';
// !!! and don't get it again here
} while ($row);
You need to make sure that your SQL query sorts by category first
I have a table that pulls tickets from a MYSQL database and displays them to the user. This part works wonderfully! But, once the user gets 5-10 tickets, the page becomes long and ugly. I am wanting to paginate the responses automatically to show maybe 5 tickets per page and show the rest on following pages.
I am using Bootstrap and have the following for the display of the pagination. "Although I fear this is only pseudo code" I added id's to each main element.
<ul class="pager" id="pagerUL">
<li class="previous" id="previousUL">
← Previous
</li>
<li class="next" id="nextUL">
Next →
</li>
</ul>
Essentially the only code used to pull the database information on the page is:
<?php if(count($tickets) > 0) : ?>
<?php foreach ($tickets as $ticket): ?>
//table content
<?php endforeach ?>
<?php else : ?>
<tr>
<td colspan="7">No Tickets Created.</td>
</tr>
<?php endif; ?>
I thought we could add something to the <?php if(count($tickets) > 0) : ?> But honestly, I am not sure as I am not a expert at php and never even attempted or had the need to build pagination up until now. Any help, guidance, thoughts would be appreciated.
Pass the page number thru the URL and then grab it via php with $_GET.
$page = $_GET['page'];
$per_page = 10; // Define it as you please
$start = $page*$per_page;
$query = "SELECT * FROM table LIMIT ".$start.", ".$per_page;
$result = mysql_query($query);
$count = mysql_num_rows($result);
$i = 0;
for($i=0;$i<$count;$i++)
{
//echo out what you want
echo "";
}
$total_pages = ceil($count/$per_page);
for($i=0;$i<$total_pages;$i++)
{
if($page != $i)
{
echo "<a href='/page.php?page=".$i."'>".$i."</a>";
} else
{
echo $i;
}
}
I am new to both PHP and the Codeigniter(v2.0) framework. Hoping you can help me find my way through my first webapp. Details below, and thank you in advance!
Goal/Issue Summary: I would like to display within my view all blog_Comments that are attached to each paticular blog_Post.
Details: My blog_Posts table contains all original blog posts [id(int), title, entry, author (all varchar), and date(timestamp)]. My blog_Comments table[id(int), entry_id(int), author, comment(varchar)] contains all comments; they are associated with the original blog_Post via the *entry_id* attribute.
Controller:
$query1 = $this->blog_model->get_posts();
$query2 = $this->blog_model->get_comments();
$data = array();
$data['posts'] = $query1;
$data['comments'] = $query2;
Model:
function get_posts() {
$query = this->db->get('blog_Posts');
return $query->result;
}
function get_comments() {
$query = this->db->get('blog_Comments');
return $query->result;}
View:
<?php if(isset($posts)) : foreach($posts as $posts=>$row) : ?>
<?php $row->title; ?>
<?php $row->author; ?>
<?php $row->entry; ?>
<?php foreach($comments as $comments=>$com) : ?>
<?php if($com->entry_id == $row->id) : ?>
<p>author: <?php echo $com->author; ?></p>
<p>comment: <?php echo $com->comment; ?></p>
<?php endif; ?>
<?php endforeach; ?>
<?php endforeach; ?>
<?php else : ?> <p>no blog_Posts found</p>
<?php endif; ?>
Edit/Update:
My attempt to display the comments is pasted into the view code block above, I've also listed the two issues it is giving me. Right now I have 2 sample original blog posts, and comments associated with each.
Issues:
the first blog entry (first time through the loop) it is displaying ALL comments, including those associated with other entry_id s.
The second blog entry (second time through loop), it throws the following error: "Invalid argument supplied for foreach()", and points to the line in my view containing the foreach for $comments.
In short, I'm trying to loo through only those comments with the entry_id that matches the original posts "id."
Thanks again for your assistance and time.
-AJ
Well since you do not need to display all comments at once, you could just alter your get_comments function like below to return comments for each post and of course display them in your way, order by date created, last entry etc:
So for the model part:
function get_comments($post_id){
$query = $this->db->query("select * from `blog_Comments` where `entry_id` = $post_id ORDER BY `created_on` DESC");
if($query->num_rows() != 0){
return $query->result();
}else{
return false;
}
}
And in your view file:
foreach($posts as $row){
echo 'Title: ' . $row->title .
'Author: ' . $row->author .
'Entry:' . $row->entry;
$comments = $this->blog_model->get_comments($row->id);
if(!$comments){
echo 'No comments';
}else{
foreach($comments as $com){
echo $com->comments . '<br/>' . $com->user . '<br/>' . etc etc
}
}
}
I'm too lazy to test, but i think you are trying to use $row, but you are outside the foreach where its defined. you introduce $row here
<?php if(isset($posts)) : foreach($posts as $posts=>$row) : ?>
and then you close the foreach -- so $row is no longer available down here:
<?php if($com->entry_id == $row->id); ?>
so yeah. but really you should be doing as much logic and checking as you can in the controller and model. verify your data objects - like Posts - THEN the controller determines the correct view. so then if there aren't any posts to show -- you dont have messy 'what if there are no posts' conditionals in your view. you just call the no posts view file.