Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Prev/Next when ordered by DATE?


Go to End


5 Posts   1308 Views

Avatar
neilcreagh

Community Member, 136 Posts

22 August 2013 at 12:29am

Edited: 22/08/2013 12:32am

Hi, I have news articles ordered by their date, all working fine.

static $db = array(
	'Date' => 'Date',
	);

But on each article I want a next/previous buttons, but this function below isn't working for me, can anyone see where I've gone wrong?

function NextArticle() { 
return DataObject::get("NewsArticle", "Date < ($this->Date)", "", "", "1");
}

function PreviousArticle() { 
return DataObject::get("NewsArticle", "Date > ($this->Date)", "", "", "1");
}

On my ArticlePage template I'm using:

<% control PreviousArticle %><a class="prev" href="$Link"><</a><% end_control %>
<% control NextArticle %><a class="next" href="$Link">></a><% end_control %>

Avatar
Theak

Community Member, 2 Posts

22 August 2013 at 7:28am

Edited: 22/08/2013 7:36am

Assuming NewsArticle is a DataObject and not a SiteTree/Page subclass, you can try this:

public function NextArticle() {
    $next = DataObject::get("NewsArticle","NewsArticle.Date <= '{$this->Date}' AND NewsArticle.ID <> {$this->ID}","NewsArticle.Date.DESC, NewsArticle.ID ASC","","0,1");
    if ($next && $next->exists()) {
        return $next->First();
    }
    return null;
}

public function PreviousArticle() {
    $prev = DataObject::get("NewsArticle","NewsArticle.Date >= '{$this->Date}' AND NewsArticle.ID <> {$this->ID}","NewsArticle.Date.ASC, NewsArticle.ID DESC","","0,1");
    if ($prev && $prev->exists()) {
        return $prev->First();
    }
    return null;
}

We need to use '<=' and not '<' for checking the date in the 'NextArticle' function because two articles may have been posted on the same date and we don't want to skip over those. We need to exclude the current article from the list though, hence the 'NewsArticle.ID <> {$this->ID}' clause.

I'd also recommend escaping the bracket in your template code like this:

<% if PreviousArticle %>

    <% control PreviousArticle %>

        <a class="prev" href="$Link">&lt;</a>

    <% end_control %> 

<% end_if %>



<% if NextArticle %>

    <% control NextArticle %>

        <a class="next" href="$Link">&gt;</a>

    <% end_control %>

<% end_if %>

Avatar
neilcreagh

Community Member, 136 Posts

22 August 2013 at 8:43am

Thank you so much for replying Theak. NewsArticle is in fact a Page subclass. Also, I don't understand why my code doesn't work, is there anything wrong with it? Good advise though, what changes would need to be made to this in order for it to work with the SiteTree? Changing all instances of NewsArticle.Date to just Date ?

I'm using Silverstripe 3 by the way.

Avatar
Theak

Community Member, 2 Posts

22 August 2013 at 5:40pm

The main thing I spotted was that you weren't quoting the date in the 'NextArticle' and 'PreviousArticle' functions. The DataObject::get() syntax is deprecated in SS 3, so try this instead:

public function NextArticle() {
return NewsArticle::get()->filter("Date:GreaterThan:Negation",$this->Date)->exclude("ID",$this->ID)->sort(array('Date' => 'DESC', 'ID' => 'ASC'))->limit(1)->first();
}

public function PreviousArticle() {
return NewsArticle::get()->filter("Date:LessThan:Negation",$this->Date)->exclude("ID",$this->ID)->sort(array('Date' => 'ASC', 'ID' => 'DESC'))->limit(1)->first();
}

The <% control %> block is also deprecated in SS 3. Try this in your templates instead:

<% if $PreviousArticle %>

<% with $PreviousArticle %>

<a class="prev" href="$Link">&lt;</a>

<% end_with %>

<% end_if %>

<% if $NextArticle %>

<% with $NextArticle %>

<a class="next" href="$Link">&gt;</a>

<% end_with %>

<% end_if %>

Avatar
neilcreagh

Community Member, 136 Posts

22 August 2013 at 10:00pm

Thanks so much!
Your code works great, I just had to switch the Previous/Next functions 'GreaterThan/LessThan' and change the sort order a little bit ('next' being older articles).

public function PreviousArticle() { 
	return NewsArticle::get()->filter("Date:GreaterThan:Negation",$this->Date)->exclude("ID",$this->ID)->sort(array('Date' => 'ASC', 'ID' => 'ASC'))->limit(1)->first(); 
	}

	public function NextArticle() { 
	return NewsArticle::get()->filter("Date:LessThan:Negation",$this->Date)->exclude("ID",$this->ID)->sort(array('Date' => 'DESC', 'ID' => 'ASC'))->limit(1)->first(); 
	}

This is working perfectly for me - thank you.