Jump to content

Display categories and create list of category links


Alex
 Share

Recommended Posts

Hi,

I am creating a simple blog section, I want to display categories on each blog post.

For the categories I have created a page (hidden) called 'Categories' and for each category a child page under this:

categories.jpg

On my blog-entry template I have added a page field type called 'categories' which allows me to select multiple categories from my parent page shown in the image above. Is this the right approach?

Just having trouble displaying the categories on my blog-entry template:

<?php
/**
* Blog Entry
*
*/
include("./head.inc");
?>
<h1><?=$page->title?></h1>
<p>Date:<?=$page->date?></p>
<p>Category:<?=$page->categories?></p>
<div id='bodycopy'>
   <?=$page->body?>
</div>
<?php
echo $page->comments->render();
echo $page->comments->renderForm();
?>
<?php
include("./foot.inc");

I have applied 2 categories to this blog post

my categories are being listed as '1034|1033' so obviously my code is not right.

heres a link which shows this:

http://www.hoof.net.au/pwire/blog/blog-entry-1/

Also, how do i go about having a list of category links which display those blog posts, would it require a new page template like an 'archive' blog posts template. I'm not sure how to approach this.

thanks,

Alex

Link to comment
Share on other sites

Your categories are in an array, so you have to iterate through them like this

<? foreach ( $page->categories as $category ) {
  echo category->title . '<br/>';
}?>

or, how i would probably do it:

<?
if ($page->categories){
 echo '<ul class="categories">';
 foreach ( $page->categories as $category ) {
 echo '<li><a href="' . $category->url . '">' . $category->title . '</a></li>';
 }
echo '</ul>';
}?>

Edit: I don't know if you prepared a template for the categories pages to list all the post of each one there. But, because it makes sense, I changed the second block of code to reflect this.

Link to comment
Share on other sites

Hi Diogo,

thanks - yes creating them as links is a better idea.

I haven't created a categories template - thats my next task!

Can the one template work for all the categories or do i need a template for each category?

I guess it needs to cycle through each post that has that category applied to it perhaps?… i'm not sure if anyone can help that would be great.

I'm at the point now where I'm working out that:

<?php
echo $page->title;
?>

is the same as:

<?=$page->title?>

So my coding is a bit limited! But I feel like i am making progress. :wacko:

Link to comment
Share on other sites

<?=$page->title?>

is a shortcut to

<?php echo $page->title?>

to use the first form, it has to be supported by your server, so if your not sure, use the second form.

In the same way as

<?

is a shortucut to

<?php

If you don't mind typing more, I would advise to use the complete version.

You can use the same template for all categories. It should be something like this:

<?php

//find all the articles that have this category
$articles = $pages->find("categories=$page");

//for each article found, print the fields you want
foreach ($articles as $article) {
  echo "<h2>" . $article->title ."</h2>";
  echo "<div class="body">" . $article->body ."</div>";
}

?>

I didn't tested the code. Don't rely completely ;)

Maybe you could read an introduction to PHP. It's not difficult, and would help a lot to understand all this.

Edited by ryan
Code correction: changed "categories=$thisCategory" to "categories=$page"
Link to comment
Share on other sites

Diogo, I made a little correction above because the "categories=$thisCategory" would not work. You actually need to pass the $page object into the string rather than the title.

Alex, if you want to get everything up and running quickly, and then go back and tweak the markup later, you can also go to Modules > Markup > Page Array Markup > Install. That adds a render() method to PageArrays, so that it'll output some basic list markup for you. Then you can do this:

Category: <?php echo $page->categories->render(); ?>

For your category template that lists all entries in a given category, you can do this:

<?php echo $pages->find("categories=$page")->render(); ?>

As things grow, you may want to add pagination:

http://processwire.c...rkup-pager-nav/

Then you can do this:

<?php echo $pages->find("categories=$page, limit=10")->render(); ?>

...and it'll paginate the results by 10 items per page.

Unless the output of the render() functions is provided what you would want anyway, it's better to go back and replace them with your own foreach() statements to iterate the pages like in Diogo's example. But i sometimes like to use these shortcuts to get the functionality down quickly.

Link to comment
Share on other sites

Hi Diogo & Ryan,

Both methods are great, the render method is good to know about,

I have edited Diogo's with a bit of trial and error, to display a title, summary, small image that links to its post.

<?php
//find all the articles that have this category
$articles = $pages->find("categories=$page");
//for each article found, print the fields you want
foreach ($articles as $article) {
echo "<a href='{$article->url}'>" . $article->title . "</a>";
  //Display images if available
if ($article->image) {
foreach($article->image as $image) {
$thumbnail = $image->size(300,0);
echo "<div class='blogImg'><a class='workImg' href='{$article->url}'><img class='photo' src='{$thumbnail->url}' alt='{$image->description}' /></a>";
echo "<div class='blogDescript'>{$image->description}</div></div>";
//Display summary
echo "<div class='body'>" . $article->summary ."</div>";
		}
}
}
?>

I'm also still having problems displaying the image on the main parent blog page which shows the latest posts.

I adapted my template page from a 'news section' template example from a previous post, but i don't know how to code in the image between the 'date' and the 'body'. I tried a few variations but all ended in errors.

This is my blog template:

<?php
include("./head.inc");
?>
<?php
echo "<div id='content' class='grid_9'>";
?>
<h1><?=$page->title?></h1>
<?php
// start the blog posts list
echo "<ul>";
// get the posts for this page
$posts = $page->children("limit=4, sort=-date");
// note if you set the posts to sort by date descending on the /blog/ page
// in the admin, then you can omit the "sort=-date" above.
// cycle through each post and print it in a <li>
foreach($posts as $post) {
echo "
	<li><a href='{$post->url}'>{$post->title}</a>
	<p><strong>Date:</strong> {$post->date}</p>
	{$post->body}
	</li>
	";	
}

echo "</ul>";
// get values for our placemarker headline
$start = $posts->getStart();
$end = $start + count($posts);
$total = $posts->getTotal();
$num = $input->pageNum;
$lastNum =  ceil($total / $posts->getLimit());
// output the placemarker headline
echo "<h4>Showing $start - $end of $total Article/s | Page $num of $lastNum</h4>";
echo "</div>";		  
include("./foot.inc");

Diogo, yes i'll have to get a starter's PHP book, sounds like some fun bedtime reading! will check out amazon.

thanks - Alex

Link to comment
Share on other sites

In the way your code is written, if you put a for each statement between date and body, you have to finish the echo statement with a colon, and start another echo after. To keep the same logic has you have, can go like this:

foreach($posts as $post) {

  echo "
       <li><a href='{$post->url}'>{$post->title}</a>
       <p><strong>Date:</strong> {$post->date}</p>
       ";

       foreach($post->image as $image) {
             //code for the images here
       }

   echo "
        {$post->body}
        </li>
        ";	  
}

Your code is very confusing because of all those copy/pastes. Maybe you could look at each block and choose your favorite way of writing the code. Than you can apply that logic to all the code. For instance, the same code as above, can be also written in a completely different way. Here I'm coming in and out of php, and keeping the structure of html more visible:

<?php foreach($posts as $post) { ?>
  <li>
   <a href='<?=$post->url?>'><?=$post->title?></a>
   <p><strong>Date:</strong><?=$post->date?></p>

   <?php foreach($post->image as $image) { ?>
		<!--code for the images here in html-->
   <?php }?>

   <?=$post->body?>
 </li>
<?php } ?>

For a start PHP book have a look at "PHP 5 For Dummies" by Janet Valade. No kidding :)

Link to comment
Share on other sites

i've got it working with your first method above, and thank-you for explaining it a bit more.

Yeah I think 'Dummies' is appropriate, i'll check it out. I got turned off PHP when i was playing around with wordpress, but it seems much easier / logical with processwire to do what you want.

I can see the different styles of code through my templates, so it will be good to focus on one style a bit more and become proficient with it.

Anyway I seem to be able to solve a few of my own really basic problems as they come up, so i'm making a bit of progress.

thanks

Alex

Link to comment
Share on other sites

I got turned off PHP when i was playing around with wordpress

Same as me :)

Forget the dummies book, apparently it has some typos. I chose to tell you about that one because it focuses on the sintax and on how to write PHP, while others go into SQL queries and reading files for example, and PW already takes cares of those for you.

Link to comment
Share on other sites

I read that too about typos in that book, maybe theres a new corrected edition I will check first.

I'm trying to display the categories on my main parent blog page, attached to each blog post. I've tried something here and it displays the categories but only once at the bottom of the page. I know both posts have categories applied to them.

I guess the code is not cycling through each post properly?

also heres the page link to show what i mean:

http://www.hoof.net.au/pwire/blog/

<?php
echo "<ul>";
$posts = $page->children("limit=4, sort=-date");
foreach($posts as $post) {
foreach($post->image as $image) {
$thumbnail = $image->size(460,0);
echo "<li><a class='workImg' href='{$post->url}'><img class='photo' src='{$thumbnail->url}' alt='{$image->description}' /></a>";
}
echo "
	<h2 class='blogTitle'><a href='{$post->url}'>{$post->title}</a></h2>
	";

echo "
	 {$post->body}
	 <a href='{$post->url}'>read more...</a>
	 <p><strong>Date:</strong> {$post->date}</p>
	 ";	  
}
if ($post->categories){
 foreach ( $post->categories as $category ) {
	 echo '<a href="' . $category->url . '">' . $category->title . '</a>';
 }
}
echo "</li>";
echo "</ul>";
?>
Link to comment
Share on other sites

Try:

<?php

echo "<ul>";
$posts = $page->children("limit=4, sort=-date");
foreach($posts as $post) {
foreach($post->image as $image) {
$thumbnail = $image->size(460,0);
echo "<li><a class='workImg' href='{$post->url}'><img class='photo' src='{$thumbnail->url}' alt='{$image->description}' /></a>";
}
echo "<h2 class='blogTitle'><a href='{$post->url}'>{$post->title}</a></h2>";

echo "{$post->body}
	  <a href='{$post->url}'>read more...</a>
	  <p><strong>Date:</strong> {$post->date}</p>";	  

if($post->categories) {
 foreach ($post->categories as $category) {
echo '<a href="' . $category->url . '">' . $category->title . '</a>';
 }
}
}
echo "</li>";
echo "</ul>";
?>

Otherwise it would only show categories for the last post ;)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...