$Title
Posted on $Date.Nice by $Author
# Tutorial 2 - Extending a basic site ## Overview In the [first tutorial](1-building-a-basic-site) we learnt how to create a basic site using SilverStripe. This tutorial will build on that, and explore extending SilverStripe by creating our own page types. After doing this we should have a better understanding of how SilverStripe works. ## What are we working towards? We are going to work on adding two new sections to the site we built in the first tutorial. The first of these new sections will be *News*, with a recent news listing on the homepage and an RSS feed: ![](_images/tutorial2_newslist.jpg) The second will be a *Staff* section, to demonstrate more complex database structures (such as associating an image with each staff member): ![](_images/tutorial2_einstein.jpg) ## The SilverStripe data model A large part of designing complex SilverStripe sites is the creation of our own page types. Before we progress any further, it is important to understand what a page type is and how the SilverStripe data model works. SilverStripe is based on the **"Model-View-Controller"** design pattern. This means that SilverStripe attempts to separate data, logic and presentation as much as possible. Every page has three separate parts which are combined to give you the final page. Lets look at each one individually: ### Model All content on our site is stored in a database. Each class that is a child of the `[api:DataObject]` class will have its own table in our database. Every object of such a class will correspond to a row in that table - this is our "data object", the **"model"** of Model-View-Controller. A page type has a data object that represents all the data for our page. Rather than inheriting directly from `[api:DataObject]`, it inherits from `[api:SiteTree]`. We generally create a "Page" data object, and subclass this for all other page types. This allows us to define behavior that is consistent across all pages in our site. ### View The **"view"** is the presentation of our site. As we have already seen, the templates SilverStripe uses to render a page are dependent on the page type. Using templates and css, we are able to have full control over the presentation of our website. ### Controller Each page type also has a **"controller"**. The controller contains all the code used to manipulate our data before it is rendered. For example, suppose we were making an auction site, and we only wanted to display the auctions closing in the next ten minutes. We would implement this logic in the controller. The controller for a page should inherit from `[api:ContentController]`. Just as we create a "Page" data object and subclass it for the rest of the site, we also create a "Page_Controller" that is subclassed. Creating a new page type requires creating each of these three elements. We will then have full control over presentation, the database, and editable CMS fields. A more in-depth introduction of Model-View-Controller can be found [here](http://www.slash7.com/articles/2005/02/22/mvc-the-most-vexing-conundrum). ![](_images/tutorial2_pagetype-inheritance.jpg) ## Creating the news section page types To create a news section we'll need two new page types. The first one is obvious: we need an *ArticlePage* page type. The second is a little less obvious: we need an *ArticleHolder* page type to contain our article pages. We'll start with the *ArticlePage* page type. First we create the model, a class called "ArticlePage". We put the *ArticlePage* class into a file called "ArticlePage.php" inside *mysite/code*. All other classes relating to *ArticlePage* should be placed within "ArticlePage.php", this includes our controller (*ArticlePage_Controller*). **mysite/code/ArticlePage.php** :::php It is SilverStripe convention to suffix general page types with "Page", and page types that hold other page types with > "Holder". This is to ensure that we don't have URLs with the same name as a page type; if we named our *ArticleHolder* > page type "News", it would conflict with the page name also called "News". ## Adding date and author fields Now that we have an *ArticlePage* page type, let's make it a little more useful. Remember the *$db* array? We can use this array to add extra fields to the database. It would be nice to know when each article was posted, and who posted it. Change the *$db* array in the *ArticlePage* class to look like this: :::php 'Date', 'Author' => 'Text' ); // ..... } Every entry in the array is a *key => value* pair. The **key** is the name of the field, and the **value** is the type. See *`[api:Date]`* for a complete list of data types associated with *Date*. > Note: The names chosen for the fields you add must not already be used. Be careful using field names such as Title, > Content etc. as these may already be defined in the page types your new page is extending from. When we rebuild the database, we will see that the *ArticlePage* table has been created. Even though we had an *ArticlePage* page type before, a table was not created because there were no fields unique to the article page type. There are now extra fields in the database, but still no way of changing them. To add our new fields to the CMS we have to override the *getCMSFields()* method, which is called by the CMS when it creates the form to edit a page. Add the method to the *ArticlePage* class. :::php setConfig('showcalendar', true); $fields->addFieldToTab('Root.Main', $datefield, 'Content'); $fields->addFieldToTab('Root.Main', new TextField('Author'), 'Content'); return $fields; } } // ... Let's walk through this method. :::php $fields = parent::getCMSFields(); Firstly, we get the fields from the parent class; we want to add fields, not replace them. The *$fields* variable returned is a `[api:FieldList]` object. :::php $fields->addFieldToTab('Root.Main', new TextField('Author'), 'Content'); $fields->addFieldToTab('Root.Main', new DateField('Date'), 'Content'); We can then add our new fields with *addFieldToTab*. The first argument is the tab on which we want to add the field to: "Root.Main" is the tab which the content editor is on. The second argument is the field to add; this is not a database field, but a `[api:FormField]` - see the documentation for more details. > Note: By default, the CMS only has one tab. Creating new tabs is much like adding to existing tabs. For instance: > $fields->addFieldToTab('Root.NewTab', new TextField('Author')); > would create a new tab called "New Tab", and a single "Author" textfield inside. We have added two fields: A simple `[api:TextField]` and a `[api:DateField]`. There are many more FormFields available in the default installation, please refer to [Form Field Types](form-field-types) for the list. :::php return $fields; Finally, we return the fields to the CMS. If we flush the cache (by adding ?flush=all at the end of the URL), we will be able to edit the fields in the CMS. Now that we have created our page types, let's add some content. Go into the CMS and create an *ArticleHolder* page named "News", then create a few *ArticlePage*'s within it. ![](_images/tutorial2_news-cms.jpg) ## Modifing the date field At the moment, your date field will look just like a text field. This makes it confusing and doesn't give the user much help when adding a date. To make the date field a bit more user friendly, you can add a dropdown calendar, set the date format and add better title. By default, the date field will have the date format defined by your locale. :::php addFieldToTab('Root.Main', $dateField = new DateField('Date','Article Date (for example: 20/12/2010)'), 'Content'); $dateField->setConfig('showcalendar', true); $dateField->setConfig('dateformat', 'dd/MM/YYYY'); $fields->addFieldToTab('Root.Main', new TextField('Author','Author Name'), 'Content'); return $fields; } Let's walk through these changes. :::php $fields->addFieldToTab('Root.Content', $dateField = new DateField('Date','Article Date (for example: 20/12/2010)'), 'Content'); *$dateField* is declared only to in order to change the configuration of the DateField. :::php $dateField->setConfig('showcalendar', true); Set *showCalendar* to true to have a calendar appear underneath the Date field when you click on the field. :::php $dateField->setConfig('dateformat', 'dd/MM/YYYY'); *dateFormat* allows you to specify how you wish the date to be entered and displayed in the CMS field. See the `[api:DateField]` documentation for more details of the DateField configuration. :::php $fields->addFieldToTab('Root.Content', new TextField('Author','Author Name'), 'Content'); By default the field name *'Date'* or *'Author'* is shown as the title, however this might not be that helpful so to change the title, add the new title as the second argument. ## Creating the templates Because our new pages inherit their templates from *Page*, we can view anything entered in the content area when navigating to these pages on our site. However, as there is no reference to the date or author fields in the *Page* template this data is not being displayed. To fix this we will create a template for each of our new page types. We'll put these in *themes/tutorial/templates/Layout* so we only have to define the page specific parts: SilverStripe will use *themes/tutorial/templates/Page.ss* for the basic page layout. ###ArticlePage Template First, the template for displaying a single article: **themes/simple/templates/Layout/ArticlePage.ss** :::ss
Posted on $Date.Nice by $Author
$Content.FirstParagraph
Read more >>$Content.FirstParagraph
Read more >>$Content.FirstParagraph
Read more >>