How to group posts by category using PHP & MySql? - php

I’ve tried using GROUP BY in my query but that only returns one post per category. This is an example of what is returned with my current setup. What I need is for all posts with the same category to be grouped together, can someone point me in the right direction? Thanks for your time.

Like suggested by Charlotte, you could group your posts in an associative array, with the categories as keys.
<?php
// Connecting to database
$categories = array(); // Create an empty array
while ($post = mysqli_fetch_array($result)) {
if(!array_key_exists($post['category'], $categories)) { // Check if the category is already present
$categories[$post['category']] = array(); // Create an array indexed with the category name
}
$categories[$post['category']][] = $post; // Add the post to the category
}
?>
Now you have to iterate twice : to display the categories and to display each post in the category.
When I have to deal with nested foreach to render html, I preferably use inline foreach.
The rendering of the posts should look like :
<?php foreach ($categories as $category => $posts) : ?>
<h2><?php echo $category; ?></h2>
<?php foreach ($posts as $post) : ?>
<a href='article.php?id=<?php echo $post['post_id']; ?>' ><?php echo $post['title']; ?></a>
<p>Posted on <?php echo date('d-m-y h:i:s',strtotime( $post['posted'] ) );?> In <a href='category5.php?id=<?php echo $post['category_id']; ?>' ><?php echo $post['category']; ?></a>
</p>
<?php endforeach; ?>
<hr/>
<?php endforeach; ?>
Edit: I ometted the opening and closing php tags in the first block of code.
If you assemble the two blocks of code in your php file, it should work.

Related

How can I skip multiple strings from php array?

I have the categories: 2D, 3D, Photo, Animation, which become buttons.
How can I skip the 3D and Animation from being displayed? on this particular page when running foreach. For example, the buttons that will appear have to be: All, 2D, Photo.
I tried to find a solution, but no luck.
What I managed to remove was only a string, but not multiple ones, with:
$key = array_search('3D',$terms);
unset($terms[$key]);
This is my code that I want to apply the changes to:
$terms = get_terms("portfolio_category",$cat_arguments);
if($terms):
?> <!-- category menu, this -->
<div class="row categories-p">
<ul class="col-sm-12">
<li><?php _e("All","um_lang"); ?></li>
<?php
sort($terms);
foreach($terms as $term):?>
<li>
<?php echo $term->name; ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
You can use php's in_array, here's a basic example:
Assuming you have the following:
$categories = ['2D', '3D', 'Photo', 'Animation'];
And your skip list looks like this:
$skipList = ['3D', 'Animation'];
Then your render function will look like this:
iterate over category list
if the item is not in the skip list, render
foreach ($categories as $category) {
if (!in_array($category, $skipList)) {
// Display the category button
// e.g. echo "<button>{$category}</button>";
}
}

Need to combine/eliminate duplicates in nested array

I need to create an accordion list of news article titles grouped by year. So far the contents of the accordion panels are correct with each panel showing all of the news posts for that year.
The problem is that I'm getting multiple panels for years based on the number of articles for the year. So for example year 2003 has three news articles, so I'm getting three accordion panels for 2003, each with the three corresponding news articles for that year. For 2004 I get one accordion panel because there's only one article for 2004. 2006 has six articles so I get six panels each with the six articles inside.
What do I need to do to get only one panel with the correct number of titles inside?
Here's my SQL:
$newsposts = $wpdb->get_results("
SELECT YEAR(wp_posts.post_date) AS post_year, wp_posts.post_title, wp_posts.ID AS post_id
FROM wp_posts LEFT JOIN wp_term_relationships ON
(wp_posts.ID = wp_term_relationships.object_id)
WHERE wp_term_relationships.term_taxonomy_id = 3
AND wp_posts.post_status = 'publish'
ORDER BY post_date
", OBJECT );
Here's my markup:
<?php foreach($newsposts as $year) : ?> <?php //print_r($year); ?>
<li class="accordion-item" data-accordion-item>
<?php echo $year->post_year; ?>
<div class="accordion-content" data-tab-content>
<?php foreach($newsposts as $post) : ?> <?php //print_r($post); ?>
<?php // Continue unless years match
if ( $post->post_year != $year->post_year ) continue; ?>
<?php echo $post->post_title; ?><br/>
<?php endforeach; //$posts ?>
</div>
</li>
<?php endforeach; //$year ?>
</ul>
Somehow I need to limit the first foreach to only one for each year represented. I would appreciate any help.
I worked through this and found an answer thanks to this post:remove duplicates in foreach
In my case here is my revised markup:
<?php $yearposts = array(); ?>
<?php foreach($newsposts as $year) : ?> <?php $postyear = $year->post_year; ?>
<?php if(!in_array($postyear, $yearposts)) { ?>
<li class="accordion-item" data-accordion-item>
<?php echo $postyear; array_push($yearposts,$postyear); ?>
<div class="accordion-content" data-tab-content>
<ul class="accordlist">
<?php foreach($newsposts as $post) : ?>
<?php // Continue unless years match
if ( $post->post_year != $year->post_year ) continue; ?>
<li><a class="newstitle" href="<?php the_permalink($post->post_id); ?>"><?php echo $post->post_title; ?></a></li>
<?php endforeach; //$posts ?>
</ul>
</div>
</li>
<?php } // end in_array conditional ?>
<?php endforeach; //$year ?>
</ul>
As the indicated post says,
Basically we are just using an additional array to store the printed values. Each time we see a new value, we print it and add it to the array.
My version is broken into pieces to surround the elements that are required for the accordion formatting.
Anyway, I hope this helps someone else. I needed answers from different questions to find my solution. Now maybe someone will find everything in this one place.
Cheers

How to loop within a for loop to get multiple values with the same ID

I want to get some data from a MySql database which has the same ID but different values. see the image (this is just a sample)
Although the venue styles are different, I want to pull all the styles with the same ID. I'm using a foreach loop to get the data from the database.
How can I improve my code to achieve what I want.
<?php
$myrows = $wpdb->get_results( "SELECT vf_venues.title, vf_venues.mainimage,
vf_venues.permalink, vf_venuestyles.slug
FROM vf_venues
LEFT JOIN vf_venuestyles ON vf_venuestyles.vid=vf_venues.vid WHERE
vf_venuestyles.vid=vf_venues.vid" );?>
<div class="venue-list venue-grid">
<?php
foreach ( $myrows as $myrow ) {
//pull the data from the DB
"<pre>"
$venueName = $myrow->title;
$mainImage = $myrow->mainimage;
$permalink = $myrow->permalink;
$slug = $myrow->slug;
$vid = $myrow->vid;
"<pre>"
?>
<li class="venue-block block">
<div class="venue-img">
<a href="<?php echo $permalink; ?>">
<img src="<?php echo $mainImage; ?>">
</a>
</div>
<div class="venue-details"><h2><?php echo $venueName; ?></h2></div>
<?php echo $slug; ?>
<?php echo $vid; ?>
</li>
<?php
}
?>
</div>
I managed to fix this by creating a for loop within the existing for loop. I then created a sql query to pull the venue styles for that venue.

Get Subcategory in Magento

I need help. I use this code to get the category link under products info on a few pages in Magento:
<?php $categories = $_product->getCategoryIds(); ?>
<span>In </span>
<?php $i=1; foreach($categories as $k => $_category_id): ?>
<?php if($i>1) {break;} ?>
<?php $_category = Mage::getModel('catalog/category')->load($_category_id) ?>
<a class="in-category" href="<?php echo $_category->getUrl() ?>"><?php echo $_category->getName() ?></a>
<?php $i++; endforeach; ?>
You can see it here: http://192.241.178.130/new_arrivals
Problem I'm having is that I want the script to display the category closest to the product but it's instead displaying the root category (Default category of the site)
M
Thanks.
Try something like this:
<?php
$categoryIds = $_product->getCategoryIds();
$categories = Mage::getModel('catalog/category')
->addAttributeToSelect('url_key')//add url key to select
->addAttributeToSelect('name')//add name to select
->getCollection() //get categories as collection
->addAttributeToFilter('entity_id', $categoryIds)//filter only by selected ids
->addAttributeToFilter('is_active', 1)//get only active categories
->addAttributeToFilter('level', array('gte'=>2))//ignore root category and 'root of roots'
->setOrder('level', 'desc');//sort by level descending
$mainCategory = $categories->getFirstItem();//get only the category lowest in the tree
if ($mainCategory->getId()) : ?>
<a class="in-category" href="<?php echo $mainCategory->getUrl() ?>"><?php echo $mainCategory->getName() ?></a>
<?php endif;?>
Instead of using a foreach to walk one time through the array you can use array_pop.
Anyhow the function getCategoryIds() will return an array of all categories the product is in. This also include parent categories and are in logical order. The category with the lowest id will show up first.
Perhaps something like this will work for you:
<?php $_category_id = array_pop($_product->getCategoryIds()); ?>
<span>In </span>
<?php $_category = Mage::getModel('catalog/category')->load($_category_id) ?>
<a class="in-category" href="<?php echo $_category->getUrl() ?>">
<?php echo $_category->getName() ?>
</a>

Magicfields foreach not stopping, iterating too many

Using the magicfields 2.0 plugin for Wordpress 3.1.
Here's the broken page:
http://sseko.wecreativeagency.com/style/
and here's a page with it working:
http://sseko.wecreativeagency.com/university-bound/
Note the footer on the first page is receiving the id info from the magicfields
<?php get_header(); ?>
<div id="content">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<article id="post-<?php the_ID(); ?>">
<?php the_content(); ?>
<div id="note" class="grid_12"><p class="note grid_6 alpha"><span class="special">Style your Ssekos!</span> There are so many ways to tie your Ssekos. Watch the videos and learn how! Then, come up with your own!</p><h1 class="grid_6 omega"><?php wp_title(' ','true','right'); ?></h1></div>
<?php $styles = getFieldOrder('image');
if(is_array($styles))
{foreach($styles as $style)
{
echo "<div class='grid_3'>";
echo "<a rel='styles' href='#info$style'class='inlineimg grid_3'>";
echo "<img src='";
echo get_image('image',1,$style,$tag_img=0);
echo "'class='grid_3' title='";
echo get('name',1,$style);
echo "'alt='";
echo get('name',1,$style);
echo "'";
echo "</a>";
echo "<h2 class='grid_3'>";
echo get('name',1,$style);
echo "</h2></div>";
echo "<div style='display:none'><div id='info$style' class='grid_8 lightbox'>";
echo get('link',1,$style);
echo "</div></div>";
}
}
?>
<div class="clear"></div>
</article>
<?php endwhile; endif; ?>
I've check the database for extra entries but I can't find the reason for it continuing to iterate out into the elements below.
For some reason I could not check your site .. but I believe this is hapenning because you have 2 nested loops ..
One is the Wordpress loop if--> while , and then your Foreach loop.
When the Wordpress loop encounters posts , it will iterate your second loop FOR EACH ONE of the posts ...
for example, on a page where there are 10 $post, it will iterate 10 times for each $style ...
When you have 1 post , it will iterate once .
Like I said, for some reason your site was not available to me , but seeing your URL construction, My guess is that it does not work on the first example, because it is some kind of category (which returns multiple posts ) and the second url is a SINGLE post ...

Categories