Display all pages under categories in PHP with joins - php

I have 2 tables. The first one, pages, contains a foreign key category_id and the other table, categories, contains an id and a title field.
Here is my sql query :
SELECT categories.title as titleCategory, pages.title as titlePage FROM categories INNER JOIN pages ON pages.category_id = categories.id ORDER BY categories.title
What is want is to display the pages and categories like this :
category 1
page 1
page 2
category 2
page 1
etc...
Is there a way to do that using a foreach or do I have to use 2 queries?
Thank you very much for your help.

Assuming PHP, but the logic shoudl work in any language.
$cur_cat = null;
foreach($results as $result){
if($cur_cat != $result['titleCategory']){
echo $result['titleCategory'];
}
$cur_cat = $result['titleCategory'];
echo $result['titlePage'];
}

Just put a check in the single foreach loop.
$currentCategory = null;
foreach( $results as $result ) {
if( $currentCategory != $result['titleCategory'] ) {
$currentCategory = $result['titleCategory'];
echo $result['titleCategory'];
}
echo $result['titlePage'];
}
This will only print out the title if it has changed. You already have the, ordered by categoryTitle so if the category doesn't change it will only print the pageTitle.

Related

MySQL group result [duplicate]

in order to keep as few SQL statements as possible, I want to do select set from MySQL:
SELECT * FROM products WHERE category IN (10,120,150,500) ORDER BY category,id;
Now, I have list of products in following manner:
CATEGORY
- product 1
- product 2
CATEGORY 2
- product 37
...
What's the best and most efficent way to process MySQL result?
I thought something like (pseudo PHP)
foreach ($product = fetch__assoc($result)){
$products[$category][] = $product;
}
and then when outputting it, do foreach loop:
foreach($categories as $category){
foreach($products[$category] as $product){
$output;
}
}
Is this the best, or is something magical like mysql_use_groupby or something?
Like mluebke commented, using GROUP means that you only get one result for each category. Based on the list you gave as an example, I think you want something like this:
$sql = "SELECT * FROM products WHERE category IN (10,120,150,500) GROUP BY category ORDER BY category, id";
$res = mysql_query($sql);
$list = array();
while ($r = mysql_fetch_object($res)) {
$list[$r->category][$r->id]['name'] = $r->name;
$list[$r->category][$r->id]['whatever'] = $r->whatever;
// etc
}
And then loop through the array. Example:
foreach ($list as $category => $products) {
echo '<h1>' . $category . '</h1>';
foreach ($products as $productId => $productInfo) {
echo 'Product ' . $productId . ': ' . $productInfo['name'];
// etc
}
}
Nope, I think your solution is the best for this problem. It seems that what's important for you is the output later on, so you should stick with your approach.
Do you want to get a list of categories or actually get all products grouped into categories?
If it's the latter, best to do:
SELECT
p.product_id,
p.name,
p.category_id,
c.name AS category
FROM products p
JOIN categories c ON (c.category_id = p.category_id AND p.category_id IN (x,y,z))
Then in PHP you can go through the array (psuedo code):
$cats = array();
foreach($products as $product) {
if(!in_array($product['category'], $cats)) {
$cats[$product['category_id']] = $product['category'];
}
$cats[$product['category_id']][$product['product_id']] = $product['name'];
}
Which will leave you with $cats as an array with products sorted into it.

PHP Mysql Left Join

<?php
$q = mysql_query("SELECT sub_cat.*, links.*
FROM links
LEFT JOIN sub_cat
ON links.p_id = sub_cat.id
WHERE sub_cat.p_id = '$id'
ORDER BY name ASC") or die (mysql_error());
while ($r = mysql_fetch_assoc($q))
{
$links_name = $r['name'];
$link_h3 = $links_name != '' ? '<h3>' . $links_name . '</h3>' : '';
//print $link_h3;
print '<pre>';
print_r ($r);
}
?>
I have two tables with rows like:
sub_cat
id
name
p_id
links
id
links
p_id
In sub cat i have movie categories, like foreign language movies, national movies, uncategorised movies and so on. In links table i have concrete movie links and depending on sub category.
The only thing is that i do not want dublicate titles (sub_cat.name).
result is:
Without Category www.moviesite.com
Without Category www.moviesite2.com
Without Category www.moviesite3.com
Foreign Movies www.moviesite1.bla
Foreign Movies www.moviesite2.bla
I want to be
Without Category www.moviesite.com
www.moviesite2.com
www.moviesite3.com
Foreign Movies www.moviesite1.bla
www.moviesite2.bla
and do not have any idea how to do this :(
any help appreciated.
To do the job, you have 2 solutions:
The first solution is to process your data before showing it, in order to group all movies by category.
You can do for example:
$moviesByCategory = array();
while ($r = mysql_fetch_assoc($q))
{
// Create the new sub array for the new category if necessary
if (!isset($moviesByCategory[$r['name']]))
$moviesByCategory[$r['name']] = array();
// Add the movie in the category
$moviesByCategory[$r['name']][] = $r['links'];
}
And then, you can now iterate on this new array like
foreach($moviesByCategory as $category => $movies)
{
// Print the category name
echo '<h1>' . $category . '</h1>';
// Print all movies of the category
foreach($movies as $movie)
echo '<h3>' . $movie . '</h3>';
}
The second solution is to modify the SQL query to group directly all movies that have the same category. You just have to use a GROUP BY clause on sub_cat.id and then apply an agregate function on all other fields in the select.
For performance aspect, the best solution is the SQL solution, but doing it with PHP will give you more flexibility for the presentation.
Try something like:
$lastSubcatName = "";
while ($r = mysql_fetch_assoc($q))
{
$links_name = $r['name'];
if($lastSubcatName != $links_name)
{
echo "<h1>".$links_name."</h1>";
$lastSubcatName = $links_name;
}
echo '<h3>' . $r['links'] . '</h3>';
}

Listing Items by Category in PHP

Can someone help me with listing items by category in PHP?
I'm trying to create a simple list of books by category:
JavaScript
JavaScript Patterns
Object-Oriented JavaScript
Ajax
Ajax Definitive Guide
Bulletproof Ajax
jQuery
jQuery Cookbook
Learning jQuery 1.3
I have no problems with the data structure or SQL query:
BOOK: book_id, book_title, fk_category_id
CATEGORY: category_id, category_name
SELECT category.category_name, book.book_title
FROM category LEFT OUTER JOIN book
ON category.category_id = book.fk_category_id;
My problem is that I don't know how to write the PHP script to list the books under each category header.
I know enough to get the result set into an array, but then I'm stumped on using that array to group the items as shown.
Another Stack question addresses almost the same thing, but the responses stop short of solving the PHP code: List items by category
Thanks!
Add an ORDER BY category.category_name clause to your query so that as you loop through the resulting rows, the items in each category will be grouped together. Then, each time the category is different from the previous one seen, print out the category as the heading before printing the title.
$category = null;
foreach ($rows as $row) {
if ($row['category_name'] != $category) {
$category = $row['category_name'];
print "<h1>".$category."</h1>\n";
}
print $row['book_title']."<br/>\n";
}
Order the results by category and then just iterate thru, putting a category header whenever the category name changes.
The ordering is most easily done in the SQL query. You don't even need an intermediate array.
SELECT category.category_name, book.book_title
FROM category LEFT OUTER JOIN book
ON category.category_id = book.fk_category_id
ORDER BY category.category_name
And then for the PHP
$res = mysql_query($query);
$lastCategory = '';
while ($row = mysql_fetch_assoc($res))
{
if($row['category_name'] != $lastCategory)
{
$lastCategory = $row['category_name'];
echo "<br /><strong>$lastCategory</strong>";
}
echo $row['book_title'] . ' <br />';
}
You do not need to put all your results into an array first. You can just fetch them as you go.

List category names from database as menu

I want to create a menu from category names in database, so far I have this:
$list = "SELECT category FROM posts";
$rlist = mysql_query($list) or die(mysql_error());
while($rows = mysql_fetch_assoc($rlist))
{
$catname = $rows['category'];
echo '<li>' . $catname . '</li>';
}
Which lists everything but I need to make each only list once so its a menu.
Maybe you want
SELECT DISTINCT category FROM posts;
And assuming you want them ordered
SELECT DISTINCT category FROM posts ORDER BY category ;
If you want your category to be only listed once, you chould change your query to
SELECT DISTINCT(category) FROM POSTS

PHP/MySQL group results by column

in order to keep as few SQL statements as possible, I want to do select set from MySQL:
SELECT * FROM products WHERE category IN (10,120,150,500) ORDER BY category,id;
Now, I have list of products in following manner:
CATEGORY
- product 1
- product 2
CATEGORY 2
- product 37
...
What's the best and most efficent way to process MySQL result?
I thought something like (pseudo PHP)
foreach ($product = fetch__assoc($result)){
$products[$category][] = $product;
}
and then when outputting it, do foreach loop:
foreach($categories as $category){
foreach($products[$category] as $product){
$output;
}
}
Is this the best, or is something magical like mysql_use_groupby or something?
Like mluebke commented, using GROUP means that you only get one result for each category. Based on the list you gave as an example, I think you want something like this:
$sql = "SELECT * FROM products WHERE category IN (10,120,150,500) GROUP BY category ORDER BY category, id";
$res = mysql_query($sql);
$list = array();
while ($r = mysql_fetch_object($res)) {
$list[$r->category][$r->id]['name'] = $r->name;
$list[$r->category][$r->id]['whatever'] = $r->whatever;
// etc
}
And then loop through the array. Example:
foreach ($list as $category => $products) {
echo '<h1>' . $category . '</h1>';
foreach ($products as $productId => $productInfo) {
echo 'Product ' . $productId . ': ' . $productInfo['name'];
// etc
}
}
Nope, I think your solution is the best for this problem. It seems that what's important for you is the output later on, so you should stick with your approach.
Do you want to get a list of categories or actually get all products grouped into categories?
If it's the latter, best to do:
SELECT
p.product_id,
p.name,
p.category_id,
c.name AS category
FROM products p
JOIN categories c ON (c.category_id = p.category_id AND p.category_id IN (x,y,z))
Then in PHP you can go through the array (psuedo code):
$cats = array();
foreach($products as $product) {
if(!in_array($product['category'], $cats)) {
$cats[$product['category_id']] = $product['category'];
}
$cats[$product['category_id']][$product['product_id']] = $product['name'];
}
Which will leave you with $cats as an array with products sorted into it.

Categories