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.

Data Model Questions /

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

Selecting One DataObject Every Two Weeks


Go to End


6 Posts   2128 Views

Avatar
taligent

Community Member, 18 Posts

10 September 2010 at 12:05am

Edited: 10/09/2010 12:06am

I've created a table for Book Excerpts on my site using two classes. BookExcerpt and BookExcerptPage. They are very simple classes. However, now I want to ensure that every 14 days a new excerpt will be listed in the content area of my site. So I added a NextChangeDate field to my page so that every time the page is accessed, the page will check today's date and if it is equal to the NextChangeDate, the next article will be displayed. For this to happen, I need to update the change date field by adding 14 days to it. That shouldn't be a problem. My problem right now is how to query the excerpt table by ID and when there are no further records grab the first record in the table and start the article loop over. Any thoughts on how to do that would be great. I'm a little stumped on that part.

I've enclosed my BookExcerpt classes in case it is easier to respond by looking at the classes.

<?php
class BookExcerpt extends DataObject {
   static $db = array(
      'Sequence' => 'Int',
      'Pages' => 'Text',
      'Title' => 'Text',
      'Quote' => 'Text',
      'Excerpt' => 'Text'
   );
   
   // Each excerpt exists in one and only one category.
   static $has_one = array(
      'BookExcerptPage' => 'BookExcerptPage'
   );
     
   static $singular_name = 'Book Excerpt';
   static $plural_name = 'Book Excerpts';
   
   function getCMSFields() {
      $fields = new FieldSet(
         new NumericField('Sequence', 'Display Sequence'),
         new TextField('Pages', 'Quoted From Page(s)'),
         new TextField('Title', 'Excerpt Title'),
         new TextField('Quote', 'Chapter Quote'),
         new TextareaField('Excerpt', 'Book Excerpt')
      );
      
      return $fields;
   }
}
?>

<?php
class BookExcerptPage extends SendPage {
   //Each BookExcerpt can have multiple excerpts.
   static $has_many = array(
      'BookExcerpt' => 'BookExcerpt'      
   );
   
   static $singular_name = 'Book Excerpt Page';
   static $plural_name = 'Book Excerpt Pages';
   
   function getCMSFields() {
      $fields = parent::getCMSFields();
      $fields->renameField("Content", "Common Text - Copyright,Order Link, etc...");
      $excerptsTable = new ComplexTableField($this, 'BookExcerpts', 'BookExcerpt', array('Sequence'=>'Display Sequence', 'Title'=>'Title', 'Excerpt'=>'Excerpt'));
      $fields->addFieldToTab('Root.Content.BookExcerpts', $excerptsTable);
      $fields->addFieldToTab('Root.Content.Main', new NumericField('ChangeFrequency', 'Number of Days to Display Article'), 'Content');
      $fields->addFieldToTab('Root.Content.Main', new NumericField('CurrentArticle', 'Article Currently Displayed'), 'Content');
      $fields->addFieldToTab('Root.Content.Main', new CalendarDateField('ChangeDate', 'Next Date to Change the Article'), 'Content');
      return $fields;
   }
}

class BookExcerptPage_Controller extends Page_Controller {
   
}

Avatar
MarijnKampf

Community Member, 176 Posts

11 September 2010 at 4:44am

I haven't tested this but I would use the MySQL random function to select a random book. You can seed the random function with a number that changes every week. Then get a dataobject for your bookexcerpt.

class BookExcerptPage_Controller extends Page_Controller { 
  function RandomContent() {
    $week =  (int)date('YW', $date); // Create seed for rand that changes each week
    return DataObject::get_one("BookExcerpt",null, false, "RAND(" . $week . ")");
  }
}

The only drawback is if you add/remove bookexcerpts you'll get a new random number.

Avatar
taligent

Community Member, 18 Posts

22 September 2010 at 1:45am

Thanks for the info, but its not quite what I am looking for. I need a sequential return of an excerpt. I have the following code, but keep getting an error indicating that the function InFuture() does not exist on class date. I don't understand why and my knowledge of php is a bit sketchy, although growing. Here is what I currently have. How would I access the ChangeDate variable from my page as a Date class so that I can check InFuture() on it?

Here is my BookExcerptPage Class

<?php
class BookExcerptPage extends SendPage {
   static $db = array(
      'ChangeFrequency' => 'Int',
      'CurrentArticle' => 'Int',
      'ChangeDate' => 'Date'
   );
   //Each BookExcerpt can have multiple excerpts.
   static $has_many = array(
      'BookExcerpt' => 'BookExcerpt'      
   );
   
   static $singular_name = 'Book Excerpt Page';
   static $plural_name = 'Book Excerpt Pages';
   
   function getCMSFields() {
      $fields = parent::getCMSFields();
      $fields->renameField("Content", "Common Text - Copyright,Order Link, etc...");
      $excerptsTable = new ComplexTableField($this, 'BookExcerpts', 'BookExcerpt', array('Sequence'=>'Display Sequence', 'Title'=>'Title', 'Excerpt'=>'Excerpt'), "", "", "Sequence ASC");
      $fields->addFieldToTab('Root.Content.BookExcerpts', $excerptsTable);
      $fields->addFieldToTab('Root.Content.Main', new NumericField('ChangeFrequency', 'Number of Days to Display Article'), 'Content');
      $fields->addFieldToTab('Root.Content.Main', new NumericField('CurrentArticle', 'Article Currently Displayed'), 'Content');
      $fields->addFieldToTab('Root.Content.Main', new CalendarDateField('ChangeDate', 'Next Date to Change the Article'), 'Content');
      return $fields;
   }
}

class BookExcerptPage_Controller extends Page_Controller {
   public function nextExcerpt() {
      $be = DataObject::get_one("BookExcerpt", "Sequence > $this->CurrentArticle");
      if($be) {
         return $be;
      } else {
         $be = DataObject::get_one("BookExcerpt", "Sequence > 0");
         if($be) {
            return $be;
         } else {
            return false;
         }
      }
   }
   
   public function currentExcerpt() {
      $curChangeDate = new Date();
      $curChangeDate->setValue($this->ChangeDate);
      
      if ($curChangeDate->InFuture() == false) {
         return nextExcerpt();
      }
      
      $be = DataObject::get_one('BookExcerpt', "Sequence = $this->CurrentArticle");
      if($be) {
         return $be;
      } else {
         return false;
      }
   }
}

And here is my template code

   <% if currentExcerpt %>
      <p>$currentExcerpt.Title</p>
      <p>$currentExcerpt.Quote</p>
      <p>$currentExcerpt.Excerpt</p>
   <% end_if %>

Avatar
MarijnKampf

Community Member, 176 Posts

22 September 2010 at 2:46am

Why don't you use $this->ChangeDate->InFuture() ?

Avatar
taligent

Community Member, 18 Posts

22 September 2010 at 9:05pm

Edited: 22/09/2010 9:07pm

This is where my shaky knowledge of SS and php is not sufficient. I've tried that and get the following error:

Fatal error: Call to a member function InFuture() on a non-object in C:\Users\dan\Sync\SilverStripe\send\code\BookExcerptPage.php on line 48

I think I am missing a definition somewhere in my code, but can't find it. To me it appears that it is grabbing the database field rather than wrapping it in an object, but I don't know why...

Avatar
taligent

Community Member, 18 Posts

30 September 2010 at 2:20am

Edited: 30/09/2010 2:20am

I still don't know why $this-ChangeDate->InFuture() does not work. However I got the code to work with the following exerpt:

   public function currentExcerpt() {
      $curChangeDate = new Date();
      $curChangeDate->setValue($this->ChangeDate);
      
      if ($curChangeDate->InFuture() == false) {
         return $this->nextExcerpt();
      }
      
      $be = DataObject::get_one('BookExcerpt', "Sequence = $this->CurrentArticle");
      if($be) {
         return $be;
      } else {
         return false;
      }
   }

Can someone say why $this-ChangeDate->InFuture() does not work? I am a bit confused on that point.