Skip to content

Commit

Permalink
Tutorial 2/3 and some howto tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
chillu committed Aug 7, 2012
1 parent 6d8976e commit 0308cc2
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 181 deletions.
56 changes: 9 additions & 47 deletions docs/en/howto/navigation-menu.md
@@ -1,59 +1,21 @@
#How to create a navigation menu
# How to create a navigation menu

To create a navigation menu, we will create a new template file: Navigation.ss. Put this file inside the templates/Includes folder in your theme.
In this how-to, we'll create a simple menu which
you can use as the primary navigation for your website.

Add the following code to your main template,
most likely the "Page" template in your theme,
located in `themes/<mytheme>/templates/Page.ss`.

:::ss
<ul>
<% loop Menu(1) %>
<li>
<li>
<a href="$Link" title="Go to the $Title page" class="$LinkingMode">
<span>$MenuTitle</span>
</a>
</li>
<% end_loop %>
</ul>

To include this file in your main template, use the 'include' control code. The include control code will insert a template from the Includes folder into your template. The code for including our navigation menu looks like this:

:::ss
<% include Navigation %>

Add this to the templates/Page.ss file where you want the menu to render. The template code in Menu1.ss is rendered as an unordered list in HTML; let's break down this file to see how this works.

The first and last lines of the file are HTML tags to open and close an unordered list.

:::ss
<ul>
<% loop Menu(1) %>
<li>
<a href="$Link" title="Go to the $Title page" class="$LinkingMode">
<span>$MenuTitle</span>
</a>
</li>
<% end_loop %>
</ul>

Line 2 and 4 use a template code called a loop. A loop iterates over a DataObjectSet; for each DataObject inside the set, everything between the <% loop %> and <% end_loop %> tags are repeated. Here we iterate over the Menu(1) DataObjectSet and this returns the set of all pages at the top level. (For a list of other controls you can use in your templates, see the [templates page](../reference/templates) .)

:::ss
<ul>
<% loop Menu(1) %>
<li>
<a href="$Link" title="Go to the $Title page" class="$LinkingMode">
<span>$MenuTitle</span>
</a>
</li>
<% end_loop %>
</ul>

Line 3 is where we insert the list item for each menu item. It is sandwiched by the list item opening and closing tags, <li> and </li>. Inside we have a link, using some template codes to fill in the information for each page:

* $Link – the link to the page
* $Title – the full title of the page (this is a field in the CMS)
* $MenuTitle – the menu title of the page (this is a field in the CMS)
* $LinkingMode – which returns one of three things used as a CSS class to style each scenario differently.
* current – this is the page that is currently being rendered
* section – this page is a child of the page currently being rendered
* link – this page is neither current nor section


More details on creating a menu are explained as part of ["Tutorial 1: Building a basic site"](/tutorials/1-building-a-basic-site), as well as ["Page type templates" topic](/topics/page-type-templates).
106 changes: 52 additions & 54 deletions docs/en/howto/simple-contact-form.md
@@ -1,56 +1,51 @@
# How to make a simple contact form

To make a contact form, begin by making a page type for the form to live on – we don't want to see the contact form on every page. Here we have the skeleton code for a ContactPage page type:
In this how-to, we'll explain how to set up a specific page type
holding a contact form, which submits a message via email.
Let's start by defining a new `ContactPage` page type:

:::php
<?php
class ContactPage extends Page {
static $db = array(
);
}
class ContactPage_Controller extends Page_Controller {

function Form() {
$fields = new FieldList(
new TextField('Name'),
new EmailField('Email'),
new TextareaField('Message')
);
$actions = new FieldList(
new FormAction('submit', 'Submit')
);
return new Form($this, 'Form', $fields, $actions);
}
}

To create a form, we create a Form object on a function on our page controller. We'll call this function 'Form()' on our ContactPage_Controller class. It doesn't matter what you call your function, but it's standard practice to name the function Form() if there's only a single form on the page. Below is the function to create our contact form:

:::php
function Form() {
$fields = new FieldSet(
new TextField('Name'),
new EmailField('Email'),
new TextareaField('Message')
);
$actions = new FieldSet(
new FormAction('submit', 'Submit')
);
return new Form($this, 'Form', $fields, $actions);
}
To create a form, we instanciate a `Form` object on a function on our page controller. We'll call this function `Form()`. You're free to choose this name, but it's standard practice to name the function `Form()` if there's only a single form on the page.

There's quite a bit in this function, so we'll step through one piece at a time.

:::php
$fields = new FieldSet(
$fields = new FieldList(
new TextField('Name'),
new EmailField('Email'),
new TextareaField('Message')
);

First we create all the fields we want in the contact form, and put them inside a FieldSet. You can find a list of form fields available on the `[api:FormField]` page.
First we create all the fields we want in the contact form, and put them inside a FieldList. You can find a list of form fields available on the `[api:FormField]` page.

:::php
$actions = FieldSet(
$actions = FieldList(
new FormAction('submit', 'Submit')
);

We then create a `[api:FieldSet]` of the form actions, or the buttons that submit the form. Here we add a single form action, with the name 'submit', and the label 'Submit'. We'll use the name of the form action later.
We then create a `[api:FieldList]` of the form actions, or the buttons that submit the form. Here we add a single form action, with the name 'submit', and the label 'Submit'. We'll use the name of the form action later.

:::php
return new Form('Form', $this, $fields, $actions);

Finally we create the Form object and return it. The first argument is the name of the form – this has to be the same as the name of the function that creates the form, so we've used 'Form'. The second argument is the controller that the form is on – this is almost always $this. The third and fourth arguments are the fields and actions we created earlier.
Finally we create the `Form` object and return it. The first argument is the name of the form – this has to be the same as the name of the function that creates the form, so we've used 'Form'. The second argument is the controller that the form is on – this is almost always $this. The third and fourth arguments are the fields and actions we created earlier.

To show the form on the page, we need to render it in our template. We do this by appending $ to the name of the form – so for the form we just created we need to add $Form. Add $Form to the themes/currenttheme/Layout/Page.ss template, below $Content.

Expand All @@ -64,26 +59,38 @@ If you now create a ContactPage in the CMS (making sure you have rebuilt the dat
Now that we have a contact form, we need some way of collecting the data submitted. We do this by creating a function on the controller with the same name as the form action. In this case, we create the function 'submit' on the ContactPage_Controller class.

:::php
function submit($data, $form) {
$email = new Email();
$email->setTo('siteowner@mysite.com');
$email->setFrom($data['Email']);
$email->setSubject("Contact Message from {$data["Name"]}");
$messageBody = "
<p><strong>Name:</strong> {$data['Name']}</p>
<p><strong>Website:</strong> {$data['Website']}</p>
<p><strong>Message:</strong> {$data['Message']}</p>
";
$email->setBody($messageBody);
$email->send();
return array(
'Content' => '<p>Thank you for your feedback.</p>',
'Form' => ''
);
class ContactPage_Controller extends Page_Controller {
function Form() {
// ...
}
function submit($data, $form) {
$email = new Email();
$email->setTo('siteowner@mysite.com');
$email->setFrom($data['Email']);
$email->setSubject("Contact Message from {$data["Name"]}");
$messageBody = "
<p><strong>Name:</strong> {$data['Name']}</p>
<p><strong>Website:</strong> {$data['Website']}</p>
<p><strong>Message:</strong> {$data['Message']}</p>
";
$email->setBody($messageBody);
$email->send();
return array(
'Content' => '<p>Thank you for your feedback.</p>',
'Form' => ''
);
}
}

<div class="hint" markdown="1">
Caution: This form is prone to abuse by spammers,
since it doesn't enforce a rate limitation, or checks for bots.
We recommend to use a validation service like the ["recaptcha" module](http://www.silverstripe.org/recaptcha-module/)
for better security.
</div>

Any function that receives a form submission takes two arguments: the data passed to the form as an indexed array, and the form itself. In order to extract the data, you can either use functions on the form object to get the fields and query their values, or just use the raw data in the array. In the example above, we used the array, as it's the easiest way to get data without requiring the form fields to perform any special transformations.

This data is used to create an email, which you then send to the address you choose.
Expand All @@ -95,20 +102,11 @@ The final thing we do is return a 'thank you for your feedback' message to the u

All forms have some basic validation built in – email fields will only let the user enter email addresses, number fields will only accept numbers, and so on. Sometimes you need more complicated validation, so you can define your own validation by extending the Validator class.

The Sapphire framework comes with a predefined validator called 'RequiredFields', which performs the common task of making sure particular fields are filled out. Below is the code to add validation to a contact form:
The framework comes with a predefined validator called `[api:RequiredFields]`, which performs the common task of making sure particular fields are filled out. Below is the code to add validation to a contact form:

function Form() {
$fields = new FieldSet(
new TextField('Name'),
new EmailField('Email'),
new TextareaField('Message')
);
$actions = new FieldSet(
new FormAction('submit', 'Submit')
);
// ...
$validator = new RequiredFields('Name', 'Message');
return new Form($this, 'Form', $fields, $actions, $validator);
}

Expand Down
13 changes: 1 addition & 12 deletions docs/en/reference/database-structure.md
Expand Up @@ -111,15 +111,4 @@ The information documented in this page is reflected in a few places in the code
* augmentQuery() is responsible for altering the normal data selection queries to support versions.
* augmentDatabase() is responsible for specifying the altered database schema to support versions.
* `[api:MySQLDatabase]`: getNextID() is used when creating new objects; it also handles the mechanics of
updating the database to have the required schema.


## Future work

* We realise that a fixed mapping between the database and object-model isn't appropriate in all cases. In particular,
it could be beneficial to set up a SilverStripe data-object as an interface layer to the databases of other
applications. This kind of configuration support is on the cards for development once we start looking more seriously
at providing avenues for clean integration between systems.
* Some developers have commented that the the database layer could be used to maintain the relational integrity of this
database structure.
* It could be desirable to implement a non-repeating auto-numbering system.
updating the database to have the required schema.
6 changes: 3 additions & 3 deletions docs/en/tutorials/2-extending-a-basic-site.md
Expand Up @@ -236,7 +236,7 @@ By default the field name *'Date'* or *'Author'* is shown as the title, however

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
To fix this we will create a template for each of our new page types. We'll put these in *themes/simple/templates/Layout* so we only have to define the page specific parts: SilverStripe will use *themes/simple/templates/Page.ss* for the basic
page layout.

### ArticlePage Template
Expand Down Expand Up @@ -366,7 +366,7 @@ It would be nice to greet page visitors with a summary of the latest news when t

This function simply runs a database query that gets the latest news articles from the database. By default, this is five, but you can change it by passing a number to the function. See the [Data Model](../topics/datamodel) documentation for details. We can reference this function as a page control in our *HomePage* template:

**themes/tutorial/templates/Layout/Homepage.ss**
**themes/simple/templates/Layout/Homepage.ss**

:::ss
...
Expand Down Expand Up @@ -514,7 +514,7 @@ resize the image every time the page is viewed.

The *StaffPage* template is also very straight forward.

**themes/tutorial/templates/Layout/StaffPage.ss**
**themes/simple/templates/Layout/StaffPage.ss**

:::ss
<div class="content-container">
Expand Down

0 comments on commit 0308cc2

Please sign in to comment.