4. Next, add the following line. This says that you no longer want content from the website channel. {/exp:channel:entries}
5. In between the opening {exp:channel:entries} and closing {/ exp:channel:entries} tags, add the following code. This displays the title from your entry as an
header. {title}
6. Underneath the title, add the following code to place the image from your channel entry onto the page. The {if website_image} statement means that if there is no image defined in the channel entry, do not display the img code at all. {if website_image}{/if}
7. Finally, add the following tag to display the content of your content field: {website_content}
[ 82 ]
Chapter 4
8. The content section should now look like: {exp:channel:entries channel="website" limit="1" url_ title="welcome_to_our_website"} {title}
{if website_image}{/if} {website_content} {/exp:channel:entries}
9. Finally, update the page title to reflect the entry title. To do this, replace the line Ed & Eg Financial Advisors with the following code. Although it looks complicated, it's actually the same as the {exp:channel:entries} code in the steps above, except that all you are displaying is the {title} field and not any of the other custom fields you created. By default, the {exp:channel:entries} tag requests a lot of information from your database, which can increase the amount of time it takes to display your page. Since you are only displaying one field, the disable parameter tells ExpressionEngine not to request other information you know you do not need (including the data in your custom fields). For more information on this parameter, you can visit http://expressionengine.com/user_guide/modules/ channel/parameters.html#par_disable {exp:channel:entries channel="website" limit="1" url_title="welcome_to_our_website" disable="categories|category_ fields|custom_fields|member_data|pagination"}{title}{/ exp:channel:entries} - Ed & Eg Financial Advisors
10. Click Update to save your changes and then browse to http://localhost/ site to view your updated website. If everything is well, then you should not notice much difference at all, but behind the scenes, your content is now coming from your channel entry, rather than being part of your template.
[ 83 ]
Moving a Website to ExpressionEngine
Adding more pages
So far you have created a new channel with custom fields, posted to the new channel, and created a template to display your channel content. However, you have not yet seen how to manage multiple pages. The most obvious solution to having multiple pages is to create a template for each page that is an exact copy of the template you already have, except with a different url_title channel parameter so that the template fetches a different channel entry. For example, the individual/index template would request the Individual/ Family channel entry. The downside to this solution is that you would end up with multiple templates all containing much of the same code. While this is fine when the code is not changing, if (for example), you wanted to adjust something on the page (such as the sidebar), you would have to update multiple templates. To get around this repetition, you can use embedded templates. Embedded templates are templates that are included within another template. The included template can be a small piece of code (such as code to display breadcrumbs) or can be an entire HTML page. Embedded templates can accept variables, allowing you to alter the output of the embedded template dynamically. In the following steps, you will create a hidden embedded template that is a copy of the template you have just created. However, instead of having the url_title of the entry you want hardcoded into the template, it will instead be a variable. You will then change your site/index template so that instead of it building the HTML page itself, it will simply call the embedded template and pass in the URL title welcome_ to_our_website as the variable. Once you have done this, there is no limit to how many templates you can create to display different entries from your channel. This solution still requires you to create a template each time you want to add a static page to your website, but instead of each template containing the entire HTML to construct the page design, each template will only include a few lines of code to call the embedded template and display the required entry.
[ 84 ]
Chapter 4
There are actually many ways of handling static content within ExpressionEngine, of which this is just one example. Another good option is the free Pages module: this first-party module allows you to override the standard URL structure (of http:// localhost/tempate_group/template) and instead manually set a channel entry to appear at any URL you choose, using any template of your choice. In this way, you can use one template to display different channel entries at different URLs. Michael Boyink has also written several tutorials on building both two and three-tier static content in ExpressionEngine without using add-ons like Structure or Pages, and this is done in a way that allows you to add new pages without having to create a corresponding template. These can be found at http://www.train-ee.com/courseware/static/.
Begin by creating an embedded template and pointing your existing site/index template to embed this template instead: 1. In the control panel, click on Design | Templates | Template Manager from the top menu. Select the includes template group on the left-hand side and then select New Template on the right-hand side. 2. Call the new template .website_page. The preceding period indicates this template is hidden (meaning that a visitor to your website or a search engine spider cannot see the output of this template directly at the URL http:// localhost/includes/.website_page). You can also use an underscore at the beginning of a template name to mark the template as hidden.
3. Leave the template type as Web Page. Under Default Template Data, select Duplicate an existing template. In the drop-down list of templates, select site/index as the template to duplicate. Click on Create and Edit.
[ 85 ]
Moving a Website to ExpressionEngine
4. In the new template, there are two places where you can see the {exp:channel:entries} parameter url_title="welcome_to_our_ website"—one at the top of the page in the tag and one at the start of the content section. Change both these parameters to read url_ title="{embed:url_title}" instead. This says to use the variable for url_title that is passed in from the calling template. Click on Update and Finished. 5. Now edit the site/index template and delete everything in it. Instead, add just this code (to call the embedded template includes/.website_page with a variable url_title set to welcome_to_our_website). {embed="includes/.website_page" url_title="welcome_to_our_ website"}
6. Click on Update and Finished and now visit http://localhost/site. Even though your updated site/index template is much shorter than before, notice how the web page itself looks no different. That's it! The design is now such that you can have as many static website pages as you like, each of which use the same embedded template. Now all that is left to do is prove this works by creating a second page.
Publishing a second page
There are two steps to carry out every time you want to create a new static website page. First create a channel entry with the content for the page and then create a template group and edit the index template to embed the .website_page template with a URL title of the channel entry you wish to display. If you wish to have a static second tier page (such as a URL of business/ news), then you would create a template called news in the business template group and then embed the .website_page template as you normally would.
To demonstrate how this works, create a second channel entry. This time, it should be based on the individual.html page in Ed & Eg's website. 1. Open the downloaded individual.html page in your browser. 2. In the control panel, select Content | Publish | Website. Use a Title of Individual/Family and a URL Title of individual_family. 3. Under Image, select Add File. However, this time, instead of having to upload the same image again, you can click on Main Upload Directory on the left hand-side of the File Manager and click on the previously uploaded money.jpg. [ 86 ]
Chapter 4
4. Then, as before, copy the content from the Individual/Family page in your browser, marking up the headings as . For the hyperlink in the How Much Do We Cost? section, use a hyperlink such as promotions, which will resolve to http://localhost/promotion in anticipation of you creating the Promotions page at that URL. When you are done, click Submit. The {site_url} variable is a global ExpressionEngine variable that substitutes itself with the URL to the root directory of your website (as defined in Admin | General Configuration). The benefit of using this ExpressionEngine variable, instead of typing in the (much longer) root directory of your website (such as http://localhost/), is that if you ever change your website domain, you only have to change it in one place in ExpressionEngine (rather than changing every occurrence of the domain name.).
Now that there is a second channel entry, we can go ahead and create a template for it. [ 87 ]
Moving a Website to ExpressionEngine
Creating a second template
Call the new template group individual so that its output appears at the URL http://localhost/individual. 1. In the control panel, click on Design | Templates | Template Manager from the top menu. Select New Group on the left-hand side. 2. Call the new group individual. Then, under Duplicate an Existing Template Group?, select the site template group to duplicate. Click Submit.
3. Edit the index template of the individual template group and change the code to read as follows: {embed="includes/.website_page" url_title="individual_family"}.
4. Click Update and Finished and visit your new page at http://localhost/ individual to verify it. It looks identical to the individual.html page from Ed & Eg's static website. 5. Verify that the promotions link you created in the entry links to http:// localhost/promotion. Although you have not yet created that page, if the link appears as http://localhostpromotion, it's likely the URL to the root directory of your website doesn't include the final forward slash (for example, it might be set as http://localhost instead of http:// localhost/). To change this, go to Admin | General Configuration and update the setting called URL to the root directory of your website. By now, you can see that the website is relatively easy to maintain. To create a new page, all you need to do is create a new channel entry and a new template that references the URL title of your new entry. To change the wording or the image on an existing page is even easier; all you have to do is edit the entry. No dealing with templates or template code at all! Finally, should you ever wish to change the site design, you only have to do so in a single template. [ 88 ]
Chapter 4
Going live
Currently, unless you have already changed this, the default template group is the Agile Records website (news/index), meaning that if you go to http://localhost/, the news/index template will be rendered. (If you didn't install Agile Records and didn't already define a default template group, then visiting http://localhost will display a blank screen). Change the default template group to be site/index (which is where the Welcome to Our Website entry is displayed). Follow these instructions: 1. To change the default template group, go to Design | Templates | Template Manager in the control panel. 2. Highlight the site template group on the left-hand side and then select Edit Group (the left-most button above the list of individual templates).
3. Check the box that says Make the index template in this group your site's home page? and click Update.
4. Now, when you visit http://localhost/, you should see Ed & Eg's website in place of Agile Records.
[ 89 ]
Moving a Website to ExpressionEngine
Note that you can still access the Agile Records website at http:// localhost/news. If you are following along on your own computer, this allows you to refer to the Agile Records site at any time. However, if you are on a live web server, you may wish to suppress the Agile Records website completely. You can do this in Template Manager—next to each template associated with Agile Records (about, global_embeds, news, search), there is an option called Access. You can change the access for each template to say that visitors to your website cannot view the output of these templates, but that instead they should be routed back to the site/index template. (You and other SuperAdmins will still be able to see the template output at their current URLs. So if you wish to verify that the re-direct is working, you must first log out of ExpressionEngine).
Avoiding repetition
You have already created an embedded template that saves you from having lots of templates with the same basic HTML code inside. When working with templates in ExpressionEngine, it's best to avoid code repetition of code as much as possible— whether the repetition is within a single template or across multiple templates. Any situation where code is repeated can be a major headache, should you ever wish to update that code; instead of being able to make an update in a single location, you instead have multiple places to make the same update, increasing the likelihood that you miss one. On a small site with only one or two templates, it's easy to manage code that is repeated, but as your site grows, having the same code in more than one template can make changes very difficult and time-consuming to accomplish. ExpressionEngine has four ways to reduce repetition: 1. 2. 3. 4.
Preload text replacements User-defined global variables Snippets Embedded templates
Each of these methods involve assigning the repeated code to a custom ExpressionEngine tag and then using that tag whenever you want to use the repeated code in a template. The key differences between these methods are: • •
Preload text replacements only work within the same template and can only contain a string (no ExpressionEngine tags). Global variables can contain a single line or multiple lines of static HTML and text—in fact, anything except ExpressionEngine tags and code. [ 90 ]
Chapter 4
•
Snippets are identical to global variables, except that snippets can contain ExpressionEngine tags.
•
Embedded templates, as you have already seen, are an entirely separate template that can be included in another template.
For performance reasons, it's best to use the first available option that will meet your needs. If the text is a string that is only being repeated in a single template, use Preload text replacements. If your code is repeated in more than one template, but does not contain ExpressionEngine tags, use global variables. If the repeated code includes ExpressionEngine tags, use snippets. Embedded templates are usually only necessary in special circumstances such as when you want to use variables to dynamically vary the code that results (a snippet cannot be passed variables). You have already seen how powerful embedded templates can be. What follows are examples of the other tools.
Preload text replacements
Preload text replacements are useful as local constant variables. In ExpressionEngine, you will find that there are certain references that are made multiple times within a single template, such as the channel where the main content is coming from or the template group that the template is in. By creating Preload text replacements for these references, you can gain several benefits: •
It gives you a single place in each template to change one of these references, should one of the names ever change.
•
When creating a new section of your website, you will often start with an existing template as a base. If the existing template has Preload text replacements, you can simply copy the existing template and change those preload replacements, saving a lot of time.
•
The Preload text replacement may be shorter to type (although if it's not, it is still sometimes a good idea to use a Preload text replacement than have repetition).
For the remainder of this book, each template you create will have a Preload text replacement called my_channel for the channel that the template references the most. By doing this, it will save you from having to constantly remember what the channel short name is; you will simply set it at the top of each template and then use {my_channel} instead. Go ahead and create a {my_channel} Preload text replacement in the includes/. website_page template now. [ 91 ]
Moving a Website to ExpressionEngine
1. Edit the includes/.website_page template. At the very top of the template, insert the following code: {preload_replace:my_channel="website"}
2. In this template, there are two places where you can see the {exp:channel:entries} parameter channel="website"—one towards the top of the page in the tag and one at the start of the content section. Change both these parameters to read channel="{my_channel}" and click on Update. 3. Visit your website and you should see no difference in the content. (If the content has suddenly disappeared, there may be a misspelling).
User-defined global variables
User-defined global variables can be used for any code that is repeated and that does not contain ExpressionEngine tags. Unlike Preload text replacements, a global variable can contain multiple lines of text and can be used in any template. The site name at the top of each page is a good example of this—although it's only three lines and it does not contain any ExpressionEngine tags. However, it will be needed in every template, so it's worth extracting into a global variable. This way, if Ed & Eg ever change their site name, the update only has to happen in one place and the entire website will be updated. 1. In the control panel, select Design | Templates | Global Variables from the top menu. 2. You will see that there are already some global variables that have been defined. These are being used by the Agile Records website. Click on Create a New Global Variable at the top right. 3. Call your new variable website_sitename. 4. The variable content will be as follows. Ed & Eg Financial Advisors
5. Click Update to save the global variable.
[ 92 ]
Chapter 4
6. Now go back to the includes/.website_page template and replace the section of code that displays the site name, starting with down to and including the corresponding closing with the global variable tag {website_sitename}. When you are done, the two lines of code after should look as follows. Click Update. {website_sitename}
7. Visit your website and you should see no difference. Reducing repetition is something that makes the website easier to maintain for you, but does not change anything for your visitors.
Snippets
Snippets are ideal for code that is repeated and that contains ExpressionEngine tags. For this example, you will convert the sidebar that appears on the right-hand side of each page into a snippet. Although the sidebar does not currently have any ExpressionEngine tags, meaning you could use a global variable, you will be adding additional functionality into the sidebar as you progress through the book. In anticipation of this, it therefore makes sense to convert the sidebar into a snippet, rather than a global variable.
[ 93 ]
Moving a Website to ExpressionEngine
1. In the control panel, select Design | Templates | Snippets from the top menu. 2. You will see that there are already some snippets that have been defined for the Agile Records website. Agile Records uses snippets prefixed with global for items that appear on every page (like the footer) and snippets prefixed with the template group name for items that only appear in templates in that group. We are going to create a new snippet, so click on Create a New Snippet at the top right. 3. Call your new snippet website_sidebar, using website instead of global to distinguish this snippet from the Agile Records snippets. 4. To save typing, copy the following code from the includes/.website_page template: -
Promotion!
From now until the end of the year, Ed & Eg are offering a <strong>free initial 90 minute consultation, plus <strong>25% off your first return visit. Learn More…
-
Key Services
- -Budgeting
- -Debt Management
- -Investing
- -Financial Planning
- -Tax Services
- -Book-keeping & Cash Flow
- -Accounts Preparation
- -Payroll Services
5. Before saving this snippet, update the link that appears in the Promotion! box from promotion.html to {site_url}promotion. (Although you have not yet created a promotion template group and a corresponding website channel entry, when you do, this link will work). [ 94 ]
Chapter 4
6. Click on Update and Finished to save the snippet.
7. Now go to the includes/.website_page template and replace the sidebar code you just copied into the snippet with the snippet tag {website_ sidebar}. The four lines after should now look as follows. When you are done, click Update. {website_sidebar}
8. If you now visit your website, you should not see much change. The only difference that indicates the sidebar is now coming from your snippet rather than from the template is the link in the Promotions! box that points to http://localhost/promotion instead of promotion.html.
Creating a menu
Another good candidate for a snippet is the site menu that appears at the top of every page. Creating the menu as a snippet (rather than a global variable) allows you to use the ExpressionEngine variable {site_url} in place of your domain name, just like you did when creating the link to the promotions page within the Individual/ Family entry. Although you have not yet created all the entries (and template groups) for the following page links to work, you can create this menu snippet in anticipation of creating the corresponding pages later (as part of the exercises at the end of this chapter). [ 95 ]
Moving a Website to ExpressionEngine
1. In the control panel, select Design | Templates | Snippets from the top menu and click on Create a New Snippet at the top right. 2. Call your new snippet website_menu. 3. Type in the following code:
4. Click on Update and Finished to save your new snippet. 5. Now go to the includes/.website_page template and replace the menu code that starts with , till the closing with the snippet tag {website_menu}. When you are done, the section should look as follows. Click on Update. {website_sitename} {website_menu}
6. If you now visit your website, you should see that your menu links have all changed. Verify that you can successfully click between the Homepage and the Individual/Family pages you have already created.
Embedded templates
You have already seen an example of an embedded template. An embedded template can do everything a snippet can do with two main differences: 1. Embedded templates can be passed variables, and the output can then vary based on those variables.
[ 96 ]
Chapter 4
2. An embedded template is a template. ExpressionEngine has many different options that can be defined on a per-template basis (different templates can have different access controls, different caching preferences and different PHP settings) whereas snippets have the same settings as the template they are in. Furthermore, you can restrict certain template groups so that other administrative control panel users cannot see them, but with snippets, you can only give other administrative control panel users access to all snippets or none of them. Note that when using embedded templates, you can define as many or as few variables as you wish. Simply listing the variables and their values in the tag creates the variables, for example, {embed="template group/template" variable1="dog" variable2="cat"}. If you do not want any variables, then the tag is simply {embed="template group/template"}.
Now that you have seen examples of Preload text replacements, global variables, snippets, and embedded templates, you can certainly go further and extract even more repeated code into these tools. The page footer could be a global variable, as could the widebar. However, it is important to strike a balance between reducing repetition and writing code that you will understand a year or two later. Although only you can know where that balance lies for you, here are some recommendations: •
•
Keep custom tags descriptive as to what the code is that they represent (for example, instead of {widget}, use a name that makes it obvious to you what the tag represents). As you start out, avoid putting opening tags (such as a ) into a global variable, snippet, or embedded template, without the corresponding closing tag (such as a ). While ExpressionEngine does allow this, it can make the template code more difficult to troubleshoot. As you grow more experienced, there can be cases when your website page requires certain elements in a certain order simply to build the layout, so you may find it more efficient to replace a series of opening 's with a global variable and then create a second global variable for the corresponding closing 's.
•
Do not bundle unrelated parts of your page into the same global variable, snippet, or embedded template. While you could use one snippet for the entire footer, including the FAQs and the copyright notice, it would cause problems if, on one page, you only need the copyright notice, but not the FAQs. [ 97 ]
Moving a Website to ExpressionEngine
For an example of just how far you can take these techniques, check out Derek Jones' official ExpressionEngine blog series 'Behind the Curtains' that talks about how EllisLab uses ExpressionEngine on their own websites. (Note that the series was written in 2007, before snippets existed): http://expressionengine.com/blog/ article_list/category/behind_the_curtain/
Creating a 404 Page not found
A 404 Page is an essential part of any website, and working through this chapter, you may have noticed that your 404 Page is still themed like the Agile Records website. In this section, you will take advantage of all the repetition-reduction you have done as you create a new 404 Page. 1. Select Design | Templates | Template Manager, select the Includes template group, and then select New Template. Call the new template 404. The Template Type will be Web Page, select Duplicate an Existing Template, and finally select the includes/.website_page template to copy from. Click on Create and Edit. 2. Since the 404 Page content does not come from a channel, delete the line that reads {preload_replace:my_channel="website"}. 3. Change the line to: Page Not Found - Ed & Eg Financial Advisors
Replace everything from to with: Page not Found (404)
The page you were looking for does not exist. There may be a spelling mistake in the URL in the address bar, or we may have removed this page inadvertently. Please use the menu at the top to visit a page that does exist.
4. Click Update to save the changes. 5. Now that you have a 404 Page that is consistent with your site design, you can define this page to appear when a page is not found. Select Design | Templates | Global Preferences from the top menu. 6. Under 404 Page, select includes/404 as the template to display. At the same time, make sure Enable Strict URLs is set to Yes (or your 404 Page will not work). Click Update. [ 98 ]
Chapter 4
Now, when you visit an invalid URL (such as http://localhost/toast), you will see your 404 page instead of the Agile Records 404 page.
Templates as files
While working with templates within the web-based control panel interface works well, it does have limitations. If you are used to coding HTML files using your favorite text editor, you may wish to continue using that text editor and FTP the files to your website instead. In ExpressionEngine, this is entirely doable. 1. If you are following along on an actual website, you will need to ensure that the directory permissions for /system/expressionengine/ templates are set to 777. If you are using a localhost environment, this is not necessary. This directory is where your template files will be saved. [ 99 ]
Moving a Website to ExpressionEngine
2. In the control panel, select Design | Templates | Global Preferences from the top menu. 3. Set Allow Templates to be Saved as Files to Yes. The likelihood is that the Basepath to Template File Directory is already set to the full server path for / system/expressionengine/templates, but if it is not, you will need to set it.
4. Click Update to save your changes. 5. Although this option allows you to start creating templates as files, it does not automatically go back and create files for your existing templates. To do this, you have to mark each template to save as a file. Edit each template in the site, individual, and includes template groups in turn, check the box marked Save Template as File (just above the Update button), and then click Update and Finished.
6. You will now see your template files in system/expressionengine/ templates in a sub-directory called default_site. You can now edit your template code by editing these files directly. You can easily create new templates and new template groups without using the control panel by putting new files and directories in this directory. When creating new templates and new template groups, there are certain conventions to be aware of: template groups are separate directories with the name of the group followed by a .group extension. Webpage templates end in .html and CSS templates end in .css. You can edit templates in the control panel and in the files interchangeably. When opening a template in the control panel, ExpressionEngine will look to see if the file is newer than the database version, and if so, load the file. Updating your template will then update the ExpressionEngine database and file simultaneously (unless you uncheck the box to save it as a file). [ 100 ]
Chapter 4
Know that when displaying pages to visitors, ExpressionEngine will always use the file before using the template saved in the ExpressionEngine database. This means that you can feel confident updating the files outside of the control panel, knowing that the changes will immediately reflect on your website. Occasionally, when using templates as files, you may find that a file for a template has gone missing. ExpressionEngine has a utility to synchronize the templates periodically to ensure that the templates in the database match the content of the files and that there are files for every template. To run this, you can go to Design | Templates | Synchronize Templates. The screen will summarize whether the templates are in sync or if the files are newer than the database templates. If any are not in sync, check which templates you want to sync and click on Submit to update the database with the updated files (as well as recreate any template files that may have accidentally gone missing). For more information on templates as files, see the ExpressionEngine documentation at http://expressionengine.com/user_guide/templates/flat_file_ templates.html
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. In this chapter, you only created the home page and the Individual/Family page. Go ahead and create the Small Business, Contact Us, and Promotions page. Leave out the Frequently Asked Questions page. You will convert this page in the next chapter.
Summary
In this chapter, you have seen how to build a complete website using ExpressionEngine. You have taken advantage of many of ExpressionEngine's features to reduce repetition and make your website as simple to maintain as possible. In the next chapter, you will learn more about channels and how you can use ExpressionEngine to turn the Frequently Asked Questions page of Ed & Eg's website into a more interactive experience for your visitors. [ 101 ]
Moving a Website to ExpressionEngine
The key points to remember after working through this chapter are: •
Custom fields, categories, and statuses can all be customized on a perchannel basis (or different channels can share the same custom fields, categories, or statuses). This lends itself to enormous flexibility in how you design your channel (but also means there is usually more than one way to accomplish anything in ExpressionEngine).
•
When creating a new channel, you create custom fields/statuses and categories for the new channel (optional), create the channel itself, create content inside the channel, and create or modify templates to display the channel content. These steps can be completed in any order and are usually iterative.
•
Preload text replacements are useful as constants, allowing you to take a line of text that is repeated throughout a template, such as the channel name, and define it in one place.
•
Global variables can be used for static text, HTML, or scripts that are used in more than one template. Therefore, by using this, if you want to make a change, you only have to update the global variable, rather than every template that might be using that code.
•
Snippets are like global variables, except that they also allow ExpressionEngine code and tags.
•
Embedded templates are like snippets, except that they allow variables to be passed to them to dynamically vary the output.
[ 102 ]
Creating a Fully-Equipped Channel So far you have used ExpressionEngine to create a website where you can easily edit the content through the Publish screen in ExpressionEngine and where it is easy to add new pages, should you wish to. In this chapter, you are going to take your ExpressionEngine-powered (but still static) website and enhance it to make it interactive. The Frequently Asked Questions page is an ideal candidate for this. Currently, there are only two questions on the page. However, Ed & Eg would like to start posting new questions and answers regularly. The frequently updated content would encourage visitors to keep coming back to the site. Although Ed & Eg is the example in this chapter, the concepts could easily be applied to any regularly updated content that you would want to post on your website; including a regular blog, book reviews, recipes, or products that you are selling. You will be: •
Displaying multiple entries
•
Allowing visitors to browse entries and select the ones that interest them
•
Allowing visitors to comment on entries, just like they might comment on a blog posting
•
Creating a feed to allow visitors to keep up with new entries using their favorite news reader (such as Google Reader)
From what you learned in the last chapter, you should now be familiar with the process of creating a channel, creating custom fields, posting content, and creating a template to display the content. You will follow that same process in this chapter.
Creating a Fully-Equipped Channel
Designing your channel
One of the biggest benefits to using ExpressionEngine is the ability to customize your channel fields. This allows you to really tailor the fields to the content that will be in the channel. In this case, you are creating a channel for Ed & Eg's Frequently Asked Questions. You will need two text fields—one for the question and one for the answer. By splitting up the question and answer fields in this way, you gain the ability to display the question separately from the answer—a design you will take full advantage of. You will create a multiple-entry page where visitors can see the various questions that have been asked and (hopefully) be tempted to click to find out the answers. When they click on a given question, the visitor will be taken to a single-entry page where the question and the answer will be displayed, along with comments from other visitors, with the ability to add their own comments. This design of single and multiple-entry pages is actually fundamental to ExpressionEngine. The key differences between the two types of pages are: 1. A multiple-entry page displays the content from more than one entry in your channel. You can choose to display all the information from the channel or just a teaser (such as only the question, but not the answer). You have control over how many entries are displayed on a page and how they are displayed. A multiple-entry page can change frequently—if a visitor bookmarks a multiple-entry page and returns at a later date, the page will likely reflect new content. 2. A single-entry page displays the content from only one entry in your channel. The content does not change over time (unless you edit the entry in question). This means that a visitor can bookmark the URL or e-mail it to a friend, and when they return, they will see the same content that they originally saw (plus any new comments). A single-entry page is required to accept comments for a specific entry and to display those comments. The URL for a single-entry page is determined by the URL Title on the Publish screen for the entry. A single-entry page URL typically takes the format of http:// localhost/template_group/template/entry_url_title, whereas a multiple-entry page URL would not have the entry_url_title at the end. ExpressionEngine uses the URL to dynamically determine what content to display using each template. If the URL has the URL Title of an entry in it, ExpressionEngine will only display that entry. If the URL does not have the URL Title of an entry in it, ExpressionEngine will return as many entries as meet the criteria in the parameters of the {exp:channel:entries} tag. [ 104 ]
Chapter 5
The includes/.website_page template that is used to display content from the website channel is actually an example of a multipleentry page. However, you used the parameter url_title to limit the number of entries to one specific entry.
In general, not all channels need both single and multiple-entry pages. However, it's good practice to have single-entry pages for channels with content that a visitor might want to bookmark and return to. Furthermore, if your channel allows visitors to leave comments on your posts, a single-entry page is required. Whether or not to allow comments is, in fact, a design decision in itself. Although it can encourage visitors to engage with your brand, having a website that allows comments but does not have any can be worse than not allowing comments at all. Ed & Eg have a plan to ensure their website will receive comments once it goes live.
Creating your custom channel fields The custom fields you are going to create are: • •
faqs_question faqs_answer
The question and answer fields will be Textarea fields with Auto
formatting. This formatting will put line breaks between paragraphs in the answer, but will not wrap the question and answer in paragraph tags. The benefit to doing this is that you can put an A: at the beginning of each answer in your template and know that the first paragraph of the answer will be on the same line. 1. From the top menu of the control panel, select Admin | Channel Administration | Custom Fields. Now select Create a New Channel Field Group.
[ 105 ]
Creating a Fully-Equipped Channel
2. Use a Field Group Name of faqs, as this field group will only be suitable for the Frequently Asked Questions channel. Click Submit. 3. Select Add/Edit Custom Fields for your faqs field group, and then select Create a New Custom Field.
4. The first field to create is the Question field. The Field Type will be Textarea. Give it a Field Label of Question and a Field Name of faqs_question. Leave the Field Instructions blank (these appear only on the Publish page).
5. This will be a required field and will be searchable. Say Yes to show this field by default and do not change the value of the Field Display Order. 6. The Textarea Rows can be left at 6. Set the Default Text Formatting to Auto
and say No to allowing an override on the Publish page. Leave the Text Direction as Left to Right and say Yes to show the Formatting Buttons, Smileys, Spellcheck, Writemode and File Chooser. Leave everything else set to No.
[ 106 ]
Chapter 5
7. Click Submit. 8. Go ahead and create the field Answer (faqs_answer) with the same settings as the faqs_question field. 9. Once your fields have been created, your Field Group should look as follows:
That's it! Your custom fields have been created and you can now move on to creating some custom categories.
[ 107 ]
Creating a Fully-Equipped Channel
Creating your categories
In the last chapter, when you created the website channel, you did not create categories because there was no need to organize your content by category. In this chapter, since the number of questions in your channel could quickly become numerous, it makes sense to use categories to relate questions to each other (and hopefully keep your visitors browsing longer). 1. To create a new category group, go to Admin | Channel Administration and then Categories.
2. Select Create a New Category Group. 3. Call the new category group FAQ Categories and select Allow ALL HTML from the formatting drop-down box. Ignore the options about editing and deleting categories—if you had other member groups with administrative control panel access, you could have granted them permission to edit and/ or delete categories in this category group. ExpressionEngine automatically recognizes that no other member groups have administrative control panel access at the moment.
[ 108 ]
Chapter 5
4. Click Submit. 5. You have now created a category group, but you have not yet created any categories. From the Category Management screen, select Add/Edit Categories for the FAQ Categories group. 6. At the top right, select Create a New Category.
7. For now, you will have two parent categories (Life Events and General Advice) as well as a number of sub-categories. Name this first category Life Events. The Category URL Title will default to life_events. Leave the Category Description blank and do not assign an image to your category. Leave the Category Parent set to None and click Submit.
8. Back on the FAQ Categories screen, select Create a New Category again.
[ 109 ]
Creating a Fully-Equipped Channel
9. Your first sub-category will be Going to College (with a URL title of going_ to_college). Type in a short category description such as Questions relating to college/university. Under Category Parent, select Life Events. Do not select a Category Image. Click Submit.
10. The rest of the categories will be set up similar to the two already created (except that the names, URLs, and descriptions will be different). Create the following categories/sub-categories and go ahead and make up your own descriptions; later, you will display the descriptions on your website, so be sure they are full sentences. Category Name
Category URL Title
Category Parent
Getting Married
getting_married
Life Events
Having a Baby
having_a_baby
Life Events
Changing Jobs
changing_jobs
Life Events
Retiring
retiring
Life Events
General Advice
general_advice
None
Budgeting
budgeting
General Advice
Buying a Car
buying_a_car
General Advice
Buying a Home
buying_a_home
General Advice
Debt
debt
General Advice
Savings
savings
General Advice
Investments
investments
General Advice
[ 110 ]
Chapter 5
Your categories have been created. If you want to, you could use the arrows on the left-hand side to re-order the fields (currently, they are ordered alphabetically).
Now that you have created your custom categories, the next step is to create your FAQ channel. Note that you could create your channel first and then create your categories and your custom fields afterwards. However, if you do this, you would then have to go back and edit your channel to associate it with your custom fields/categories. By creating your categories/custom fields first, you can associate the category/custom field group when you create your channel.
Creating your new channel
As you have previously seen, a channel contains content. In this chapter, the questions Ed & Eg get asked and their answers are your content. You have already built new custom fields and a new category group for your channel. You do not need a new custom status group; the open and closed statuses that are in the pre-existing Statuses status group are all you need. 1. From the control panel top menu, select Admin, then Channel Administration, and then Channels. Now select Create a New Channel. [ 111 ]
Creating a Fully-Equipped Channel
2. The Full Name for your channel will be FAQs and the Channel Name will be faqs. Do not duplicate an existing channel's preferences, but say Yes to editing the group preferences.
3. Under Edit Group Preferences, choose a Category Group of FAQ Categories, a Status Group of Statuses, and a Field Group of faqs.
4. Further down, say No to creating new templates for this channel (you will do this later). Finally, click Submit. Your channel has now been created!
Publishing your first set of questions
You have a channel created, complete with custom fields and categories. The next step is to publish some entries so that there are some entries to work with when you start building the templates that will display your channel content. Take the initial questions from the existing questions.html page in the original Ed & Eg website that you downloaded in chapter 4. 1. From the top menu, select Content, Publish, and then FAQs. Title your first question Living Paycheck to Paycheck with a URL Title of living_ paycheck_to_paycheck.
[ 112 ]
Chapter 5
2. Open questions.html in your browser and copy the text of the question and the answer into your channel. Do not copy any of the HTML (such as paragraph tags). Also, do not copy the Q: or A: and do not worry about putting the question in italics—this can be done at the template level to save you from having to remember to do it for each and every question. Do go ahead and apply any italics in the answer by highlighting the words to italicize and then clicking the i button above the field.
3. Select the Categories tab at the top and check the appropriate categories for this entry (such as Budgeting, Debt, and Savings). Next click Submit.
[ 113 ]
Creating a Fully-Equipped Channel
4. Repeat all these steps for the second question called Giving Gifts. Select a category for this entry of Budgeting and click Submit. You now have your first entries published, but before you can see them on your website, you will need to create some templates.
Creating your FAQ templates
Earlier in the chapter, you learned about single-entry versus multiple-entry pages. However, in reality, a channel with more than a handful of entries needs more than one multiple-entry page to keep the number of entries on each page down to a digestible number for your visitors. ExpressionEngine, therefore, offers you three ways to organize your multiple-entry page content: 1. By Category: Organizing your entries by category involves having a category page for each category. On that page, only the entries in that category are displayed. 2. By Date: Organizing your content by date creates an archive page for each month, with only the entries in each month displayed. This technique can be combined with a mini-calendar so that visitors can select a month or even a specific day and see only the entries from that timeframe. 3. By Pagination (showing 10 entries per page): There are two types of pagination—one that shows how many pages there are and allows you to jump to a specific page (including the last page). The other is a simple Next/ Previous link that your visitors can use to traverse through your pages oneby-one. Pagination can be combined with organizing by category so that categories that have a lot of entries are paginated. You can choose one or more of the preceding techniques to organize your content. You can even use all the techniques together, paginating your multiple-entry page while also providing links for visitors to filter either by date or by category should they wish to do so. For Ed & Eg's website, the content is such that it makes more sense to organize by category than it does by date. (A new visitor to Ed & Eg is going to care less about when each FAQ was posted and care more about whether the FAQ is relevant to them). It also makes sense to use pagination to keep the number of entries on each page to a reasonable number. You will therefore create two templates—one for the multiple-entry pages (faqs/ index) so that a visitor can browse the FAQs and one for the single-entry page (faqs/browse) where visitors can read an individual FAQ and post their own comments. Within the multiple-entry page template, you will use conditional statements to identify whether the page being displayed is the main multiple-entry page (with no filtering by category) or a category-specific multiple-entry page. [ 114 ]
Chapter 5
It is possible to go even further and combine the single-entry page and the multiple-entry page into a single template using conditional statements based on the URL. However, your template quickly becomes complicated when doing this, particularly if you are organizing your entries by category, by date, or by pagination, since each of these techniques results in different URLs which have to be accounted for. If this is something you are interested in doing, then a plugin such as MD Detect Page Type (http://devot-ee. com/add-ons/plugins/md-detect-page-type/) will help.
You will start by creating a basic multiple-entry page template with pagination (you will add the category archiving later). 1. First, since you are creating a new section for your website, it makes sense to create a new template group to house it in. In the control panel, click on Design, Templates, and then Template Manager. Select New Group and call the new template group faqs. Do not duplicate a group and do not make the index template in this group your site's home page. (You still want the site template group to be the site's home page). Click Submit. 2. Next, copy the includes/404 template (created in the previous chapter, or can be downloaded from http://www.packtpub.com/support or from the chapter 4 page at http://www.leonardmurphy.com/book2/chapter4) into the faqs/index template. Remove the heading and the following paragraph so that there is nothing between the and the closing . Click on Update. This will result in a page at http:// localhost/faqs with a header, sidebar and footer, but no content.
[ 115 ]
Creating a Fully-Equipped Channel
3. At the top of the template, create three new Preload Text Replacements (below). The first represents the channel name, the second represents the template group, and the third represents the single-entry template that you will create next. Each of these will be used in multiple-places throughout the template, so they are good candidates for Preload Text Replacements. {preload_replace:my_channel="faqs"} {preload_replace:my_template_group="faqs"} {preload_replace:my_single_entry_template="browse"}
4. Update the HTML attribute as follows (this is the title that appears at the top of the window): Frequently Asked Questions - Ed & Eg Financial Advisors
5. Next, write the code to display the Frequently Asked Questions' introduction. After the line, insert the following: Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
6. Now you are going to write the code to display up to ten questions on a page using pagination. This first piece of code displays the title of each entry. The limit parameter is what determines how many entries to display on each page, and the paginate parameter indicates where you would like the pagination links to appear (the choices are top, bottom, or both). Within the paginate variable pair, a conditional statement makes sure that there is more than one page of entries before displaying in order to display the pagination links. (This means that, initially, since you do not have more than ten entries, you will not see these pagination links). Insert the following code just before the line that appears immediately above : [ 116 ]
Chapter 5 {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom"} {title}
{paginate} {if "{total_pages}" != 1}
Page {current_page} of {total_pages} pages {pagination_links}
{/if} {/paginate} {/exp:channel:entries}
7. If you click Update and then visit http://localhost/faqs, you will see the titles for the channel entries you have already submitted.
8. Now you can add the questions for each entry, along with a link to read the answers. Insert the following code after the header:
<strong>Q: <em>{faqs_question}
<strong>A: Read the answer here!
[ 117 ]
Creating a Fully-Equipped Channel
The permalink tag generates an HTML link to the URL for the single-entry page for each entry. A permalink is so called because it is a permanent link to that entry. For example, the multiple-entry page http://localhost/faqs may display different FAQs in different orders at different times, but the permalink http://localhost/ faqs/browse/living_paycheck_to_paycheck will always be a link to the Living Paycheck to Paycheck entry. (Note that you have not yet created the browse single-entry template). The permalink tag includes one parameter, which is the template group and the template to use to display the entry. It then dynamically adds the URL title for you. In this case, you are linking to the browse template of the faqs template group (although you are using Preload Text Replacements instead of referencing faqs/browse directly).
Now visit http://localhost/faqs and you can see the questions along with links to read the answers. The links do not work yet since you have not yet created your single-entry template. You will do this next.
You are done with your multiple-entry page template! Next, you have to create the single-entry page.
Creating your single-entry page
As previously explained, you are going to use the faqs/browse template for your single-entry pages. 1. In the control panel, go to Design, Templates, and then click on Template Manager. Highlight the faqs template group and select New Template. [ 118 ]
Chapter 5
2. Name the new template browse. Leave the template type as Web Page. Under Default Template Data, highlight Duplicate an Existing Template and select faqs/index as the template to duplicate. Click Create and Edit.
3. The first change you are going to make is the HTML that appears in the browser title bar. In the includes/.website_page template in Chapter 4, Moving a Website to ExpressionEngine, you used the {exp:channel:entries} tag to get the title of the entry from the channel and use it as part of your HTML title. You will now do this again. Remember that the disable parameter cuts down on unnecessary database queries given that you are just retrieving the title of the entry and nothing else. Change the to read as follows: {exp:channel:entries channel="{my_channel}" disable="categories|category_fields|custom_fields|member_data|pagi nation"}{title}{/exp:channel:entries} - Ed & Eg Financial Advisors
4. Underneath the line , delete the entire block of code from the down to (and including) the {/exp:channel:entries} tag. 5. Now add the following code in the section instead. This code is very similar to the code for your browsing page, except that you are displaying the answer and instead of links to the single-entry page, you have a link back to the main browsing page. {exp:channel:entries channel="{my_channel}"} {title}
<strong>Q: <em>{faqs_question}
<strong>A: {faqs_answer}
[ 119 ]
Creating a Fully-Equipped Channel {/exp:channel:entries}
Note the use of the path variable to provide a link back to the index template of the faqs template group. If you wanted a link to a template that was not index, you would have to write it as: {path=template_ group/template}. The difference between the permalink variable used to link to the single-entry page and the path variable used to link back is that the permalink variable automatically adds the URL Title of the entry to the template specified (so you are taken to the URL specific to the entry), whereas the path variable does no such thing (it simply takes you to the template group and template specified).
You now have a FAQs page that displays all your faqs (with built-in pagination once you post enough entries). You can also click on individual questions to see the answer. The next step is to add some user interactivity to the single-entry page by allowing visitors to leave comments or add their own suggestions to each question.
Allowing comments on your entries
Comments are one of the easiest ways for visitors to interact with your site. They are also an easy way to attract spammers, who will be glad to leave hundreds of comments linking to websites of dubious quality. Luckily, ExpressionEngine includes features designed to prevent abuse.
Preventing comment spam
1. Comment preferences are set on a per-channel basis, allowing you to have different preferences for different channels (although when you create a new channel, you can copy the preferences from an existing channel to make things simpler). Go to Admin | Channel Administration | Channels and select Edit Preferences for the FAQs channel. [ 120 ]
Chapter 5
2. Here are all the aspects of the channel that you can fine-tune, organized into expandable groups. The General Channel Preferences were set when you created the channel, and include the channel name and short name.
3. Click on Path Settings. The path settings are the URLs that are unique to this channel. When creating links in your templates, ExpressionEngine will use these settings to know what URL to link to. Set your Channel URL to http://localhost/faqs and set your Comment Page URL and Search Results URL both to http://localhost/faqs/browse. You have not yet created an RSS template, but you can set your RSS Feed URL to be http:// localhost/faqs/rss in anticipation. The Ping Return URL does not apply to this channel.
When the Live Look Template is set, you will see a new Live Look link after publishing a new entry, as well as a new View link on the Content | Edit page. When you click one of these links, you will be taken to the livelook template to see the entry. A live-look template is coded exactly like an ordinary single-entry page template, and although you can define your single-entry template to be your live-look template, the true power comes into play when you define a live-look template that displays entries that would not be visible in your single-entry page template (either because they are future-dated or because they do not have an open status). This allows you to draft an entry with a closed status, for example, and view what it will look like on your website before you publish it with an open status.
[ 121 ]
Creating a Fully-Equipped Channel
4. The Administrative Preferences sets up defaults for each entry. For example, if you know the channel does not have comments, instead of having to click No to Allow Comments on each entry, you can set the default for every new entry to be no here (leave it set to Yes right now). The field for the search excerpt allows you to define which custom field is displayed when a member searches your site—the excerpt will automatically strip out any HTML formatting. For now, leave this set to Question. 5. The Channel Posting Preferences determines what to do with URLs inside a channel entry—you can either automatically link to them or leave them as plain text. Since only trusted people (such as yourself, Ed & Eg) will be able to post to this channel, you can Allow ALL HTML and say Yes to allowing images as well as to converting URLs into links. If your channel will involve lots of example HTML code, you could Convert HTML into character entities, meaning that any HTML entered as part of an entry will display on screen as-is and not be interpreted by the browser. At this time, no changes are needed. 6. Next, click on Versioning Preferences and set Enable Entry Versioning to Yes. By doing this, you can keep old versions of a channel entry saved. This is useful as it provides a quick undo feature for edits which were made erroneously. Enabling this option creates a new Revisions tab on your channel Publish page where you can load previous revisions. This option is not a substitute for doing a full database backup at regular intervals. [ 122 ]
Chapter 5
7. Select Notification Preferences. These preferences allow you to set up individuals to receive e-mails whenever a new entry or comment is posted. Setting this is essential if you require a moderator to approve all comments but can also be useful if you do not moderate your comments, as a means to monitor comments for comment spam. If you are using a localhost environment, outgoing e-mails may not work. So for now, leave all the notification options set to No. 8. Select Comment Posting Preferences. This is where you can either lock down or open up who can post comments and how many hoops they have to jump through in order to do so. Right now, say Yes to allow comments and No to requiring membership in order to post comments. As you are not requiring membership, say Yes to enabling a CAPTCHA for comment posting and say Yes to requiring an e-mail address to be entered when a reader tries to post a comment, but say No to moderating comments. Comment moderation means that an administrator, such as you, must approve every comment before it actually appears on your website. CAPTCHA stands for a Completely Automated Public Turing test to tell Computers and Humans Apart and is a puzzle that is easy for a human to solve, but not easy for a computer to solve. It is designed to filter out real people posting comments from automated scripts that are posting comment spam. ExpressionEngine's CAPTCHA technology relies on an image of letters with a background that makes it difficult for a computer to identify the letters. The person submitting the comment must type in the letters from the image correctly in order to post their comment. The downside to using an image in CAPTCHA technology is that it is not very accessible for visually-impaired visitors who might be relying on screen-readers to navigate your website. There are add-ons that provide a solution to this, such as Accessible Captcha (available at http://devotee.com/add-ons/extensions/accessible-captcha/). This addon changes the graphic to a user-defined question and answer, such as 2+2. A human could easily answer 4, but an automated spam program would not be able to do so. Search for CAPTCHA at http://devotee.com/ for other add-ons [ 123 ]
Creating a Fully-Equipped Channel
9. Leave the Maximum number of characters allowed in comments at 5,000, but set a comment re-submission time interval of 30 seconds. This option prevents an automated script from submitting more than one comment every 30 seconds. It can be useful as a deterrent against comment spam (especially if you are not moderating your comments or using CAPTCHA technology). Leave the comment expiration setting at 0 (meaning comments do not expire). If desired, you can use this setting to stop accepting comments on entries after a certain number of days. This can be useful to reduce the number of places on your website where comment spam can be posted. For the Comment Text Formatting, select XHTML but Allow only safe HTML. This means that formatting HTML, such as <strong> and <em>, will work, but more complex HTML will be rendered in plain text rather than being interpreted by a browser (thereby preventing malicious code being executed on your website). Do not allow image URLs in comments and do not automatically turn URLs and e-mail addresses into links (these options discourage spammers because their comments do not become links that could drive traffic to their website).
[ 124 ]
Chapter 5
10. Finally, the Publish Page Customization allows you to set a default entry title or URL title prefix that will apply to all new entries. This can be useful if you want all your entries to have the same prefix. Right now, leave these blank. Also, leave the Display Rich Formatting Buttons option set to Yes. Setting this to No would turn off the HTML formatting buttons (such as bold and italics) on all your custom fields, regardless of each individual custom field setting. 11. Click on Update and Finished to save all your settings. The settings you have just seen are useful in combating comment spam, especially from automated scripts, and it's recommended to consider them carefully before enabling comments. Using some combination of either requiring membership to post comments, enabling CAPTCHA technology, and/or enabling comment moderation along with setting an administrator up to receive notifications of new comments allows you to minimize comment spam as much as possible and quickly identify it when it does occur. You are now ready to create a form to accept comments. More information on all of these preferences can be found in the ExpressionEngine documentation at http://expressionengine. com/user_guide/cp/admin/content_admin/channel_edit_ preferences.html.
Creating a comment form
The first step in accepting comments is to create a form where visitors can write and submit their comments. Comments have to be tied to a specific channel entry, and therefore, the comment form can only appear on single-entry pages. Therefore, you will add your comment form to the faqs/browse template. 1. Open the browse template in the faqs template group for editing and type in the following code after {/exp:channel:entries}. This code displays the comments that other people have submitted. The title of the section is Comments. Comments
{exp:comment:entries} {if comments} {comment}
Posted by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/if} [ 125 ]
Creating a Fully-Equipped Channel {if no_results} There are no comments at this time - be the first to share your thoughts!
{/if} {/exp:comment:entries}
2. Next, add the code to create a comment form. Add this after the {/ exp:comment:entries} tag. First, this creates the fields for the visitors name and e-mail address. Since you would already have the name and e-mail address of any member who is logged in, you only need to ask for this information if the visitor is logged out. {exp:comment:form} Post Your Own Comment
{if logged_out}
{/if}
{if logged_out}
{/if}
{if captcha} {captcha}
[ 126 ]
Chapter 5
{/if}
{/exp:comment:form}
You can also add fields for a visitor's location or website. Use the same format as the email field in the previous code, but replace the word email with either location or url.
3. Now try posting your first comment. In order to see the website as a visitor will see it, log out of the control panel by clicking on Logout at the top-right and confirming you want to log out. (Closing the control panel without logging out will leave you logged in). Now visit http://localhost/faqs and click on a question. 4. Fill in your name, e-mail, type in a comment, and leave the box to remember your personal information, and the box to notify you of follow-up comments unchecked. If you check Remember my Personal Information, then the next time you see a comment form, your name and e-mail address will be pre-filled. Note that if you are logged in when you visit this page (for example, if you were previously logged into the control panel), then you will not see the fields for the name or e-mail and you will not see the CAPTCHA.
5. Enter the CAPTCHA word. Notice that each time you refresh the page, a different image with a different word is shown for your CAPTCHA. When you have completely filled in the comment form, click Submit.
[ 127 ]
Creating a Fully-Equipped Channel
Note that currently the Preview button will not work as you have not yet set up a preview template. If you are using a localhost environment, posting comments can be more difficult than when using an installation on a real website. If you are unable to post comments in the localhost environment, try changing the setting Require IP Address and User Agent for Login to No. This setting can be found in the control panel under Admin | Security and Privacy | Security and Sessions.
6. The page will auto-refresh, and you should now see the comment that you submitted.
Allowing visitors to preview comments
One final aspect of comments that hasn't yet been covered is the ability to preview the comment before publishing. You may have noticed the Preview button on the comment form that does not work yet. 1. First, modify the faqs/browse template to include the following code after the {/exp:comment:entries} and before the {exp:comment:form} line. Notice how the code is almost exactly the same as the code to display an actual comment, except that you are using the {exp:comment:preview} tag instead of the {exp:comment:entries} tag. This means that the look and feel of the previewed comment is identical to how it would look if it were an actual comment. {exp:comment:preview} {comment}
Being previewed by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/exp:comment:preview}
[ 128 ]
Chapter 5
2. Next, change the line {exp:comment:form} to include the preview parameter as follows. This parameter tells the form which template to load if the preview button is clicked. {exp:comment:form preview="{my_template_group}/{my_single_entry_template}"}
3. Now go to the FAQs page, type in a comment, and click Preview instead of Submit. You can see that the comment appears and looks exactly as if you had submitted it, except that instead of Posted by in the footnote, it says Being previewed by. You can keep editing the text and clicking on Preview as often as you like.
Organizing your data with categories
Although you have created custom categories and assigned your entries to some of your categories, you haven't yet used categories to help visitors browse the FAQs. You will now do this, but first set ExpressionEngine to use category names rather than ID numbers in the URL. This means that instead of category browsing pages having a URL such as http://localhost/faqs/C8, the category URL will be more like http://localhost/faqs/category/getting_married 1. In the control panel, go to Admin, Channel Administration, and then Global Preferences.
[ 129 ]
Creating a Fully-Equipped Channel
2. Say Yes to using category URL titles in links. Leave the Category URL Indicator as category. (If you do change this, bear in mind that whatever word you use here becomes a reserved word and cannot be used as a template name).
3. While you are on this page, also select No to auto-assigning category parents and click on Submit. Later in the chapter, you will use categories to show visitors who are viewing one question other related questions from the same categories. If all questions have the same two parent categories autoassigned, the related questions that are displayed are going to be less tightly coupled to the question being viewed.
Displaying categories with your entries
To encourage visitors to browse by category, it makes sense to display the categories that each entry belongs to underneath the questions on the faqs/index page. For this, you will use the channel {categories} tag, which allows you to list the categories, along with the {comment_total} tag to show how many comments each entry has and the {comment_url_title_auto_path} tag to link to your single-entry page for comments. Note that the {comment_url_title_auto_path} tag autogenerates the URL to your category template, as defined in Admin | Channel Administration | Channels, under Edit Preferences for the FAQs channel, then under Path Settings. The option Comment Page URL should be set to http://localhost/faqs/browse.
1. Edit the faqs/index page and add the following code underneath the Read the answer here! permalink and above the {paginate} line. <strong>Categories: [ 130 ]
Chapter 5 {categories backspace="3"}{category_name} | {/categories}Comments ({comment_total})
Everything between the {categories} opening tag and the {/ categories} closing tag is repeated for each category that the channel entry is assigned to. In this code, there is a vertical bar (|) after the category name and before the next category name to separate the categories. To prevent this vertical bar appearing after the last category, we use the backspace parameter. This parameter removes the specified number of characters from the end of our code after the last category name only (in this case, the | and the surrounding two spaces). This parameter is specifically designed to remove separators or other code that it makes sense to have between categories, but not after the last category.
2. Click on Update and Finished and then visit the FAQs page. You should now see underneath each answer—a piped list of categories that the entry belongs to. Clicking on one of the categories takes you to a category browsing page where you can see other entries that have the same category. At the moment, given that you only have two entries right now, namely, your category browsing pages and your main multiple-entry page, it will not be substantially different unless you pick a category that is unique to just one entry. Once the number of entries starts getting higher, browsing by category will be a much faster way of finding related questions than simply browsing through all the questions.
[ 131 ]
Creating a Fully-Equipped Channel
Distinguishing your category browsing page
Currently your category browsing page and your main multiple-entry page look identical—they have the same page title and the same introduction. Within the faqs/ index template, you can tell if you are on the main multiple-entry page or a category browsing page by looking at the URL. If segment_2 (the part of the URL after faqs) is category, you are on a category browsing page. You can, therefore, use this condition to display slightly different content accordingly. 1. First update the HTML title (which appears on the title bar of the window). To do this, edit the faqs/index template and replace the
Frequently Asked Questions - Ed & Eg Financial Advisors with the following: {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} Questions About {category_name} - Ed & Eg Financial Advisors {/exp:channel:category_heading} {if:else} Frequently Asked Questions - Ed & Eg Financial Advisors {/if}
2. Next, you can replace the code appearing after down to, but not including, the exp:channel:entries tag with the following: {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} Questions About {category_name}
{category_description}
{/exp:channel:category_heading} {if:else} Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
{/if}
[ 132 ]
Chapter 5
This code says that if you are on a category-browsing page, then the page heading should be Questions About {category_name} and the introductory text should be the category description. To edit the category descriptions, you have to edit the individual category in question. Go to Admin | Channel Administration | Categories, then click on Add/Edit Categories for the FAQ Categories group, and edit the category you want.
Now your category browsing pages look markedly different to your main multipleentry browsing page. However, this setup still requires your visitors to deliberately click on a category that interests them in order to find other FAQs that might be of interest. A different approach would be to display, at the end of the single-entry page, a list of other FAQs that have the same category (and therefore, are likely to be of interest to the visitor). In this way, the visitor is encouraged to keep browsing without ever realizing they are using categories.
Displaying related entries by category
To display other entries in the same category on your single-entry page, you need to make use of the ExpressionEngine parameter related_categories_mode. This looks at the URL of your single-entry page and then brings back the data of other entries that are in the same category as the page you are on. 1. Edit the faqs/browse template. Insert the following code after the line {/ exp:comment:form}: Other Questions Like This
{exp:channel:entries channel="{my_channel}" limit="5" related_categories_mode="yes" custom_fields="yes" orderby="random"} {if no_results} There are no questions like this currently – check back soon though...we're always adding more!
{/if} <strong>Q: <em>{faqs_question}
[ 133 ]
Creating a Fully-Equipped Channel <strong>A: Read the answer here!
{/exp:channel:entries}
Here you are bringing back up to five entries that are in the same categories as the question being viewed. To ensure variety, the entries are displayed in a random order, meaning that if you have more than five entries, no two sets of related questions will be the same.
2. If you now visit http://localhost/faqs and click on an entry, you should see a link to the entry you did not click on at the bottom of the single-entry page. If you do not see a link to your entry, it means the entry you are viewing is the only one in that category.
Now, as Ed & Eg go through and start adding hundreds of questions and answers, ExpressionEngine will dynamically organize the content. In this way, you may catch a visitor's eye with a question they want to know the answer to, and then keep them hooked by dynamically showing them other questions that are similar to the question they initially clicked on.
The FAQ snippet
The final step in getting visitors into the Frequently Asked Questions section of the website is to display Frequently Asked Questions in the widebar at the bottom of each page. Currently, there are two, static FAQs that are displayed in the widebar. In this section, you will update the widebar to display three random entries from the FAQs channel. To do this, it makes sense to use a snippet. Why a snippet? If you recall from Chapter 4, a snippet is used when you want to reduce repetition. In this case, since the widebar will be used on lots of templates, it is a great candidate for becoming a snippet. Why not a global variable? Remember that global variables do not support ExpressionEngine tags. Since you are planning to show data from an ExpressionEngine channel, a snippet is required. [ 134 ]
Chapter 5
In this section, you are choosing to display three random entries in your widebar. If you wanted more control over which FAQs were displayed at the bottom of every page, you could manually set the status of three entries to a custom status such as Featured (instead of open). Then, in your snippet, you could specify in the {exp:channel:entries} tag that you only want to include entries where status="Featured". You would also have to add a parameter status="open|featured" to the {exp:channel:entries} tags in all your other templates that use the FAQs channel. ExpressionEngine does not display entries that do not have a status of open, by default.
1. In the control panel, click on Design, then Templates, and finally Snippets. Then click on Create a New Snippet. 2. Call the snippet website_faqs and type in the following code to display your random entries. Note the use of the switch parameter—this essentially says that for the first entry, use colA as the div id. The second entry should use colB and the third entry should use colC. If you were displaying more than three entries, the fourth entry would use colA again, which, in this case, does not make sense to do. {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off"} Frequently Asked Question
{faqs_question} Find out…
{/exp:channel:entries}
Remember that ExpressionEngine uses the URL to dynamically determine whether you are on a single-entry page or a multiple-entry page. (If the URL has the url_title of a specific entry after the template name, then ExpressionEngine recognizes that you are on single-entry page and will only display content from that entry). This means that you cannot display content from another entry (or another channel) on a single-entry page unless you tell ExpressionEngine to ignore the fact that you are on a single-entry page. This is what the dynamic="off" parameter does.
[ 135 ]
Creating a Fully-Equipped Channel
3. Next, edit all your existing templates that show the widebar (includes/. website_page, includes/404, faqs/index, and faqs/browse) and replace the widebar code with a reference to this snippet instead. For each template, delete all the code including and between to and replace it with {website_faqs}.
Your work with the FAQ page is almost complete. The next step is to provide a way for visitors to be notified about new FAQs, without having to constantly re-visit your website. For this, you will use a feed.
Setting up an RSS or Atom feed
RSS or Atom feeds are an alternative way of allowing visitors to keep up-to-date on your website. Essentially, the visitor subscribes to your feed through their e-mail software, browser, or other news readers, and then they get notified when you post new entries. This saves them from having to periodically revisit your website to see if there is new content or not. Having a feed available can make the difference between a visitor being someone who visited your website and liked it (but does not come back) and someone who visited your website and now reads every new post. When building a feed, the easiest approach is to start with a pre-built ExpressionEngine feed template. This will take care of the top portion of the feed (containing meta-information such as the date, the URL of the entry, and so forth), meaning you only have to make a few customizations so that the feed displays the content from your custom fields. An RSS 2.0 template can be found at http://expressionengine.com/wiki/RSS_ Template_for_EE2/. However, since Agile Records comes with both an RSS 2.0
and an Atom 1.0 template, you can also base your template on theirs. If you did not install Agile Records, using the template from the wiki will have the same results. 1. From the Template Manager, select the FAQs template group and create a new template called rss. The template type should be RSS Page and you should duplicate a template, namely, the news/rss template. Click on Create and Edit. [ 136 ]
Chapter 5
2. On the first line, change {exp:rss:feed channel="news"} to {exp:rss:feed channel="faqs"}. (If you are starting from the wiki template, then the channel on the first line is howto, but should still be changed to faqs). 3. About half-way down, you will see a familiar {exp:channel:entries} tag. In this tag, change news to faqs. The limit parameter limits the number of results to 10 and the disable parameter tells ExpressionEngine not to query the database for member data (reducing the amount of data that is queried). Finally, every time a news-reader polls your website for new entries, it provides the last date/time that it checked. The dynamic_start parameter tells ExpressionEngine to only return entries (if any) that have been posted since that particular last date/time. {exp:channel:entries channel="faqs" limit="10" dynamic_start="on" disable="member_data"}
4. Even further down, look for the XML tag <description>. On that line, you will see an ExpressionEngine tag {news_body} (or {body} if you are starting from the wiki template). This is a custom field, so you should change this line to use your own custom field—{faqs_question}. You could display both the question and the answer in the feed. However, in this example, you are going to display only the question, followed by a link to the answer page (using code you have already used on your multiple-entry page). <description>{faqs_question}]]>
[ 137 ]
Creating a Fully-Equipped Channel
5. Click on Update and Finished. If you now browse to the RSS template (http://localhost/faqs/rss), your browser will likely recognize it as an RSS feed.
If you get an error, you may not have set the template to be an RSS Page. Check the template preferences for your RSS template.
6. Now all you have to do is link to the feed from your FAQs page so that people know it is there. Edit the faqs/index template and add the following after the introductory paragraph and before the {/if}: Don't forget to subscribe to our RSS feed to stay up-to-date with new FAQs as they are posted.
[ 138 ]
Chapter 5
You can now use your favorite RSS reader to view the content. If you do not have a favorite RSS reader, your e-mail client will likely already support it. For example, Mozilla Thunderbird 1.0 and greater and Outlook 2007 and greater, both have builtin support for feeds. Alternatively, Google Reader is a popular and free web-based alternative (http://www.google.com/reader). If you are following along in a localhost environment, then web-based feed readers will not be able to access your feed.
The instructions for creating an Atom feed are almost identical to those for creating an RSS feed: 1. Create a template faqs/atom and duplicate the news/atom template from the Agile Records example site into your new template. (The template type should still be RSS Page). 2. Change the feed channel on the first line to faqs. {exp:rss:feed channel="faqs"}
3. Change the channel in the exp:channel:entries tag to faqs. {exp:channel:entries channel="faqs" limit="15" dynamic_start="on" disable="member_data"}
4. Unique to Atom feeds, change the scheme to point to the single-entry template where the entry is: scheme="{path=faqs/browse}"
5. Change the custom fields inside the CDATA[] tag to reflect the content that you want to display inside your feed: {faqs_question} ]]>
6. Save your template and verify that you can subscribe to your new feed (http://localhost/faqs/atom). What is the difference between an RSS and an Atom feed? RSS 2.0 is the older and more established feed. Atom 1.0 was designed as a modern alternative to RSS. For practical purposes, news readers can read either feed, so which one you choose is up to you or you can use both types of feed and let your visitors pick whichever they prefer.
[ 139 ]
Creating a Fully-Equipped Channel
Improving your 404 Page
In the last chapter, you created a 404 Page for your site. ExpressionEngine allows for great flexibility with URLs and the downside of that is that invalid URLs can often return valid content. As an example, if you type in an entry URL that does not exist (such as http:// localhost/faqs/browse/ihatetoast, you see an actual page with content instead of your 404 template. This can be confusing to visitors if they mistype the URL. Luckily, there are options available to fix this. ExpressionEngine comes with a redirect tag that you can use to redirect visitors to another template, based on a conditional. Typically, the syntax of this tag would be {redirect="template_group/template"}. However, when redirecting to a 404 Page, rather than redirecting to "includes/404", you can redirect to "404". This will return the template that you defined in chapter 4 as your 404 template (if you have not yet defined this template, you can do so in Design | Templates | Global Preferences). The difference between a redirect to the template directly and a redirect to 404 is that, if you redirect to just 404, the redirect also includes 404 Page headers, meaning that search engines visiting that URL will recognize it as invalid and will not index it. 1. First edit the browse template of the faqs template group. Change the HTML to read {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes"}. This change means that if the URL does not match up to the URL of an entry, it will not display any content from the channel. 2. Next, between the opening {exp:channel:entries} tag and the closing {/ exp:channel:entries} tag, add the following code. This change says that if there is not an entry to display, then show your 404 Page instead. {if no_results} {redirect="404"} {/if}
3. Now visit http://localhost/faqs/browse/ihatetoast and you can see that your 404 template is now returned. 4. You can go one step further with your redirect. For example, you know that there should not be a segment in the URL after the URL of the entry (that is, http://localhost/faqs/browse/living_paycheck_to_paycheck is a valid URL, but http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus is not). Right now, the hippopotamus URL will still display your entry. If you add the following code to your faqs/browse template, immediately after the code you added above, it will cause a 404 redirect to take place instead: [ 140 ]
Chapter 5 {if segment_4!=""} {redirect="404"} {/if}
5. Now visit isit http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus and you will see a 404 Page instead. What about your multiple-entry page? For example, a URL of http://localhost/ faqs/rubbish should return a 404 Page, but it currently displays your multiple-
entry page. If you were not using categories or pagination, you could safely say that there should not be a segment 2, and if there is, redirect to 404. However, category URLs (such as http://localhost/faqs/category/debt) also use the faqs/index template, so you would need to build in logic to say that if segment 2 is category, then do not redirect to a 404. However, this logic gets more complicated. Once you have more than 10 entries, your entries will paginate over different pages, and the URLs for the pages will also be category 2 segments (for example, http://localhost/faqs/P0). Entries can also be archived by date. For example, a URL of http://localhost/ faqs/2011/11 will only display entries from November 2011. If you are organizing your entries by date in this way, then any year could appear in segment 2. One solution is to use an add-on such as MD Detect Page Type (http://devot-ee. com/add-ons/plugins/md-detect-page-type/), which makes it easy to tell if
you are on a category page, paginated page, or archive page, and therefore makes it much easier to build a conditional statement to display a 404 Page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. You have suddenly started getting spam comments on old FAQs. Set the comments on the FAQ channel so that after 60 days, no more comments are accepted. 2. Your FAQs currently have no indication of when they were posted or who posted them. On both the single-entry and multiple-entry pages, modify the question to include who posted the question and the date of the post (although this is something that might not make sense on the FAQs channel, in most situations where articles are being posted regularly, displaying the date of the post is a common requirement). to include the date of the post. [ 141 ]
Creating a Fully-Equipped Channel
3. Update the snippet that displays the three FAQs on every page of your website so that instead of displaying three random entries, it displays three featured entries (based on a custom status of "Featured").
Summary
In this chapter, you got more practice in using custom fields, channels, and templates. You also got introduced to categories, comments, and feeds. In the next chapter, you will get an in-depth look at the built-in membership module, including registering members, managing members, setting member privileges and permissions, and creating parts of your website that only members can see. The key points to remember after working through this chapter: •
You used a FAQ example in this chapter. However, all the functionality covered in this chapter would equally apply to any dynamic content that your site might have—whether it's a blog, news articles, recipes, or the products you sell.
•
ExpressionEngine contains many options to help you control and filter comments. You can use CAPTCHAs, you can moderate all comments, and you can require membership for comments. You can also set it up so that you get e-mailed when new comments are posted.
•
Feeds are a great option to encourage repeat visitors—they are easy to set up and give people an alternative way to keep up with your website.
•
Preload Text Replacements, Global Variables, Snippets, and Embedded Templates are incredibly useful—it is definitely worth becoming comfortable using them.
•
Conditional {if} statements are also a powerful tool, allowing you to account for different situations in a single template such as redirecting to a 404 Page if there are no entries or displaying category-specific information if the URL segment is a category.
[ 142 ]
Members You have now used ExpressionEngine to build a fully-functional website for Ed & Eg. So far, however, you are the only one who has logged into ExpressionEngine on your website and the only one who has been making any changes. Now is a good time to explore the member functionality of ExpressionEngine. The Freelancer license does not include member management, so this chapter will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing. In this chapter, you will: •
Allow visitors to register on your website and see what they see
•
Create a member group for Ed & Eg, so they can log into the control panel and publish and edit entries (but not edit template code or change administrative options like you can)
•
Use conditional statements to create content that only members can see
First, however, it makes sense to review how membership management works in ExpressionEngine and what all your options are.
Designing your membership ExpressionEngine allows two types of members:
1. Members who can log in to your website, but not into the administrative control panel. These members can see any content that you have coded in your templates as member-only as well as perform any actions that you have set to require membership (such as post comments).
Members
2. Members who can log into your website and also the administrative control panel. Depending on the permissions you give these members, they may be able to complete tasks such as creating or modifying channel content, creating or modifying templates, or changing global settings. If you have an ExpressionEngine-powered website, allowing members is not a requirement. If you do not intend to support members on your website, it is recommended to turn off new member registrations completely (the first option under Members | Preferences in the main menu). Membership in ExpressionEngine is based on member groups, which are what determine the permissions a member has. Each member can only be in a single member group. For members with administrative control panel access, ExpressionEngine offers a huge amount of granularity over what the members can see and do inside the control panel. You can define which channels they can post to (if any), which template groups they can modify (if any), and much more. For members without administrative control panel access, ExpressionEngine offers a member control panel, where members can post a profile, see other members' profiles, as well as send an e-mail or a private message to another member. As with the administrative control panel, you have control over what different member groups can actually do. To make joining your website attractive, you can make some or all of your content member-only by using conditional statements in your templates. You can look to see if a member is logged in and then display different content based on that, or you can display different content to different member groups. In this chapter, you will create a new member group for Ed & Eg that allows them to edit and post channel entries, but that does not allow them to edit templates. Then, to encourage members to join your website, you will update the FAQs channel so that some FAQs are viewable only to members. First, though, you will explore the membership preferences, and then explore the member profile screens as if you were a new member.
Membership preferences
There are many options you can set for your members on a global level that will impact their experience on your site. 1. First, log in to the control panel (http://localhost/admin.php) with your administrator login. [ 144 ]
Chapter 6
Note that you are also assigned to a member group—the Super Admins group. This group gives you access to everything. ExpressionEngine also comes with a Members member group, which does not have administrative control panel access, but can do everything in the member control panel. The permissions of the Members member group can be modified in Members | Member Groups, but the Super Admins group cannot be altered.
2. From the top menu, select Members and then select Preferences. 3. The first section is called General Configuration. Here, you can set whether you want members to be able to register themselves or not and the hoops they have to jump through in order to register. For example, you can require member account activation. If you do not require this, then any new members automatically become assigned to the Default Member Group (which is Members, but can be changed further down). If you require activation (either by an administrator or by requiring the new member to click on a link in their e-mail), then members will be placed into a Pending member group until they are actually activated (by selecting Members | Activate Pending from the main menu). For now, if you are using a localhost environment, say Yes to allow new members and select No activation required (since a localhost environment does not include an e-mail server and so cannot send activation e-mails). If you are following along on an actual website, it is recommended that you require activation of some kind.
4. Further down, you can require new members to accept a terms of service (if you say No, the terms of service will still display) or to complete a CAPTCHA form when they register. You can also allow members to set their own localization preferences (that is, members can set what time zone they are in and then see all times in their local time zone). Ensure that all these are set to Yes.
[ 145 ]
Members
5. Further down, you can set the member group that new members are assigned to (for now, leave this set to Members). You can also change the Default Member Profile Theme. You have two choices: Agile Records or Default. Since the Agile Records theme is designed specifically for the Agile Records website, select Default here. Finally, you can change the Profile Triggering Word, which changes the URL for the member control panel. (For example, if you changed this to guest, then all member control panel URLs would include the word guest instead of member). Leave this set to member for now and click Update. If you do not see any options for the default member profile theme (not even default), then you may be using the Freelancer license, which does not include member management.
6. The Member List Preferences allows you to change the default sort and order of your public member list page (which lists all the members on your site). Do not make any changes right now. 7. The Notification Preferences allows you to receive an e-mail whenever a new member registers at your site. This can be useful if you require an administrator to activate all new member registrations, or if you simply want to monitor new member registrations. If you are using a localhost testing environment, do not make any changes to this screen right now (as the localhost environment does not include an e-mail server, meaning such e-mails cannot be sent). If you are following along on a live website, type in your e-mail address here.
[ 146 ]
Chapter 6
8. ExpressionEngine includes functionality to allow members to contact each other via your website through Private Messages. The Private Messaging Preferences allows you to restrict the number of characters or the size of the attachments that can be attached to private messages. 9. ExpressionEngine includes the ability for members to associate an avatar (image) with themselves, which you can then display next to comments or forum posts that the member makes. The Avatar Preferences allows you to control whether avatars are enabled and whether members can upload their own images. 10. You can also choose whether you want to allow members to upload photos of themselves (which are then displayed on their profile). 11. Finally, you can choose whether or not you want to allow signatures, which appear after every forum post. Signatures are enabled by default, though signature images are turned off. 12. If you have not already done so, click Update to save any changes you have made. Now that you have made these modifications, the next step is to walk through registering as a member and explore the member control panel.
Registering as a new member
The membership functionality in ExpressionEngine is very rich, so rather than having to design your own membership templates from scratch, ExpressionEngine comes with pre-built member templates that you can use for members to login, register, share profiles, change settings, and send e-mails/private messages to other members. When following along in this section, remember that you are a member of your own website. This means that in order to register as a new member, you must first log out of the control panel by clicking Logout at the top right. 1. After logging out of the control panel, visit http://localhost/member/ register. (Remember, if you have the Freelancer license, this URL will not work). 2. You will be presented with a standard Member Registration screen, complete with a generic terms of service. Fill in the form with settings different than the administrator login that you have been using up to this point.
[ 147 ]
Members
Note that, by default, there can only be one username per e-mail address, so you cannot use the same e-mail address for this member as you did for your administrator login. This setting can be changed in Admin | Security and Privacy | Security and Sessions, although it is recommended not to change this setting as it can cause issues if a member with two accounts associated with their e-mail address forgets their password.
3. Select the check box to agree to the terms of service, fill in the CAPTCHA, and click Submit.
[ 148 ]
Chapter 6
4. As long as there were no errors with the information provided, you should be presented with a registration complete message and a link to go back to the main website. You are now registered as a new member!
The member profile
Now that you have walked through registering as a new member, you can see what the member control panel looks like. For this section, you can either be logged in as the member you just created or logged in using your Super Admin username. 1. Go to http://localhost/member/profile. If you are prompted to log in, log in first. 2. You should see a screen with your account statistics: your e-mail address, when you became a member, when you last visited the website, how many channel entries you have posted, and how many comments you have made. Along the top are links to log out or to see the member list. Along the left are links that allow the member to modify and personalize their account.
3. Click Edit Profile on the left-hand side and you can change what other members see about you. Go ahead and fill it in so that when you later visit your profile screen, you can see how it looks. 4. As mentioned earlier, Edit Signature and Edit Avatar are more relevant if you have purchased the forum module. If enabled, members can set their signature and avatar here. ExpressionEngine comes with a default set of avatars that members can select from. [ 149 ]
Members
5. With Edit Photo, you can also associate a member photo that other members can see when they visit your profile (although this option is not enabled by default).
6. Select Email Settings from the left-hand side. This allows members to finetune what notification e-mails they receive. By default, ExpressionEngine allows members to e-mail other members—a member can turn this off here. You can also change your e-mail address on this page. 7. Username and Password allows you to change your username, your screen name, or your password. 8. Edit Preferences allows members to determine whether avatars, signatures, or smiley images are displayed. Members can also prevent Private Messages from being sent to them on this screen.
[ 150 ]
Chapter 6
9. The Localization Settings allow a member to specify their Time Zone, their Time Formatting (US or European), and their Language (if you have multiple language packs installed). By selecting a different time zone, the member can see times in their local time zone. If the times on your website do not appear correct, it may be that either the server timezone or the daylight savings (summer) time setting has been set wrongly. These can be set in Admin | Localization Settings.
10. If a member has posted comments and selected to be notified of follow-up comments, then they are considered subscribed to that channel post. The Subscription Manager shows which posts a member is subscribed to and allows them to unsubscribe if desired. 11. The Ignore List allows members to ignore other members. As a result, any forum posts made by them will not display. 12. The Private Messages section is where members can send private messages to each other and view the ones they have received. 13. Finally, the Notepad is a scratch pad—any text typed into the notepad will be there next time the member logs in. This is most useful for members with administrative control panel access, as the notepad contents also appears on the right-hand side of the administrative control panel. The member control panel is very feature rich, allowing for a lot of functionality and configurability right out of the box. Members can send messages to other members, control what other members can see about them, and personalize settings such as their signature, avatar, or photo to suit their preferences.
The member list
Another option your members have access to is the member list. This can be used for members to browse other members and find their profiles or to send messages. 1. Click on Member List at the top-right of the member control panel or go to http://localhost/member/memberlist. Here, you are provided with a list of all active members. If there are lots of members, you can use filters or searches to find the person you are looking for.
[ 151 ]
Members
2. Click on a specific member and you can see the member profile, including any information the member may have personalized on their profile page.
3. Notice how the member's e-mail address is not publicly displayed. Click on the EMAIL button and you are brought to a form that you must fill in to send an e-mail. It is up to the recipient to decide whether they want to reply (and thereby reveal their e-mail address). With all this functionality, it is easy to build a website that members can use as a springboard to interact with other like-minded people. If you want to customize the member screens so that they share the same look and feel as the rest of your website, the templates can be edited in Design | Themes | Member Profile Templates and the corresponding files can be found in the /themes/profile_themes directory. (Note that it is best to make a backup of the templates before modifying them, in case you need to undo a change). Since each member page is made up of multiple templates, one technique (that you can see in the Agile Records templates) is to put an HTML comment in each template with the template name. In this way, you can view the source of the member pages and more clearly see which templates make up the page.
Linking to the member templates
As you have just seen, all the member functionality is pre-built. All you have to do is link to the pre-existing member URLs on your website and members can start registering and using your website.
[ 152 ]
Chapter 6
Next, you will set up the links in the sidebar on the right-hand side. If the visitor is logged out, there will be links to log in, register, or reset their password. If they are logged in, there will be links to log out, go to the member profile pages, or see the member list. 1. Log in to the control panel as a Super Admin. From the top-menu, select Design | Templates | Snippets. Select the website_sidebar snippet that you created in Chapter 5, Creating a Fully-Equipped Channel. 2. Add the following code to create the links immediately before the last in the snippet. Notice the use of the ExpressionEngine path variable (that you first saw in chapter 5)—this auto-generates a URL to the specific template group and template you specify. In this case, member is not a traditional template group, but rather the keyword you have defined in member preferences. If you do not feel like typing this in, remember that the finished code for each chapter can be downloaded at either http://www.packtpub. com/support or http://www.leonardmurphy.com/book2. Member Links
{if logged_out} - Login
- Forgot Password?
- Register
{/if} {if logged_in} - Profile
[ 153 ]
Members - Member list
- Logout
{/if}
3. Click Update and Finished and now visit the main website home page. Underneath Key Services, you should now see Member Links (depending on whether you are logged in or out will determine which links you see). Try the links to make sure they work.
You have now enabled the ability for visitors to register themselves on your website.
Introduction to member groups
By default, there are five member groups. You are already familiar with the Super Admins member group (which you are a member of). The Members member group is the group that approved members are put into (unless you have changed the default member group in the member preferences). By default, members in this group can do everything available on the member screens (such as sending private messages) as long as you have not disabled the option in the global Member Preferences. However, members cannot log into the control panel. The Pending members group is for members who have registered but have either not activated their membership via e-mail (if you allow self-activation by e-mail) or have not yet been manually approved (if you require members to be approved by an administrator). If you do allow self-activation by e-mail, it is a good idea to review the members of this group periodically and delete stale applicants (do this via Member | Activate Pending). [ 154 ]
Chapter 6
Members in the Banned member group cannot see your ExpressionEngine website, and the Guests member group is used for members who are not logged in. Since Super Admins can do anything and everything in ExpressionEngine and cannot be restricted, you should be very cautious about which members you assign to the Super Admin group. For example, while Ed & Eg need to be able to post and modify channel entries, it would be better not to give them access to templates, where they might accidentally change something. To accomplish this, you can create a new member group for Ed & Eg.
Creating a member group
In this section, you will create a new new member group called Editors for Ed & Eg. This will allow them to be able to log into the main control panel and publish or edit entries but will not allow them to view templates or change administrative preferences. After you create the member group, there will be two sets of options to configure. The first set of options applies to the member profile screens (and controls such things as whether they can send private messages). The second set of options control what the members can do within the control panel. For most members, you would not even allow them access to your control panel, so this second set would not apply. Throughout the configuration process, any options that you would not want to assign to someone you do not know and trust is bolded and colored red. 1. The first step is to create the member group. Log into the control panel as a Super Admin and go to Members | Member Groups. 2. Rather than creating a member group from scratch, you will base the new member group on the Super Admins member group. Underneath the member group listing is the option Create a new group based on an existing one. Select the Super Admins group from the drop-down box and click Submit.
[ 155 ]
Members
3. You will be brought to a new screen where you can give the new group the name Editors. Optionally, you can type in a description.
4. Continuing down the screen, the next option is Security Lock. If you allow groups, other than Super Admins, to administer members, you can control which member groups they can assign users to. As editors and owners of the website, you would want Ed & Eg to be able to approve and manage their members, but you would not want them to be able to assign members to the Super Admin or Editors group (for example). To accomplish this, leave this group Locked (meaning only Super Admins can assign members to the Editors group). To allow Ed & Eg to be able to assign members to the Members group, you would have to edit the Members group and adjust the group security lock to be Unlocked (by default, the Members group is locked, meaning only Super Admins can assign members to it).
5. The next option is Site Access. Since you would want Ed & Eg to have access to the website when it is offline, leave both options as Yes. (If you were creating a member group for members of the public, you would typically set this to No). [ 156 ]
Chapter 6
Within Admin | General Configuration, you can choose whether your system is on or not. You might choose to turn it off if you are doing updates and do not want members of the public to stumble across an incomplete site while the changes are in progress.
6. In the next option, Member Account Privileges, say No to allowing Ed & Eg to be able to delete their own account—if they accidentally did this, it would cause any content they had created to be deleted as well.
7. Comment Posting Privileges, Search Privileges, and Private Messaging Privileges allow you to control whether this member group can use these functions (and allows you to set member group-specific restrictions on their use). Since Ed & Eg own this website, do not make any changes to these screens.
[ 157 ]
Members
8. Control Panel Access is where you can allow (or prevent) the member group from accessing either the entire control panel or specific sections within the control panel. Since you want Ed & Eg to only have access to options they can safely use, say No to the following sections: DESIGN, add-ons (all five sections), ADMIN (all three sections), and say No to TOOLS (Utilities, Data, and Logs only). Leave the TOOLS section and the TOOLS: Communication set to Yes. Ed & Eg will only have access to the options set to yes here.
9. Under Control Panel Administration, say No to all the options except administrating member accounts, changing member groups, and banning users.
[ 158 ]
Chapter 6
10. Control Panel Email Privileges allows you to prevent Ed & Eg from sending e-mails through ExpressionEngine. Since there is no reason to do this, leave all the options as Yes. If you have a website where a large number of people will have control panel access (such as in a larger business), you might want to set this setting to No. 11. The Channel Posting Privileges allows you to decide what Ed & Eg can do with channel content (for example, if they can delete entries or edit other peoples' entries). Since Ed & Eg are the owners of the website, do not make any changes. 12. The Channel Assignment allows you to choose which channels Ed & Eg can publish to and edit. If you have Agile Records installed, you would want to ensure that Ed & Eg cannot see the Agile Record channels. Therefore, only say Yes to FAQs and Website—say No to Information Pages and News if they are there.
13. Comment Administration allows you to configure what comments Ed & Eg can view, moderate, edit, or delete. Leave all these options set to Yes. 14. Template Editing Privileges allows you to control which template groups Ed & Eg can edit. Since you do not want Ed & Eg editing any templates, say No to all of them. 15. Module Access Privileges allows you to control which modules Ed & Eg can access. Since you are not giving Ed & Eg access to the Add-On screens, you can say No to all modules (if there are any listed). 16. Click Submit to create the member group. You will be returned to the Member Groups page, where you will see your new member group in red and bold (because it has access to the control panel). You have now created an Editors member group, and all your changes have been saved. Next, you can log into the control panel as Ed or Eg and see what it looks like.
[ 159 ]
Members
Creating a member
Earlier in this chapter, you saw how to register yourself as a new member. Thankfully, as Super Admins, you can bypass this process and create new members directly in the control panel. In this section, you will create your first editor group member, Ed the Editor. 1. From the top menu, select Members | Register Member. 2. Fill in the username (edward), password, screen name (Ed), and e-mail address for your new member. (Remember that, by default, only one e-mail address can be used per member). Be sure to select the Editors member group as the member group assignment and then click Register a New Member.
3. You will be returned to a list of members in the Editors member group (right now, Ed is your first and only editor). Do not close this listing.
Logging in as Editor Ed
Another advantage of being a Super Admin is that you can log in as any other member without having to know that member's password. This allows you to see your website as they see it—which is helpful when you are developing new features or troubleshooting reported issues. 1. From the View / Search Members screen that you are on, click on the edward hyperlink.
[ 160 ]
Chapter 6
2. You will be taken to the member control panel for this member. From the left-hand side, select Login as Member (the second option from the bottom).
3. You can now choose which page of your website you want to see as Editor Ed. Select the Control Panel radio button and click Submit.
[ 161 ]
Members
4. You will then be logged in as Editor Ed. Although it looks like the control panel you have been working in so far, notice that there are far fewer options, both in the menu and on the main screen. Essentially, all Ed can do is publish new entries, edit existing entries, and administer members. ExpressionEngine has many options that allow you to decide how much access other people have to the control panel—you could set up a member group that can only post entries to a single channel or you could set up a member group that can do everything but post entries to a given channel. You can also set up member groups that do not have control panel access such as a trusted members group, which is exempt from comment moderation or that can search more frequently than regular members. You have now created a member group specifically for Ed & Eg to be able to create content without risk. However, there is one more area that can be customized by the member group: the Publish Page.
Modifying the Publish page layout
By default, the Publish page contains lots of options, spread across several tabs, some of which you will be unlikely to use for a given channel (such as the expiration date for an entry) and some of which you will intend to use, but will be liable to forget about (such as selecting the categories for an entry). Luckily, as a Super Admin, you can customize the Publish page so that the workflow better suits your needs. In the FAQs channel, you know you must select the category for a new entry, so instead of having the categories on a separate tab, you will move it to the bottom of the main tab so that you must scroll past it in order to submit your entry. In this way, you are less likely to forget to fill it in. 1. Log into the control panel as a Super Admin, and go to the Publish screen for the FAQs channel (Content | Publish | FAQs). 2. Towards the top-right (just to the left of the Notepad on the right-hand side), you should see an option that says show toolbar. Click this. (If you are not logged in as a Super Admin, you will not see this).
[ 162 ]
Chapter 6
3. A toolbar will appear with a list of fields, tabs, and authors. First, notice the eye on the right-hand side of each field name. If the eye is open, it means the field is visible. If the eye is closed, it means the field is not visible. (If there is no eye, it means the field is mandatory and cannot be made invisible). Click on the eye to toggle between open and closed. Close the following fields that Ed or Eg will be unlikely to modify on a per-entry basis in the FAQs channel: Expiration Date, Comment Expiration Date, Pings, Channel, and Options.
[ 163 ]
Members
4. The Tabs section allows you to delete tabs or create your own. For example, there are several tabs that have only one or two options on them. Rather than having all these tabs, you could delete all of them, and create a new tab for all your lesser-used options (such as the URL title and entry date, which you may want to alter for an entry, but not every entry). First, click Add a New Tab and call it Rarely-Used Options. Then click Add a Tab.
5. Next, click on the newly created tab and drag fields from the list of fields in the toolbar onto the main window in the position you would like them. Move the following fields: Entry Date, URL Title, Author, Status, and Revisions. If you do not see the revisions tab, you may not have enabled entry versioning while following chapter 5—to do so, go to Admin | Channel Preferences | Channels and then Edit Preferences for the FAQs channel. 6. Since Categories is something you always want Ed or Eg to select when they publish an FAQ (because the content is organized by category), click on the Publish tab and drag the Categories field from the toolbar onto the Publish tab. 7. Next, you can delete all the other tabs that you no longer need. Click on the trash can to the right of each tab name (other than Publish and Rarely-Used Options).
[ 164 ]
Chapter 6
Finally, each field on the main screen also has a little triangle at the bottom right and a little rectangular tab on the left. The triangle allows you to modify the size of the field (for example, so that it does not take up the entire width of the screen) and the rectangle allows you to modify the position of the field in relation to other fields. In this way, for example, you can put two smaller fields beside each other or you can reorder the fields as you see fit. 1. Now you can save your updated layout. At the bottom of the toolbar, check the boxes to apply the layout to both the Super Admins and the Editors member groups and then click Save Layout.
2. Now click hide toolbar to hide the toolbar, and you can see that the Publish page is substantially simplified. Instead of six tabs and lots of options you never use, there are two tabs—the first tab with options that you always want to set for a new entry, and the second tab with options that you rarely need to set, but might want to on occasion. To summarize, there are three ways to configure options on the Publish page: 1. The Member Group options allows you to configure which member groups can publish to which channels (or even whether a given member group with control panel access can publish to any channels). 2. The Custom Field options (reviewed in previous chapters) allows you to configure which options appear for each field—such as the HTML formatting buttons, write-mode, the spell-check, and so forth (and also whether the fields are mandatory or not). 3. The toolbar on the Publish page allows you to configure which options are visible on a per-channel, per-member group basis. This level of flexibility allows you to build a website for someone else to maintain, and to keep the interface uncluttered for that person, so that they only see the options they need to use. [ 165 ]
Members
Creating member-only content
So far you have seen the options available to you in the control panel for different member groups. For members with control panel access, the options are very comprehensive—you can disable entire sections (such as template editing) or disable individual items within a section (such as which template groups can be edited or which fields on the Publish page are visible). For members without control panel access, it is up to you how attractive you make the membership of your site, because any member-only feature has to be specifically coded that way in your templates. There are two ways you can restrict what nonmembers can see: 1. You can configure templates to not be viewable by certain member groups. If a person in an unauthorized member group attempts to access one of these templates, you can redirect them to a different template that says the content is for members only. From the Template Manager, where you would normally click to edit the template, click Access to change who can view the template and what template they should see instead. This can be useful if you are creating a new section to your website and want to allow certain member groups to try it out before going live to everyone.
[ 166 ]
Chapter 6
2. Alternatively, you can use conditional tags within templates to display different content. This allows you much more control and flexibility over what your visitors see—you can display different content depending on whether the member is logged in, depending on the member group of the member or based on any number of variables (for example, the username of the member or how many comments a member has posted). Read more about conditional tags at http://expressionengine.com/user_guide/ templates/globals/conditionals.html. Next, you are going to create a new custom status called Premium. If an FAQ is marked with a premium status, only registered members will be able to see the answer. Non-members will be able to browse all the FAQs, but if they select a premium FAQ, they will only see the question, along with a message encouraging them to register to see the answer.
Making content visible to members only
You have already seen the {if logged_in} and {if logged_out} tags to display different links, depending on whether a member is logged in or not. You will now use these same tags to determine whether or not to show them member-only content. WARNING: If you use conditional statements {if logged_in} and {if logged_out} inside the {exp:channel:entries} tag on a template, do not enable caching on that template or the conditionals will not work. The first person to visit the template will have their logged in state cached, meaning every subsequent visitor will be treated as if they have the same logged in state as that first visitor. Caching can be set for each template on the Template Manager screen by clicking on Edit Preferences for the template in question—by default, template caching is not enabled.
1. Before you can assign any channel entries to a premium status, you must first create the premium status by going to Admin | Channel Administration | Custom Status Groups. You currently only have one status group (statuses), so click Add/Edit Statuses.
[ 167 ]
Members
2. Next, click Create a New Status at the top right. (The Featured status you see in the screenshot will only exist if you installed Agile Records).
3. Call the new status Premium. Leave the Highlight Color blank. This controls the color of the status in the control panel—for example, if you typed red, the status would be in red text. Leave the specific groups who can access the status set to Yes. Click Submit.
The ability to restrict status to members of specific groups allows you to use statuses as a workflow on your website. For example, if you have a member group called authors, you could allow them to publish to a channel, but restrict what status they can assign the new entry so that their work is not open (for example they might only be able to publish to a 'needs review' status). You can then have another member group (such as editors) that do have the right to change the status from 'needs review' to 'open'—thereby ensuring that anything published on your website has been reviewed by a member of the editors group.
[ 168 ]
Chapter 6
4. Now post a new entry to the FAQs channel, and before clicking Submit, ensure that you set the status to Premium (on the Rarely-Used Options tab if you customized your Publish Page layout in the previous section, otherwise on the Options tab).
5. If you now visit http://localhost/faqs you will notice that your new entry does not appear. This is because you must specify in the {exp:channel:entries} tag in each template if you want entries to appear that have a status other than open. Modify the four templates (faqs/index, faqs/browse, faqs/rss, and faqs/atom) and the website_ faqs snippet to include the status="Open|Premium" parameter in the {exp:channel:entries} tag. The | means OR—as in, you want to entries that have either the Open or the Premium status. If you just specified status="Premium", then any entries with a status of open would not display. •
faqs/index: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Premium"}
•
faqs/browse (in HTML ): {exp:channel:entries channel="{my_channel}" disable="categories|category_fields|custom_fields|member_ data|pagination" status="Open|Premium"}{title}{/ exp:channel:entries} - Ed & Eg Financial Advisors title>
•
faqs/browse (after ): {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes" status="Open|Premium"}
•
faqs/rss: {exp:channel:entries channel="faqs" limit="10" dynamic_ start="on" disable="member_data" status="Open|Premium"}
•
faqs/atom: {exp:channel:entries channel="faqs" limit="15" dynamic_ start="on"disable="member_data" status="Open|Premium"} [ 169 ]
Members
•
website_faqs: {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off" status="Open|Premium"}
6. Now, modify the faqs/browse template and replace the line <strong>A: {faqs_answer}
with the following conditional statement. This says to display the answer if either the status is not Premium or if the visitor is logged in. If neither of these conditions are true (that is, the status is Premium and the visitor is not logged in), then do not display the answer. {if status!='Premium' OR logged_in} <strong>A: {faqs_answer}
{if:else} <strong>A: This answer is available to registered members only. If you are already a member, please login. Otherwise, consider registering for free & unlimited access to all our advice.
{/if}
7. Click Update and Finished, and now log out of the control panel (link in the upper-right-hand corner of the screen). 8. Now that you are not logged in, visit your premium content FAQ. Instead of seeing the answer, you should see a message telling you to log-in (as shown below). Verify that you can log in and see the answer.
[ 170 ]
Chapter 6
You have now given Ed & Eg the ability to make content Premium, encouraging visitors to register on the website. Although this is a simple example, ExpressionEngine's conditional statements are very flexible and very powerful. For example, you could show a promotion (5 percent off!) on your homepage, but only to registered members, or even only to registered members who have commented a set number of times. You could also show different content to different member groups. Each member group has a Group ID number, viewable under Members | Member Groups. Using this Group ID, you can use a condition such as {if member_group='6'} (where 6 is the Group ID of the Editors member group) and then create a draft status and allow Editors to see entries with a draft status, but keep them invisible to all other members and non-members. The choices are limitless.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. Try creating a new member group called Designers that can only be used to modify templates. Members of this group should not be able to post or modify any channel entries. 2. When a member registers for the first time, you have the option to collect additional information (beyond the username, name, and e-mail address) in Custom Member Fields. For example, if you have a motorcycle website, you could have a custom field to ask new members what make/model of motorcycle they have. Alternatively, if you give a free t-shirt to new members, you could ask for their t-shirt size. For this exercise, create a custom member field that asks "Are you an existing customer of Ed & Eg?" with possible answers being Yes or No. 3. On the right-hand side of your website is a box with a title of Promotion! that links to a Promotions page. Ed & Eg have decided that they want promotions to be visible only to registered members of the website. Modify the promotions/index template to display the promotion if a visitor is logged in, but otherwise display a message asking the visitor to register. (The promotions/index template is created as part of the challenges in Chapter 4, Moving a Website to ExpressionEngine).
[ 171 ]
Members
Summary
In this chapter, you learned all about member functionality in ExpressionEngine, including the built-in member control panel. You also looked at setting up new member groups and customizing the administrative control panel for different member groups (that have control panel access). Finally, you looked at how to use conditional statements in your templates in order to make membership attractive to visitors. The key points to remember after working through this chapter are as follows: •
You can control what all members can or cannot do in the Member | Preferences screens. You can also make exceptions on a member group basis in Members | Member Groups. So, for example, you can require that all comments are moderated, but make an exception for members in a specific group.
•
Be cautious about who you assign to the Super Admins member group. If someone needs control panel access, but does not need access to everything in the control panel, it is a better practice to set up a new member group with only the permissions that the member group needs.
•
If you are building a website for a client, remember that you can modify the Publish page to make it more intuitive. You can hide fields that are not relevant and at the same time make other fields more prominent.
•
How attractive membership is on your site is up to you. Using conditional statements, you can control what content members can see, displaying different content for different member groups or based on different conditions.
•
If you have a template that uses the conditional statements {if logged_in} or {if logged_out} inside the {exp:channel:entries} tag to display different content to different members, do not enable caching for that template.
[ 172 ]
Creating a Calendar Many organizations have events, and a calendar is a very visual way of indicating what is going on and when. The built-in ExpressionEngine calendar functionality is limited (for example, it does not allow recurring appointments). However, you can use it to display event titles with clickable links for more information. If a calendar is a key part of your website, you may be interested in checking out Solspace's calendar module (at the time of publication, it is not yet available for ExpressionEngine 2). http://www. solspace.com/software/detail/calendar/. The module contains support for more sophisticated calendar functionality such as recurring appointments.
In this chapter, you are going to use the built-in functionality of ExpressionEngine to build a simple events calendar that is easy to post to using the Publish page in the control panel. You will use the jQuery module to display more information when an event is clicked. Finally, you will also be introduced to the concept of Related Entries (relating the post from one channel to a post in another channel)—a useful tool to reduce repetition in channel entries.
Designing the calendar
Ed & Eg frequently host free seminars for customers and members of the community in their conference room. These seminars are usually sponsored by another organization. Ed & Eg would like a calendar on their website that shows each seminar on the date that it is to take place, along with a link so that visitors can read more about the topic of a given seminar as well as who the sponsor company is.
Creating a Calendar
One way you can design such a calendar is to create an events channel, which contains all the information regarding both the event and the event sponsor. This would work, but because a single event sponsor is often associated with more than one seminar, this design would result in you having to include the same information about the same sponsors in more than one channel entry. For example, if Anytown Bank sponsors five seminars, there would be five entries where you would have to provide information about Anytown Bank. Related Entries is a way to reduce repetition in channel entries. (Not to be confused with relating entries by category—which you did when you built the FAQs channel). Essentially, if you have two kinds of data (events and event sponsors), you can create two channels and then include the data from one channel in the other. In this way, you can have an event_sponsors channel, which contains all the pertinent information on the event sponsors (such as their name, location, opening hours, and services offered). The event channel itself will then only contain information about the event (such as the date, time, and topic). When Ed or Eg creates a new event, they can simply select the sponsor (such as Anytown Bank) from a drop-down list of sponsors in the event_sponsors channel, and all the information about the event sponsor will automatically populate for them—no retyping necessary.
Setting up your channels
To set up an event and an event sponsors channel, you will first create the custom fields, then create the channels, then populate the channels with example data, before finally creating the templates that you will use to display the channel data. When creating two channels that are to be related, it's best to start with the channel whose data will be included in the other channel—therefore, start with the event sponsors channel.
Creating custom fields for event sponsors 1. Select Admin | Channel Administration | Custom Fields.
2. Select Create a New Channel Field Group and call the field group event_ sponsors. Click Submit. 3. Now select Add/Edit Custom Fields for the event_sponsors field group. 4. For now, keep things simple and create only one field—a generic about field. (You could, of course, create as many fields as you want). Select Create a New Custom Field. [ 174 ]
Chapter 7
5. The field type will be Textarea. The field label will be About and the field name will be event_sponsors_about. The field will be required, will not be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. The event_sponsors field group is now ready to go. The next step is to create the event_sponsors channel.
Creating the event sponsors channel
By now, you should be familiar with the process of creating a channel. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Event Sponsors with a short name of event_sponsors. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and event_sponsors for the field group (the category group can be left as none, as you will not be using categories with this channel). Remember, if you do not select a Status Group when creating a new channel, then only Super Admins can post open entries. If any other member group posts an entry, it will be closed by default (and therefore not visible on your website).
3. Finally, select No to creating new templates and then click Submit. 4. Now, go to the Content | Publish | Event Sponsors and create a couple of example sponsors (for example, Anytown Houses, Anytown Bank, and Anytown Law Firm).
[ 175 ]
Creating a Calendar
Now that you have your sponsors channel set up with some sponsors, you can go ahead and create the events channel.
Creating the events custom fields
As before, you will first create your channel custom fields, before creating the channel, and then some example content. 1. Select Admin | Channel Administration | Custom Fields. 2. Select Create a New Channel Field Group and call the new field group events. Click Submit. 3. Now select Add/Edit Custom Fields for the events field group. 4. You will create two fields for your events—Description and Sponsor. Select Create a New Custom Field. Note that you will not create a custom field for the date or the time of the event. This is because you can change the date/time of the entry to reflect the date/time of the event.
5. The field type will be Textarea, the field label will be Description, and the field name will be events_description. The field will be required, will be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. 6. Next you can create the relationship field. Click Create a New Custom Field. 7. From the drop-down of Field Types, select Relationship. The Field Label will be Sponsor, and the Field Name will be events_sponsor.
8. The field will not be required (some events might not be sponsored) and the field will not be searchable. Say Yes to show the field by default. [ 176 ]
Chapter 7
9. In the Custom Field Options, select the Event Sponsors channel and leave the display criteria at the default setting (Sort by Title in Descending Order). Click Submit.
Now all you have to do before you can start creating events is create the events channel.
Creating the events channel
Creating the events channel is a fairly straightforward process. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Events with a channel name of events. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and events for the field group (the category group can be left as none, as you will not be using categories with this channel). 3. Finally, select No to creating new templates and then click Submit. 4. Your channel is created! Now, you can bring together your Events and Event Sponsors by creating some events.
Creating example events
The final step in setting up these channels is to post some example events, so that when you create the calendar on your website, you have some events to see how it is working. Your first event is going to be a seminar called Common Pitfalls of Home Buying, sponsored by Anytown Houses. 1. Select Content, Publish, and select the Events channel. 2. Type in the title, Common Pitfalls of Home Buying. In the description field, type in some example topics that will be covered.
[ 177 ]
Creating a Calendar
3. Select Anytown Houses as the sponsor. That is all you need to do to associate the sponsor with the event.
4. Before clicking submit, select the Date tab at the top of the screen and select a date for your entry and a time of 6 p.m.
[ 178 ]
Chapter 7
5. Click Submit. 6. Go ahead and create a few more events with different sponsors, dates, and times, so that when you create the calendar, you have a few entries to play with. Now that you have the channels built and have some example events too, you can go ahead and create the calendar!
Creating the calendar
For the rest of this chapter, it will be useful to refer to the official ExpressionEngine documentation on the calendar tag at http://www.expressionengine.com/user_ guide/modules/channel/calendar.html, where much of the code in this section is adapted from. The first steps in creating a calendar are to create a calendar template group, add the basic HTML to construct the page, build the outline of the calendar, and add CSS to make the calendar look good.
Creating a blank calendar template
1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group calendar. Do not duplicate a group and do not make the index template in this group your home page. Click Submit. 2. Copy and paste the code from the includes/404 template (or any template that has all the normal page components such as the header, sidebar, widebar, and footer). Paste the code into the new calendar/index template. At the top of the template, add a my_channel preload replace as follows: {preload_replace:my_channel="events"}
3. Change the page title from Page Not Found to Calendar. Calendar - Ed & Eg Financial Advisors
4. Change the h1 title to Seminar Calendar and delete the paragraph underneath that says the page does not exist (including the and
tags). The content section should look as follows: Seminar Calendar
[ 179 ]
Creating a Calendar
Now you have a blank Ed & Eg themed template (viewable at http://localhost/ calendar) that you can use for your calendar.
Creating the calendar
The next step is to create a blank calendar—it will not display any events just yet. This code is adapted from the ExpressionEngine documentation. 1. In the calendar/index template, add the following code after the Seminar Calendar
line. The first piece of code is the exp:channel:calendar tag. This is a pair of tags with a number of parameters. {exp:channel:calendar switch="calendarToday|calendarCell" channel="{my_channel}" show_future_entries="yes"} {/exp:channel:calendar}
The channel parameter specifies that the entries on the calendar are coming from {my_channel}, where {my_channel} is a Preload Text Replacement corresponding to the events channel. The parameter show_future_entries="yes" means that the calendar will show future entries. In most channel applications, if you set an entry date in the future, ExpressionEngine does not make that entry visible until that date. This is useful if (say), you are going away but want to schedule new content to appear at a certain time while you are gone. In this case, if a calendar only showed entries that have already happened, it would not be a very useful calendar. The switch parameter is used to switch between two different stylesheet styles (you will create the calendar stylesheet next). If the day being displayed is not today, then the stylesheet's style will be calendarCell. If the day being displayed is today, then the stylesheet's style will be calendarToday. This allows today's date to be styled differently.
2. The next step is to start displaying the calendar itself. A calendar is a table with seven columns (one for each day of the week) so you will use the HTML table tag to display it. In the following code, you define the first row. In the top left cell, you will display << that can be clicked to move to the previous month. Likewise, in the top-right cell, you will display >> to navigate to the next month. The middle five cells will contain the name of the current month being displayed. The style calendarBG will be defined in the stylesheet that you will create in the next section. Add the following code after the {exp:channel:calendar} tag and before the closing {/ exp:channel:calendar} tag. [ 180 ]
Chapter 7 << {date format="%F %Y"} >>
The previous and next path links both point to the current template (calendar/index). < is HTML for the < symbol and > is HTML for the > symbol. The format code to display the current month and year, %F %Y, is taken from ExpressionEngine's date formatting code, available at http:// expressionengine.com/user_guide/templates/date_ variable_formatting.html
3. Go to http://localhost/calendar and you can see the calendar beginning to take shape. Click on the arrows and you can see that the name of the month changes, as does the URL of the page. 4. The next row will display the weekdays. The code {lang:weekday_abrev} refers to the one letter weekdays. You could also use weekday_long or weekday_short to either spell out the entire weekday or the first few letters of the weekday respectively. This must be wrapped in a {calendar_ heading} variable pair. Insert the following code after the closing tag and before the closing tag. {calendar_heading} {lang:weekday_abrev} {/calendar_heading}
[ 181 ]
Creating a Calendar
5. The next row will display the actual dates. There is no way to know how many rows might be needed for a given month (February might only require four rows; October might require six). ExpressionEngine dynamically determines how many rows to display using the {calendar_rows} variable pair, which repeats for as many rows as are necessary. Each row starts with the command and ends with the closing command. For each calendar cell, there are three possibilities—there may be events for that date; there may not be events for that date; or it may be an empty cell before the first day of the month or after the last day of the month. You want to handle each of these situations differently, so you will use conditional statements to distinguish between these three possibilities, although, right now, you will simply be displaying the date in each. Notice that, for your empty cells, you use a different class so that you can style it differently in your stylesheet. Insert this code after the closing tag and before the closing tag. {calendar_rows} {row_start}{/row_start} {if entries} {day_number} {/if} {if not_entries} {day_number} {/if} {if blank} {day_number} {/if} {row_end} {/row_end} {/calendar_rows}
You now have the beginnings of a calendar, although it looks a little basic.
[ 182 ]
Chapter 7
Before you start displaying your events on this calendar, first create some CSS to make the calendar look a little more calendar-like.
Formatting the calendar with CSS
Rather than adding the calendar styles to your main site/site_css stylesheet, it makes sense to create a separate stylesheet just for the calendar styles. This is because the calendar styles are only needed on the calendar page and do not need to be included on any other page.
Creating the calendar CSS template
First, you will create the template for the calendar CSS. Then you will point the calendar/index template to this new template. 1. From Design | Templates | Template Manager, click the calendar template group and select New Template. Call the new template calendar_css and choose a Template Type of CSS. Click Create and Edit.
2. The first line in your new template will import the main site/site_css template (so that the page outside the calendar continues to be formatted correctly). After typing this, click Update and Finished. @import url({site_url}includes/site_css);
[ 183 ]
Creating a Calendar
The {site_url} variable, which you have seen before, is converted to the actual URL to the root directory of your site, as stored in Admin | General Configuration. Note that the URL in this setting should have a trailing / (for example, http://localhost/ as opposed to http:// localhost) or the link above will not work (for example, it will resolve to http://localhostincludes/site_css instead of htttp:// localhost/includes/site_css).
3. The next step is to point the existing calendar/index template to use this new CSS template in place of site/site_css. To do this, edit the calendar/ index template and modify the stylesheet line to read as follows:
Now you can add some styles to your CSS.
Adding styles to your calendar CSS
In the calendar/index code so far, you have defined several styles: • • • • • •
calendarBG is used to format the overall table calendarHeader is used to format the month heading calendarDayHeading is used to format the weekday headings calendarCell is used for the calendar cells, except for today's date calendarToday is used for the calendar cell that represents today's date calendarBlank is used for calendar cells that are not for the dates this month
Helpfully, EllisLab provides a suggested stylesheet in the ExpressionEngine documentation (http://expressionengine.com/user_guide/modules/channel/ calendar_css.txt), which you can start with and then adapt to your own needs. 1. Open the template calendar/calendar_css for editing. Copy and paste the example code from the URL above into the CSS stylesheet (below the @ import line) and click Update.
[ 184 ]
Chapter 7
2. Next, modify the three cell styles (calendarCell, calendarToday, and calendarBlank) to position the date in the top-left of the cell (so that there is room for your event text). To do this, modify the following two styles for .calendarCell and .calendarToday and add them to .calendarBlank: text-align: left; vertical-align: top;
3. Now modify the same three cell styles to have a fixed width. Otherwise, as events are added to your calendar, some columns will expand and other columns will shrink. Add the following styles to .calendarCell, .calendarToday, and .calendarBlank: width: 60px; height: 60px;
4. Finally, you can create some styles for displaying your events. You want to keep the font clear to read but small. The following code will give each event a border, so that if there are two events on the same day, the text will not run together. Since all the events will be links (for more information), this code will also change the background color of the event when the mouse moves over it to make it clear that it is clickable. Add the following to the end of the calendar_css stylesheet: .calendarEvent a{ font-family: Arial, Trebuchet MS, Tahoma, Verdana, Sansserif; [ 185 ]
Creating a Calendar font-size: 10px; font-weight: normal; letter-spacing: 0em; text-decoration: none; border: 1px solid #666; vertical-align: top; text-align: left; margin: 5px; padding: 5px; display: block; } .calendarEvent a:hover{ background-color: #ccc; }
You now have a pretty, but blank, calendar. You can, of course, go further and change the styles so that it suits your site. It is all easily configurable within the CSS. The next step is to start displaying events on your calendar. Since space on the calendar is limited, you will only display the title of the event on the calendar itself, with a clickable link for more information. (In fact, only the title field from the channel is available in the {exp:channel:calendar} tag—none of the custom field tags will work). The basic way to build the clickable link is to simply create a new, single-entry page template that you link to (just as you did with the FAQs channel). However, to keep things interesting, a new approach is called for. You will still create a single-entry page template, but rather than just linking to it directly, you will use the jQuery module combined with the FancyBox plug-in (http://fancybox.net/) to display the single-entry page in an iFrame lightbox that floats over the calendar. To accomplish this, you must first download the FancyBox tool and upload the files to your website. (FancyBox is also used in the next chapter on photo galleries). If you are removing the index.php from your URLs, then you will likely have to modify your .htaccess file so that you can access the FancyBox files. You can then create your single-entry template (and a corresponding, simplified CSS file). Finally, using the jQuery module and FancyBox, you can create a link to your single-entry template from your calendar.
[ 186 ]
Chapter 7
Note that although this chapter is using a third party jQuery plugin, the focus of this book is on using ExpressionEngine—not on learning jQuery (or FancyBox). For more information about jQuery, please visit http://jquery.com/.
Setting up FancyBox
You can download the latest version of FancyBox directly from http://fancybox. net/, or a copy of the latest version is included in the code for this chapter at either http://packtpub.com/support or http://www.leonardmurphy.com/book2/ chapter7. 1. First, download FancyBox and extract all the files from the compressed directory into a directory on your computer. 2. Once extracted, you should see a directory called fancybox, complete with a number of images, JavaScript files (.js), and a CSS file. Upload this entire directory to the root of your website. Note that for the purposes of this chapter, you do not need any of the example files that ship with FancyBox. 3. Next, if you are removing the index.php from your ExpressionEngine URLs using the exclude method, you will have to add this new directory to your .htaccess file (otherwise it will be treated as an ExpressionEngine template group, rendering it inaccessible). Open .htaccess and add FancyBox to the end of the list of real directories and files as follows (but do not create a second RewriteCond line—modify the line you already have). RewriteCond $1 !^(images|system|themes|index\.php|admin\.php|fancybox) [NC]
For an example of a complete .htaccess file using the exclude method, please see either http://packtpub.com/support or http://www. leonardmurphy.com/book2/chapter2. Your .htaccess file may include other files or directories that you have in the root directory of your website (such as robots.txt or favicon.ico) that you should leave in place. 4. To verify that your .htaccess file is not blocking access to the fancy box directory, open http://localhost/fancybox in your browser. If you see your ExpressionEngine 404 page, then your .htaccess file is treating the fancybox portion of your URL as an ExpressionEngine template group. Review your .htaccess file.
[ 187 ]
Creating a Calendar
Troubleshooting problems that are due to the .htaccess file can be challenging. Many times you set up a .htaccess file when you install ExpressionEngine and then forget that it exists, so you do not even think of the .htaccess file. Remember that EllisLab does not provide support for removing the index.php using a .htaccess file (because there are so many ways to do it and every server works a little bit differently). If you suspect your .htaccess file is causing problems, you can temporarily remove it and add the index.php back into your website URLs (in Admin | Configuration, under Name of your site's index page). If you do this, it will at least confirm whether the issue you are seeing is due to your .htaccess file or something else entirely.
5. Finally, if you are using Internet Explorer, you may want to modify fancybox/jquery.fancybox-1.3.1.css to include a / at the start of the AlphaImageLoader sources. (This tells Internet Explorer that FancyBox is a directory at the root of your website and therefore enables it to find the images it needs). The easiest way to do this is to do a find and replace and replace AlphaImageLoader(src='fancybox/ with AlphaImageLoader(src='/fancybox/
FancyBox is now in place and ready to go. Next, you will create your single-entry template, along with a pared-down CSS file.
Creating your single-entry template
First, you will create a pared down CSS file, before creating your single-entry template. Both will be much smaller versions of your regular templates/CSS (since you would not view this template on its own, but rather as an overlay on an existing page, you do not need the usual Ed & Eg header, sidebar, or footer. As a result, the template and the CSS are smaller). 1. Create a new template in the calendar template group called event_css. The template type will be CSS. Duplicate an existing template, namely, includes/site_css. Click Create and Edit. 2. Delete the input, textarea style. Further down, delete everything that appears after the /* Wrapper */ comment (including /* Wrapper */ itself). 3. Now update the body style to read as follows (essentially removing the background and adding in a four percent padding so that the text in the popup overlay will not touch the sides of the pop-up overlay box): body { font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; [ 188 ]
Chapter 7 font-size: 12px; color: #6B6B6B; padding: 4%; }
4. Finally, remove the h2 from the h1,h2 style (not the h1, h2, h3, h4 style) and instead, add it to the h3 style. The styles should end up looking as follows: h1 { font-size: 28px; } h2, h3 { font-size: 16px; font-weight: bold; }
5. Click Update and Finished to save this CSS template. 6. Next, you will create your event template. In the calendar template group, click New Template and name the template event. The template type will be Web Page. Select to duplicate the calendar/index template and click Create and Edit. This template will be visible at http://localhost/calendar/ event. 7. Delete everything between the and tags. Also, change the to be Calendar Event as follows: Calendar Event - Ed & Eg Financial Advisors
8. Next, change the stylesheet so that instead of pointing to calendar_css, it is pointing to the CSS stylesheet you just created (event_css).
9. Next, after the tag, add the following code to display the event information. {exp:channel:entries channel="{my_channel}" show_future_entries="yes" limit="1" require_entry="yes"} {if no_results} {redirect="404"} {/if} {title}
<strong>Join us on {entry_date format="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{events_description}
{/exp:channel:entries} [ 189 ]
Creating a Calendar
Notice that the show_future_entries parameter has to be included here, since this template is going to be displaying event entries that have an entry date after today's date. Also note the use of require_ entry and if no_results to ensure that only valid events can be displayed—all others will be redirected to your 404 page.
10. Next, you will display the sponsor information from the event_sponsors channel. Since you are displaying the content of the event_sponsors channel inside the events channel, ExpressionEngine needs a way to know which channel it is supposed to be displaying the data from (fields such as {title} could refer to either channel). To accomplish this, you wrap all your event_sponsors information in the tag {related_entries} using an ID that corresponds to the relationship field in the events channel (in this case, the events_sponsor custom field). You can then use the custom field names from the event_sponsors channel. The ID is a way for ExpressionEngine to support more than one relationship field in the same channel. Insert the following code after the {events_description}
line: {if events_sponsor} {related_entries id="events_sponsor"} More About {title}
{event_sponsors_about}
{/related_entries} {/if}
You have now completed this separate, pared-down single-entry template to show more information on your calendar entries. Although the plan is to only display this template in a pop-up overlay on your calendar page, you can see what the template looks like by itself by going to a URL like http://localhost/calendar/event/
common_pitfalls_of_home_buying.
[ 190 ]
Chapter 7
Notice how the information from the Event Sponsors channel is populated into the event information. Although you only have a few events right now, so the effort of creating two channels might not seem to outweigh the benefits, if you had tens or hundreds of events, all of which shared the same handful of sponsors, being able to simply select the sponsor information from the drop-down menu represents a significant time-savings over having to type in information about the sponsor in every event. The next step is to display these entries on your calendar.
Displaying events on your calendar
To display the event on your calendar, you will use an ordinary hyperlink to your single-entry template with a special class (pop-up). The pop-up class will correspond to JavaScript in your HTML header that will call upon the FancyBox jQuery plugin to display the single-entry template in an overlay dialog box. First, you need to enable the jQuery module in your template. 1. First, verify that the jQuery module is enabled. It is enabled by default if you have installed Agile Records. Select Add-Ons | Modules from the main menu and verify that jQuery is marked as installed. If not, click Install in the Status column to install it. 2. Edit the template calendar/index.
[ 191 ]
Creating a Calendar
3. The first change you are going to make is to activate the jQuery module. In the section of the template, add the following tag: {exp:jquery:script_tag}
When saving your template, if you see a warning that no closing tag was found, do not worry. The jQuery tag is a tag that does not require a closing tag.
4. Next, you are going to include the FancyBox jQuery files that are in the fancybox directory that you uploaded to the root of your website. You will link to the main FancyBox JavaScript files, plus the CSS file. Type this code in directly underneath the above tag. <script type="text/javascript" src="{site_url}fancybox/jquery.fancybox-1.3.1.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.mousewheel-3.0.2.pack.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.easing-1.3.pack.js">
Note that if you downloaded the newest version of FancyBox, then the filenames and the version numbers in each of the filenames are subject to change.
5. Now you are going to include the FancyBox code for the pop-up class. This tells FancyBox how you want the lightbox to work. You want the box to be 75 percent of the width and height of the page, with no margin or padding. OverlayOpacity means that you want the calendar page underneath to still be visible, but dimmed. The hideOnContentClick means that if you click anywhere off the lightbox, the lightbox will close. The iframe type means that the lightbox will display the contents of another URL (in this case, your single-entry template URL). For more information on all the FancyBox parameters, please visit http://www.fancybox.net/api. Type this code in directly underneath the above tags (still in the section). <script type="text/javascript"> $(document).ready(function() { $(".popup").fancybox({ 'width': '75%', 'height': '75%', [ 192 ]
Chapter 7 'titlePosition': 'outside', 'autoScale': true, 'margin': 0, 'padding': 0, 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none', 'type': 'iframe' }); });
6. Finally, add your link with the class of popup (that corresponds to the .popup used in the above JavaScript so that FancyBox knows that you want to use FancyBox, and not actually open the link like you normally would). Add the following code after {if entries}, deleting the existing {day_number} line. {day_number} {entries} {/entries}
7. As one date can contain multiple events, this variable pair {entries} applies to each entry. Since this hyperlink applies to each entry, you include it within the {entries} variable pair.
[ 193 ]
Creating a Calendar
8. Go to your calendar and navigate to a month that has events to verify that you can see the hyperlinks.
9. Finally, click on one of the events to verify that your single-entry template appears with the correct information in a FancyBox overlay. If your event does not appear in a pop-up window, but rather opens in a separate window or tab, there are a number of things you can check. First, verify that the fancybox directory is at the root of your website and that you can access the files in your browser (if not, check your .htaccess file). Next, verify that the paths in the calendar/ index template point to the script/CSS files in the fancybox directory and check the filenames for misspellings.
[ 194 ]
Chapter 7
Your calendar is now complete. As you can see, the calendar functionality in ExpressionEngine is limited in what it can do and is certainly not as flexible as specialized calendar applications. However, for simpler designs, it is quite functional.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. [ 195 ]
Creating a Calendar
1. Currently, your calendar displays the days of the week using single letters (for example, M, T, W). Modify this so that the first three letters of each weekday are displayed (for example, Mon, Tue, Wed). 2. Underneath your calendar, display the next event that is coming up (no matter what month is being displayed on the calendar).
Summary
In this chapter, you took a look at the calendar functionality in ExpressionEngine. You also got to see a working example of related entries and how it can help you reduce repetition in your channels. The calendar functionality can be daunting for beginners, as there is a lot of code involved. However, once mastered, the calendar is very flexible in terms of what you can display on it, how it is displayed, and how it all works together. The key points to remember after working through this chapter: •
The calendar functionality uses all the usual channel features that you know and love—custom fields, categories, status groups, and the Publish page. You can create channels with as many custom fields as you want, although you can only display the title field on the calendar itself.
•
Related Entries is when the contents of one channel are included in another channel. Although the events calendar was a natural choice, it could be used for any kind of channel. For example, if you have a recipes channel, you may have a second channel for common sub-recipes (such as making a pie-crust). In this way, you can have 14 different recipes that call for a pie-crust and you do not need to type out the instructions to make the pie-crust 14 times. Reducing repetition by using related entries also makes your website easier to maintain and update (for example, if you wanted to adjust your standard pie recipe, you only have to do it in one spot instead of in 14 places).
•
Related Categories has nothing to do with Related Entries. Related Categories is when two entries in a channel share a category and can therefore be considered to be related.
[ 196 ]
Chapter 7
•
The jQuery module allows you to use jQuery on your website without having to download it yourself (it comes included with ExpressionEngine). ExpressionEngine also masks where the jQuery file is, so it does not reveal the location of your system directory. Teaching jQuery is beyond the scope of this book, but when used thoughtfully, it can enhance the usability of a website.
In the next chapter, you will be building a photo gallery in ExpressionEngine.
[ 197 ]
Creating a Photo Gallery Although ExpressionEngine 2 does not come with a built-in photo gallery module, it does have many features designed to make working with photos easier. In this chapter, you will create a photo gallery channel, use file manager to manage your photos, and use jQuery to display the photos on your website. This chapter uses the FancyBox jQuery plugin that you set up in the previous chapter. If you did not follow the previous chapter, please follow the instructions in Chapter 7, Creating a Calendar under Setting up FancyBox
Although this chapter focuses on building a tool for Ed & Eg to share their personal photos, the techniques in this chapter will be useful in any situation where you want to display images—whether personal photos, a portfolio of your work or items for sale.
Designing your photo gallery
There are many different ways you can approach creating a photo gallery in ExpressionEngine. At the most basic level, you have a choice between each channel entry containing only one photo (and a description) or each channel entry containing a set of photos. If you allow only one photo per entry, you can use categories to organize the photos into galleries (and you can even include the same photo in more than one gallery). If you allow multiple photos per channel entry, each entry represents a photo gallery by itself. One way to accommodate multiple photos per entry is to create as many custom fields as the photos you think you will have in a gallery. For example, if you know each gallery will have a maximum of 20 photos, then you could create 20 custom fields for the photos and 20 custom fields for the descriptions. This solution works, but is not the most flexible (that is, to add 21 photos to a gallery, you would have to modify your custom fields and your templates).
Creating a Photo Gallery
An alternative approach to accommodate multiple photos per entry without creating an abundance of custom fields is to use a third party add-on such as Matrix by Pixel & Tonic (http://pixelandtonic. com/matrix). This add-on allows for tabular data in channel entries— you define the column headings (such as the photo and the description) and then add a row in the table for each photo. In each channel entry, you can create as many rows as you need. For example, you can create one entry with 12 photos and another entry with 25 photos.
Rather than creating lots of custom fields, or using a third party add-on, this chapter will show you a simple and elegant way to create a photo gallery using the one photo per entry design and then will use categories to organize the photos into galleries. Before you create your photo gallery channel, you first need to define where your photos will be stored.
File manager
The file manager is where you can upload new photos or crop, resize, rotate, or delete the images you have already uploaded; all from within the ExpressionEngine control panel. For this photo gallery, you will create a new upload destination—this is the directory on your server where ExpressionEngine will store your photos. 1. The first step in creating a new upload destination is to create the new directory on your server. Create a new directory called photos in /images. If you are following along on an actual web server, ensure that the new directory has 777 permissions (usually right-clicking on the directory in your FTP client will allow you to set permissions). If, instead of creating a new sub-directory inside the /images directory, you prefer to create a new top-level directory and you are using the .htaccess exclude method to remove the index.php from ExpressionEngine URLs, then be sure to add the new directory to your .htaccess file.
2. Next, you need to tell ExpressionEngine where this directory is. Inside the control panel, select Content and then File Manager.
[ 200 ]
Chapter 8
3. On the left-hand side of the screen, you will see the directory or directories where you can currently upload files to (if any), along with the files currently in each directory. In the toolbar on the right-hand side, underneath File Tools, select Create New Upload Destination.
4. Enter a descriptive name of Photo Gallery. The Server Path and URL may be pre-filled, however, you should make sure they point to the actual directory you just created (/images/photos). If you are following along in a localhost environment, the URL would be http://localhost/images/ photos. Leave Allowed File Types as Images only.
[ 201 ]
Creating a Photo Gallery
5. All the fields that begin with maximum can be left blank. These fields allow you to restrict the size, height, and width of photos. If you do enter values in here, and then later try to upload a file that exceeds these limits, you will see an error message such as The file you are attempting to upload is larger than the permitted size. 6. Set the Image Properties, Image Pre Formatting, and Image Post Formatting to be blank. These fields allow you to enter code that appears inside, before, and after the img tag. However, you can format your img tag as needed inside your template.
7. The File Properties, File Pre, and Post Formatting can be ignored for now as they only apply to non-image files that you upload (and you have specified that you are only allowing images in your photo gallery). 8. If desired, you can allow certain member groups to upload files. The member groups you see listed (if any) will depend on the member groups you have. Set all the member groups to Yes except for Members, which should be set No.
[ 202 ]
Chapter 8
9. Click Submit and your new upload destination will be ready to go. Go back to the file manager and you can see the new photo gallery upload destination with no files.
Creating your photo gallery channel
Now that you have created a place to store your photos, you can create your photo gallery channel. As with every other channel you have created in this book, you will follow the same basic steps—creating custom fields and categories, creating your channel, publishing some entries, and then building your templates.
Creating your custom fields
Since you are going to have one photo per channel entry, you have a lot of flexibility to create as many custom fields for each photo as you see fit—for example, you could have fields to capture the location of the photograph, the subject of the photo, the type of camera that was used, the name of the photographer, and so forth. However, to keep things simple, you will only create two custom fields right now—one for the photo itself and one for the description. 1. From the main menu of the control panel, select Admin, Channel Administration, and then Custom Fields. 2. Select Create a New Channel Field Group and call the new group photos. Click Submit. 3. Next to the new group, select Add/Edit Custom Fields and then select Create a New Custom Field.
[ 203 ]
Creating a Photo Gallery
4. The field type will be File. The field label will be Photo and the field name will be photos_photo (the first part representing the field group name). In the instructions for the field, indicate that photos in the photo gallery should be no more than 600x800 pixels (so that they fit on a typical computer screen without scrolling). You could also prevent photos that are bigger than 600x800 pixels from being uploaded by specifying the maximum width and height in the File Upload Preferences for the photo gallery upload destination. You have not done this here because it would prevent you from being able to upload a larger photo and then re-size it using file manager.
5. The field should be required, but not searchable, and should be shown by default. The field display order should be 1 and the file type should be Image. Click Submit. 6. Click Create a New Custom Field again. This time, the field type should be Textarea, the field label Caption, and the field name photos_caption. The field instructions can be left blank. Answer Yes to it being a required field, being searchable and being shown by default. The Field Display Order should be 2. 7. The number of rows can be left as 6 and the default text formatting should be set to Auto
(this will prevent unwanted whitespace in your captions due to extra paragraph tags being added, but will also allow multi-line captions). Say No to allowing an override on the Publish page. The text direction can be left as left-to-right. [ 204 ]
Chapter 8
8. Finally, say Yes to Formatting Buttons, Spellcheck, and Write mode. Say No to Smileys, Glossary, and the File Chooser. Click Submit to create the new field. Now that you have your custom fields, you can define your categories.
Creating your categories
As discussed at the beginning of this chapter, you are going to use categories to distinguish between photo galleries. To start with, you are going to create two photo galleries—one for vacation photos and one for local photos. You can always come back and add more galleries later. 1. Still in the control panel, select Admin, Channel Administration, and then Categories. 2. Select Create a New Category Group and name it Photo Categories. Select Allow All HTML in the category field formatting and check the boxes to allow other member groups to edit (or delete) categories as appropriate. (If you see a message saying that there are no member groups allowed to edit/ delete categories, this is fine too). Click Submit.
3. Back on the Category Management screen, select Add/Edit Categories for the Photo Categories category group.
[ 205 ]
Creating a Photo Gallery
4. Click Create a New Category. The first category will be called Local Photos. The Category URL will default to local_photos. Type in a category description (you will later display this on your website), leave the Category Image URL blank, leave the Category Parent set to None, and click Submit.
5. Select Create a New Category again. This time call the new category Vacation Photos, with a URL of vacation_photos. Type in a category description such as A selection of vacation photos taken by Ed & Eg. Leave the category image URL blank and the category parent as None. Click Submit.
Now that you have your category group and custom field group defined, you can go ahead and create your channel. [ 206 ]
Chapter 8
Creating your channel
The process of creating your channel is straightforward. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Photos with a short name of photos. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Photo Categories for the category group, Statuses for the status group, and photos for the field group.
3. Answer No to creating new templates and then click Submit. Your channel is created! Now you can start creating some content and displaying the photos on your website.
Uploading your first photos
There are three ways to upload photos to your website. Your first option is to go to File Manager (under the Content menu) and select File Upload on the right-hand toolbar. Alternatively, you can go to publish an entry in the Photos channel, click on Add File, and upload a file. Both of these options are convenient since they use the built-in ExpressionEngine file manager to upload your file—you never have to leave the control panel. However, you can upload only one photo at a time and you may run into issues if you try and upload very large photos (greater than 2 MB).
[ 207 ]
Creating a Photo Gallery
The third option for uploading photos is to do so directly, using FTP, just as you would upload any files to your website. Since this requires another tool, it is less convenient than uploading a single photo from within ExpressionEngine, but if you are uploading lots of photos, then using FTP is a lot faster to do. That is the method we will use here. The built-in file manager also allows you to crop, resize, and rotate images (although you can take advantage of these tools even if you do not use file manager to upload the files).
1. Download the example photos (local1.jpg through local8.jpg and vacation1.jpg through vacation8.jpg) from either the Packtpub support page at http://www.packtpub.com/support or from http://www. leonardmurphy.com/book2/chapter8. (Or you can substitute your own photos). 2. Copy or FTP the photos into the /images/photos directory that you created earlier in the chapter. 3. Back in the ExpressionEngine control panel, select Content | Publish and then select the Photos channel. 4. Type in a title of Fireworks and a caption Fireworks exploding with a bang. Then select Add File. 5. The first screen to appear in the Upload File screen. Since you have already uploaded the files, you can simply select the photo gallery option in the lefthand menu. If no photos appear under the photo gallery, or the files appear but no thumbnails appear, try logging out of the control panel and logging back in. (This helps to refresh ExpressionEngine so it recognizes the new files—the first time you access the files after uploading via FTP, ExpressionEngine has to create the thumbnails).
[ 208 ]
Chapter 8
6. Select local1.jpg.
7. On the Categories tab, select Local Photos. Then click Submit. 8. Now, repeat the same steps to create entries for the rest of the photos, using appropriate captions that describe the photos. Be sure to select a category for each photo. There are 16 example photos (eight local and eight vacation photos). Having several example photos in each category will demonstrate how the photo gallery works better.
Creating your templates
As with everything in ExpressionEngine, everything that appears on your website must be coded in a template. Your photo gallery is no exception. You will now create new templates in a design very similar to the one used by the FAQs channel—a single-entry template called comment so that visitors can leave comments on individual images, and a multiple-entry page where visitors can browse and view images by category. You will start with the single-entry page.
[ 209 ]
Creating a Photo Gallery
Creating the single-entry page
The single-entry page is where an individual photograph is displayed, along with the caption and any comments. In this section, you will create a new template group called photos and then create a new template called comment (since the primary reason to visit the single-entry template will be to view and post comments). 1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group photos. Do not duplicate a group and do not make the index template in this group your homepage. Click Submit. 2. Next, with the photos group highlighted on the left-hand side, select New Template. Call the template comment and leave the template type as Web Page. Since your single-entry page here will be very similar to the singleentry page you created for the FAQs channel, select Duplicate an existing template and then choose the faqs/browse template to duplicate. Click Create and Edit.
[ 210 ]
Chapter 8
If you did not follow Chapter 5, Creating a Fully-Equipped Channel completely and do not have an faqs/browse
template to duplicate, it can be downloaded from http:// www.packtpub.com/support or from the chapter 5 page at http://www.leonardmurphy.com/book2/chapter5.
3. Whenever you copy a template, the first thing to update is the Preload Text Replacements at the top. Update them to the following: {preload_replace:my_channel="photos"} {preload_replace:my_template_group="photos"} {preload_replace:my_single_entry_template="comment"}
4. Further down in the template, delete all the code between (but not including) the {title}
and the {/exp:channel:entries}. 5. Replace the deleted code with the following code to display your image and your image caption (centered), along with a link to your multiple-entry photos/index template (which is still blank):
<em>{photos_caption}
The limited class is defined in your site/site_css stylesheet as having the property max-width: 555px;. This value matches the width of the #content ID container. Although the channel field instructions ask that photos be no bigger than 600x800, they may still be too big to fit nicely into the #content area without overlapping the sidebar. The max-width property proportionally shrinks images if they are too big, but otherwise leaves the image alone.
6. A lot further down, underneath the line {/exp:comment:form}, remove the Other Questions Like This section: everything from the
to the {/exp:channel:entries} inclusive.
[ 211 ]
Creating a Photo Gallery
7. Click Update and visit an example photo (such as http://localhost/ photos/comment/fireworks). If you uploaded photos with different titles, then remember that because this is a single-entry page, the last part of the URL (in this case, fireworks) is actually the URL Title from the entry to be displayed. You can replace this with the URL Title of another entry in your channel, and that entry will appear instead. Refer to Chapter 5, Creating a FullyEquipped Channel for more information on single and multiple-entry pages and how they work. If something does not look right in your single-entry page page, compare your code with the final code for the template, downloadable at either http://www.packtpub.com/support or http://www. leonardmurphy.com/book2/chapter8.
[ 212 ]
Chapter 8
Your single-entry page is complete! Go ahead and try adding comments if you like— both as a member and a visitor. Next up, you will create your multiple-entry page where visitors will be able to browse photos by category.
Creating the multiple-entry page
The multiple-entry page needs to attractively display a series of photos so that your visitors can quickly browse to the photos they are most interested in. A visitor browsing your photo gallery will likely spend a lot of time on this page. Although you will use thumbnails to display the photos on your multiple-entry page, you do not have to force visitors to go to your single-entry page in order to view a larger image. Instead, you can use jQuery and the FancyBox plugin that you used in the previous chapter. When a visitor clicks on a photo, a full-size version will appear in a FancyBox overlay, complete with caption. Visitors will be able to quickly scroll through the larger images directly from the FancyBox plug-in. Underneath each thumbnail, a link can take visitors who wish to leave comments to the singleentry page where they can do so. If you did not follow the previous chapter, please, at least, follow the instructions under the heading Chapter 7, Creating a Calendar under the Setting up FancyBox section.
Rather than re-inventing the wheel, you can base the multiple-entry page template on the calendar/index template that you created in the last chapter. (If you did not follow the previous chapter, you can download the template from http:// www.packtpub.com/support or from http://www.leonardmurphy.com/book2/ chapter7). 1. In the ExpressionEngine control panel, copy the calendar/index template code and paste it into the photos/index template. You will see a message indicating that no closing tag was found for {exp:jquery. Ignore this message as this tag is one of those that do not require a closing tag. 2. Update the Preload text replacement at the top to the following: {preload_replace:my_channel="photos"}
3. Update the to be Photo Galleries as follows: Photo Galleries - Ed & Eg Financial Advisors
[ 213 ]
Creating a Photo Gallery
4. The calendar/index template used its own stylesheet with extra calendar formatting—since you do not need to do this, change the stylesheet back to includes/site_css:
5. Your calendar uses a pop-up class attribute to display links in a pop-up iFrame FancyBox. Since you will be displaying images rather than an entire page in this FancyBox, you can set different options. Specifically, you should remove the type of iFrame, display the caption inside the pop-up box (on the calendar you had it display outside so that it did not blend in with the iFrame content), and set cyclic to true—meaning that as someone cycles through the images, once they reach the end of the set, the images will loop back to the start. Finally, do not set any limitations on the width or height of the FancyBox—you can allow the pop-up to auto-size itself to the size of the image being displayed. To accomplish all this, replace everything currently between <script type="text/javascript"> and with the following (leave the <script> tags as-is): $(document).ready(function() { $("a.gallery").fancybox({ 'cyclic': true, 'titlePosition': 'inside', 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none' }); });
For more information on FancyBox, including what the different options mean, you can visit http://fancybox.net/.
6. Finally, remove all the code that appears between (and including) Seminar Calendar
and {/exp:channel:calendar}. This is where your photo gallery thumbnails will eventually go. Click Update to save your work so far. At this point, you have a blank page (with a relevant page title and a FancyBox script that is ready for you to start using). Now you can start adding content.
[ 214 ]
Chapter 8
Adding content to your multiple-entry page
There are going to be two ways to browse your photos—visitors may go to the main photos/index page, where they will see all your photos. Alternatively, they can go to a category-specific page, where they will only see photos that fall into that category. Just like you did with your faqs/index template, you are going to use conditional statements to distinguish between when a visitor is on a category browsing page versus when they are not. Remember that a category browsing page will have the word category in segment 2 of the URL. 1. Still in the photos/index template, add the following code after . If you are on a category browsing page, this code displays the category name, category description, and a link back to the non-category version of your multiple-entry template. If you are on the non-category browsing page, then it will display the generic title of photo galleries and some instructions on how to browse the photos. {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} {category_name}
{category_description}
Browse all photos
{/exp:channel:category_heading} {if:else} Photo Galleries
<strong>Instructions: Select a gallery to view or click on a photo to see enlarged. When viewing in enlarged mode, use your left & right arrow keys to scroll between photos and the escape key to exit enlarged mode.
{/if}
[ 215 ]
Creating a Photo Gallery
2. Next, you can create a drop-down category selector to allow visitors to jump quickly to a given category. This code is adapted from the Channel Categories Tag documentation viewable at http://expressionengine. com/user_guide/modules/channel/categories.html#dropdown. It essentially uses a standard HTML drop-down form, populated with options from the channel categories tag that link to the photos/index template (though you specify only the template group photos, ExpressionEngine knows you mean photos/index because the index template is the default template). Add the following immediately after the previous code:
3. Click Update and then visit your photo gallery (at http://localhost/ photos). Verify that you can browse between categories and that when you are on a category page, you see the category information, and when you are not, you see the generic instructions. JavaScript must be enabled in your browser for the drop-down menu to work.
[ 216 ]
Chapter 8
4. It makes sense to display the thumbnails in a table. Since every gallery could have a different number of thumbnails, it is impossible for you to know in advance how many rows your table might need. You will therefore use a suggestion from Mark Bowen in the ExpressionEngine wiki (http:// expressionengine.com/wiki/Entries_In_Table/) to use the {switch} variable to insert a row break () after every five photos. You will combine this with a conditional statement that checks to see if the current entry is the last entry, in order to prevent a superfluous row being added at the end of your table. Remember that the switch variable allows you to insert different code for different entries. Typically, it might be used to alternate the background color of entries (for example, {switch="blue|red"} would mean your first entry is blue, your second entry is red, and your third entry is blue again. The different pieces of code that are alternated are separated by a pipe (|). When there are more entries than pipes, ExpressionEngine starts again from the beginning. {switch="|||| "} means that on every fifth thumbnail the row will be ended and a new one started—there is no code between any of the other pipes. For more information on the switch parameter, please visit http:// expressionengine.com/user_guide/modules/channel/ variables.html#var_switch.
5. Add the following code immediately after the : {exp:channel:entries channel="{my_channel}"} ***Image will go here*** {if count!=total_results}{switch="|||| "}{/if} {/exp:channel:entries}
[ 217 ]
Creating a Photo Gallery
6. If you visit your website now, you will see a table where your images will go as well as some placeholder text. If you browse between the different galleries, you will see a different number of table rows depending on the number of images that are in that category.
7. The next step is to replace the placeholder text with actual thumbnails. When designing your custom fields, you did not include a field for a thumbnail. Whilst you could include the full-size image with a small width/height, your visitors would then have to download all the full-size images in order to see this page—significantly impacting page load times. Instead, you can use thumbnails that are automatically generated by ExpressionEngine. 8. Whether you upload photos via FTP or via file manager, ExpressionEngine automatically creates thumbnails of any photos in a _thumbs subdirectory (/ images/photos/_thumbs) when you first view them in file manager. These thumbnails are used internally by ExpressionEngine, but you can also use them on your visitor-facing pages. To do this, you will use the custom File field (photos_photo) as a tag pair instead of as a single tag. This allows you to access the different components of each file (the path, the filename, and the extension) in each entry separately. By doing this, you can then insert the _thumbs subdirectory to the end of the path, and prefix the filename with the thumbs_ prefix that is automatically added to the thumbnails.
[ 218 ]
Chapter 8
For more information about using the File custom field as a tag pair instead of as a single tag, please visit http:// expressionengine.com/user_guide/modules/ channel/custom_fields.html#file_fields
9. Replace the ***Image will go here*** placeholder text with the following code:
If, after doing this, you have some thumbnails that are not showing up, you may need to log into ExpressionEngine, edit the entry in question, and re-add the photo using file manager. Make sure you can see the thumbnail in your entry before you submit it.
10. Visit your website again, and you will see thumbnails instead of the placeholder text you had before. Additionally, if you click an image, it will pop up in a FancyBox lightbox, with the caption underneath. This is because you gave the link a class attribute of gallery (which matches the class attribute you used in your FancyBox script). You can scroll through the photos in the FancyBox by clicking the left and right arrows or by using your mouse scroll wheel—this is because all the photos on the page have the same rel attribute, letting FancyBox know this is an image gallery. FancyBox treats whatever is in the title attribute as a caption—in this case, you included the {photos_caption} caption.
[ 219 ]
Creating a Photo Gallery
If your image does not appear in a pop-up overlay, but rather opens in a separate window or tab, you can check for a number of things. First, verify that the FancyBox directory is at the root of your website and that you can access the FancyBox files in your browser (if not, check your .htaccess file). Next, verify that the paths in the photos/index template point to the script/CSS files in the FancyBox directory and check the filenames for misspellings. Then, compare the photo/index template you have created with the photo/index template that is available for download from http://www.packtpub.com/support or http://www.leonardmurphy.com/book2/chapter8. Look carefully for any spelling mistakes or typos, especially in the code and <script> sections, as well as in the link code for the thumbnails. Finally, ensure that JavaScript is enabled in your browser.
11. The final step is to include a link to your single-entry page for visitors who want to leave comments. This can be accomplished by using a hyperlink underneath each photo that will mention how many comments have already been made. Add the following code immediately before the in your template:
{if comment_total=="1"}1 comment{if:else}{comment_total} comments{/if}
12. Now visit your photo gallery page and you will find the new hyperlinks. Click on one to confirm that you are taken to the single-entry page. Add a comment and verify the total increments correctly. If you have comment moderation turned on, you will have to mark the comments as open before they will be included in these counts (although if you are logged in as a Super Admin, you will be able to see the comments on the single-entry page). To mark a comment as open, select Recent Comments from the View section of the control panel home page, click on the comment you wish to open and then click View Comments. Here you can check all the comments you wish to open, and from the drop-down box, select Open Selected and click Submit.
[ 220 ]
Chapter 8
Your photo gallery is complete. You now have an easy way for visitors to browse your photos quickly, either from the main photos/index page or by gallery. It is also easy to see which photos already have comments and for visitors to add their own.
Image editing features
Now that you have gone through the process of creating a photo gallery, uploading images, and creating the corresponding templates, it is a good time to discuss how photos can be cropped, resized, and rotated all from within ExpressionEngine. 1. From the Content menu in the control panel, select File Manager. 2. If you have multiple upload destinations, it is good to know that if you click on the title of one (such as About), it will collapse the list of files. If you click again, the file list will expand. This can help reduce screen clutter. 3. If you select a filename (such as local6.jpg), a FancyBox pop-up will appear with the full size image. (Press escape or click the x in the top-right to close). 4. For the photo local6.jpg, select Edit (in the fifth column from the left).
[ 221 ]
Creating a Photo Gallery
5. At the top-right, there are three modes (Crop, Resize, and Rotate). Select Crop Mode.
6. The picture on the left will darken. To crop the photo, you can drag the rectangle over the picture until the part of the picture you want is framed. The rectangle can be resized or repositioned as needed. On the right-hand side, you can see information about the width, height, and X/Y coordinates of your crop.
[ 222 ]
Chapter 8
7. Once the rectangle is placed, click Save Image on the right-hand side to save your changes. 8. You can also resize the photo by clicking on the Resize option. In this case, setting a width will automatically adjust the height so the photo stays in proportion (and setting the height will automatically change the width). This feature is extremely useful if you want to upload a full-sized image, but then manually adjust it so the width is no more than a certain size (for example). When you upload a photo for the first time from the Publish page, you also have the option to resize an image. In this way, you can upload full-size images directly, and resize them on the fly in ExpressionEngine, rather than shrinking them in advance or uploading them and using the file manager to resize them.
Rotate mode is also fairly self-explanatory. However, be aware that selecting a different rotation (or flipping the image horizontally or vertically) automatically saves the image.
Photo gallery add-ons
In this chapter, you have walked through how to build a photo gallery in ExpressionEngine without using any third party add-ons. As you can see, the functionality in ExpressionEngine is very robust and flexible out of the box. That said, there are times when an add-on can be useful—especially if images are a large part of the content of your website. Pixel & Tonic's Matrix was already mentioned at the beginning of the chapter as a useful add-on for designing a photo gallery with multiple photos per channel entry. In addition, the following add-ons are specific to editing photos (though they are by no means representative of all the add-ons that are available. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available.).
Image sizer
http://devot-ee.com/add-ons/image-sizer/
Written by David Rencher, this plugin takes a large image, dynamically resizes it, and caches the resized image (to reduce page load times). Using this add-on in your template saves you from having to manually resize every image you upload (and eliminates the risk of breaking your page layout if you forget). Instead, images are resized on the fly. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available. [ 223 ]
Creating a Photo Gallery
Channel Images
http://devot-ee.com/add-ons/channel-images/
For a small fee, Channel Images by DevDemon allows you to batch-upload multiple files from within the ExpressionEngine control panel and simplifies image management on the Publish page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. Since the photo gallery uses the same tools as all the other sections of your website, these exercises are not so much specific to photo galleries, but are a good reminder of the techniques learnt in previous chapters. 1. The main page of the photo gallery works great when there are only a handful of photos. However, over time, you could end up with hundreds and hundreds of photos in your channel, all of which would get displayed on your main page. Change the main page so that it limits the number of photos that are displayed and randomizes which photos are shown. 2. ExpressionEngine has the ability to track how many times a channel entry has been viewed on a single-entry page (Entry Views). Using a conditional statement, indicate on your multiple-entry template which photos are ***popular*** photos, based on the number of single-entry page views. For now, consider more than ten single-entry page views to be a sign of a popular photo. 3. The form for submitting comments and the code for displaying comments on your single-entry page are almost identical to the form for submitting comments and the code for displaying comments on your FAQs channel. In the spirit of reducing repetition, choose between a Preload Text Replacement, a Global Variable, a Snippet, or an Embedded Template and extract the code from both photos/comment and faqs/browse, so that both templates use the same code for submitting and displaying comments.
[ 224 ]
Chapter 8
Summary
In this chapter, you took a look at how to adapt the channel functionality of ExpressionEngine to a photo gallery. The lack of a formal photo-gallery module can make ExpressionEngine seem less functional. However, as you can quite clearly see, the standard channel functionality is more than adequate for the task, and indeed allows for a lot more flexibility than a separate photo gallery module might offer— with unlimited custom fields, a multitude of ways that you can organize photos within your channel (using categories and/or status groups), and with no restriction on how you can build your templates, the sky is the limit. This chapter wraps up the step-by-step introduction to ExpressionEngine. By now, you should be fairly comfortable with the basics of ExpressionEngine—channels, templates, tags, custom fields, categories, status groups, and so on. In the next chapter, you will be introduced to some more specialized first party modules that you may find useful.
[ 225 ]
Beyond the Basics So far, this book has introduced the basic concepts and the most commonly used features of ExpressionEngine. Many of the same basic skills have been used time and again such as setting up custom fields and categories, creating a new channel, posting entries to the channel, and building templates with HTML/CSS and ExpressionEngine tags. ExpressionEngine comes bundled with many other modules that may or may not be useful, given your website. The modules range from the simple to the complex—the simplest create additional tags that you can use in your templates, while the most complex include their own configuration pages and library of tags. This chapter looks at some of the offerings, including: •
The Search module
•
The Mailing List module
•
The Email module (create a contact form or a tell-a-friend form)
•
The Moblog module (submit new channel entries via e-mail)
•
The Wiki module The Mailing List and the Email modules rely on ExpressionEngine being able to send e-mails. If you are following along in a localhost environment such as WampServer, XAMPP, or MAMP, you will find that ExpressionEngine cannot send e-mails. This is because a localhost environment does not include an e-mail server. You can either follow along on an actual website server, or if you choose to follow along in your localhost environment, be aware that in places where you would expect ExpressionEngine to send an e-mail, you will not see such an e-mail.
Beyond the Basics
The Search module
ExpressionEngine comes with a pre-built search tool to allow visitors to search your site. Although technically a module, the search functionality comes pre-installed and does not have any special setup. This means that you can start using the search tags right away. There are two parts to enabling search on your website, namely: •
Creating a form that allows visitors to type in and submit search terms (this could be as simple as a search box that appears in your sidebar or it could be an entire template dedicated to an advanced search).
•
Creating templates to display the search results (or that there are no results). The Search functionality only searches channels. The Discussion Forum module and the Wiki module both have separate search functions.
When you design your search forms, you can use parameters to control what is searched. By doing this, you can limit searches to particular channels, status groups, or categories. You can also determine whether you want the search to include expired or future entries (this is important if you are searching a channel, like an events calendar, where all the entries might be in the future). Finally, you can set whether you want to search for words only in channel titles, in all the custom fields of a channel, or in the channel title, custom fields, and comments. Be very cautious if you enable your search to include future entries and the search form searches more than one channel. While one channel might routinely have entries in the future that you want to be searchable, another channel might have future-dated entries that you want to keep hidden until that date/time. The parameters you set for your search form (such as whether to include future-dated entries) apply to all channels that you allow to be searched from that form.
In addition to the search tags, there are three settings in the control panel that control how the search behaves:
[ 228 ]
Chapter 9
1. Is the field searchable? Each custom field in ExpressionEngine can be set to either be searchable or not searchable. Having this field set incorrectly on your custom fields can mean entries not being found that otherwise would be. As a general rule, fields that contain content such as sentences and paragraphs should be set to searchable, but fields such as drop-down boxes or files should not be searchable. To change the searchable setting for any individual field, go to Admin | Channel Administration | Custom Fields, and then select the field group and the field you wish to edit. You could create a custom field on a channel that is searchable, but that is not displayed on your website. This field could then be used to store likely search-terms for each individual entry that might not otherwise appear in the article (such as variations in spelling), thus improving the possibility that meaningful results are returned for people searching your website.
2. Search Page URL. Each channel has a path that is used to link the search results to the actual entries that were found. If this path is set incorrectly, clicking on a given search result will send the visitor to a wrong page. The field should be set to the single-entry template for the channel. (For example, the Photos channel should be set to http://localhost/photos/ comment). To change this setting for a given channel, go to Admin | Channel Administration | Channels, then click Edit Preferences for a specific channel, and look under Path Settings. 3. Which field should be used for search excerpt? This is also found under Channel Preferences, under Administrative Preferences. This defines the custom field from which the excerpt displayed on the results page comes from. To demonstrate the search functionality, you will create a search box in the sidebar that searches both the FAQs and the Photos channels. Before you begin, ensure that the Search Page URLs for these two channels are set to http://localhost/faqs/ browse and http://localhost/photos/comment respectively.
Adding a search box to your site
In this section, you will create a search box in the sidebar for Ed & Eg's website, thus allowing visitors to start a search from any page they like. 1. Go to Design | Templates | Snippets and edit the website_sidebar snippet.
[ 229 ]
Beyond the Basics
2. In the snippet, add the following code immediately after the final and before the final . Notice the parameters—the channel parameter restricts the search to the FAQs and Photos channels. The search_ in="everywhere" parameter means that you want the search to include titles, custom fields, and comments. The where="any" parameter means that entries containing any of the searched-for words will be returned (as opposed to requiring an exact match). The status parameter means that you will include entries with a status of open or premium (the premium status was one that you created in Chapter 6, Members, and if you did not include it explicitly, only entries with an open status would be searched). Finally, the result_page and no_result_page define which templates should be used when there are results or when there are no results (in this case, the search/ index and search/noresults templates, which you are yet to create). The rest of the code is a standard HTML form (although the input box must have the name="keywords" attribute for the search form to work). For more information on each of these parameters, including alternative settings for them and additional parameters not included here, please visit http://expressionengine.com/user_guide/modules/ search/simple.html. {exp:search:simple_form channel="faqs|photos" search_in="everywhere" status="open|premium" where="all" result_page="search" no_result_page="search/noresults"}
{/exp:search:simple_form}
3. If you visit the home page of your website, you should now see the search box on the right-hand side. If you have the Agile Records example website template groups still installed, searching will result in the Agile Records themed advanced search template being returned—otherwise, you would get a 404 page. You will create the search result templates next.
[ 230 ]
Chapter 9
Creating a search results template
The search results template is specified in the parameters of the search form as search, which translates to the search/index template. Had you not defined a specific template, the search results template would be set to search/results. If Agile Records is installed, then you are likely to already have a search template group which you can adapt to display your results. Otherwise, go ahead and create a search template group now. 1. The first step is to start with your basic site outline (header, sidebar, and so on). You can accomplish this by copying the includes/404 template into the search/index template. Edit the search/index template and paste in a copy of the code from includes/404. 2. Change the title of the page to be: Search Results - Ed & Eg Financial Advisors
3. Change the heading to be Search Results: Search Results
4. Replace the next paragraph (that talks about the page not existing) with the following. The {exp:search:keywords} tag displays the keywords used for the search.
You searched for <em>{exp:search:keywords}.
If you see a warning about there not being a closing tag when you save your template, ignore it. The {exp:search:keywords} tag is one of those that does not have a corresponding closing tag.
[ 231 ]
Beyond the Basics
5. Underneath the preceding paragraph, insert the following code (adapted from the code found at http://expressionengine.com/user_guide/ modules/search/results.html). This displays your search results in a two-column table. The first column will have the entry title and the second column will have an excerpt from the entry (the first 50 words from the field designated as the search excerpt field in your channel preferences). First create the table and the header row.
Title Excerpt
{if paginate} <span>{page_count} {paginate} {/if}
The pagination code at the end works similarly to channel pagination—allowing a long list of results to span multiple pages.
6. The following code uses the {exp:search:search_results} tag to display the actual results. This tag loops through once for each result you have. In this case, a new table row is created for each result. The switch tag makes the first row light-gray, the next white, the third light-gray, and so on. (Remember from the photo gallery chapter that the switch tag uses the first switch for the first result, the second switch for the second result, and so on, until it runs out of switches, when it starts over). Prior to the entry title, the channel name (such as Photos: or FAQs:) is added to make it clearer what kind of entry is being linked. Underneath the entry title, the number of comments that the entry has received is displayed. Add this code after the closing of the header row, within the table you created earlier: [ 232 ]
Chapter 9 {exp:search:search_results} <strong>{channel}: {title}
{if comment_total=="1"} 1 Comment {if:else} {comment_total} Comments {/if} {excerpt} {/exp:search:search_results}
Within the {exp:search:search_results} tag, there are some special variable tags you can use, including {auto_path} and {excerpt}. {auto_path} creates a path to the entry using the Search Page URL, defined in the channel preferences, and {excerpt} displays the first 50 characters of the excerpt field defined in the channel preferences. You can also use tags (such as {comment_total}, {author}, or {entry_date}), which are normally available in the {exp:channel:entries} tag. More information on search resultspecific tags can be found at http://expressionengine.com/user_ guide/modules/search/results.html and information on channel entry tag variables can be found at http://expressionengine.com/ user_guide/modules/channel/variables.html.
[ 233 ]
Beyond the Basics
7. Now click Update and Finished, go to your website, and search for something (for example, money). Your results will be displayed.
The no-results template
One other template you defined in your website_sidebar snippet was a no_ result_page of search/noresults. This can be a simple template that uses {exp:search:keywords} to display the search term and indicates that no results were found.
1. In the Search template group, create a new web page template called noresults. If you already have a results and a no_results template in the search template group, you can go ahead and delete these. 2. When creating the template, select to duplicate an existing template and duplicate search/index. Click Create and Edit. 3. Delete all the code from (and including) the
immediately above the opening tag down to (and including) the closing {/if} statement of the {if paginate} block of code. 4. Modify the You searched for… paragraph to read as follows:
[ 234 ]
Chapter 9 You searched for <em>{exp:search:keywords}. Unfortunately, nothing matching that search was found.
5. Click Update and Finished (ignoring any warnings about there being no closing tag) and now try searching for something that you know is not part of your website (for example, monkey). You will be redirected to your search/ noresults template.
Advanced search
In addition to the {exp:search:simple_form} that you used in your sidebar snippet, you also have the option of creating an advanced search form using the {exp:search:advanced_form} tag. The advanced search form allows visitors to select many of the settings that you set in the parameters of the simple search form. For example, on the simple search form, you specified which channels could be searched, whereas on the advanced search form, you can allow visitors to select which channels they can search in (although you can limit the choices they see by using parameters, just as you did with the simple search form).
[ 235 ]
Beyond the Basics
To build an advanced search form, you can create a template, such as search/ advanced, and then adapt the code from http://expressionengine.com/user_ guide/modules/search/advanced.html. This form looks much more complex than the simple_form, but most of that complexity comes from building all the form fields—how the form works is the same. Although an advanced search form on a small website like Ed & Eg would be overkill, an advanced search tool can enable power users to find what they are looking for on websites that have large amounts of content.
The Mailing List module
ExpressionEngine comes with a Mailing List module included. It is a very straightforward module that allows you to quickly and easily send e-mails to visitors who have signed up to receive e-mails or to specific member groups. You can have as many mailing lists as you want. Remember that if you are using a localhost environment such as WampServer or MAMP, ExpressionEngine will not be able to send outgoing e-mails. You will be able to follow the steps to set up a mailing list and make the sign-up box available on your website, but you will not be able to use the Mailing List module to send e-mails.
Setting up the Mailing List
The Mailing List module is included with ExpressionEngine, but is not installed by default. Installing it is easy. The following steps will show you how to do it: 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Mailing List and then click Install. 3. The Mailing List module name will turn into a clickable link. Click it to enter the Mailing List Manager. 4. To start with, there is one mailing list set up called Default Mailing List. You can change the name of the mailing list by clicking Edit next to the mailing list. You can also create multiple mailing lists by clicking Create New Mailing List at the top right.
[ 236 ]
Chapter 9
5. Click Edit Template to edit how the e-mails will look. By default, each e-mail has a footer with the unsubscribe URL (auto-generated by the Mailing List module for each e-mail address the e-mail is sent to). You can customize how this footer is worded or add text above the {message_text} variable in order to create a header for all your Mailing List e-mails. The conditionals {if plain_email} and {if html_email} allow you to distinguish between plain-text and HTML versions of an outgoing e-mail, so that people reading the e-mail in plain text do not see the HTML mark-up. For now, leave the default e-mail template as-is. 6. Also, within the Mailing List Manager, you can batch subscribe or unsubscribe people (for example, if you were transferring over a Mailing List from another application). You can also set up an administrator e-mail address, so when someone new subscribes to a Mailing List, the administrator gets notified. (Click Mailing List Preferences to do this). 7. To see who is signed up for any given Mailing List, click View next to the Mailing List name.
[ 237 ]
Beyond the Basics
Now that you have a mailing list defined, there are two more things you must do: 1. Allow people to subscribe to your mailing list 2. Send e-mails to people on your mailing list
Allowing members to sign-up
To allow visitors to sign themselves up to the mailing list, you are going to add an option to your sidebar snippet. 1. Modify the snippet called website_sidebar. 2. In the snippet, add the following code immediately after the final li> and before the final . This code is adapted from the mailing list documentation at http://expressionengine.com/user_guide/modules/ mailinglist/index.html. Notice that in the {exp:mailinglist:form} tag, you have a parameter called list that is used to determine which mailing list the member will be signed up for (in this case, default). The e-mail input box value is set to {email}, which is a global variable referring to the e-mail address of the currently logged in member. In this way, if a member wishes to register for the mailing list, they do not need to re-type their e-mail address. Mailing List
{exp:mailinglist:form list="default"}
{/exp:mailinglist:form}
3. Click Update and Finished. Visit Ed & Eg's home page and you will see the option to sign up for a mailing list. Note that any new visitors who sign up will receive an e-mail with a link which they must click within 48 hours in order to actually sign-up (remember that if you are using a localhost environment, you will not receive this e-mail). The mailing list is strictly an opt-in feature, with an opt-out link included in every e-mail that you send.
[ 238 ]
Chapter 9
You have set up your mailing list so that visitors can sign themselves up to it. Note that if you wanted to have multiple mailing lists, all you would need to do is change the list parameter to reflect the short-name of the mailing list that the person is signing up for. Of course, now that you have a mailing list with subscribers, how do you send them e-mails?
Sending e-mails
Before trying to send an e-mail, review your e-mail settings in Admin | Email Configuration. Here, you can define not only how e-mails are sent (PHP Mail, Send Mail, or SMTP), but you can also define which e-mail address they come from. If, for any reason, ExpressionEngine is not sending e-mails, you can also turn on Email Debugging, which will then display the error message explaining what is stopping the e-mail from being sent. The settings on this page apply to all e-mails sent by ExpressionEngine, including automated e-mails such as those that are sent as part of new member registration or when you sign up for a mailing list.
[ 239 ]
Beyond the Basics
To send e-mails, you must use the Communicate tool (under Tools in the main menu). This tool can be used in conjunction with the Mailing List module to send e-mails to people who have subscribed to a given mailing list, or it can be used on a standalone basis to send e-mails to certain member groups or specific e-mail addresses. Remember that if you are following along in a localhost environment, you will not actually be able to send outgoing e-mails.
The Communicate tool has lots of options, most of which are fairly self-explanatory. At the very top, there is a link to see previously sent e-mails. Underneath the message, you can choose between sending a plain-text or an HTML e-mail. If you choose HTML, you can optionally include a plain text alternative for recipients who cannot read HTML e-mails. On the right-hand side, you can choose which mailing lists or member groups get the e-mail (or manually type in your own recipients' e-mail addresses). If you are handtyping e-mail addresses, it is recommended that you use the BCC field so that you do not expose the e-mail addresses of recipients to other recipients. You can also define who the e-mail comes from (so that it is less likely to be treated as spam).
A checkbox at the very bottom allows you to suppress e-mails to members who have requested not to receive e-mails from administrators in their control panel settings—respecting this setting is recommended. [ 240 ]
Chapter 9
The Mailing List module is designed to make it easy to send e-mails to multiple recipients at once. If you want to send an e-mail to an individual member, you can also do so via the e-mail console, provided you have enabled this functionality for the member group you are in. Click on the Email button from either the individual member's profile or from the member list at http://localhost/member/list to access the e-mail console. See Chapter 6, Members for more information on member-facing functionality.
The Email module
The Email module gives you the ability to easily create contact forms (so that your visitors can e-mail you) and tell-a-friend forms (so that your visitors can e-mail their friends). In this section, you will see how to set up both of these forms for your website. If you installed the Agile Records example site, then the Email module will already be installed. Otherwise, it can be easily installed by going to Add-Ons | Modules and clicking Install.
Creating a contact form
Ed & Eg currently have an FAQs section, where they answer frequently asked questions from their customers and visitors. However, there is no easy way for visitors to submit their questions to Ed & Eg. In this section, you will create a new contact form so that visitors can submit their questions for Ed & Eg to answer. As you have done before, you will base the contact form template on the includes/404 template (which has the site header and other layout components, but does not have much in the way of content that needs to be changed). 1. From Template Manager, select the faqs member group and click New Template. 2. The new template will be called submit. The template type should be Web Page. Check the option to duplicate another template and select the includes/404 template to duplicate. Click Create and Edit. 3. Change the HTML to the following: Submit a Question - Ed & Eg Financial Advisors
[ 241 ]
Beyond the Basics
4. Change the title from Page Not Found to Submit a Question. 5. Delete the paragraph underneath the tag. 6. The following code is adapted from the example provided in the ExpressionEngine documentation for this module at http://
expressionengine.com/user_guide/modules/email/contact_form. html. The {exp:email:contact_form} tag displays your contact form. This tag has a parameter called recipients that allows you to specify the e-mail
address you want the final e-mail to be sent to—your visitors will not be able to see or change this address. The rest of the form is a standard HTML form with some values filled in, based on ExpressionEngine variables (the e-mail address of the member, their name, and the date/time). Add the following code underneath the header in the template, changing the recipient's e-mail address to match your own:
{exp:email:contact_form user_recipients="false" recipients="[email protected]" charset="utf-8"}
{/exp:email:contact_form}
7. Although the form is complete as-is, you can also add code to display a CAPTCHA. Even if you are not using the CAPTCHA system now, it does not hurt to put this code in; in case you want to use it in the future, you can quickly enable it (under Admin | Email Configuration) without changing your templates. You can do this because the {if captcha} conditional prevents the CAPTCHA from displaying, unless it is set to be required. Insert this code immediately before the Submit button (after the
) within the contact form: {if captcha} {captcha} [ 242 ]
Chapter 9
{/if}
8. Click Update and now visit your submission form at http://localhost/ faqs/submit. If ExpressionEngine is configured to send e-mails, visitors will be able to use the form to send you e-mails easily and seamlessly from within your website.
For more information about the parameters of this form and how they can be set, please see the ExpressionEngine documentation at http://expressionengine. com/user_guide/modules/email/contact_form.html. The documentation includes useful tips in case your server host does not allow e-mails to be sent from your domain with a "from e-mail address" that is not yours. [ 243 ]
Beyond the Basics
Creating a tell-a-friend form
The tell-a-friend form works very much like the Contact form, except that instead of e-mailing a person you specify, the person can e-mail a friend of their choice. The risk with this form is that spammers might use it to e-mail advertising or other junk to third parties. To prevent this, there are several options—you can restrict this functionality to signed-in members who have activated their membership via e-mail (and then pre-fill the From field with that member's e-mail address). You can fix the message text yourself so that it cannot be edited (visitors can either send or not send the message as-is). Finally, you can require CAPTCHAs (in Admin | Email Configuration) for visitors e-mailing a friend. You may also wish to consider independent social media solutions, such as adding Facebook's Like button to your website, which allows visitors to easily share that they like your website, without the concerns that the tell-a-friend form brings. Check out http://developers.facebook. com/docs/guides/web for more information.
For this example, you will create a tell-a-friend form for the FAQs channel that is only available to members. The From e-mail address will be set as the e-mail address of the logged-in member and the message will also not be editable.
Creating the tell-a-friend template
The tell-a-friend template will be based on the faqs/submit template, which you had created for your contact form. If you did not follow the steps to create a Contact form, remember that you can download the source code from either http://www. leonardmurphy.com/book2/chapter9 or from http://www.packtpub.com/support. 1. Create a new template in the FAQs template group called friend. When prompted to duplicate an existing template, select faqs/submit as the template to duplicate. Click Create and Edit. The tell-a-friend form can also be added to the bottom of the singleentry template for your channel (in this case, faqs/browse).
2. Change the HTML to: Tell a Friend - Ed & Eg Financial Advisors
3. Change the title to Tell a Friend. [ 244 ]
Chapter 9
4. Replace everything from {exp:email:contact_form} to {/ exp:email:contact_form} with the following conditional, which checks to see if the visitor is logged in. If they are not logged in, they will not be able to tell-a-friend. {if logged_out}
Sorry, you must be logged in to tell-afriend.
{if:else} {/if}
5. After the {if:else} and before the {/if}, insert the following tell_a_ friend form (adapted from http://expressionengine.com/user_guide/ modules/email/tellafriend.html). The tell-a-friend form is necessarily longer than the Contact form because there are more fields (for the send-to e-mail address and the name of the person the e-mail is coming from). Also, notice that some of the fields in the following code are read-only because the values are being populated from ExpressionEngine. {exp:email:tell_a_friend charset="utf-8" allow_html='no' status="open|premium"}
{/exp:email:tell_a_friend}
In this example, you use the {faqs_question} custom field to display data from your entry in the message. Indeed, ExpressionEngine is versatile enough that you can create a single tell-a-friend form for multiple channels, even if they have different custom fields. ExpressionEngine will suppress any custom fields that do not apply, based on the channel that is being sent to a friend. The status="open|premium" is because there are some entries that might have a premium status rather than open. Without this setting, any status that is not open would not render the tell-a-friend form.
6. As with the Contact form, add the following CAPTCHA code immediately before the Submit button (after the
) {if captcha} {captcha}
{/if}
7. Now you need to create a link to the tell-a-friend form. Edit the faqs/browse template and add the following link next to the Back to FAQs link. Like the form itself, this link will only be visible to members who are logged in. {if logged_in}Tell-aFriend | {/if}Back to FAQs
[ 246 ]
Chapter 9
8. Now if you visit a FAQs channel entry and click the Tell a Friend form, you will be brought to the faqs/friend form, where you can send an e-mail to a friend.
Word-of-mouth is one of the best marketing strategies available, and the tell-a-friend functionality allows visitors to share an entry on your site without having to a draft a special e-mail. Although this example is very locked-down, you can make it more flexible (such as by allowing visitors to edit the message). Before making changes such as that, always think of how easy it might be for a malicious person to use the form to send advertising or phishing e-mails to third parties.
[ 247 ]
Beyond the Basics
The Moblog module
So far, whenever you wanted to create content, you have had to log into the control panel and publish a new entry. The Moblog module provides a way to upload files to your website and create content directly from your Internet-enabled smart phone. The basic concept involves setting up an e-mail address which ExpressionEngine can access. When you e-mail from your phone to the e-mail address, the content can either be turned into a channel entry, or attached files can be saved to an upload location without a channel entry being created (making it an easy way to upload files to your website without FTP). The module includes ways to prevent spam or other e-mails that might also be sent to the same e-mail address from being published to your site. Unfortunately, the Moblog module can only add new content to text area custom fields. Since channels will often have other types of custom fields, does this mean that you cannot use the Moblog module? No. Take, for example, the Photos channel. There is one text area custom field (caption), but the photo itself is a File custom field. Although you cannot publish an entry to the photo channel without a photo, you can still use the Moblog module to create a closed entry with the caption you desire, and upload the photo(s) attached to your e-mail to the photo gallery upload destination. Then, when you log in to the control panel, all you have to do is edit the entry, select the photo from the file manager, and change the entry status to open. For the Moblog module to work, you must have an e-mail address that ExpressionEngine can access via POP3. Typically, an e-mail address associated with your website domain or your internet provider (ISP) would have POP3 access, but a free web-based e-mail service may or may not. Since ExpressionEngine is only reading incoming e-mails (and not sending e-mails), the Moblog module can be set up and tested even in a localhost environment.
Setting up the Moblog module
As with other modules, the Moblog module is not installed by default. Installing it is easy. 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Moblog and then click Install. 3. The Moblog module name will turn into a clickable link. Click it to enter the Moblog control panel. 4. When you first enter the control panel, no Moblogs exist. Click Create New Moblog. [ 248 ]
Chapter 9
5. First, the general settings need to be defined. Enter a full name of Photos Moblog and a short name of photos_moblog (remember that the short name is what will be used in templates). Leave the time between checks set at 15 minutes. This does not mean that the e-mail address will be checked every 15 minutes, but that if you set up a template with an {exp:moblog:check} tag, and someone visits that template and more than 15 minutes has passed since the last check, then the e-mail address will be checked. Set Moblog Enabled? to Yes and set File Archive Mode to No (File Archive Mode is where files attached to your e-mail are uploaded, but no channel entry is created).
[ 249 ]
Beyond the Basics
6. Next, choose the channel you want to post to—in this case, Photos. You can also select a default category, field, status, and author. This can be useful if, for example, you want your mobile photos to be in their own gallery or to have their own status. For this example, use a default category of None. Use a default field of Caption, a default status of Closed (since you do not want your entries to be visible until you have updated the File custom field with the photo), and a default author of you.
7. Say No to making the entry sticky (meaning that it always appears first on a multi-entry page) and Yes to allowing overrides in e-mail. This means that if you want to set the category or status differently as compared to the default, you can do so by using a special code in your e-mail—for a list of possible overrides, see http://expressionengine.com/user_guide/modules/ moblog/email_contents.html. 8. Select Photo Gallery as the upload directory. 9. The Moblog templates allow you to define exactly what will happen with your e-mails. The default is to display the text first, then any images in an img tag, and any other files as a Download File link—all within your text area. Since you do not want your images to be part of the caption, change the template to remove the {images} section as follows: {text} {files match="audio|files|movie"} Download File {/files}
[ 250 ]
Chapter 9
For more information on the different tags and parameters that are available, please visit: http://expressionengine.com/user_ guide/modules/moblog/control_panel/email_template.html.
10. Next up, you can define your e-mail settings. The e-mail server must support POP3—typically e-mail addresses associated with your website domain would have POP3 access, as would e-mail addresses from your ISP. Free e-mail services may or may not include support for POP3 access. If you already download your e-mail to your e-mail software using POP3, then the same settings that are in your e-mail client (server name, username, and password) would go here. Since the Moblog module is scanning for incoming e-mails and does not send e-mails, the Moblog module will work even if you are using a localhost environment. Simply set the settings to the e-mail address you want to scan.
11. Further down, you can specify a word or phrase that must appear in the subject of your Moblog e-mails. This allows ExpressionEngine to distinguish between a Moblog e-mail and all the other e-mails you may receive. The default setting is moblog:, meaning that any e-mail you want posted to your Photos channel needs to have moblog: in the subject. (When setting the title of the entry, this phrase will be stripped out and the rest of the subject will be used; for example, Moblog: Flower will result in an entry called Flower.) Changing the subject prefix is useful when you want multiple Moblogs to use the same e-mail address. However, for the purposes of this example, leave it set as moblog:. 12. For security, you can also set your Moblog e-mails to be from a certain e-mail address (or addresses) and you can require authentication (meaning your control panel username and password must be included in your Moblog e-mails). It is recommended to at least limit the e-mail addresses that can send Moblog e-mails. 13. The next option allows you to prevent certain text that might be included in your e-mails (such as your signature) from appearing in your channel entry.
[ 251 ]
Beyond the Basics
14. Next, you can set the parameters for any images you attach—you can require images to display with a certain height or width, you can resize, you can upload images automatically, and you can also create thumbnail images if desired. For now, say Yes to resize images on import, and resize any images to have a width of 555. Leave the height set to 0 to keep the image in proportion.
15. Finally, click Submit to create your Moblog.
Setting up your template
If you were using the Moblog module to post content directly to your website, you could set up a template to check for new Moblog entries automatically whenever it is accessed by a visitor. With the following tag, ExpressionEngine will check to see if 15 minutes have elapsed since the last check, and if so, ExpressionEngine will check again:
silent="true" means that the Moblog check will be invisible to the person viewing your template. For troubleshooting purposes, you could temporarily set this to false. If you do set this to be false, having the tag wrapped within an HTML comment, as shown, means that you can see any error messages by viewing the HTML source (by clicking View Source from your browser), while visitors see nothing unusual. [ 252 ]
Chapter 9
Since you are setting up your Moblog to act as an easy way to create entries without publishing them right away, this step does not apply.
Sending a Moblog e-mail
Now that the Moblog module is configured, you can try sending your first Moblog e-mail. 1. First, send an e-mail to the e-mail address you specified with an image attached. Be sure that the e-mail has a subject prefix as defined (moblog:) and comes from an e-mail address that is allowed to post Moblog entries. Do not forget the attachment!
2. Next, log into the control panel and select Add-Ons | Modules and then select Moblog. Click Check Moblog. If the Moblog module finds valid e-mails, you will see a green check mark at the top of the screen (which you can click to see more information).
[ 253 ]
Beyond the Basics
3. Now select Content | Edit and look for an entry with a title that matches the subject of the e-mail, a date/time of the current date/time, and a status of closed. Click the entry to edit it and you can see the body of your e-mail in the caption field.
4. Click Add File, select the Photo Gallery, and click on the file you uploaded. 5. Click on the Options tab and change the status to Open. Then click Submit. 6. Visit the photo album (http://localhost/photos) to see your new entry. Notice how the image was automatically resized to be 555 pixels wide, as specified in the Moblog preferences.
[ 254 ]
Chapter 9
The Wiki module
A wiki is an area of the website where visitors themselves can edit the content or create new content. One of the most famous wiki's on the web is Wikipedia (http://www. wikipedia.org/)—an online encyclopedia that anyone can contribute content to. Another example wiki is the ExpressionEngine wiki, located at http:// expressionengine.com/wiki/—a great tool for sharing how-tos and more with other ExpressionEngine users.
At first glance, it can be difficult to see the use for a wiki (especially for a website like Ed & Eg's). However, if you think of it as a collection of documents that can be shared among a group of people of any size, and updated in real time by the same group of people that actually use the content, the business advantages start to become clearer. As with any tool that requires active participation from others, it helps if you already have a group of people that is willing to participate. A wiki, more so than other tools (such as comments or a discussion forum), requires an unusually high commitment from end-users—first to build the content and then to be willing to edit and add to other people's content. To demonstrate how the Wiki module works, you will create a wiki for visitors to exchange money-saving tips and ideas. The Freelancer license does not include the Wiki module, so this section will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing.
Setting up the wiki
As with other modules, the Wiki module is not installed by default. Installing it is easy. 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Wiki and then click Install. 3. The Wiki module's name will turn into a clickable link. Click it to enter the wiki control panel. 4. Click on Create Wiki. 5. Change the full wiki name to Money Saving Wiki and change the short name to money_saving_wiki.
[ 255 ]
Beyond the Basics
6. Leave the text formatting as Xhtml, but Allow only safe HTML (meaning that people can use standard HTML tags to mark-up their content). 7. Choose a File Upload Directory where files associated with the wiki will be stored. (You may want to create a new directory under Content | File Manager that is specifically for wiki files). If you do not select a destination, uploading files will not be possible. 8. Select which member groups can administer the Wiki module, and which member groups can use it. Administrators can delete content, mark an article as locked (so that no-one can edit it), or mark an article as moderated (meaning that users can edit it but an administrator must approve the change before it becomes visible to others). Select Super Admins as your administrating member group, and select all your member groups as users. 9. You can set up how many revisions you keep for each article and how many edits a single individual can do in a single day. For now, leave these at their defaults. 10. Set up an e-mail address as the e-mail to receive notifications when an article marked as moderated is changed. 11. You can optionally set up a namespace for you to group articles. The main advantage to using a namespace rather than a category is to set up different member groups as administrators and users. For example, Ed & Eg cater to both businesses and individuals, so if they wanted, they could have created two namespaces so that their business articles and individual articles were separated. They could then have two member groups and allow members of the business member groups to add/edit content to articles in the Business namespace but not articles in the Individual namespace. For now, leave the namespace fields blank. 12. Click Update to create the wiki. 13. The final step is to create a new template and template group for your wiki. Go to Design | Templates | Edit | Create Group and call the new template group wiki. 14. Edit the index template of the wiki template group and add the following code. You do not need to include any other HTML or ExpressionEngine tags, as this tag will create the entire wiki. {exp:wiki base_path="wiki/index" wiki="money_saving_wiki" theme="azure"}
[ 256 ]
Chapter 9
If you use a different template group or template name, change the base_path parameter accordingly. The wiki parameter is the short name of the wiki. The theme can be either default or azure. You can also create your own themes by creating a new directory in your / themes/wiki_themes/ directory and copying and modifying the files from an existing theme. See http://expressionengine.com/user_ guide/modules/wiki/wiki_templates.html for more information.
15. Now view this template in a browser (http://localhost/wiki).
How does the wiki work? The next step is to create some content.
1. On the first page of the wiki, click Edit (at the top) to edit the page.
[ 257 ]
Beyond the Basics
2. You can type in whatever text you wish, using HTML for basic text formatting. To create a link to a new article, enclose the new article's name in double square brackets. For example: Welcome to our Money Saving Wiki. Here are some moneysaving ideas: <strong>[[Shopping]] Don't buy the name-brand of everything. Pick one or two items that you like, and for everything else, buy the store brand. Sometimes spending the extra 30 cents for the name-brand doesn't sound like much, but saving 30 cents on 30 items in a single trip, and doing 40 trips a year, will save you $360 this year!
For more money-saving tips when [[shopping]], click on the word [[shopping]].
3. In the notes section, write a brief description of the change you are making, such as "Added Tip on saving money when shopping". (This will show in the history log). Then click Submit.
4. You can now click on any one of the shopping links to be brought to a new article where you can create a new page with more text. Notice how you can have multiple links to the same article. Remember that a wiki is a multi-user environment. The intent is not to have one person create all the content, but for it to be a collaborative effort (although you may prefer to have one person add some content and develop the structure before making it more generally available).
5. The ExpressionEngine wiki also supports the use of categories. Use the following code anywhere in an article to assign the article to a Shopping category. [[Category:Shopping]] [ 258 ]
Chapter 9
You can assign an article to multiple categories. You can also assign articles to subcategories using a format such as: [[Category:Shopping:Store Brands]]
6. If enabled, you can also upload images, diagrams, and documents by clicking on File Upload on the left-hand menu. You can then embed uploaded files using either [[File:filename.txt]] (to create a link) or [[Image:image. jpg]] (to embed a picture). For more information on wiki syntax, visit http://expressionengine.com/user_ guide/modules/wiki/wiki_syntax.html.
Other ExpressionEngine modules
There are several other free modules that ExpressionEngine has which have not been covered here. •
The Discussion Forum is a module written by EllisLab but sold separately from ExpressionEngine (although it requires ExpressionEngine to run). The module leverages ExpressionEngine's Member module features, but has its own templating system and is styled via separate CSS. The best example of a discussion forum in action is the ExpressionEngine support forums (at http://expressionengine.com/forums).
•
Simple Commerce allows you to mark posts in channel entries as being for sale. You can create a channel of items for sale, set the price for each item and then accept payments through PayPal. All payment information is transferred directly between the visitor and PayPal—at no point does your website or ExpressionEngine handle payment information. Although Simple Commerce is not a fully-fledged e-commerce module, for smaller websites that do not need the complexity of a complete payment processing solution, Simple Commerce will likely meet your needs.
•
Blacklist/Whitelist is a spam prevention tool that allows you to block visitors by IP address, URL, or User-Agent. You can either block specific IP Addresses, URLs, or User-Agents, or you can enter a partial string to block anything that matches that string. You can also add items to your white-list (meaning that you could blacklist a certain IP address pattern, but make an exception for an IP address that you know is not spam). EllisLab provides a Blacklist and a Whitelist that you can download periodically to keep known spammers away.
[ 259 ]
Beyond the Basics
•
IP to Nation allows you to determine which country an IP address is associated with, and then ban visitors from that country from seeing your website (or display a flag next to comments or entries from visitors that come from that country).
•
Query is a very useful module for more advanced users, allowing you to run SQL queries against the ExpressionEngine database directly. Although it requires some familiarity with the ExpressionEngine database structure and with SQL syntax, it can allow you to display ExpressionEngine data in unique ways that might not otherwise be possible. See http:// expressionengine.com/user_guide/modules/query/index.html for examples of how to use this module within a template.
•
Referrer allows you to track which websites have links to your website that people are using to arrive at your site.
•
Statistics allows you to display certain facts about your website on a template (such as the number of people who are logged in, the date of the most recent comment, and the total number of comments that have been left on your site).
Multiple Site Manager
EllisLab also offers Multiple Site Manager for people who run multiple websites. Multiple Site Manager adds the ability to manage multiple websites from the same ExpressionEngine login (up to three sites are included with the initial purchase price, with the option to buy more if needed). The key licensing criterion is that you must be the owner of all the websites you manage. Each website is distinct in terms of templates, channels, and preferences, but addons, members, and member groups are shared across all three sites. In this way, members only have to register once for all the websites, as each of your websites can share the same modules and other add-ons (saving you from installing and configuring the same modules over and over again) and you can conveniently manage all your websites from the same control panel. Although not appropriate for everyone, Multiple Site Manager is a very powerful tool, making maintaining your websites much easier and at a lower cost than purchasing three separate licenses. More information can be found at http:// expressionengine.com/user_guide/cp/sites/index.html.
[ 260 ]
Chapter 9
Summary
In this chapter, you took a look at many of the modules that come bundled with ExpressionEngine. Some modules come pre-installed, some are included but not installed, and some have to be downloaded and installed separately. A typical module has a configuration screen (accessible via Add-Ons | Modules) and tags that can be used in templates to access the modules functionality. In the next chapter, you will be introduced to the other types of add-ons, including Accessories, Extensions, Fieldtypes, and Plugins. You will also learn about third party add-ons. Finally, you will learn key tips for running an ExpressionEngine website, including how to do database backups and version upgrades.
[ 261 ]
Extending ExpressionEngine So far, this book has taken a step-by-step approach to implementing the most popular modules in ExpressionEngine. In this chapter, you will not be building content for Ed & Eg's website, but rather looking at what else goes into maintaining an ExpressionEngine website. First, you will learn about essential maintenance tasks such as backups, restores, and upgrades. You will then be introduced to many of the most highly-rated addons that are available for ExpressionEngine before finally getting an overview of ExpressionEngine's spam controls, as well as ways to fine-tune ExpressionEngine. After completing this chapter (and the book), you will feel confident creating and maintaining an ExpressionEngine-powered website.
Backups and restores
ExpressionEngine is a database-driven application. So to back it up, you need to back up both the individual files on your web server and the database itself.
Backups
To back up ExpressionEngine, you need a tool such as phpMyAdmin. If your website is hosted by a website hosting provider, contact them and ask if phpMyAdmin or another tool is installed that will allow you to do MySQL database backups. If necessary, phpMyAdmin can be downloaded from http://www. phpmyadmin.net/. phpMyAdmin is included with local development environments, including WampServer, XAMPP, and MAMP, usually at an address such as http:// localhost/phpmyadmin (all in lower-case).
Extending ExpressionEngine
1. The first step to doing a backup is to clear all the unnecessary data from the database (such as cached templates). Log in to the control panel and select Tools | Data | Clear Caching. Select All caches and click Submit.
2. Access the phpMyAdmin control panel.
3. On the left-hand side, select the ExpressionEngine database (such as ee). After selecting the database, you are brought to a screen that shows all the ExpressionEngine tables on the left-hand side (beginning with exp). 4. In the main window, select Export from the top menu.
[ 264 ]
Chapter 10
5. On the Export page, at the top of the left column, verify that all the tables are selected.
6. All the options on the right-hand side can be left at their default settings. At the bottom, check the box Save as file. Select a Compression method of either zipped or gzipped and then select Go.
7. You are then prompted to save the file; save it to a safe place. Note that while phpMyAdmin is sufficient for smaller databases, the backup may time out when backing up very large databases. One option to work around this is to split out the database backup so that not all the tables are backed up into a single file. Another option is to look at the command line MySQL code or a utility such as My SQL Dumper (http://www.mysqldumper.de/en/).
In addition to backing up the MySQL database, it is also prudent to back up all the files on your web server, including any themes, language packs, and add-ons that may have been installed as well as any files that may have been uploaded to your File Upload Destinations (such as the /images directory).
[ 265 ]
Extending ExpressionEngine
Database restores
A backup is only useful if it is usable, and the only way to know if a backup is usable is to restore it. To test a database restore, it helps to have a second database created in phpMyAdmin (if your hosting package includes two databases). Alternatively, you can test a restore to a localhost environment. Testing a database restore using a different database or a localhost server is easy enough, but bringing up an entire ExpressionEngine website on a different database or server is more complicated. The guidelines on how you can accomplish this can be found in the ExpressionEngine wiki at http://www.expressionengine.com/wiki/.
1. If you are restoring a database to a test database, you can follow the instructions at the beginning of Chapter 1, Getting Installed to create a second database. 2. If you are restoring over the top of an existing ExpressionEngine database, you first have to delete the existing tables. In phpMyAdmin, select the database you are restoring to and select Structure from the menu at the top of the main window. Scroll all the way down and select Check All to check all the tables. In the drop-down box, select Drop. A confirmation window will appear—click Yes. Before doing this, be very sure that the database is well backed up or that losing all the data in all the tables will not be a problem.
3. Next, in the empty database, select Import from the menu in the top window. 4. Browse to the location where the database backup was saved. Leave all the other options at their defaults and click Go. [ 266 ]
Chapter 10
5. When the import is complete, there will be a message that says Import has been successfully finished.
6. If you are restoring to the same database/server that the backup was made from, make sure that the corresponding files have also been restored (including the /system directory).
Upgrading ExpressionEngine
EllisLab is always working on new versions of ExpressionEngine. These versions are often packed full of new features as well as security updates and bug fixes. Occasionally, EllisLab will put a price on a new feature (such as the discussion forum). However, the prices are very fair, and reflect the cost of development and support. Doing this keeps the cost of ExpressionEngine itself lower for those users who have no interest in the new feature.
There are two types of releases that ExpressionEngine goes through: •
A new build contains bug fixes or minor updates. It is generally not necessary to upgrade to a new build unless it contains a bug fix that you have been waiting for. Builds are numbered by date, and you can see what build you have in the footer of any page in the control panel.
•
A new version contains new features and improvements to existing functionality. A new version will include all the bug fixes and minor updates of any intermittent builds. Versions are numbered sequentially (such as 2.0.0, 2.0.1, 2.0.2, 2.1.0, and so on).
[ 267 ]
Extending ExpressionEngine
When a new version is released, ExpressionEngine will indicate this prominently on the control panel home page.
When upgrading, you can skip builds, but it is not recommended to skip too many versions. Not only will you miss out on security updates, bug fixes and new features, but if you seek support in the forums and there are significant changes between your version and the current version, you may be asked to upgrade. The instructions for updating to the latest build can be found at http://www. expressionengine.com/user_guide/installation/update_build.html and the instructions for updating to the latest version can be found at http:// www.expressionengine.com/user_guide/installation/update.html. The
instructions are basically the same, except that for a new build, you do not have to run the server update wizard. The basic instructions for upgrading to a new version are as follows: 1. Download the latest version of ExpressionEngine. Read the version update notes (step 5 at http://www.expressionengine.com/user_guide/ installation/update.html) to verify there are no changes that might have a big impact on the specific website that is being updated—for example, a compatibility issue with an add-on that is used. 2. Perform a backup of the database and ideally back up your entire website, including the system, themes, and images directories as well as the index. php file (located in the root directory of your website—though it may have been renamed as part of the ExpressionEngine installation in Chapter 1, Introduction to ExpressionEngine). 3. Take your website offline. ExpressionEngine includes an offline.html template in the /system/expressionengine/utilities/ directory that you can modify and copy to the root of your website. Rename your index. php to index_old.php and then rename offline.html to index.php. 4. If you chose to rename index.php as part of your ExpressionEngine installation, then replace the renamed file with the offline.html template instead.
[ 268 ]
Chapter 10
5. Clear your cached data. Log in to the control panel and select Tools | Data | Clear Caching. Select All caches, and click Submit. 6. On your website, rename your system and themes directories to system_old and themes_old. By keeping the directories on the server for now, it makes it easier to roll back the update if, for some reason, an issue is encountered. The official update instructions recommend renaming the new files being uploaded first, then renaming the existing files after the new files are uploaded, and finally renaming the new files to the names of the original files. This is equally effective and potentially minimizes downtime (if you wanted to keep the website up while the new files are being uploaded).
7. Upload the system and themes directories from the new ExpressionEngine version to your website. You will upload the index.php file right before the upgrade so that, for now, your website continues to reflect that it is offline. If you use additional control panel themes, such as Corporate, Fruit, or the Mobile theme, you will also need to download these themes from http://www.expressionengine.com/ and upload them to the /themes/cp_themes/ directory.
8. From the backup of your old system directory, upload the following directories to your new system directory: /system/expressionengine/third_party/ /system/expressionengine/config/ /system/expressionengine/templates/
9. Set the file permissions for /system/expressionengine/config/config. php and /system/expressionengine/config/database.php to 666 (writeable). Set /system/expressionengine/cache to 777 (writeable). 10. Now upload the index.php file, overwriting the offline template that you earlier saved as index.php. [ 269 ]
Extending ExpressionEngine
11. If this is a version update rather than a build update, point your browser to / system (for example, http://localhost/system or http://www.example. com/system) and follow the on-screen instructions to perform the update to the latest version.
12. After you see a message saying that you are running the most current version of ExpressionEngine, delete the /system/installer directory. 13. If you renamed your system directory, you will need to edit the newly uploaded index.php and update the $system_path = './system'; line towards the top of the file to reflect your renamed system directory. 14. If you mask the location of your control panel by accessing your control panel from a URL other than http://localhost/system/index.php (such as http://localhost/admin.php), you will also have to copy /system/ index.php and replace your masked-access file (such as /admin.php). Once you have done this, you will also have to update the $system_path = ''; line towards the top of the file to reflect the path to your system directory. 15. Follow the Version Specific Notes for any versions between the version you are updating to and the version you are updating from. The Version Specific Notes will contain details on any changes that need to be made above and beyond the normal upgrade changes just listed. For example, if additional files need to be uploaded, a theme or language pack has been updated, or if a new setting in the control panel needs to be defined, the Version Specific Notes is where you will find that out. If you have customized your own themes and the Version Specific Notes indicate that a theme was updated, you will have to manually update your theme with the same changes that were made to the built-in themes. Luckily, EllisLab is very good at identifying these changes in a version upgrade and at outlining what needs to be done.
16. Verify that your website is working as expected, and then delete the system_ old and themes_old directories, as well as the index_old.php file at the root of your website. [ 270 ]
Chapter 10
When you first log into the control panel, you will be warned that one or more core files have been changed—click to accept these changes. You may also receive an e-mail saying the same thing.
17. Finally, in addition to ExpressionEngine itself, modules you install (such as the Discussion Forum and Multiple Site Manager) can also be subject to new versions. For example, the discussion forum version update instructions can be found at http://expressionengine.com/user_guide/modules/forum/ forum_update.html.
ExpressionEngine add-ons
Although not open source software, ExpressionEngine has many ways in which both EllisLab and the members of the ExpressionEngine community can add to it. ExpressionEngine 2 is built on CodeIgnitor—an open source PHP web application framework also by EllisLab. CodeIgnitor is a popular framework for PHP developers, allowing rapid development of PHP web applications. For ExpressionEngine users, this means that add-on developers have the ability to build more complex add-ons (even entire applications) for ExpressionEngine by using CodeIgnitor. It also means that there is a much larger base of developers who can build ExpressionEngine add-ons. More developers building more and more complex add-ons for ExpressionEngine can only mean one thing. If there is something you need to do that is not supported natively, there is likely an add-on for it. The add-on market has grown hugely in the last few years and there are now several companies that have either started or been able to branch into developing and selling ExpressionEngine add-ons. Although this means that some add-ons come at a cost, it also means those same add-ons are likely to be high-quality, reliable tools to expand the functionality of ExpressionEngine. The best resource for ExpressionEngine add-ons is http://www.devot-ee.com/—an official EllisLab community partner.
Types of add-ons
ExpressionEngine add-ons come in five flavors, namely, modules, accessories, extensions, fieldtypes, and plugins. All add-ons are managed through the Add-Ons menu in the control panel—here you can install, uninstall, or access the configuration screens (if applicable). [ 271 ]
Extending ExpressionEngine
Modules
Throughout this book, you have been working with ExpressionEngine modules, including the Channel module, the Member module, the Comment module, and the jQuery module. A module can be simple and focused (that is, do one thing and do it well), or they can be close to applications in their own right, complete with their own control panel configuration screens and their own library of tags. Some modules are aimed at control panel users and do not add any visible functionality to the frontend of your website—an example is the Blacklist/Whitelist module, which allows you to block spammers from your website but does not change anything on your website. Other modules are designed specifically to add functionality to your website—they provide tags that can be used within templates so that you can control where this functionality appears and how it looks. The Search module works like this—it does not add any functionality to the control panel, but it allows you to add integrated searching capabilities to your website. Finally, there are modules that add functionality to both the control panel and your website. For example, the Mailing List module provides a control panel configuration screen where you can set up mailing lists and manage subscribers, and it also provides tags that you can use in templates to allow visitors to sign themselves up. Modules can read and write data to your database, making them a very powerful tool in an ExpressionEngine installation.
Accessories
Accessories are new in ExpressionEngine 2. They are the tabs that appear on the bottom of each control panel page.
ExpressionEngine comes bundled with the ExpressionEngine Info accessory installed and three other accessories that are included but not installed (Learning EE, News and Stats, and Quick Tips).
[ 272 ]
Chapter 10
To install a new accessory, you can go to Add-Ons | Accessories, and then click Install on the accessory (or accessories) of your choice (third-party accessories must be uploaded to the /system/expressionengine/third_party/ directory before they appear in this list to install). Once installed, clicking on an accessory name will open a preferences page where you can define which member groups can see the accessory and on what control panel pages the accessory appears. In this way, an accessory that is useful when creating templates (for example) can be set to appear only on Design pages of the control panel, and only to member groups that would be working with templates.
Building your own accessory is a great way to start getting into ExpressionEngine add-on development. One use for an accessory (if you build websites for clients) is that it can be used to provide easily accessible help and tips to your client, right inside the ExpressionEngine control panel.
Extensions
Extensions are a type of add-on that uses hooks within ExpressionEngine to modify how ExpressionEngine itself works. Unlike modules, extensions do not have tags that are used in templates. Instead, they modify aspects of how ExpressionEngine works. For example, there are extensions that allow you to change how CAPTCHA works, that allow you to change the page ExpressionEngine loads after a member logs in, and that allow you to change system messages so that they use a regular template instead of the template found under Design | Message Pages | User Messages. [ 273 ]
Extending ExpressionEngine
Like accessories, third-party extensions need to be uploaded to /system/ expressionengine/third_party/ before they can be enabled from the Add-Ons | Extensions control panel page. Most extensions will come with instructions on how to install them. ExpressionEngine does not come bundled with any extensions that are ready to go, but extensions are a very common type of add-on.
Field types
ExpressionEngine comes bundled with several different types of fields that can be used in entries. Throughout this book, you have used Text Input and Textarea extensively. You used File when building the photo gallery and you also used the Relationship field when building the calendar so that you could relate events in one channel to event sponsors in another. Fieldtype add-ons allow you to expand the range of fields that you can use for your channels.
Plugins
Plugins are the most basic form of add-on for ExpressionEngine. Unlike a module, plugins cannot store data in the database (though they may still query the database), and do not have their own control panels. Unlike an extension, plugins do not change the functionality of ExpressionEngine itself. A plugin works by making one or more tags available that can then be used in templates. Like other add-ons, third-party plugin directories need to be uploaded to /system/ expressionengine/third_party/ before they can be enabled from the Add-Ons |
Plugins control panel page. Clicking on the title of an installed plug-in will give you instructions on how to use it.
[ 274 ]
Chapter 10
Plugins exist for lots of nifty purposes—replacing text with other text, creating random text, converting kilograms to pounds, the list is endless. For EE2 compatible plugins and other add-ons, please visit http://www.devot-ee.com/.
Third-party add-ons and add-on developers
While there are far too many add-ons to list them all, what follows are some prominent add-on developers whose add-ons are worth knowing. This is not a comprehensive list, and it can be expected that different people would have different ideas regarding which add-ons are the most useful. Devot:ee is the best place on the web to find up-to-date information about add-ons, and EE Insider (http://www.eeinsider.com/) is another good site to follow for tips, information, and interviews on all things ExpressionEngine.
Pixel & Tonic http://www.pixelandtonic.com/
Although Pixel & Tonic is a relatively new company, Brandon Kelly has been building add-ons for many years, including the FieldFrame extension that became the basis of the Fieldtype add-on in ExpressionEngine 2. Several of Pixel & Tonic's add-ons are considered essential by ExpressionEngine developers, including: •
•
•
Matrix: This adds the ability to have tables in your channel entries. This is a huge improvement over using repeated textarea and text input fields for as many "rows" as you are likely to need. With Matrix, you can define the columns and in each entry, create as many rows as you need. Matrix can be used whenever tabular data is involved. One common use is to create photo galleries where each channel entry represents a gallery containing multiple photos (one per row) as opposed to having one photo per-entry (like you did when building the photo gallery in Chapter 8, Creating a Photo Gallery). Playa: This is a field type that works very similarly to the Relationship field that is built into ExpressionEngine, but instead of only allowing you to relate only one entry in another channel to your entry, Playa allows you to relate multiple entries in many other channels to your entry. Using the calendar example from Chapter 7, Creating a Calendar, you could have multiple sponsors for each calendar event, instead of being limited to picking just one (or having to create multiple Relationship fields). Wygwam: This adds WYSIWYG (What You See Is What You Get) functionality to ExpressionEngine's publish page. Instead of plain-text fields on the Publish page, Wygwam allows you to create content using wordprocessor-like functionality—you can add images, format, and layout the text just like you would in a word processor. [ 275 ]
Extending ExpressionEngine
Solspace http://www.solspace.com/
Solspace is a leading add-on developer for ExpressionEngine. Their work includes: •
Tag: A module that allows you to tag channel entries and organize your content by tag. You can also build a tag cloud.
•
FreeForm: A module that makes it easy to create and manage forms that collect information from your visitors.
•
User: A module that overhauls ExpressionEngine's native member functionality, bringing the default member templates into regular templates and making them much easier to customize and brand.
•
Facebook Connect: A module that adds Facebook SSO (Single Sign-On) capabilities to your website.
•
Super Search: This is a module that overhauls ExpressionEngine's native search functionality, improving the performance and allowing results to be sorted by relevance.
•
Friends: A module that updates the member functionality to be more like a social network. Members can invite each other to become friends, they can restrict their profile so that it is only visible to their friends and they can post status updates similar to Facebook or LinkedIn (at the time of writing, this module was not yet compatible with EE2).
•
Calendar: A full-featured calendar that goes far beyond what is possible with ExpressionEngine's built-in calendar functionality (the main improvement being the addition of recurring events—a key requirement of most calendar applications) (at the time of writing, this module was not yet compatible with EE2).
Newism (Leevi Graham) http://www.expressionengine-addons.com/
Newism is the author of many very popular ExpressionEngine 1 add-ons. Newism's add-ons include: •
NSM Addon Updater (previously LG Addon Updater): This accessory works with other compatible add-ons to let you know when a new version of the add-on is released. Each compatible add-on is listed in an accessory tab, along with the installed version and the latest available version.
[ 276 ]
Chapter 10
•
NSM Better Meta (previously LG Better Meta): This extension makes it easy for you to generate unique HTML meta tags for each entry without having to create custom fields in each of your channels for the meta tags (such as description, keywords, author, and so on). By having unique meta tags on your pages, your website is more search-engine friendly, potentially making it easier for people to find you through search engines. The extension can also generate search engine XML sitemaps.
•
NSM TinyMCE (previously LG TinyMCE): This is a free WYSIWYG custom field type, similar to Wygwam.
•
NSM Transplant (previously LG Replace): When creating new entries on the Publish page, this plugin allows you to insert the contents of one custom field inside the contents of another custom field. For example, if you have one or more image fields and a textarea field, you could insert a tag (called a needle) inside the text area so that the images appear within your text. (In your template, you can only place custom fields before or after each other, not inside each other).
•
NSM Live Look (previously LG Live Look): This extension allows you to view what your entry will look like on your website, directly from the Publish page.
Low (Lodewijk Schutte) http://www.loweblog.com/software/
Low has created many ExpressionEngine add-ons, including Low NoSpam, which will check comments, forum posts, and wiki articles submitted to your site against a service such as Akismet or TypePad AntiSpam to see if the submission is spam. Low Variables is another add-on that builds upon and improves ExpressionEngine's native variable management, allowing you to hide variables from other control panel users on a per-variable basis, as well as allowing you to group, sort, and label them.
nGen works http://www.ngenworks.com/software/ee/
nGen Works have built a number of ExpressionEngine add-ons, of which one of the most popular is Structure (http://www.buildwithstructure.com/). Structure bypasses the template structure of the standard ExpressionEngine website and instead allows you to define static and dynamic pages in an easy-to-use site-map view.
[ 277 ]
Extending ExpressionEngine
Other notable add-ons
The following add-ons can also be useful when building ExpressionEngine websites: •
Template Variables (by Matthew Krivanek) is a third-party accessory that displays the custom field names, snippets, and global variables that are on your site, so that you never again forget what you called a particular field, snippet or variable. The accessory includes quick links to add or edit custom fields, snippets, and global variables. Clicking a name copies the syntax onto the clipboard for easy pasting into a template (http://www.devot-ee.com/ add-ons/template-variables/).
•
Image Sizer (by David Rencher) is plugin that makes a template tag available which, when wrapped around an HTML tag, will resize the corresponding image to the size specified in the parameters and cache the resized image. This means that instead of having to require images to be of a certain size when they are uploaded to ExpressionEngine, they can be dynamically resized from within the template the first time the template is accessed. The plugin has won Devot:ee's AcademEE Plugin of the Year award multiple times (http://www.devot-ee.com/add-ons/imagesizer/).
•
First Timer (by Ryan Irelan) is an extension that allows you to alter where members are redirected to after they log in (http://www.devot-ee.com/ add-ons/first-timer/).
•
Backup (by Thomas Myer) is a module that makes it easy to do a database backup and download the file right from within the ExpressionEngine control panel—no logging into phpMyAdmin needed (http://www.devotee.com/add-ons/backup/).
•
Accessible Captcha (by Greg Salt) is an extension that changes the graphic CAPTCHA to a random question & answer system that plays well with screen-readers in a way that image-based CAPTCHAs do not. It works in much the same way as a regular CAPTCHA—making it easy for a person to complete the question, but making it difficult for an automated script to do so (http://www.devot-ee.com/add-ons/accessible-captcha/).
•
MD Detect Page Type (by Ryan Masuga) is a plugin that can be used in a template to detect what type of page is being rendered. This makes it easy to build conditional statements based on whether a page is a basic multipleentry page, a category page, a paginated page, an archive page or a singleentry page, and therefore makes it easier to use a single template for some or all of these scenarios (http://www.devot-ee.com/add-ons/md-detectpage-type/).
[ 278 ]
Chapter 10
•
Custom System Messages (by Brian Litzinger) is an extension that allows you to change the template that system messages are displayed with, allowing your system messages to share the same layout as the rest of your website and allowing you to use the full range of ExpressionEngine tags on the page (http://www.devot-ee.com/add-ons/custom-systemmessages/).
•
Channel Images (by DevDemon) is a module/extension that improves upon ExpressionEngine's native file manager functionality, including features such as multi-select image uploads from the control panel (http://www.devotee.com/add-ons/channel-images/).
•
Search Results (by Planet/EE) is a module that improves upon ExpressionEngine's default search capabilities, allowing you to group and sort search results, highlight search terms, use custom fields in search results, and more (http://www.devot-ee.com/add-ons/search-results/).
•
Cartthrob (by Chris Newton) and FoxEE (by HCC Development) are both full-featured shopping cart modules. (At the time of writing, they are not yet available for ExpressionEngine 2; http://www.devot-ee.com/add-ons/ cartthrob/ and http://www.devot-ee.com/add-ons/foxee/).
There are many more add-ons available for ExpressionEngine—more than can possibly be listed here. If there is something you wish ExpressionEngine could do (or could do differently), search the add-on library at http://www.devot-ee.com/ first.
Optimizing ExpressionEngine
Out-of-the-box, ExpressionEngine works very well, but on larger sites that attract more traffic, there are several options to fine-tune that can help you keep ExpressionEngine humming.
[ 279 ]
Extending ExpressionEngine
Spam
One downside of any website that allows members of the public to submit content is spam. Spam can take many forms, including comment spam, forum spam, and member registration spam (where spammers register as new members on your site and then place links in their profile pages), Luckily, ExpressionEngine has several tools you can use to combat spam, many of which are outlined in the ExpressionEngine documentation at http://www.expressionengine.com/user_ guide/general/spam_protection.html. Suggestions include: •
Use the blacklist/whitelist module to keep known spammers from your website and prevent content (in comments or member profile fields) that matches anything in the blacklist from being submitted. There is a oneclick option to download the latest blacklist from ExpressionEngine and you can also add items to the blacklist/whitelist that may be unique to you (downloading the list will not overwrite anything you add manually). The bottom line is that there is no reason not to use this module. (This module can be found in Addons | Modules in the control panel).
•
Require all comments to be moderated, require membership in order to post comments, or enable CAPTCHA for comment postings. If nothing else, you should ensure that you are set up to receive e-mails whenever comments are posted. All these settings can be found under Admin | Channel Administration | Channels for each channel.
•
Enable membership CAPTCHA (under Members | Preferences) or require all new member registrations to be activated manually by an administrator (though even administrators may not be able to spot spam registrations).
•
Disable New Member Registrations entirely (under Members | Preferences) if you do not plan to use the member features of ExpressionEngine. Remember that this feature is enabled by default, meaning that even if your website does not link to the member URLs, the member URLs are active. [ 280 ]
Chapter 10
•
Use Word Censoring (under Admin | Security and Privacy | Word Censoring), which allows you to replace any user-submitted word (or partial word) with the # symbol (or a word of your choice).
•
Apply Rank Denial (under Admin | Security and Privacy | Security and Sessions). This makes your website less attractive to spammers because user-submitted links point to a redirect page on your own site rather than pointing directly to the spammer's site. This means that any links posted to your website will not improve the spammers search engine page rank.
•
To prevent Denial of Service attacks, ExpressionEngine has Throttling Preferences (under Admin | Security and Privacy) that allow you to set how many pages can be downloaded in a given time period by a single person before that person is temporarily locked out.
•
Other recommendations in the documentation include setting a longer Comment Time Interval in the preferences for each channel (to prevent spammers from submitting hundreds of comments in a short space of time), using Secure Form Mode in the Security and Session preferences to prevent the same form being submitted multiple times without being refreshed and Deny Duplicate Data (also in the Security and Session preferences) to prevent the same comment being made more than once.
•
Finally, in addition to ExpressionEngine's built-in features, there are also several add-ons including Accessible CAPTCHA, Low NoSpam, and No Follow, all designed to make your website less attractive to spammers. Search for these and others at http://www.devot-ee.com/.
In summary, none of these options are a perfect solution, and there is certainly a trade-off between functionality and anti-spam controls. For example, requiring membership to post comments does not prevent a member from posting spam in comments but it at least provides an extra layer of protection.
Performance
ExpressionEngine is database-driven, and for most websites, the performance is excellent out of the box. With that said, if you are expecting high traffic volumes, it is worth being aware of (and following) good design practices as you build your website. The most fundamental technique that you can use to reduce template load times is reducing the number of ExpressionEngine tags in a template. A template that uses multiple embedded templates, nested conditionals, add-ons, and so forth involves more database queries and so will take longer for ExpressionEngine to render than a simple template with only a handful of standard ExpressionEngine tags. [ 281 ]
Extending ExpressionEngine
Other techniques to reduce page load times include the following: •
Use embedded templates, snippets, and global variables appropriately. An embedded template comes with all the overhead of rendering a template, whereas a snippet does not. So, if a snippet can be used instead of an embedded template, it should be.
•
Use the Disable Parameter liberally. By default, the {exp:channel:entries} tag fetches all the information about the channel entry that is stored in your database (including category information, member data, and the data in the custom fields). In many cases, you do not use all this data, so there is no point in retrieving it from the database. The disable parameter allows you to reduce the number of database queries by turning off queries for certain types of data. For example, you used this parameter when retrieving the entry title for the HTML in your single-entry templates. Since you only needed the title of the entry (which is not a custom field), disabling all the extra database queries made sense: disable="categories|category_fields|custom_fieldsmember_ data|pagination".
For more information on the disable parameter, visit http://www. expressionengine.com/user_guide/modules/channel/ parameters.html#par_disable.
•
Use Simple Conditionals instead of complex conditionals. A simple conditional is an if statement that evaluates one condition and does not have any if:else clauses. A simple conditional is parsed early, meaning that any ExpressionEngine tags within the simple conditional are ignored if the condition is false. More complex conditional statements (involving multiple conditions or multiple else clauses) are parsed later, meaning any ExpressionEngine tags within them are parsed, even if the condition turns out to be false.
•
Consider enabling GZIP output. This option (under Admin | System Adminstration | Output and Debugging Preferences) compresses website pages (which are then decompressed seamlessly by most modern browsers). This can result in faster download speeds.
•
Optimize ExpressionEngine's SQL tables. Under Admin | Utilities | SQL Manager, select Manage Database Tables, select all tables, and click Optimize. When run from time to time, this can help make database queries faster by eliminating database fragmentation.
[ 282 ]
Chapter 10
ExpressionEngine also includes a variety of different types of caching that can help improve performance by minimizing the number of queries needed to render a template. The benefits of enabling these options can vary depending on the server the website is hosted on (if the server already has caching enabled, then enabling caching within ExpressionEngine may cause double-caching and therefore an increase in load). More information can be found at http://www. expressionengine.com/user_guide/general/caching.html. ExpressionEngine caching is useful to reduce the number of database queries that a specific URL creates (such as your home page). However, caching is done by URL, meaning that for each new URL, a new cache is created, even if the elements on the pages at two different URLs come from the same template. Given that a single template can be the basis of hundreds or thousands of URLs (depending on the number of channel pages), websites with a lot of traffic spread over a large number of URLs may not see much benefit in page load times by caching, even if the traffic is concentrated on a small number of templates.
For sites with high traffic loads, the documentation also includes information on how to further optimize ExpressionEngine by turning off tracking and minimizing Disk I/O. Please see http://www.expressionengine.com/user_guide/general/ handling_extreme_traffic.html for more information. Solspace offers a Site Performance Evaluation for ExpressionEngine sites (http://www.solspace.com/development/ performance/) that may be worth considering for large, high-traffic websites.
Summary
In this chapter, you learned about the routine maintenance tasks that come with running a powerful database-driven website (such as database backups and software upgrades). You learned about the different types of add-ons that ExpressionEngine accommodates, and about specific add-ons and add-on developers that are worth being aware of. Finally, you learned about optimizing ExpressionEngine to fight spam and improve page-load times. The key points to remember after working through this chapter (and the book) are: •
Back up your website, including the database.
•
Upgrade ExpressionEngine when new versions are released (or at least every few versions). If you continue to use an older version, you will not have all the latest features and bug-fixes, and newer add-ons may not be compatible. [ 283 ]
Extending ExpressionEngine
•
ExpressionEngine is highly extensible, and many of the add-ons are highquality commercial grade pieces of software. If there is something you wish ExpressionEngine could do, research the add-on library first.
•
The ExpressionEngine documentation is an excellent resource—clear, concise, accurate, and with plenty of examples. It is a great way to learn about a new feature (or to learn more about a feature you are already familiar with).
•
Visit the ExpressionEngine support forums often (http://www. expressionengine.com/forums). If there is something you are trying to accomplish, the chances are good that someone else has tried the same thing. A quick search can often reveal lots of ideas. The how-to forum is a great place to get ideas, seek advice, or even get feedback.
[ 284 ]
Installing WampServer In this appendix, you will walk through downloading, installing, and setting up WampServer. This will allow you to run ExpressionEngine on your own computer. If you already have WampServer installed (or an alternative product such as XAMPP or MAMP for Mac OS X), then you can skip these instructions. WampServer is a free package that includes an easy-to-set up web server (Apache), database server (MySQL), and server-side scripting language (PHP), all of which are requirements of ExpressionEngine. Installing WampServer lets you experiment with ExpressionEngine on your own computer instead of a live website. Setting up each piece of an Apache, MySQL, and PHP (AMP) environment individually can be complicated, but with WampServer, the system comes pre-configured and ready to go, so you can concentrate on learning ExpressionEngine. You are installing WampServer as a development (or testing) environment only. You will not be using WampServer to build a live server that presents your website to the outside world. Setting up and securing a production web and database server is a topic beyond the scope of this text.
WampServer is a Windows only package. If you are using Mac OS X, MAMP is a good alternative (http://www.mamp.info). XAMPP is another alternative that is available for Windows, Linux, Mac OS X, and Solaris. If you choose to use an alternative package, the installation instructions for that package are going to be different and there may be some differences when you install and configure ExpressionEngine on your server in Chapter 2, Getting Installed. However, ExpressionEngine itself will work exactly the same.
Installing WampServer
WampServer is free to download, and the package contains the following: •
The AMP environment of Apache, MySQL, and PHP (needed to install ExpressionEngine)
•
phpMyAdmin, which is the leading web-based interface to MySQL (needed to manage the ExpressionEngine database)
Installing WAMPServer First, you must download WampServer:
1. Visit http://www.wampserver.com/en 2. On that page, there will be a link to the download page of WampServer. Select it and you should see a link to download WampServer. 3. Clicking the download link will take you to SourceForge.net where you can download the file. The file download should begin automatically, but if it does not start, there should be a direct link that you can use to start the download. If you have Internet Explorer 7 or higher, it may block the site from downloading files to your computer. A warning will appear in a small bar at the top of your browser screen. Click on it and select Download File.
4. Next you will be prompted to save the file. Save it to your Downloads, Desktop, or My Documents area. Depending on the speed of your Internet connection, the file may take some time to download. Now that you have downloaded the software, the next step is to install it. If you are running the Skype VOIP application, or IIS Server, you will need to exit them before proceeding. Apache cannot start as a service if Skype or IIS is also running as they all use port 80. If you have Skype, you can set it to no longer use port 80 by going into the Advanced page of the options screen in Skype.
1. Double-click on the file that you downloaded in order to run it. If you get a Windows security warning, click on Run. 2. A welcome screen will display. Click on Next.
[ 286 ]
Appendix A
3. A license agreement screen will display. WampServer is an open source software package released under the GNU General Public License. Accept the license agreement. 4. WAMPServer, by default, installs in C:\wamp, and that is where this book will assume it is installed.
5. Select whether you would like a Quick Launch or Desktop icon, then click on Next. 6. A summary screen will display, showing where WampServer will be installed. Click on Install.
[ 287 ]
Installing WampServer
7. The installation will take a few minutes to run, during which you will see all the files being extracted. After all the files have extracted, a dialog box will appear asking you to pick your default browser (this is used by WampServer to know what browser to use when you use WampServer shortcuts to open your website; it does not prevent you from using other browsers installed on your machine if you later wish to do so). If you have Firefox installed, it will ask if you wish to use Firefox. If you do not, browse to Internet Explorer (typically located in C:\Program Files\Internet Explorer\iexplore. exe). Click on Open.
8. The installation will run for a little longer, and then you will be prompted for your PHP mail parameters. Although ExpressionEngine does make use of e-mail (for example, when registering new members), it is not an essential part of this book. If you have an SMTP server you can use, feel free to enter the information, otherwise accept the default settings. Click on Next.
[ 288 ]
Appendix A
9. Finally, leave the checkbox to launch WampServer checked and click on Finish.
WampServer is now installed and running.
Using WampServer
When WampServer is running, you should see a new icon on your taskbar next to the clock. Clicking on this will produce a menu with useful links. (If you do not see the icon, try launching WampServer again by clicking on start WampServer under WampServer in your Start menu).
[ 289 ]
Installing WampServer
Localhost will launch your website (you can also access your website by visiting http://localhost/ in your browser). phpMyAdmin is used to manage your website databases, and we will use it in Chapter 2 to set up the database that ExpressionEngine will use. www directory will open C:\wamp\www in Windows Explorer. Any files placed in this directory will be visible on your website. This directory is therefore where you will place your ExpressionEngine installation files. The other options allow us to control the different services individually. You can stop and start services individually (or stop and start all services). You can also switch between versions and change settings specific to each service. By default, when you visit http://localhost/, you will see a WampServer home page. If you are using Internet Explorer and see a message at the top of your screen that says Intranet settings are now turned off by default, left-click on it and select Don't show this message again.
In order for us to develop our website, you should delete this welcome page.
[ 290 ]
Appendix A
This welcome page displays configuration information about your PHP installation. A comprehensive view of the same information can be accessed from within the ExpressionEngine control panel (under Tools | Utilities | PHP Info).
1. Navigate to C:\wamp\www and delete the file index.php. 2. In your browser, navigate to http://localhost/, and you should now see an empty directory listing.
Allowing .htaccess files to be used
To take advantage of some features in ExpressionEngine (such as removing the index. php from ExpressionEngine URLs), you need to use a .htaccess file, which requires the Apache module mod_rewrite to be enabled. 1. Left-click the WampServer task bar icon, click Apache | Apache Modules, and then scroll down the list of modules until you see the rewrite_module. Left-click on the rewrite_module option to enable it.
[ 291 ]
Installing WampServer
It will take a few seconds for it to enable, but then your .htaccess files will be recognized; you will be using them in Chapter 2, Getting Installed.
Summary
In this appendix, you walked through the installation of WampServer, one of several products available for simulating an Apache, MySQL, and PHP environment on your computer. Other alternatives include XAMPP and MAMP (for Mac OS X). The key points to remember after working through this appendix: •
Your website can be accessed in a browser at http://localhost/.
•
To upload files to your local website, you have to save them in C:\wamp\www.
[ 292 ]
Solutions to Exercises Most of the exercises throughout this book have more than one solution. The following are the example solutions to some of the exercises in this book. Where a solution has not been provided, the instructions in the chapter can be adapted to complete the exercise. Chapter 3, Exercise 1 To limit the entries that are displayed to 2, you need to edit the channel tag to read as follows: {exp:channel:entries channel="news" limit="2"}
Chapter 3, Exercise 2 To post a new entry to a channel, log into the control panel at http://localhost/ admin.php (or http://localhost/system/index.php), and select Content from
the menu at the top of the screen. Highlight Publish and then select the channel you wish to post to (in this case, News), and type in the new entry. Select an image and then click Submit when you are done. Chapter 3, Exercise 3 To edit an entry, you can either select Content from the main menu, then select Edit, or you can select Entry under Modify or delete. Click on the entry you wish to edit and then edit away.
Solutions to Exercises
Chapter 3, Exercise 4 Try searching for html css tutorials in your favorite search engine. A couple of good resources include: • •
http://www.htmldog.com/guides/ http://www.w3.org/Style/Examples/011/firstcss
If you prefer learning from a book, pop down to your local bookstore's Computing & Technology section, and you will find plenty of books. Look for ones that focus on HTML and CSS, rather than other software applications (such as Dreamweaver). Chapter 4, Exercise 1 To create new pages, select Content | Publish | Website and copy in the text from the corresponding static HTML file. Add in HTML tags for the headings (), links (using {site_url}), and italic (<em>) where appropriate, and remember that you can choose the previously uploaded picture, rather than uploading the picture again. Make sure that the URL title for each entry matches the URL title in the table below. Next, create the following template groups and select to duplicate the site template group. Then edit the index template of each group and adjust the url_title parameter to be as follows: Template Group Name
URL Title
business
small_business
contact
get_in_touch
promotion
promotion
Notice how when you enter e-mail addresses into the Contact Us entry, they are automatically converted to links on your page. The links are automatically encrypted using JavaScript to make it harder to harvest by spambots.
Chapter 5, Exercise 1 To set the amount of time to show a comment, go to Admin | Channel Administration | Channels. Select the FAQs weblog and click Edit Preferences. Select Comment Posting Preferences and change the Comment Expiration field to 60. Optionally, check the box to update existing comments with this setting and then click Update.
[ 294 ]
Appendix B
Chapter 5, Exercise 2 To include the author and the date of a post, update the line of code that reads
<strong>Q: <em>{faqs_question}
in both the faqs/ index and faqs/browse templates to read as follows: <strong>Q: <em>{faqs_question}
<strong>Posted by {author} on {entry_date format="%m/%d"} p>
More information about the different types of dates that you can display in your entries can be found at http://www.expressionengine. com/user_guide/modules/channel/variables.html#date_ variables. More information about date formatting code can be found at http://www.expressionengine.com/user_guide/ templates/date_variable_formatting.html.
Chapter 5, Exercise 3 If your installation included Agile Records, then you will already have a custom status called Featured. If you are using the blank installation, then you will need to create such a custom status. To create it, go to Admin | Channel Administration | Custom Status Groups, click Add/Edit Statuses, and then click Create a New Status on the top right. Call the new status Featured and click Submit. Before you update your snippet, you should first make at least three of the entries in your channel Featured entries. To do this, edit an entry and select the Options tab. Under Status, change the status to Featured. Next, update the snippet code to include a new parameter which says that the status must be featured in order to display. {exp:channel:entries channel="faqs" limit="3" orderby="random" dy namic="off" status="featured"}
[ 295 ]
Solutions to Exercises
Finally, you have to update the faqs/index, faqs/browse (both in the title and in the body of the page), faqs/rss and faqs/atom to display featured entries in these templates. By default, ExpressionEngine will only display entries with an open status—if you want to display entries with a different status, you have to explicitly tell ExpressionEngine to do so. Modify any {exp:channel:entries} tags in these templates to have the status="Open|Featured" parameter as in this example: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Featured"}
Chapter 6, Exercise 1 To create a new member group that can only modify templates, go to Members | Member Groups and select Create a New Member Group. Call the new member group Designers. Click on Control Panel Access and say Yes to accessing the control panel, and Yes to the design section. Under Template Editing Privileges, select which templates can be edited (business, contact, faqs, includes, individual, promotion, and site). Click Submit. Next, select Members | Register Member and create a new member in the Designers member group. Log in as the new member and verify that it works as expected. Chapter 6, Exercise 2 To create a custom member field, you go to Members | Custom Member Fields. Select Create a New Member Field. Choose a field name of existing_customer and a field label of Are you an existing customer of Ed & Eg?. Change the field type to Select List and enter two options (one on each line)—Yes and No. Leave Text Formatting set to None. Say Yes to this being a required field, No to the field being visible in public profiles, and Yes to being visible in registration pages. Click Submit. Log out of the control panel, then visit your website and click Register. You should see the new field on the registration screen.
[ 296 ]
Appendix B
Chapter 6, Exercise 3 Copy the includes/404 template code and then edit the promotion/index template (created as part of the exercises in Chapter 4, Moving a Website to ExpressionEngine). At the top of the template, add a line of code that says {if logged_in}. Underneath the {embed} line, add in another line of code that says {if:else}. Underneath this, paste in the code from includes/404. Then modify the
and the to reflect that you are on the Promotions page rather than the 404 page and modify the paragraph of text to indicate that promotions are available to members who are logged in only. Finally, at the very end of the template, add a closing {/if} tag. The overall template structure will be as follows: {if logged_in} {embed="includes/.website_page" url_title="promotion"} {if:else} [Modified template code from includes/404] {/if}
Chapter 7, Exercise 1 To modify how the days of the week in the calendar are displayed, you need to edit the code in between the calendar_heading tags in the calendar/index template to read as follows: {calendar_heading}
{lang:weekday_short} {/calendar_heading}
Another alternative is to use {lang:weekday_long}, which will output the full name
of the day (such as Friday). Chapter 7, Exercise 2
To display the next event that is coming up underneath your calendar, you need to use the {exp:channel:entries} tag with two parameters, namely, dynamic="off" and start_on="{current_time format='%Y-%m-%d %H:%i'}".
[ 297 ]
Solutions to Exercises
The dynamic="off" parameter decouples the channel entries being displayed at the URL. By default, the channel tag will look at the URL of the page you are on to determine the entries to display. So, if you were viewing May 2012 (and the URL was http://localhost/calendar/2012/05), your {exp:channel:entries} tag would also only display entries from May 2012. dynamic="off" means that the channel will display any entry from your channel, regardless of the URL. The second parameter is start_on="{current_time format='%Y-%m-%d %H:%i'}". The current_time is a system global variable for the current time on the server. The start_on parameter says that you only want to display channel entries with an entry date on or after the date you provide—in this case, the current date. This means that events in the past will not be displayed—you will only display events that are yet to happen. Read more about global variables at http://www. expressionengine.com/user_guide/templates/globals/ single_variables.html and read more about the start_on parameter at http://www.expressionengine.com/user_ guide/modules/channel/parameters.html#par_start_on
Insert the following code after the {/exp:channel:calendar} tag and immediately before the tag in the calendar/index template: Upcoming Event
{exp:channel:entries channel="{my_channel}" limit="1" re quire_entry="yes" show_future_entries="yes" sort="asc" dynamic="off" start_on="{current_time format='%Y-%m-%d %H:%i'}"} {if no_results}
No Upcoming Events
{/if} <strong>{title}
<em>{entry_date for mat="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{if events_description} {events_description}
{/if} {if events_sponsor} {related_entries id="events_sponsor"} More About Our Sponsor: {title}
{if event_sponsors_about} {event_sponsors_about}
{/if} {/related_entries} {/if} {/exp:channel:entries} [ 298 ]
Appendix B
Chapter 8, Exercise 1 Limiting the number of photos and randomizing them simply requires adding parameters to the {exp:channel:entries} tag in the photos/index template. This also limits the number of photos that will display in each category, so you want to be sure not to add more photos in a given category than the limit you set here. Alternatively, you can use pagination so that if there are more photos than the limit, they display on separate pages. {exp:channel:entries channel="{my_channel}" or derby="random" limit="10"}
Chapter 8, Exercise 2 To track the number of single-entry page views, you must first add a parameter to the {exp:channel:entries} tag in your single-entry page template (photos/ comment). ExpressionEngine offers four view counters that can be added to different single-entry pages, helpfully numbered one through four. Since you only have one single-entry page, you can use view counter one. {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes" status="Open|Premium" track_views="one"}
Next, add a conditional statement to your multiple-entry page (photos/index), immediately after the code that displays how many comments there are and before the :
{if view_count_one>="10"}***Popular***{/if}
The second
helps keep the photo thumbnails aligned, when some are considered popular and some are not.
Note that the view counter is not incremented when a photo is viewed in the lightbox because the lightbox is displaying the actual image file and not the single-entry template.
[ 299 ]
Solutions to Exercises
For channel entry view tracking to work, it must be enabled in Admin | Security and Privacy | Tracking Preferences (by default, it is enabled). The single-entry template in question must also not have caching enabled (by default, caching is disabled). To change the caching preferences of a template, select Preferences from either the Template Manager or the Edit Template screens. For more information on entry view tracking, please see http://www.expressionengine.com/ user_guide/modules/channel/entry_tracking.html.
Chapter 8, Exercise 3 When extracting code that is repeated, you must decide on the best tool to use. In this case, since you use this repeated code in more than one template, Preload Text Replacements are automatically ruled out (since they can only be used in the template in which they are defined). Global variables are also not an option here because the code contains ExpressionEngine tags such as {exp:comment:form}. The choice, therefore, comes down to Snippets or Embedded Templates. Snippets are preferable if the code is identical, regardless of which template might be using it. Embedded Templates are useful if you need to pass in variables to account for small variances in the code. In this case, the {exp:comment:form} requires you to define the preview template. Since this is different for the FAQs channel versus the Photos channel, you will need to use an Embedded Template and pass in the preview template information as a variable. First, create a template called .comment in the includes template group. The preceding dot means that the template is hidden and cannot be accessed directly. The template type should be Web Page. In the .comment template, copy in all the code from photos/comment from Comments
all the way down to {/exp:comment:form}. Change the {exp:comment:form} line to read {my_template_group} and {my_single_entry_ template} as embedded variables rather than Preload Text Replacements: {exp:comment:form pre view="{embed:my_template_group}/{embed:my_single_entry_template}"}
Click Submit to save the new template. Now edit faqs/browse and photos/ comment and replace all the code from Comments
all the way down to {/ exp:comment:form} with the following: {embed="includes/.comment" my_template_group="{my_template_group}" my_single_entry_template="{my_single_entry_template}"}
[ 300 ]
Appendix B
Both the faq/browse and photos/comment templates have Preload Text Replacements for {my_template_group} and {my_single_entry_template}. This line simply passes these text replacements to the embedded template. In this way, even though both the Photos and FAQs channel are using the same chunk of code to display comments, if a member chooses to preview their comment, they are redirected to the appropriate template based on the channel. Visit both the FAQs and Photo sections of your website, and you should see no difference in the functionality of viewing, previewing, and posting comments. The only difference is that now your single entry templates contain a lot less code and if you ever want to change the comment form, you can do so in one template, instead of having to go through multiple templates. Reducing repetition in this way is a powerful feature of ExpressionEngine, and it makes websites easier to maintain.
[ 301 ]
Index Symbols 404 Page improving 140 404 Page not found 98 {exp:search:advanced_form} tag 235 .htaccess files allowing, to be used 291, 292 {site_url} variable 87
A Accessible Captcha extension 278 accessories 272, 273 add-ons, ExpressionEngine about 271 accessible Captcha extension 278 accessories 272, 273 add-on developers 275 backup module 278 Cartthrob module 279 channel images add-ons 279 channel images module/extension 279 custom system messages extension 279 extensions 273 field types 274 first timer extension 278 FoxEE module 279 image sizer plug-in 278 Low (Lodewijk Schutte) 277 MD detect page type plugin 278 modules 272 Newism (Leevi Graham) 276 nGen works 277 notable add-ons 278, 279 Pixel & Tonic 275
plugins 274, 275 resources, URL 271 search results module 279 Solspace 276 template variables accessory 278 third-party add-ons 275 types 271 advanced search form, Search module 235, 236 Agile Records website 37 Atom feed about 136 and RSS feed, differences 139 creating 139 setting up 136-139
B backup module 278 backups, ExpressionEngine 263-265 banned member group 155 Blacklist/Whitelist module 259 blank calendar template creating 179 Body field 46 build release 267
C caching 283 calendar blank calendar template, creating 179 calendar CSS template, creating 183, 184 creating 179-182 designing 173, 174 events, displaying 191-195 exercise 196
formatting, with CSS 183 solution 297 styles, adding to calendar CSS 184-187 weblog, creating 207 calendar CSS styles, adding to 184-186 calendar CSS template creating 183, 184 Calendar module, Solspace 276 calendar template blank calendar template, creating 210 blank calendar, creating 182 CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) 123 Cartthrob module 279 categories about 64 browsing page, distinguishing 132, 133 creating 108-111 data, organizing 129, 130 displaying, with entries 130, 131 related entries, displaying by 133, 134 categories, photo gallery channel creating 205, 206 category browsing page distinguishing 132, 133 channel categories 64 categories, creating 108-111 content, creating 75-77 creating 63 custom channel fields, creating 105-107 custom field group, creating 65 custom fields 64, 65 custom fields for event sponsors, creating 174, 175 custom statuses 64 designing 104, 105 events custom fields, creating 176, 177 event sponsors channel, creating 175, 176 example events, creating 177-179 first custom field, creating 66 Information Pages channel 45 new channel, creating 73, 74 new channel. creating 111, 112 News channel 45
setting up 174 templates, pointing to 82, 83 channel images module/extension 279 channel images, photo gallery add-ons 224 comments allowing, on entries 120 form, creating 125-128 previewing, by visitors 128, 129 spam, preventing 120-125 Constrain Proportions checkbox 49 contact form, Email module 241-243 content about 44 Body field 46 Constrain Proportions checkbox 49 Extended text field 48 Information Pages channel 45 new content, creating 45 News channel 45 selecting, from top menu 45 URL title 46 View Entry page 50 Write Mode 47 content management system (CMS) 7, 9 control panel, ExpressionEngine about 38 administrative control panel access 39 Corporate theme 44 Default Control Panel Theme 43 ExpressionEngine Info tab 39 Fruit theme 44 hide sidebar link 39 home icon 39 home page 39 logging into 29, 30 navigation 39 notepad 41 profile 39 Quick Links Manager link 42 Quick Links section 39 reveal sidebar 39 tab manager 40, 41 themes 42 website 39 CSS calendar, formatting with 183 custom field group
[ 304 ]
creating 65 custom fields about 64, 65 creating 66, 70, 71, 105-107 creating, for event sponsors 174, 175 options 72 custom fields, photo gallery channel creating 203-205 custom statuses 64 custom system messages extension 279
D data organizing, with categories 129, 130 Default Control Panel Theme 43 design, photo gallery changing 209, 210 single-entry page layout, creating 210 Devot-ee 275 Discussion Forum module 259 Duplicate an Existing Template Group option 53
E Ed & Eg 61, 62 Editors 155 Email module about 241 contact form, creating 241-243 tell-a-friend form, creating 244 tell-a-friend template, creating 244-247 embedded template 96-98 entries categories, displaying with 130, 131 editing, solution 293 limiting, solution 293 posting to channel, solution 293 events displaying, on calendar 191-194 solution 297, 298 events channel creating 177 events custom fields creating 176, 177 event sponsors custom fields, creating for 174, 175
event sponsors channel creating 175, 176 example events creating 177, 179 exercises solutions 293-301 ExpressionEngine 404 Page, improving 140 .htaccess files, allowing to be used 291, 292 about 9, 11 accessories 272, 273 add-ons 271 Agile Records website 37 assumptions 20 backups 263, 264, 265 business case 12 calendar 173 CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) 123 channel, designing 104, 105 control panel 38, 39 control panel, logging into 29, 30 database restores 266, 267 database, setting up 21, 22 documentation, URL 15 Email module 241 extensions 273 field types 274 file manager 200-203 files, downloading 22, 23 files, uploading 23, 24 image editing, features 221-223 installing, steps 24-28 Mailing List module 236 members, types 39 Moblog module 248 modules 272 official installation guide, URL 19 photo gallery channel, creating 203 photo gallery, designing 199, 200 phpMyAdmin 21 repetition, reducing 90, 91 requisites 20 resources, URL 16, 17 search box, adding to site 229, 230 Search module 228 [ 305 ]
technical case 12 templates, creating 209 templates 50 updating 19 upgrading 267 upgrading, steps 268-271 user-friendly URLs, creating 31 WampServer 21, 285 WampServer, downloading 286, 287 WampServer, installing 288, 289 wiki module 255 ExpressionEngine 2 15 ExpressionEngine database setting up 21, 22 ExpressionEngine documentation, URL 15 ExpressionEngine modules Blacklist/Whitelist 259 Discussion Forum 259 IP to Nation 260 Query 260 Referrer 260 ExpressionEngine modulesSimple Commerce 259 Statistics 260 ExpressionEngine, optimizing performance 281-283 spam 280, 281 ExpressionEngine page index.php 31 ExpressionEngine URLs index.php, hiding 32, 33 index.php, renaming 34, 35 Extended text field 48 extensions 273
F Facebook Connect module, Solspace 276 FancyBox setting up 187, 188 FAQ snippet 134-136 FAQ template creating 114-118 single-entry page, creating 118-120 field types, ExpressionEngine about 274 checkboxes 67
date 67 file 67 multi select 67 radio buttons 67 relationship 67 select dropdown 67 textarea 67 text input 67 file manager 200-203 first timer extension 278 FoxEE module 279 FreeForm module, Solspace 276 Friends module, Solspace 276
G guests member group 155
H hide sidebar link, ExpressionEngine control panel 39
I image editing features 221- 223 image sizer, photo gallery add-ons 223 image sizer plugin 278 includes, template group 78 index.php hiding, in ExpressionEngine URLs 32, 33 renaming, in ExpressionEngine URLs 34, 35 Information Pages channel 45 installing photo gallery 203 installing, ExpressionEngine files, downloading 22, 23 files, uploading 23, 24 steps 24-28 IP to Nation module 260
J jQuery module 173
[ 306 ]
L Low (Lodewijk Schutte) 277 Low NoSpam 277 Low Variables 277
M Mailing List module about 236 e-mails, sending 239, 240 mailing list, setting up 236, 237 member registration, allowing 238, 239 Make the index template in this group your site's home page? box 53 MAMP 285 Matrix 275 MD Detect Page Type URL 141 MD Detect Page Type plugin 278 member groups about 154 banned member group 155 Channel Assignment 159 Channel Posting Privileges 159 Comment Administration 159 configuring, options 155, 156 control panel access 158 Control Panel Email Privileges 159 creating, solution 296 custom member field, solution 296 editor member group, creating 155 guests member group 155 members member group 154 Module Access Privileges 159 new member group, creating 159 pending member group 154 site access 156 Template Editing Privileges 159 member-only content content, making visible to members 167-170 creating 166, 167 members creating 160 Editor Ed, logging in as 160-162 list 151, 152 member groups 154 member-only content, creating 166
new member, registering as 147-149 profile 149-151 templates, linking to 152-154 types 143, 144 with administrative control panel access 144 without administrative control panel access 144 membership designing 143 member groups 144, 154 member, list 151, 152 member, profile 149,-151 member templates, linking to 152-154 new member, registering as 147-149 preferences 144-147 members member group 154 menu, snippets creating 95, 96 Moblog e-mail, Moblog module sending 253, 254 Moblog module about 248 Moblog e-mail, sending 253, 254 setting up 248-252 template, setting up 252, 253 modules about 272 multiple-entry page content, adding 215-221 creating 213, 214 Multiple Site Manager 260
N Newism (Leevi Graham) NSM Addon Updater 276 NSM Better Meta 277 NSM TinyMCE 277 NSM Transplant 277 News channel 45 nGen works 277 no-results template 235 no-results template, Search module 234 notepad, control panel 41 NSM Addon Updater, Newism (Leevi Graham) 276
[ 307 ]
NSM Live Look, Newism (Leevi Graham 277 NSM TinyMCE, Newism (Leevi Graham) 277 NSM Transplant, Newism (Leevi Graham) 277
O official installation guide URL 19
P page load times reducing, techniques 282 pages adding 84, 85 creating, solution 294 second page, publishing 86, 87 second template, creating 88-90 Pages module URL 85 pending member group 154 photo gallery add-ons 223 advanced features 221 channel, creating 203 design, changing 209, 210 designing 199, 200 installing 203 photo gallerysolution 299 setting up 205 photo gallery, add-ons channel images 224 image sizer 223 photo gallery channel categories, creating 205, 206 creating 203, 207 custom fields, creating 203-205 photos, uploading 207-209 photos direct upload 208 uploading, to website 207 phpMyAdmin 21, 290 Pixel & Tonic about 275 Matrix 275 Playa field type 275
Wygwam 275 URL 200 Playa field type 275 plugins 274, 275 Pluralism 62 preload text replacements 91, 92 Publish page layout modifying 162-164 options, configuring 165
Q Query module 260 question set publishing 112, 113 Quick Links Manager, control panel 42
R Referrer module 260 repetition preload text replacements 91, 92 reducing, ways 90, 91 user-defined global variables 92, 93 resources ExpressionEngine documentation, URL 15 URL 17 restores, ExpressionEngine build release 267 database restores 266 releases, types 267 version release 267 RSS feed about 136 and Atom feed, differences 139 setting up 136-139
S search box Search module adding, to site 230 search box, Search module adding, to site 229 Search module advanced search 235 no-results template 234, 235 search results template, creating 231-233 search results module 279 [ 308 ]
setting up 252, 253 templates, ExpressionEngine about 10, 50 Access section 54 as files 99-101 content displaying, tags used 55-58 content, adding to multiple-entry page 215-221 creating 78-82, 290 Duplicate an Existing Template Group option 53 editing 54 group, creating 53, 54 index template 52, 55 Make the index template in this group your site's home page? box 53 multiple-entry page, creating 213, 214 pointing, to channel 82, 83 Preferences section 54 second template, creating 88 single-entry page, creating 210-213 tag 56 tag pair 57 Template Notes section 54 URL, relationship 52 URLs, relating to 51, 52 template variables accessory 278 themes, control panel corporate theme 44 Default Control Panel Theme 43 downloading 42 fruit theme 44 mobile theme 43 switching 43
search results template, Search module creating 231-233 Simple Commerce module 259 single-entry page creating 210-213 single-entry page, FAQ template creating 118-120 solution 299 single-entry page layout, photo gallery creating 210 photo comments, displaying 213 single-entry template creating 188-191 snippets about 93-95 menu, creating 95, 96 Solspace about 276 Calendar module 276 Facebook Connect module 276 FreeForm module 276 Friends module 276 Super Search module 276 Tag module 276 User module 276 solutions to exercises 293-301 spam 280, 281 Statistics module 260 styles adding, to calendar CSS 184-186 Super Search module, Solspace 276
T tab manager, control panel Template Manager screen 40, 41 Tag module, Solspace 276 tag pair 57 tags about 10, 56 used, to display content in templates 55-58 tell-a-friend form, Email module creating 244 tell-a-friend template, Email module creating 244-247 template, Moblog module
U upgrading, ExpressionEngine steps 268-71 URL title 46 user-defined global variables 92, 93 user-friendly URLs, ExpressionEngine creating 31 index.php, hiding 32, 33 index.php, renaming 34, 35 User module, Solspace 276
[ 309 ]
V version release 267 View Entry page 50 visitors allowing, to preview comments 128, 129
W WampServer about 285 downloading 286, 287 home page, URL 290 installing 288, 289 Localhost 290 package 286 using 289 welcome page, deleting 290 www directory 290 WampServer, package AMP environment 286 phpMyAdmin 286 website converting into ExpressionEngine, approaches 62, 63 wiki module about 255 wiki, setting up 255, 256 wiki, working 257-259 Write Mode 47 Wygwam 275
X XAMPP 285
[ 310 ]
Thank you for buying Building Websites with ExpressionEngine 2
About Packt Publishing
Packt, pronounced 'packed', published its first book "Mastering phpMyAdmin for Effective MySQL Management" in April 2004 and subsequently continued to specialize in publishing highly focused books on specific technologies and solutions. Our books and publications share the experiences of your fellow IT professionals in adapting and customizing today's systems, applications, and frameworks. Our solution based books give you the knowledge and power to customize the software and technologies you're using to get the job done. Packt books are more specific and less general than the IT books you have seen in the past. Our unique business model allows us to bring you more focused information, giving you more of what you need to know, and less of what you don't. Packt is a modern, yet unique publishing company, which focuses on producing quality, cutting-edge books for communities of developers, administrators, and newbies alike. For more information, please visit our website: www.packtpub.com.
Writing for Packt
We welcome all inquiries from people who are interested in authoring. Book proposals should be sent to author@packtpub.com. If your book idea is still at an early stage and you would like to discuss it first before writing a formal book proposal, contact us; one of our commissioning editors will get in touch with you. We're not just looking for published authors; if you have strong technical skills but no writing experience, our experienced editors can help you develop a writing career, or simply get some additional reward for your expertise.
CodeIgniter 1.7 Professional Development ISBN: 978-1-849510-90-5
Paperback: 300 pages
Become a CodeIgniter expert with professional tools, techniques and extended libraries 1.
Learn expert CodeIgniter techniques and move beyond the realms of the User Guide
2.
Create mini-applications that teach you a technique and allow you to easily build extras on top of them
3.
Create CodeIgniter Libraries to minimize code bloat and allow for easy transitions across multiple projects
CodeIgniter 1.7 ISBN: 978-1-847199-48-5
Paperback: 300 pages
Improve your PHP coding productivity with the free compact open-source MVC CodeIgniter framework! 1.
Clear, structured tutorial on working with CodeIgniter for rapid PHP application development
2.
Careful explanation of the basic concepts of CodeIgniter and its MVC architecture
3.
Use CodeIgniter with databases, HTML forms, files, images, sessions, and email
4.
Full of ideas and examples with instructions making it ideal for beginners to CodeIgniter
Please check www.PacktPub.com for information on our titles
jQuery 1.4 Reference Guide ISBN: 978-1-849510-04-2
Paperback: 336 pages
A comprehensive exploration of the popular JavaScript library 1.
Quickly look up features of the jQuery library
2.
Step through each function, method, and selector expression in the jQuery library with an easy-to-follow approach
3.
Understand the anatomy of a jQuery script
4.
Write your own plug-ins using jQuery's powerful plug-in architecture
Drupal 6 Content Administration ISBN: 978-1-847198-56-3
Paperback: 196 pages
Maintain, add to, and edit content of your Drupal site with ease 1.
Keep your Drupal site up to date: easily edit, add to, and maintain your site's content, even if you've never used Drupal before!
2.
Covers the full range of content that you might want on your site: richly formatted text, images, videos, as well as blog posts, calendar events, and more
3.
Get to grips with managing users, slaying spam, and other activities that will help you maintain a content-rich site
4.
Concise, targeted information with easy-tofollow hands-on examples
Please check www.PacktPub.com for information on our titles
Recommend Documents
Building Websites with ExpressionEngine 2
A step-by-step guide to ExpressionEngine: the web-publishing system used by ...
Building Websites with ExpressionEngine 2
A step-by-step guide to ExpressionEngine: the web-publishing system used by ...
Building Websites with XOOPS A step-by-step Tutorial
Get your XOOPS website up fast using this easy-to-follow guide
S...
Building Websites with Joomla! A step by step tutorial to getting your Joomla! CMS website up fast
Hagen Graf
BIRMING...
Building Websites with Joomla! A step by step tutorial to getting your Joomla! CMS website up fast
Hagen Graf
BIRMING...
Building Websites with XOOPS A step-by-step Tutorial
Get your XOOPS website up fast using this easy-to-follow guide
S...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Sign In
Our partners will collect data and use cookies for ad personalization and measurement. Learn how we and our ad partner Google, collect and use data. Agree & close
{title}
{if website_image}{/if} {website_content} {/exp:channel:entries}6. Click on Update and Finished and now visit http://localhost/site. Even though your updated site/index template is much shorter than before, notice how the web page itself looks no different. That's it! The design is now such that you can have as many static website pages as you like, each of which use the same embedded template. Now all that is left to do is prove this works by creating a second page.
Publishing a second page
There are two steps to carry out every time you want to create a new static website page. First create a channel entry with the content for the page and then create a template group and edit the index template to embed the .website_page template with a URL title of the channel entry you wish to display. If you wish to have a static second tier page (such as a URL of business/ news), then you would create a template called news in the business template group and then embed the .website_page template as you normally would.
To demonstrate how this works, create a second channel entry. This time, it should be based on the individual.html page in Ed & Eg's website. 1. Open the downloaded individual.html page in your browser. 2. In the control panel, select Content | Publish | Website. Use a Title of Individual/Family and a URL Title of individual_family. 3. Under Image, select Add File. However, this time, instead of having to upload the same image again, you can click on Main Upload Directory on the left hand-side of the File Manager and click on the previously uploaded money.jpg. [ 86 ]
Chapter 4
4. Then, as before, copy the content from the Individual/Family page in your browser, marking up the headings as
. For the hyperlink in the How Much Do We Cost? section, use a hyperlink such as promotions, which will resolve to http://localhost/promotion in anticipation of you creating the Promotions page at that URL. When you are done, click Submit. The {site_url} variable is a global ExpressionEngine variable that substitutes itself with the URL to the root directory of your website (as defined in Admin | General Configuration). The benefit of using this ExpressionEngine variable, instead of typing in the (much longer) root directory of your website (such as http://localhost/), is that if you ever change your website domain, you only have to change it in one place in ExpressionEngine (rather than changing every occurrence of the domain name.).
Now that there is a second channel entry, we can go ahead and create a template for it. [ 87 ]
Moving a Website to ExpressionEngine
Creating a second template
Call the new template group individual so that its output appears at the URL http://localhost/individual. 1. In the control panel, click on Design | Templates | Template Manager from the top menu. Select New Group on the left-hand side. 2. Call the new group individual. Then, under Duplicate an Existing Template Group?, select the site template group to duplicate. Click Submit.
3. Edit the index template of the individual template group and change the code to read as follows: {embed="includes/.website_page" url_title="individual_family"}.
4. Click Update and Finished and visit your new page at http://localhost/ individual to verify it. It looks identical to the individual.html page from Ed & Eg's static website. 5. Verify that the promotions link you created in the entry links to http:// localhost/promotion. Although you have not yet created that page, if the link appears as http://localhostpromotion, it's likely the URL to the root directory of your website doesn't include the final forward slash (for example, it might be set as http://localhost instead of http:// localhost/). To change this, go to Admin | General Configuration and update the setting called URL to the root directory of your website. By now, you can see that the website is relatively easy to maintain. To create a new page, all you need to do is create a new channel entry and a new template that references the URL title of your new entry. To change the wording or the image on an existing page is even easier; all you have to do is edit the entry. No dealing with templates or template code at all! Finally, should you ever wish to change the site design, you only have to do so in a single template. [ 88 ]
Chapter 4
Going live
Currently, unless you have already changed this, the default template group is the Agile Records website (news/index), meaning that if you go to http://localhost/, the news/index template will be rendered. (If you didn't install Agile Records and didn't already define a default template group, then visiting http://localhost will display a blank screen). Change the default template group to be site/index (which is where the Welcome to Our Website entry is displayed). Follow these instructions: 1. To change the default template group, go to Design | Templates | Template Manager in the control panel. 2. Highlight the site template group on the left-hand side and then select Edit Group (the left-most button above the list of individual templates).
3. Check the box that says Make the index template in this group your site's home page? and click Update.
4. Now, when you visit http://localhost/, you should see Ed & Eg's website in place of Agile Records.
[ 89 ]
Moving a Website to ExpressionEngine
Note that you can still access the Agile Records website at http:// localhost/news. If you are following along on your own computer, this allows you to refer to the Agile Records site at any time. However, if you are on a live web server, you may wish to suppress the Agile Records website completely. You can do this in Template Manager—next to each template associated with Agile Records (about, global_embeds, news, search), there is an option called Access. You can change the access for each template to say that visitors to your website cannot view the output of these templates, but that instead they should be routed back to the site/index template. (You and other SuperAdmins will still be able to see the template output at their current URLs. So if you wish to verify that the re-direct is working, you must first log out of ExpressionEngine).
Avoiding repetition
You have already created an embedded template that saves you from having lots of templates with the same basic HTML code inside. When working with templates in ExpressionEngine, it's best to avoid code repetition of code as much as possible— whether the repetition is within a single template or across multiple templates. Any situation where code is repeated can be a major headache, should you ever wish to update that code; instead of being able to make an update in a single location, you instead have multiple places to make the same update, increasing the likelihood that you miss one. On a small site with only one or two templates, it's easy to manage code that is repeated, but as your site grows, having the same code in more than one template can make changes very difficult and time-consuming to accomplish. ExpressionEngine has four ways to reduce repetition: 1. 2. 3. 4.
Preload text replacements User-defined global variables Snippets Embedded templates
Each of these methods involve assigning the repeated code to a custom ExpressionEngine tag and then using that tag whenever you want to use the repeated code in a template. The key differences between these methods are: • •
Preload text replacements only work within the same template and can only contain a string (no ExpressionEngine tags). Global variables can contain a single line or multiple lines of static HTML and text—in fact, anything except ExpressionEngine tags and code. [ 90 ]
Chapter 4
•
Snippets are identical to global variables, except that snippets can contain ExpressionEngine tags.
•
Embedded templates, as you have already seen, are an entirely separate template that can be included in another template.
For performance reasons, it's best to use the first available option that will meet your needs. If the text is a string that is only being repeated in a single template, use Preload text replacements. If your code is repeated in more than one template, but does not contain ExpressionEngine tags, use global variables. If the repeated code includes ExpressionEngine tags, use snippets. Embedded templates are usually only necessary in special circumstances such as when you want to use variables to dynamically vary the code that results (a snippet cannot be passed variables). You have already seen how powerful embedded templates can be. What follows are examples of the other tools.
Preload text replacements
Preload text replacements are useful as local constant variables. In ExpressionEngine, you will find that there are certain references that are made multiple times within a single template, such as the channel where the main content is coming from or the template group that the template is in. By creating Preload text replacements for these references, you can gain several benefits: •
It gives you a single place in each template to change one of these references, should one of the names ever change.
•
When creating a new section of your website, you will often start with an existing template as a base. If the existing template has Preload text replacements, you can simply copy the existing template and change those preload replacements, saving a lot of time.
•
The Preload text replacement may be shorter to type (although if it's not, it is still sometimes a good idea to use a Preload text replacement than have repetition).
For the remainder of this book, each template you create will have a Preload text replacement called my_channel for the channel that the template references the most. By doing this, it will save you from having to constantly remember what the channel short name is; you will simply set it at the top of each template and then use {my_channel} instead. Go ahead and create a {my_channel} Preload text replacement in the includes/. website_page template now. [ 91 ]
Moving a Website to ExpressionEngine
1. Edit the includes/.website_page template. At the very top of the template, insert the following code: {preload_replace:my_channel="website"}
2. In this template, there are two places where you can see the {exp:channel:entries} parameter channel="website"—one towards the top of the page in the tag and one at the start of the content section. Change both these parameters to read channel="{my_channel}" and click on Update. 3. Visit your website and you should see no difference in the content. (If the content has suddenly disappeared, there may be a misspelling).
User-defined global variables
User-defined global variables can be used for any code that is repeated and that does not contain ExpressionEngine tags. Unlike Preload text replacements, a global variable can contain multiple lines of text and can be used in any template. The site name at the top of each page is a good example of this—although it's only three lines and it does not contain any ExpressionEngine tags. However, it will be needed in every template, so it's worth extracting into a global variable. This way, if Ed & Eg ever change their site name, the update only has to happen in one place and the entire website will be updated. 1. In the control panel, select Design | Templates | Global Variables from the top menu. 2. You will see that there are already some global variables that have been defined. These are being used by the Agile Records website. Click on Create a New Global Variable at the top right. 3. Call your new variable website_sitename. 4. The variable content will be as follows. Ed & Eg Financial Advisors
5. Click Update to save the global variable.
[ 92 ]
Chapter 4
6. Now go back to the includes/.website_page template and replace the section of code that displays the site name, starting with down to and including the corresponding closing with the global variable tag {website_sitename}. When you are done, the two lines of code after should look as follows. Click Update. {website_sitename}
7. Visit your website and you should see no difference. Reducing repetition is something that makes the website easier to maintain for you, but does not change anything for your visitors.
Snippets
Snippets are ideal for code that is repeated and that contains ExpressionEngine tags. For this example, you will convert the sidebar that appears on the right-hand side of each page into a snippet. Although the sidebar does not currently have any ExpressionEngine tags, meaning you could use a global variable, you will be adding additional functionality into the sidebar as you progress through the book. In anticipation of this, it therefore makes sense to convert the sidebar into a snippet, rather than a global variable.
[ 93 ]
Moving a Website to ExpressionEngine
1. In the control panel, select Design | Templates | Snippets from the top menu. 2. You will see that there are already some snippets that have been defined for the Agile Records website. Agile Records uses snippets prefixed with global for items that appear on every page (like the footer) and snippets prefixed with the template group name for items that only appear in templates in that group. We are going to create a new snippet, so click on Create a New Snippet at the top right. 3. Call your new snippet website_sidebar, using website instead of global to distinguish this snippet from the Agile Records snippets. 4. To save typing, copy the following code from the includes/.website_page template: -
Promotion!
From now until the end of the year, Ed & Eg are offering a <strong>free initial 90 minute consultation, plus <strong>25% off your first return visit. Learn More…
-
Key Services
- -Budgeting
- -Debt Management
- -Investing
- -Financial Planning
- -Tax Services
- -Book-keeping & Cash Flow
- -Accounts Preparation
- -Payroll Services
5. Before saving this snippet, update the link that appears in the Promotion! box from promotion.html to {site_url}promotion. (Although you have not yet created a promotion template group and a corresponding website channel entry, when you do, this link will work). [ 94 ]
Chapter 4
6. Click on Update and Finished to save the snippet.
7. Now go to the includes/.website_page template and replace the sidebar code you just copied into the snippet with the snippet tag {website_ sidebar}. The four lines after should now look as follows. When you are done, click Update. {website_sidebar}
8. If you now visit your website, you should not see much change. The only difference that indicates the sidebar is now coming from your snippet rather than from the template is the link in the Promotions! box that points to http://localhost/promotion instead of promotion.html.
Creating a menu
Another good candidate for a snippet is the site menu that appears at the top of every page. Creating the menu as a snippet (rather than a global variable) allows you to use the ExpressionEngine variable {site_url} in place of your domain name, just like you did when creating the link to the promotions page within the Individual/ Family entry. Although you have not yet created all the entries (and template groups) for the following page links to work, you can create this menu snippet in anticipation of creating the corresponding pages later (as part of the exercises at the end of this chapter). [ 95 ]
Moving a Website to ExpressionEngine
1. In the control panel, select Design | Templates | Snippets from the top menu and click on Create a New Snippet at the top right. 2. Call your new snippet website_menu. 3. Type in the following code:
4. Click on Update and Finished to save your new snippet. 5. Now go to the includes/.website_page template and replace the menu code that starts with , till the closing with the snippet tag {website_menu}. When you are done, the section should look as follows. Click on Update. {website_sitename} {website_menu}
6. If you now visit your website, you should see that your menu links have all changed. Verify that you can successfully click between the Homepage and the Individual/Family pages you have already created.
Embedded templates
You have already seen an example of an embedded template. An embedded template can do everything a snippet can do with two main differences: 1. Embedded templates can be passed variables, and the output can then vary based on those variables.
[ 96 ]
Chapter 4
2. An embedded template is a template. ExpressionEngine has many different options that can be defined on a per-template basis (different templates can have different access controls, different caching preferences and different PHP settings) whereas snippets have the same settings as the template they are in. Furthermore, you can restrict certain template groups so that other administrative control panel users cannot see them, but with snippets, you can only give other administrative control panel users access to all snippets or none of them. Note that when using embedded templates, you can define as many or as few variables as you wish. Simply listing the variables and their values in the tag creates the variables, for example, {embed="template group/template" variable1="dog" variable2="cat"}. If you do not want any variables, then the tag is simply {embed="template group/template"}.
Now that you have seen examples of Preload text replacements, global variables, snippets, and embedded templates, you can certainly go further and extract even more repeated code into these tools. The page footer could be a global variable, as could the widebar. However, it is important to strike a balance between reducing repetition and writing code that you will understand a year or two later. Although only you can know where that balance lies for you, here are some recommendations: •
•
Keep custom tags descriptive as to what the code is that they represent (for example, instead of {widget}, use a name that makes it obvious to you what the tag represents). As you start out, avoid putting opening tags (such as a ) into a global variable, snippet, or embedded template, without the corresponding closing tag (such as a ). While ExpressionEngine does allow this, it can make the template code more difficult to troubleshoot. As you grow more experienced, there can be cases when your website page requires certain elements in a certain order simply to build the layout, so you may find it more efficient to replace a series of opening 's with a global variable and then create a second global variable for the corresponding closing 's.
•
Do not bundle unrelated parts of your page into the same global variable, snippet, or embedded template. While you could use one snippet for the entire footer, including the FAQs and the copyright notice, it would cause problems if, on one page, you only need the copyright notice, but not the FAQs. [ 97 ]
Moving a Website to ExpressionEngine
For an example of just how far you can take these techniques, check out Derek Jones' official ExpressionEngine blog series 'Behind the Curtains' that talks about how EllisLab uses ExpressionEngine on their own websites. (Note that the series was written in 2007, before snippets existed): http://expressionengine.com/blog/ article_list/category/behind_the_curtain/
Creating a 404 Page not found
A 404 Page is an essential part of any website, and working through this chapter, you may have noticed that your 404 Page is still themed like the Agile Records website. In this section, you will take advantage of all the repetition-reduction you have done as you create a new 404 Page. 1. Select Design | Templates | Template Manager, select the Includes template group, and then select New Template. Call the new template 404. The Template Type will be Web Page, select Duplicate an Existing Template, and finally select the includes/.website_page template to copy from. Click on Create and Edit. 2. Since the 404 Page content does not come from a channel, delete the line that reads {preload_replace:my_channel="website"}. 3. Change the line to: Page Not Found - Ed & Eg Financial Advisors
Replace everything from to with: Page not Found (404)
The page you were looking for does not exist. There may be a spelling mistake in the URL in the address bar, or we may have removed this page inadvertently. Please use the menu at the top to visit a page that does exist.
4. Click Update to save the changes. 5. Now that you have a 404 Page that is consistent with your site design, you can define this page to appear when a page is not found. Select Design | Templates | Global Preferences from the top menu. 6. Under 404 Page, select includes/404 as the template to display. At the same time, make sure Enable Strict URLs is set to Yes (or your 404 Page will not work). Click Update. [ 98 ]
Chapter 4
Now, when you visit an invalid URL (such as http://localhost/toast), you will see your 404 page instead of the Agile Records 404 page.
Templates as files
While working with templates within the web-based control panel interface works well, it does have limitations. If you are used to coding HTML files using your favorite text editor, you may wish to continue using that text editor and FTP the files to your website instead. In ExpressionEngine, this is entirely doable. 1. If you are following along on an actual website, you will need to ensure that the directory permissions for /system/expressionengine/ templates are set to 777. If you are using a localhost environment, this is not necessary. This directory is where your template files will be saved. [ 99 ]
Moving a Website to ExpressionEngine
2. In the control panel, select Design | Templates | Global Preferences from the top menu. 3. Set Allow Templates to be Saved as Files to Yes. The likelihood is that the Basepath to Template File Directory is already set to the full server path for / system/expressionengine/templates, but if it is not, you will need to set it.
4. Click Update to save your changes. 5. Although this option allows you to start creating templates as files, it does not automatically go back and create files for your existing templates. To do this, you have to mark each template to save as a file. Edit each template in the site, individual, and includes template groups in turn, check the box marked Save Template as File (just above the Update button), and then click Update and Finished.
6. You will now see your template files in system/expressionengine/ templates in a sub-directory called default_site. You can now edit your template code by editing these files directly. You can easily create new templates and new template groups without using the control panel by putting new files and directories in this directory. When creating new templates and new template groups, there are certain conventions to be aware of: template groups are separate directories with the name of the group followed by a .group extension. Webpage templates end in .html and CSS templates end in .css. You can edit templates in the control panel and in the files interchangeably. When opening a template in the control panel, ExpressionEngine will look to see if the file is newer than the database version, and if so, load the file. Updating your template will then update the ExpressionEngine database and file simultaneously (unless you uncheck the box to save it as a file). [ 100 ]
Chapter 4
Know that when displaying pages to visitors, ExpressionEngine will always use the file before using the template saved in the ExpressionEngine database. This means that you can feel confident updating the files outside of the control panel, knowing that the changes will immediately reflect on your website. Occasionally, when using templates as files, you may find that a file for a template has gone missing. ExpressionEngine has a utility to synchronize the templates periodically to ensure that the templates in the database match the content of the files and that there are files for every template. To run this, you can go to Design | Templates | Synchronize Templates. The screen will summarize whether the templates are in sync or if the files are newer than the database templates. If any are not in sync, check which templates you want to sync and click on Submit to update the database with the updated files (as well as recreate any template files that may have accidentally gone missing). For more information on templates as files, see the ExpressionEngine documentation at http://expressionengine.com/user_guide/templates/flat_file_ templates.html
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. In this chapter, you only created the home page and the Individual/Family page. Go ahead and create the Small Business, Contact Us, and Promotions page. Leave out the Frequently Asked Questions page. You will convert this page in the next chapter.
Summary
In this chapter, you have seen how to build a complete website using ExpressionEngine. You have taken advantage of many of ExpressionEngine's features to reduce repetition and make your website as simple to maintain as possible. In the next chapter, you will learn more about channels and how you can use ExpressionEngine to turn the Frequently Asked Questions page of Ed & Eg's website into a more interactive experience for your visitors. [ 101 ]
Moving a Website to ExpressionEngine
The key points to remember after working through this chapter are: •
Custom fields, categories, and statuses can all be customized on a perchannel basis (or different channels can share the same custom fields, categories, or statuses). This lends itself to enormous flexibility in how you design your channel (but also means there is usually more than one way to accomplish anything in ExpressionEngine).
•
When creating a new channel, you create custom fields/statuses and categories for the new channel (optional), create the channel itself, create content inside the channel, and create or modify templates to display the channel content. These steps can be completed in any order and are usually iterative.
•
Preload text replacements are useful as constants, allowing you to take a line of text that is repeated throughout a template, such as the channel name, and define it in one place.
•
Global variables can be used for static text, HTML, or scripts that are used in more than one template. Therefore, by using this, if you want to make a change, you only have to update the global variable, rather than every template that might be using that code.
•
Snippets are like global variables, except that they also allow ExpressionEngine code and tags.
•
Embedded templates are like snippets, except that they allow variables to be passed to them to dynamically vary the output.
[ 102 ]
Creating a Fully-Equipped Channel So far you have used ExpressionEngine to create a website where you can easily edit the content through the Publish screen in ExpressionEngine and where it is easy to add new pages, should you wish to. In this chapter, you are going to take your ExpressionEngine-powered (but still static) website and enhance it to make it interactive. The Frequently Asked Questions page is an ideal candidate for this. Currently, there are only two questions on the page. However, Ed & Eg would like to start posting new questions and answers regularly. The frequently updated content would encourage visitors to keep coming back to the site. Although Ed & Eg is the example in this chapter, the concepts could easily be applied to any regularly updated content that you would want to post on your website; including a regular blog, book reviews, recipes, or products that you are selling. You will be: •
Displaying multiple entries
•
Allowing visitors to browse entries and select the ones that interest them
•
Allowing visitors to comment on entries, just like they might comment on a blog posting
•
Creating a feed to allow visitors to keep up with new entries using their favorite news reader (such as Google Reader)
From what you learned in the last chapter, you should now be familiar with the process of creating a channel, creating custom fields, posting content, and creating a template to display the content. You will follow that same process in this chapter.
Creating a Fully-Equipped Channel
Designing your channel
One of the biggest benefits to using ExpressionEngine is the ability to customize your channel fields. This allows you to really tailor the fields to the content that will be in the channel. In this case, you are creating a channel for Ed & Eg's Frequently Asked Questions. You will need two text fields—one for the question and one for the answer. By splitting up the question and answer fields in this way, you gain the ability to display the question separately from the answer—a design you will take full advantage of. You will create a multiple-entry page where visitors can see the various questions that have been asked and (hopefully) be tempted to click to find out the answers. When they click on a given question, the visitor will be taken to a single-entry page where the question and the answer will be displayed, along with comments from other visitors, with the ability to add their own comments. This design of single and multiple-entry pages is actually fundamental to ExpressionEngine. The key differences between the two types of pages are: 1. A multiple-entry page displays the content from more than one entry in your channel. You can choose to display all the information from the channel or just a teaser (such as only the question, but not the answer). You have control over how many entries are displayed on a page and how they are displayed. A multiple-entry page can change frequently—if a visitor bookmarks a multiple-entry page and returns at a later date, the page will likely reflect new content. 2. A single-entry page displays the content from only one entry in your channel. The content does not change over time (unless you edit the entry in question). This means that a visitor can bookmark the URL or e-mail it to a friend, and when they return, they will see the same content that they originally saw (plus any new comments). A single-entry page is required to accept comments for a specific entry and to display those comments. The URL for a single-entry page is determined by the URL Title on the Publish screen for the entry. A single-entry page URL typically takes the format of http:// localhost/template_group/template/entry_url_title, whereas a multiple-entry page URL would not have the entry_url_title at the end. ExpressionEngine uses the URL to dynamically determine what content to display using each template. If the URL has the URL Title of an entry in it, ExpressionEngine will only display that entry. If the URL does not have the URL Title of an entry in it, ExpressionEngine will return as many entries as meet the criteria in the parameters of the {exp:channel:entries} tag. [ 104 ]
Chapter 5
The includes/.website_page template that is used to display content from the website channel is actually an example of a multipleentry page. However, you used the parameter url_title to limit the number of entries to one specific entry.
In general, not all channels need both single and multiple-entry pages. However, it's good practice to have single-entry pages for channels with content that a visitor might want to bookmark and return to. Furthermore, if your channel allows visitors to leave comments on your posts, a single-entry page is required. Whether or not to allow comments is, in fact, a design decision in itself. Although it can encourage visitors to engage with your brand, having a website that allows comments but does not have any can be worse than not allowing comments at all. Ed & Eg have a plan to ensure their website will receive comments once it goes live.
Creating your custom channel fields The custom fields you are going to create are: • •
faqs_question faqs_answer
The question and answer fields will be Textarea fields with Auto
formatting. This formatting will put line breaks between paragraphs in the answer, but will not wrap the question and answer in paragraph tags. The benefit to doing this is that you can put an A: at the beginning of each answer in your template and know that the first paragraph of the answer will be on the same line. 1. From the top menu of the control panel, select Admin | Channel Administration | Custom Fields. Now select Create a New Channel Field Group.
[ 105 ]
Creating a Fully-Equipped Channel
2. Use a Field Group Name of faqs, as this field group will only be suitable for the Frequently Asked Questions channel. Click Submit. 3. Select Add/Edit Custom Fields for your faqs field group, and then select Create a New Custom Field.
4. The first field to create is the Question field. The Field Type will be Textarea. Give it a Field Label of Question and a Field Name of faqs_question. Leave the Field Instructions blank (these appear only on the Publish page).
5. This will be a required field and will be searchable. Say Yes to show this field by default and do not change the value of the Field Display Order. 6. The Textarea Rows can be left at 6. Set the Default Text Formatting to Auto
and say No to allowing an override on the Publish page. Leave the Text Direction as Left to Right and say Yes to show the Formatting Buttons, Smileys, Spellcheck, Writemode and File Chooser. Leave everything else set to No.
[ 106 ]
Chapter 5
7. Click Submit. 8. Go ahead and create the field Answer (faqs_answer) with the same settings as the faqs_question field. 9. Once your fields have been created, your Field Group should look as follows:
That's it! Your custom fields have been created and you can now move on to creating some custom categories.
[ 107 ]
Creating a Fully-Equipped Channel
Creating your categories
In the last chapter, when you created the website channel, you did not create categories because there was no need to organize your content by category. In this chapter, since the number of questions in your channel could quickly become numerous, it makes sense to use categories to relate questions to each other (and hopefully keep your visitors browsing longer). 1. To create a new category group, go to Admin | Channel Administration and then Categories.
2. Select Create a New Category Group. 3. Call the new category group FAQ Categories and select Allow ALL HTML from the formatting drop-down box. Ignore the options about editing and deleting categories—if you had other member groups with administrative control panel access, you could have granted them permission to edit and/ or delete categories in this category group. ExpressionEngine automatically recognizes that no other member groups have administrative control panel access at the moment.
[ 108 ]
Chapter 5
4. Click Submit. 5. You have now created a category group, but you have not yet created any categories. From the Category Management screen, select Add/Edit Categories for the FAQ Categories group. 6. At the top right, select Create a New Category.
7. For now, you will have two parent categories (Life Events and General Advice) as well as a number of sub-categories. Name this first category Life Events. The Category URL Title will default to life_events. Leave the Category Description blank and do not assign an image to your category. Leave the Category Parent set to None and click Submit.
8. Back on the FAQ Categories screen, select Create a New Category again.
[ 109 ]
Creating a Fully-Equipped Channel
9. Your first sub-category will be Going to College (with a URL title of going_ to_college). Type in a short category description such as Questions relating to college/university. Under Category Parent, select Life Events. Do not select a Category Image. Click Submit.
10. The rest of the categories will be set up similar to the two already created (except that the names, URLs, and descriptions will be different). Create the following categories/sub-categories and go ahead and make up your own descriptions; later, you will display the descriptions on your website, so be sure they are full sentences. Category Name
Category URL Title
Category Parent
Getting Married
getting_married
Life Events
Having a Baby
having_a_baby
Life Events
Changing Jobs
changing_jobs
Life Events
Retiring
retiring
Life Events
General Advice
general_advice
None
Budgeting
budgeting
General Advice
Buying a Car
buying_a_car
General Advice
Buying a Home
buying_a_home
General Advice
Debt
debt
General Advice
Savings
savings
General Advice
Investments
investments
General Advice
[ 110 ]
Chapter 5
Your categories have been created. If you want to, you could use the arrows on the left-hand side to re-order the fields (currently, they are ordered alphabetically).
Now that you have created your custom categories, the next step is to create your FAQ channel. Note that you could create your channel first and then create your categories and your custom fields afterwards. However, if you do this, you would then have to go back and edit your channel to associate it with your custom fields/categories. By creating your categories/custom fields first, you can associate the category/custom field group when you create your channel.
Creating your new channel
As you have previously seen, a channel contains content. In this chapter, the questions Ed & Eg get asked and their answers are your content. You have already built new custom fields and a new category group for your channel. You do not need a new custom status group; the open and closed statuses that are in the pre-existing Statuses status group are all you need. 1. From the control panel top menu, select Admin, then Channel Administration, and then Channels. Now select Create a New Channel. [ 111 ]
Creating a Fully-Equipped Channel
2. The Full Name for your channel will be FAQs and the Channel Name will be faqs. Do not duplicate an existing channel's preferences, but say Yes to editing the group preferences.
3. Under Edit Group Preferences, choose a Category Group of FAQ Categories, a Status Group of Statuses, and a Field Group of faqs.
4. Further down, say No to creating new templates for this channel (you will do this later). Finally, click Submit. Your channel has now been created!
Publishing your first set of questions
You have a channel created, complete with custom fields and categories. The next step is to publish some entries so that there are some entries to work with when you start building the templates that will display your channel content. Take the initial questions from the existing questions.html page in the original Ed & Eg website that you downloaded in chapter 4. 1. From the top menu, select Content, Publish, and then FAQs. Title your first question Living Paycheck to Paycheck with a URL Title of living_ paycheck_to_paycheck.
[ 112 ]
Chapter 5
2. Open questions.html in your browser and copy the text of the question and the answer into your channel. Do not copy any of the HTML (such as paragraph tags). Also, do not copy the Q: or A: and do not worry about putting the question in italics—this can be done at the template level to save you from having to remember to do it for each and every question. Do go ahead and apply any italics in the answer by highlighting the words to italicize and then clicking the i button above the field.
3. Select the Categories tab at the top and check the appropriate categories for this entry (such as Budgeting, Debt, and Savings). Next click Submit.
[ 113 ]
Creating a Fully-Equipped Channel
4. Repeat all these steps for the second question called Giving Gifts. Select a category for this entry of Budgeting and click Submit. You now have your first entries published, but before you can see them on your website, you will need to create some templates.
Creating your FAQ templates
Earlier in the chapter, you learned about single-entry versus multiple-entry pages. However, in reality, a channel with more than a handful of entries needs more than one multiple-entry page to keep the number of entries on each page down to a digestible number for your visitors. ExpressionEngine, therefore, offers you three ways to organize your multiple-entry page content: 1. By Category: Organizing your entries by category involves having a category page for each category. On that page, only the entries in that category are displayed. 2. By Date: Organizing your content by date creates an archive page for each month, with only the entries in each month displayed. This technique can be combined with a mini-calendar so that visitors can select a month or even a specific day and see only the entries from that timeframe. 3. By Pagination (showing 10 entries per page): There are two types of pagination—one that shows how many pages there are and allows you to jump to a specific page (including the last page). The other is a simple Next/ Previous link that your visitors can use to traverse through your pages oneby-one. Pagination can be combined with organizing by category so that categories that have a lot of entries are paginated. You can choose one or more of the preceding techniques to organize your content. You can even use all the techniques together, paginating your multiple-entry page while also providing links for visitors to filter either by date or by category should they wish to do so. For Ed & Eg's website, the content is such that it makes more sense to organize by category than it does by date. (A new visitor to Ed & Eg is going to care less about when each FAQ was posted and care more about whether the FAQ is relevant to them). It also makes sense to use pagination to keep the number of entries on each page to a reasonable number. You will therefore create two templates—one for the multiple-entry pages (faqs/ index) so that a visitor can browse the FAQs and one for the single-entry page (faqs/browse) where visitors can read an individual FAQ and post their own comments. Within the multiple-entry page template, you will use conditional statements to identify whether the page being displayed is the main multiple-entry page (with no filtering by category) or a category-specific multiple-entry page. [ 114 ]
Chapter 5
It is possible to go even further and combine the single-entry page and the multiple-entry page into a single template using conditional statements based on the URL. However, your template quickly becomes complicated when doing this, particularly if you are organizing your entries by category, by date, or by pagination, since each of these techniques results in different URLs which have to be accounted for. If this is something you are interested in doing, then a plugin such as MD Detect Page Type (http://devot-ee. com/add-ons/plugins/md-detect-page-type/) will help.
You will start by creating a basic multiple-entry page template with pagination (you will add the category archiving later). 1. First, since you are creating a new section for your website, it makes sense to create a new template group to house it in. In the control panel, click on Design, Templates, and then Template Manager. Select New Group and call the new template group faqs. Do not duplicate a group and do not make the index template in this group your site's home page. (You still want the site template group to be the site's home page). Click Submit. 2. Next, copy the includes/404 template (created in the previous chapter, or can be downloaded from http://www.packtpub.com/support or from the chapter 4 page at http://www.leonardmurphy.com/book2/chapter4) into the faqs/index template. Remove the heading and the following paragraph so that there is nothing between the and the closing . Click on Update. This will result in a page at http:// localhost/faqs with a header, sidebar and footer, but no content.
[ 115 ]
Creating a Fully-Equipped Channel
3. At the top of the template, create three new Preload Text Replacements (below). The first represents the channel name, the second represents the template group, and the third represents the single-entry template that you will create next. Each of these will be used in multiple-places throughout the template, so they are good candidates for Preload Text Replacements. {preload_replace:my_channel="faqs"} {preload_replace:my_template_group="faqs"} {preload_replace:my_single_entry_template="browse"}
4. Update the HTML attribute as follows (this is the title that appears at the top of the window): Frequently Asked Questions - Ed & Eg Financial Advisors
5. Next, write the code to display the Frequently Asked Questions' introduction. After the line, insert the following: Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
6. Now you are going to write the code to display up to ten questions on a page using pagination. This first piece of code displays the title of each entry. The limit parameter is what determines how many entries to display on each page, and the paginate parameter indicates where you would like the pagination links to appear (the choices are top, bottom, or both). Within the paginate variable pair, a conditional statement makes sure that there is more than one page of entries before displaying in order to display the pagination links. (This means that, initially, since you do not have more than ten entries, you will not see these pagination links). Insert the following code just before the line that appears immediately above : [ 116 ]
Chapter 5 {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom"} {title}
{paginate} {if "{total_pages}" != 1}
Page {current_page} of {total_pages} pages {pagination_links}
{/if} {/paginate} {/exp:channel:entries}
7. If you click Update and then visit http://localhost/faqs, you will see the titles for the channel entries you have already submitted.
8. Now you can add the questions for each entry, along with a link to read the answers. Insert the following code after the header:
<strong>Q: <em>{faqs_question}
<strong>A: Read the answer here!
[ 117 ]
Creating a Fully-Equipped Channel
The permalink tag generates an HTML link to the URL for the single-entry page for each entry. A permalink is so called because it is a permanent link to that entry. For example, the multiple-entry page http://localhost/faqs may display different FAQs in different orders at different times, but the permalink http://localhost/ faqs/browse/living_paycheck_to_paycheck will always be a link to the Living Paycheck to Paycheck entry. (Note that you have not yet created the browse single-entry template). The permalink tag includes one parameter, which is the template group and the template to use to display the entry. It then dynamically adds the URL title for you. In this case, you are linking to the browse template of the faqs template group (although you are using Preload Text Replacements instead of referencing faqs/browse directly).
Now visit http://localhost/faqs and you can see the questions along with links to read the answers. The links do not work yet since you have not yet created your single-entry template. You will do this next.
You are done with your multiple-entry page template! Next, you have to create the single-entry page.
Creating your single-entry page
As previously explained, you are going to use the faqs/browse template for your single-entry pages. 1. In the control panel, go to Design, Templates, and then click on Template Manager. Highlight the faqs template group and select New Template. [ 118 ]
Chapter 5
2. Name the new template browse. Leave the template type as Web Page. Under Default Template Data, highlight Duplicate an Existing Template and select faqs/index as the template to duplicate. Click Create and Edit.
3. The first change you are going to make is the HTML that appears in the browser title bar. In the includes/.website_page template in Chapter 4, Moving a Website to ExpressionEngine, you used the {exp:channel:entries} tag to get the title of the entry from the channel and use it as part of your HTML title. You will now do this again. Remember that the disable parameter cuts down on unnecessary database queries given that you are just retrieving the title of the entry and nothing else. Change the to read as follows: {exp:channel:entries channel="{my_channel}" disable="categories|category_fields|custom_fields|member_data|pagi nation"}{title}{/exp:channel:entries} - Ed & Eg Financial Advisors
4. Underneath the line , delete the entire block of code from the down to (and including) the {/exp:channel:entries} tag. 5. Now add the following code in the section instead. This code is very similar to the code for your browsing page, except that you are displaying the answer and instead of links to the single-entry page, you have a link back to the main browsing page. {exp:channel:entries channel="{my_channel}"} {title}
<strong>Q: <em>{faqs_question}
<strong>A: {faqs_answer}
[ 119 ]
Creating a Fully-Equipped Channel {/exp:channel:entries}
Note the use of the path variable to provide a link back to the index template of the faqs template group. If you wanted a link to a template that was not index, you would have to write it as: {path=template_ group/template}. The difference between the permalink variable used to link to the single-entry page and the path variable used to link back is that the permalink variable automatically adds the URL Title of the entry to the template specified (so you are taken to the URL specific to the entry), whereas the path variable does no such thing (it simply takes you to the template group and template specified).
You now have a FAQs page that displays all your faqs (with built-in pagination once you post enough entries). You can also click on individual questions to see the answer. The next step is to add some user interactivity to the single-entry page by allowing visitors to leave comments or add their own suggestions to each question.
Allowing comments on your entries
Comments are one of the easiest ways for visitors to interact with your site. They are also an easy way to attract spammers, who will be glad to leave hundreds of comments linking to websites of dubious quality. Luckily, ExpressionEngine includes features designed to prevent abuse.
Preventing comment spam
1. Comment preferences are set on a per-channel basis, allowing you to have different preferences for different channels (although when you create a new channel, you can copy the preferences from an existing channel to make things simpler). Go to Admin | Channel Administration | Channels and select Edit Preferences for the FAQs channel. [ 120 ]
Chapter 5
2. Here are all the aspects of the channel that you can fine-tune, organized into expandable groups. The General Channel Preferences were set when you created the channel, and include the channel name and short name.
3. Click on Path Settings. The path settings are the URLs that are unique to this channel. When creating links in your templates, ExpressionEngine will use these settings to know what URL to link to. Set your Channel URL to http://localhost/faqs and set your Comment Page URL and Search Results URL both to http://localhost/faqs/browse. You have not yet created an RSS template, but you can set your RSS Feed URL to be http:// localhost/faqs/rss in anticipation. The Ping Return URL does not apply to this channel.
When the Live Look Template is set, you will see a new Live Look link after publishing a new entry, as well as a new View link on the Content | Edit page. When you click one of these links, you will be taken to the livelook template to see the entry. A live-look template is coded exactly like an ordinary single-entry page template, and although you can define your single-entry template to be your live-look template, the true power comes into play when you define a live-look template that displays entries that would not be visible in your single-entry page template (either because they are future-dated or because they do not have an open status). This allows you to draft an entry with a closed status, for example, and view what it will look like on your website before you publish it with an open status.
[ 121 ]
Creating a Fully-Equipped Channel
4. The Administrative Preferences sets up defaults for each entry. For example, if you know the channel does not have comments, instead of having to click No to Allow Comments on each entry, you can set the default for every new entry to be no here (leave it set to Yes right now). The field for the search excerpt allows you to define which custom field is displayed when a member searches your site—the excerpt will automatically strip out any HTML formatting. For now, leave this set to Question. 5. The Channel Posting Preferences determines what to do with URLs inside a channel entry—you can either automatically link to them or leave them as plain text. Since only trusted people (such as yourself, Ed & Eg) will be able to post to this channel, you can Allow ALL HTML and say Yes to allowing images as well as to converting URLs into links. If your channel will involve lots of example HTML code, you could Convert HTML into character entities, meaning that any HTML entered as part of an entry will display on screen as-is and not be interpreted by the browser. At this time, no changes are needed. 6. Next, click on Versioning Preferences and set Enable Entry Versioning to Yes. By doing this, you can keep old versions of a channel entry saved. This is useful as it provides a quick undo feature for edits which were made erroneously. Enabling this option creates a new Revisions tab on your channel Publish page where you can load previous revisions. This option is not a substitute for doing a full database backup at regular intervals. [ 122 ]
Chapter 5
7. Select Notification Preferences. These preferences allow you to set up individuals to receive e-mails whenever a new entry or comment is posted. Setting this is essential if you require a moderator to approve all comments but can also be useful if you do not moderate your comments, as a means to monitor comments for comment spam. If you are using a localhost environment, outgoing e-mails may not work. So for now, leave all the notification options set to No. 8. Select Comment Posting Preferences. This is where you can either lock down or open up who can post comments and how many hoops they have to jump through in order to do so. Right now, say Yes to allow comments and No to requiring membership in order to post comments. As you are not requiring membership, say Yes to enabling a CAPTCHA for comment posting and say Yes to requiring an e-mail address to be entered when a reader tries to post a comment, but say No to moderating comments. Comment moderation means that an administrator, such as you, must approve every comment before it actually appears on your website. CAPTCHA stands for a Completely Automated Public Turing test to tell Computers and Humans Apart and is a puzzle that is easy for a human to solve, but not easy for a computer to solve. It is designed to filter out real people posting comments from automated scripts that are posting comment spam. ExpressionEngine's CAPTCHA technology relies on an image of letters with a background that makes it difficult for a computer to identify the letters. The person submitting the comment must type in the letters from the image correctly in order to post their comment. The downside to using an image in CAPTCHA technology is that it is not very accessible for visually-impaired visitors who might be relying on screen-readers to navigate your website. There are add-ons that provide a solution to this, such as Accessible Captcha (available at http://devotee.com/add-ons/extensions/accessible-captcha/). This addon changes the graphic to a user-defined question and answer, such as 2+2. A human could easily answer 4, but an automated spam program would not be able to do so. Search for CAPTCHA at http://devotee.com/ for other add-ons [ 123 ]
Creating a Fully-Equipped Channel
9. Leave the Maximum number of characters allowed in comments at 5,000, but set a comment re-submission time interval of 30 seconds. This option prevents an automated script from submitting more than one comment every 30 seconds. It can be useful as a deterrent against comment spam (especially if you are not moderating your comments or using CAPTCHA technology). Leave the comment expiration setting at 0 (meaning comments do not expire). If desired, you can use this setting to stop accepting comments on entries after a certain number of days. This can be useful to reduce the number of places on your website where comment spam can be posted. For the Comment Text Formatting, select XHTML but Allow only safe HTML. This means that formatting HTML, such as <strong> and <em>, will work, but more complex HTML will be rendered in plain text rather than being interpreted by a browser (thereby preventing malicious code being executed on your website). Do not allow image URLs in comments and do not automatically turn URLs and e-mail addresses into links (these options discourage spammers because their comments do not become links that could drive traffic to their website).
[ 124 ]
Chapter 5
10. Finally, the Publish Page Customization allows you to set a default entry title or URL title prefix that will apply to all new entries. This can be useful if you want all your entries to have the same prefix. Right now, leave these blank. Also, leave the Display Rich Formatting Buttons option set to Yes. Setting this to No would turn off the HTML formatting buttons (such as bold and italics) on all your custom fields, regardless of each individual custom field setting. 11. Click on Update and Finished to save all your settings. The settings you have just seen are useful in combating comment spam, especially from automated scripts, and it's recommended to consider them carefully before enabling comments. Using some combination of either requiring membership to post comments, enabling CAPTCHA technology, and/or enabling comment moderation along with setting an administrator up to receive notifications of new comments allows you to minimize comment spam as much as possible and quickly identify it when it does occur. You are now ready to create a form to accept comments. More information on all of these preferences can be found in the ExpressionEngine documentation at http://expressionengine. com/user_guide/cp/admin/content_admin/channel_edit_ preferences.html.
Creating a comment form
The first step in accepting comments is to create a form where visitors can write and submit their comments. Comments have to be tied to a specific channel entry, and therefore, the comment form can only appear on single-entry pages. Therefore, you will add your comment form to the faqs/browse template. 1. Open the browse template in the faqs template group for editing and type in the following code after {/exp:channel:entries}. This code displays the comments that other people have submitted. The title of the section is Comments. Comments
{exp:comment:entries} {if comments} {comment}
Posted by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/if} [ 125 ]
Creating a Fully-Equipped Channel {if no_results} There are no comments at this time - be the first to share your thoughts!
{/if} {/exp:comment:entries}
2. Next, add the code to create a comment form. Add this after the {/ exp:comment:entries} tag. First, this creates the fields for the visitors name and e-mail address. Since you would already have the name and e-mail address of any member who is logged in, you only need to ask for this information if the visitor is logged out. {exp:comment:form} Post Your Own Comment
{if logged_out}
{/if}
{if logged_out}
{/if}
{if captcha} {captcha}
[ 126 ]
Chapter 5
{/if}
{/exp:comment:form}
You can also add fields for a visitor's location or website. Use the same format as the email field in the previous code, but replace the word email with either location or url.
3. Now try posting your first comment. In order to see the website as a visitor will see it, log out of the control panel by clicking on Logout at the top-right and confirming you want to log out. (Closing the control panel without logging out will leave you logged in). Now visit http://localhost/faqs and click on a question. 4. Fill in your name, e-mail, type in a comment, and leave the box to remember your personal information, and the box to notify you of follow-up comments unchecked. If you check Remember my Personal Information, then the next time you see a comment form, your name and e-mail address will be pre-filled. Note that if you are logged in when you visit this page (for example, if you were previously logged into the control panel), then you will not see the fields for the name or e-mail and you will not see the CAPTCHA.
5. Enter the CAPTCHA word. Notice that each time you refresh the page, a different image with a different word is shown for your CAPTCHA. When you have completely filled in the comment form, click Submit.
[ 127 ]
Creating a Fully-Equipped Channel
Note that currently the Preview button will not work as you have not yet set up a preview template. If you are using a localhost environment, posting comments can be more difficult than when using an installation on a real website. If you are unable to post comments in the localhost environment, try changing the setting Require IP Address and User Agent for Login to No. This setting can be found in the control panel under Admin | Security and Privacy | Security and Sessions.
6. The page will auto-refresh, and you should now see the comment that you submitted.
Allowing visitors to preview comments
One final aspect of comments that hasn't yet been covered is the ability to preview the comment before publishing. You may have noticed the Preview button on the comment form that does not work yet. 1. First, modify the faqs/browse template to include the following code after the {/exp:comment:entries} and before the {exp:comment:form} line. Notice how the code is almost exactly the same as the code to display an actual comment, except that you are using the {exp:comment:preview} tag instead of the {exp:comment:entries} tag. This means that the look and feel of the previewed comment is identical to how it would look if it were an actual comment. {exp:comment:preview} {comment}
Being previewed by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/exp:comment:preview}
[ 128 ]
Chapter 5
2. Next, change the line {exp:comment:form} to include the preview parameter as follows. This parameter tells the form which template to load if the preview button is clicked. {exp:comment:form preview="{my_template_group}/{my_single_entry_template}"}
3. Now go to the FAQs page, type in a comment, and click Preview instead of Submit. You can see that the comment appears and looks exactly as if you had submitted it, except that instead of Posted by in the footnote, it says Being previewed by. You can keep editing the text and clicking on Preview as often as you like.
Organizing your data with categories
Although you have created custom categories and assigned your entries to some of your categories, you haven't yet used categories to help visitors browse the FAQs. You will now do this, but first set ExpressionEngine to use category names rather than ID numbers in the URL. This means that instead of category browsing pages having a URL such as http://localhost/faqs/C8, the category URL will be more like http://localhost/faqs/category/getting_married 1. In the control panel, go to Admin, Channel Administration, and then Global Preferences.
[ 129 ]
Creating a Fully-Equipped Channel
2. Say Yes to using category URL titles in links. Leave the Category URL Indicator as category. (If you do change this, bear in mind that whatever word you use here becomes a reserved word and cannot be used as a template name).
3. While you are on this page, also select No to auto-assigning category parents and click on Submit. Later in the chapter, you will use categories to show visitors who are viewing one question other related questions from the same categories. If all questions have the same two parent categories autoassigned, the related questions that are displayed are going to be less tightly coupled to the question being viewed.
Displaying categories with your entries
To encourage visitors to browse by category, it makes sense to display the categories that each entry belongs to underneath the questions on the faqs/index page. For this, you will use the channel {categories} tag, which allows you to list the categories, along with the {comment_total} tag to show how many comments each entry has and the {comment_url_title_auto_path} tag to link to your single-entry page for comments. Note that the {comment_url_title_auto_path} tag autogenerates the URL to your category template, as defined in Admin | Channel Administration | Channels, under Edit Preferences for the FAQs channel, then under Path Settings. The option Comment Page URL should be set to http://localhost/faqs/browse.
1. Edit the faqs/index page and add the following code underneath the Read the answer here! permalink and above the {paginate} line. <strong>Categories: [ 130 ]
Chapter 5 {categories backspace="3"}{category_name} | {/categories}Comments ({comment_total})
Everything between the {categories} opening tag and the {/ categories} closing tag is repeated for each category that the channel entry is assigned to. In this code, there is a vertical bar (|) after the category name and before the next category name to separate the categories. To prevent this vertical bar appearing after the last category, we use the backspace parameter. This parameter removes the specified number of characters from the end of our code after the last category name only (in this case, the | and the surrounding two spaces). This parameter is specifically designed to remove separators or other code that it makes sense to have between categories, but not after the last category.
2. Click on Update and Finished and then visit the FAQs page. You should now see underneath each answer—a piped list of categories that the entry belongs to. Clicking on one of the categories takes you to a category browsing page where you can see other entries that have the same category. At the moment, given that you only have two entries right now, namely, your category browsing pages and your main multiple-entry page, it will not be substantially different unless you pick a category that is unique to just one entry. Once the number of entries starts getting higher, browsing by category will be a much faster way of finding related questions than simply browsing through all the questions.
[ 131 ]
Creating a Fully-Equipped Channel
Distinguishing your category browsing page
Currently your category browsing page and your main multiple-entry page look identical—they have the same page title and the same introduction. Within the faqs/ index template, you can tell if you are on the main multiple-entry page or a category browsing page by looking at the URL. If segment_2 (the part of the URL after faqs) is category, you are on a category browsing page. You can, therefore, use this condition to display slightly different content accordingly. 1. First update the HTML title (which appears on the title bar of the window). To do this, edit the faqs/index template and replace the
Frequently Asked Questions - Ed & Eg Financial Advisors with the following: {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} Questions About {category_name} - Ed & Eg Financial Advisors {/exp:channel:category_heading} {if:else} Frequently Asked Questions - Ed & Eg Financial Advisors {/if}
2. Next, you can replace the code appearing after down to, but not including, the exp:channel:entries tag with the following: {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} Questions About {category_name}
{category_description}
{/exp:channel:category_heading} {if:else} Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
{/if}
[ 132 ]
Chapter 5
This code says that if you are on a category-browsing page, then the page heading should be Questions About {category_name} and the introductory text should be the category description. To edit the category descriptions, you have to edit the individual category in question. Go to Admin | Channel Administration | Categories, then click on Add/Edit Categories for the FAQ Categories group, and edit the category you want.
Now your category browsing pages look markedly different to your main multipleentry browsing page. However, this setup still requires your visitors to deliberately click on a category that interests them in order to find other FAQs that might be of interest. A different approach would be to display, at the end of the single-entry page, a list of other FAQs that have the same category (and therefore, are likely to be of interest to the visitor). In this way, the visitor is encouraged to keep browsing without ever realizing they are using categories.
Displaying related entries by category
To display other entries in the same category on your single-entry page, you need to make use of the ExpressionEngine parameter related_categories_mode. This looks at the URL of your single-entry page and then brings back the data of other entries that are in the same category as the page you are on. 1. Edit the faqs/browse template. Insert the following code after the line {/ exp:comment:form}: Other Questions Like This
{exp:channel:entries channel="{my_channel}" limit="5" related_categories_mode="yes" custom_fields="yes" orderby="random"} {if no_results} There are no questions like this currently – check back soon though...we're always adding more!
{/if} <strong>Q: <em>{faqs_question}
[ 133 ]
Creating a Fully-Equipped Channel <strong>A: Read the answer here!
{/exp:channel:entries}
Here you are bringing back up to five entries that are in the same categories as the question being viewed. To ensure variety, the entries are displayed in a random order, meaning that if you have more than five entries, no two sets of related questions will be the same.
2. If you now visit http://localhost/faqs and click on an entry, you should see a link to the entry you did not click on at the bottom of the single-entry page. If you do not see a link to your entry, it means the entry you are viewing is the only one in that category.
Now, as Ed & Eg go through and start adding hundreds of questions and answers, ExpressionEngine will dynamically organize the content. In this way, you may catch a visitor's eye with a question they want to know the answer to, and then keep them hooked by dynamically showing them other questions that are similar to the question they initially clicked on.
The FAQ snippet
The final step in getting visitors into the Frequently Asked Questions section of the website is to display Frequently Asked Questions in the widebar at the bottom of each page. Currently, there are two, static FAQs that are displayed in the widebar. In this section, you will update the widebar to display three random entries from the FAQs channel. To do this, it makes sense to use a snippet. Why a snippet? If you recall from Chapter 4, a snippet is used when you want to reduce repetition. In this case, since the widebar will be used on lots of templates, it is a great candidate for becoming a snippet. Why not a global variable? Remember that global variables do not support ExpressionEngine tags. Since you are planning to show data from an ExpressionEngine channel, a snippet is required. [ 134 ]
Chapter 5
In this section, you are choosing to display three random entries in your widebar. If you wanted more control over which FAQs were displayed at the bottom of every page, you could manually set the status of three entries to a custom status such as Featured (instead of open). Then, in your snippet, you could specify in the {exp:channel:entries} tag that you only want to include entries where status="Featured". You would also have to add a parameter status="open|featured" to the {exp:channel:entries} tags in all your other templates that use the FAQs channel. ExpressionEngine does not display entries that do not have a status of open, by default.
1. In the control panel, click on Design, then Templates, and finally Snippets. Then click on Create a New Snippet. 2. Call the snippet website_faqs and type in the following code to display your random entries. Note the use of the switch parameter—this essentially says that for the first entry, use colA as the div id. The second entry should use colB and the third entry should use colC. If you were displaying more than three entries, the fourth entry would use colA again, which, in this case, does not make sense to do. {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off"} Frequently Asked Question
{faqs_question} Find out…
{/exp:channel:entries}
Remember that ExpressionEngine uses the URL to dynamically determine whether you are on a single-entry page or a multiple-entry page. (If the URL has the url_title of a specific entry after the template name, then ExpressionEngine recognizes that you are on single-entry page and will only display content from that entry). This means that you cannot display content from another entry (or another channel) on a single-entry page unless you tell ExpressionEngine to ignore the fact that you are on a single-entry page. This is what the dynamic="off" parameter does.
[ 135 ]
Creating a Fully-Equipped Channel
3. Next, edit all your existing templates that show the widebar (includes/. website_page, includes/404, faqs/index, and faqs/browse) and replace the widebar code with a reference to this snippet instead. For each template, delete all the code including and between to and replace it with {website_faqs}.
Your work with the FAQ page is almost complete. The next step is to provide a way for visitors to be notified about new FAQs, without having to constantly re-visit your website. For this, you will use a feed.
Setting up an RSS or Atom feed
RSS or Atom feeds are an alternative way of allowing visitors to keep up-to-date on your website. Essentially, the visitor subscribes to your feed through their e-mail software, browser, or other news readers, and then they get notified when you post new entries. This saves them from having to periodically revisit your website to see if there is new content or not. Having a feed available can make the difference between a visitor being someone who visited your website and liked it (but does not come back) and someone who visited your website and now reads every new post. When building a feed, the easiest approach is to start with a pre-built ExpressionEngine feed template. This will take care of the top portion of the feed (containing meta-information such as the date, the URL of the entry, and so forth), meaning you only have to make a few customizations so that the feed displays the content from your custom fields. An RSS 2.0 template can be found at http://expressionengine.com/wiki/RSS_ Template_for_EE2/. However, since Agile Records comes with both an RSS 2.0
and an Atom 1.0 template, you can also base your template on theirs. If you did not install Agile Records, using the template from the wiki will have the same results. 1. From the Template Manager, select the FAQs template group and create a new template called rss. The template type should be RSS Page and you should duplicate a template, namely, the news/rss template. Click on Create and Edit. [ 136 ]
Chapter 5
2. On the first line, change {exp:rss:feed channel="news"} to {exp:rss:feed channel="faqs"}. (If you are starting from the wiki template, then the channel on the first line is howto, but should still be changed to faqs). 3. About half-way down, you will see a familiar {exp:channel:entries} tag. In this tag, change news to faqs. The limit parameter limits the number of results to 10 and the disable parameter tells ExpressionEngine not to query the database for member data (reducing the amount of data that is queried). Finally, every time a news-reader polls your website for new entries, it provides the last date/time that it checked. The dynamic_start parameter tells ExpressionEngine to only return entries (if any) that have been posted since that particular last date/time. {exp:channel:entries channel="faqs" limit="10" dynamic_start="on" disable="member_data"}
4. Even further down, look for the XML tag <description>. On that line, you will see an ExpressionEngine tag {news_body} (or {body} if you are starting from the wiki template). This is a custom field, so you should change this line to use your own custom field—{faqs_question}. You could display both the question and the answer in the feed. However, in this example, you are going to display only the question, followed by a link to the answer page (using code you have already used on your multiple-entry page). <description>{faqs_question}]]>
[ 137 ]
Creating a Fully-Equipped Channel
5. Click on Update and Finished. If you now browse to the RSS template (http://localhost/faqs/rss), your browser will likely recognize it as an RSS feed.
If you get an error, you may not have set the template to be an RSS Page. Check the template preferences for your RSS template.
6. Now all you have to do is link to the feed from your FAQs page so that people know it is there. Edit the faqs/index template and add the following after the introductory paragraph and before the {/if}: Don't forget to subscribe to our RSS feed to stay up-to-date with new FAQs as they are posted.
[ 138 ]
Chapter 5
You can now use your favorite RSS reader to view the content. If you do not have a favorite RSS reader, your e-mail client will likely already support it. For example, Mozilla Thunderbird 1.0 and greater and Outlook 2007 and greater, both have builtin support for feeds. Alternatively, Google Reader is a popular and free web-based alternative (http://www.google.com/reader). If you are following along in a localhost environment, then web-based feed readers will not be able to access your feed.
The instructions for creating an Atom feed are almost identical to those for creating an RSS feed: 1. Create a template faqs/atom and duplicate the news/atom template from the Agile Records example site into your new template. (The template type should still be RSS Page). 2. Change the feed channel on the first line to faqs. {exp:rss:feed channel="faqs"}
3. Change the channel in the exp:channel:entries tag to faqs. {exp:channel:entries channel="faqs" limit="15" dynamic_start="on" disable="member_data"}
4. Unique to Atom feeds, change the scheme to point to the single-entry template where the entry is: scheme="{path=faqs/browse}"
5. Change the custom fields inside the CDATA[] tag to reflect the content that you want to display inside your feed: {faqs_question} ]]>
6. Save your template and verify that you can subscribe to your new feed (http://localhost/faqs/atom). What is the difference between an RSS and an Atom feed? RSS 2.0 is the older and more established feed. Atom 1.0 was designed as a modern alternative to RSS. For practical purposes, news readers can read either feed, so which one you choose is up to you or you can use both types of feed and let your visitors pick whichever they prefer.
[ 139 ]
Creating a Fully-Equipped Channel
Improving your 404 Page
In the last chapter, you created a 404 Page for your site. ExpressionEngine allows for great flexibility with URLs and the downside of that is that invalid URLs can often return valid content. As an example, if you type in an entry URL that does not exist (such as http:// localhost/faqs/browse/ihatetoast, you see an actual page with content instead of your 404 template. This can be confusing to visitors if they mistype the URL. Luckily, there are options available to fix this. ExpressionEngine comes with a redirect tag that you can use to redirect visitors to another template, based on a conditional. Typically, the syntax of this tag would be {redirect="template_group/template"}. However, when redirecting to a 404 Page, rather than redirecting to "includes/404", you can redirect to "404". This will return the template that you defined in chapter 4 as your 404 template (if you have not yet defined this template, you can do so in Design | Templates | Global Preferences). The difference between a redirect to the template directly and a redirect to 404 is that, if you redirect to just 404, the redirect also includes 404 Page headers, meaning that search engines visiting that URL will recognize it as invalid and will not index it. 1. First edit the browse template of the faqs template group. Change the HTML to read {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes"}. This change means that if the URL does not match up to the URL of an entry, it will not display any content from the channel. 2. Next, between the opening {exp:channel:entries} tag and the closing {/ exp:channel:entries} tag, add the following code. This change says that if there is not an entry to display, then show your 404 Page instead. {if no_results} {redirect="404"} {/if}
3. Now visit http://localhost/faqs/browse/ihatetoast and you can see that your 404 template is now returned. 4. You can go one step further with your redirect. For example, you know that there should not be a segment in the URL after the URL of the entry (that is, http://localhost/faqs/browse/living_paycheck_to_paycheck is a valid URL, but http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus is not). Right now, the hippopotamus URL will still display your entry. If you add the following code to your faqs/browse template, immediately after the code you added above, it will cause a 404 redirect to take place instead: [ 140 ]
Chapter 5 {if segment_4!=""} {redirect="404"} {/if}
5. Now visit isit http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus and you will see a 404 Page instead. What about your multiple-entry page? For example, a URL of http://localhost/ faqs/rubbish should return a 404 Page, but it currently displays your multiple-
entry page. If you were not using categories or pagination, you could safely say that there should not be a segment 2, and if there is, redirect to 404. However, category URLs (such as http://localhost/faqs/category/debt) also use the faqs/index template, so you would need to build in logic to say that if segment 2 is category, then do not redirect to a 404. However, this logic gets more complicated. Once you have more than 10 entries, your entries will paginate over different pages, and the URLs for the pages will also be category 2 segments (for example, http://localhost/faqs/P0). Entries can also be archived by date. For example, a URL of http://localhost/ faqs/2011/11 will only display entries from November 2011. If you are organizing your entries by date in this way, then any year could appear in segment 2. One solution is to use an add-on such as MD Detect Page Type (http://devot-ee. com/add-ons/plugins/md-detect-page-type/), which makes it easy to tell if
you are on a category page, paginated page, or archive page, and therefore makes it much easier to build a conditional statement to display a 404 Page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. You have suddenly started getting spam comments on old FAQs. Set the comments on the FAQ channel so that after 60 days, no more comments are accepted. 2. Your FAQs currently have no indication of when they were posted or who posted them. On both the single-entry and multiple-entry pages, modify the question to include who posted the question and the date of the post (although this is something that might not make sense on the FAQs channel, in most situations where articles are being posted regularly, displaying the date of the post is a common requirement). to include the date of the post. [ 141 ]
Creating a Fully-Equipped Channel
3. Update the snippet that displays the three FAQs on every page of your website so that instead of displaying three random entries, it displays three featured entries (based on a custom status of "Featured").
Summary
In this chapter, you got more practice in using custom fields, channels, and templates. You also got introduced to categories, comments, and feeds. In the next chapter, you will get an in-depth look at the built-in membership module, including registering members, managing members, setting member privileges and permissions, and creating parts of your website that only members can see. The key points to remember after working through this chapter: •
You used a FAQ example in this chapter. However, all the functionality covered in this chapter would equally apply to any dynamic content that your site might have—whether it's a blog, news articles, recipes, or the products you sell.
•
ExpressionEngine contains many options to help you control and filter comments. You can use CAPTCHAs, you can moderate all comments, and you can require membership for comments. You can also set it up so that you get e-mailed when new comments are posted.
•
Feeds are a great option to encourage repeat visitors—they are easy to set up and give people an alternative way to keep up with your website.
•
Preload Text Replacements, Global Variables, Snippets, and Embedded Templates are incredibly useful—it is definitely worth becoming comfortable using them.
•
Conditional {if} statements are also a powerful tool, allowing you to account for different situations in a single template such as redirecting to a 404 Page if there are no entries or displaying category-specific information if the URL segment is a category.
[ 142 ]
Members You have now used ExpressionEngine to build a fully-functional website for Ed & Eg. So far, however, you are the only one who has logged into ExpressionEngine on your website and the only one who has been making any changes. Now is a good time to explore the member functionality of ExpressionEngine. The Freelancer license does not include member management, so this chapter will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing. In this chapter, you will: •
Allow visitors to register on your website and see what they see
•
Create a member group for Ed & Eg, so they can log into the control panel and publish and edit entries (but not edit template code or change administrative options like you can)
•
Use conditional statements to create content that only members can see
First, however, it makes sense to review how membership management works in ExpressionEngine and what all your options are.
Designing your membership ExpressionEngine allows two types of members:
1. Members who can log in to your website, but not into the administrative control panel. These members can see any content that you have coded in your templates as member-only as well as perform any actions that you have set to require membership (such as post comments).
Members
2. Members who can log into your website and also the administrative control panel. Depending on the permissions you give these members, they may be able to complete tasks such as creating or modifying channel content, creating or modifying templates, or changing global settings. If you have an ExpressionEngine-powered website, allowing members is not a requirement. If you do not intend to support members on your website, it is recommended to turn off new member registrations completely (the first option under Members | Preferences in the main menu). Membership in ExpressionEngine is based on member groups, which are what determine the permissions a member has. Each member can only be in a single member group. For members with administrative control panel access, ExpressionEngine offers a huge amount of granularity over what the members can see and do inside the control panel. You can define which channels they can post to (if any), which template groups they can modify (if any), and much more. For members without administrative control panel access, ExpressionEngine offers a member control panel, where members can post a profile, see other members' profiles, as well as send an e-mail or a private message to another member. As with the administrative control panel, you have control over what different member groups can actually do. To make joining your website attractive, you can make some or all of your content member-only by using conditional statements in your templates. You can look to see if a member is logged in and then display different content based on that, or you can display different content to different member groups. In this chapter, you will create a new member group for Ed & Eg that allows them to edit and post channel entries, but that does not allow them to edit templates. Then, to encourage members to join your website, you will update the FAQs channel so that some FAQs are viewable only to members. First, though, you will explore the membership preferences, and then explore the member profile screens as if you were a new member.
Membership preferences
There are many options you can set for your members on a global level that will impact their experience on your site. 1. First, log in to the control panel (http://localhost/admin.php) with your administrator login. [ 144 ]
Chapter 6
Note that you are also assigned to a member group—the Super Admins group. This group gives you access to everything. ExpressionEngine also comes with a Members member group, which does not have administrative control panel access, but can do everything in the member control panel. The permissions of the Members member group can be modified in Members | Member Groups, but the Super Admins group cannot be altered.
2. From the top menu, select Members and then select Preferences. 3. The first section is called General Configuration. Here, you can set whether you want members to be able to register themselves or not and the hoops they have to jump through in order to register. For example, you can require member account activation. If you do not require this, then any new members automatically become assigned to the Default Member Group (which is Members, but can be changed further down). If you require activation (either by an administrator or by requiring the new member to click on a link in their e-mail), then members will be placed into a Pending member group until they are actually activated (by selecting Members | Activate Pending from the main menu). For now, if you are using a localhost environment, say Yes to allow new members and select No activation required (since a localhost environment does not include an e-mail server and so cannot send activation e-mails). If you are following along on an actual website, it is recommended that you require activation of some kind.
4. Further down, you can require new members to accept a terms of service (if you say No, the terms of service will still display) or to complete a CAPTCHA form when they register. You can also allow members to set their own localization preferences (that is, members can set what time zone they are in and then see all times in their local time zone). Ensure that all these are set to Yes.
[ 145 ]
Members
5. Further down, you can set the member group that new members are assigned to (for now, leave this set to Members). You can also change the Default Member Profile Theme. You have two choices: Agile Records or Default. Since the Agile Records theme is designed specifically for the Agile Records website, select Default here. Finally, you can change the Profile Triggering Word, which changes the URL for the member control panel. (For example, if you changed this to guest, then all member control panel URLs would include the word guest instead of member). Leave this set to member for now and click Update. If you do not see any options for the default member profile theme (not even default), then you may be using the Freelancer license, which does not include member management.
6. The Member List Preferences allows you to change the default sort and order of your public member list page (which lists all the members on your site). Do not make any changes right now. 7. The Notification Preferences allows you to receive an e-mail whenever a new member registers at your site. This can be useful if you require an administrator to activate all new member registrations, or if you simply want to monitor new member registrations. If you are using a localhost testing environment, do not make any changes to this screen right now (as the localhost environment does not include an e-mail server, meaning such e-mails cannot be sent). If you are following along on a live website, type in your e-mail address here.
[ 146 ]
Chapter 6
8. ExpressionEngine includes functionality to allow members to contact each other via your website through Private Messages. The Private Messaging Preferences allows you to restrict the number of characters or the size of the attachments that can be attached to private messages. 9. ExpressionEngine includes the ability for members to associate an avatar (image) with themselves, which you can then display next to comments or forum posts that the member makes. The Avatar Preferences allows you to control whether avatars are enabled and whether members can upload their own images. 10. You can also choose whether you want to allow members to upload photos of themselves (which are then displayed on their profile). 11. Finally, you can choose whether or not you want to allow signatures, which appear after every forum post. Signatures are enabled by default, though signature images are turned off. 12. If you have not already done so, click Update to save any changes you have made. Now that you have made these modifications, the next step is to walk through registering as a member and explore the member control panel.
Registering as a new member
The membership functionality in ExpressionEngine is very rich, so rather than having to design your own membership templates from scratch, ExpressionEngine comes with pre-built member templates that you can use for members to login, register, share profiles, change settings, and send e-mails/private messages to other members. When following along in this section, remember that you are a member of your own website. This means that in order to register as a new member, you must first log out of the control panel by clicking Logout at the top right. 1. After logging out of the control panel, visit http://localhost/member/ register. (Remember, if you have the Freelancer license, this URL will not work). 2. You will be presented with a standard Member Registration screen, complete with a generic terms of service. Fill in the form with settings different than the administrator login that you have been using up to this point.
[ 147 ]
Members
Note that, by default, there can only be one username per e-mail address, so you cannot use the same e-mail address for this member as you did for your administrator login. This setting can be changed in Admin | Security and Privacy | Security and Sessions, although it is recommended not to change this setting as it can cause issues if a member with two accounts associated with their e-mail address forgets their password.
3. Select the check box to agree to the terms of service, fill in the CAPTCHA, and click Submit.
[ 148 ]
Chapter 6
4. As long as there were no errors with the information provided, you should be presented with a registration complete message and a link to go back to the main website. You are now registered as a new member!
The member profile
Now that you have walked through registering as a new member, you can see what the member control panel looks like. For this section, you can either be logged in as the member you just created or logged in using your Super Admin username. 1. Go to http://localhost/member/profile. If you are prompted to log in, log in first. 2. You should see a screen with your account statistics: your e-mail address, when you became a member, when you last visited the website, how many channel entries you have posted, and how many comments you have made. Along the top are links to log out or to see the member list. Along the left are links that allow the member to modify and personalize their account.
3. Click Edit Profile on the left-hand side and you can change what other members see about you. Go ahead and fill it in so that when you later visit your profile screen, you can see how it looks. 4. As mentioned earlier, Edit Signature and Edit Avatar are more relevant if you have purchased the forum module. If enabled, members can set their signature and avatar here. ExpressionEngine comes with a default set of avatars that members can select from. [ 149 ]
Members
5. With Edit Photo, you can also associate a member photo that other members can see when they visit your profile (although this option is not enabled by default).
6. Select Email Settings from the left-hand side. This allows members to finetune what notification e-mails they receive. By default, ExpressionEngine allows members to e-mail other members—a member can turn this off here. You can also change your e-mail address on this page. 7. Username and Password allows you to change your username, your screen name, or your password. 8. Edit Preferences allows members to determine whether avatars, signatures, or smiley images are displayed. Members can also prevent Private Messages from being sent to them on this screen.
[ 150 ]
Chapter 6
9. The Localization Settings allow a member to specify their Time Zone, their Time Formatting (US or European), and their Language (if you have multiple language packs installed). By selecting a different time zone, the member can see times in their local time zone. If the times on your website do not appear correct, it may be that either the server timezone or the daylight savings (summer) time setting has been set wrongly. These can be set in Admin | Localization Settings.
10. If a member has posted comments and selected to be notified of follow-up comments, then they are considered subscribed to that channel post. The Subscription Manager shows which posts a member is subscribed to and allows them to unsubscribe if desired. 11. The Ignore List allows members to ignore other members. As a result, any forum posts made by them will not display. 12. The Private Messages section is where members can send private messages to each other and view the ones they have received. 13. Finally, the Notepad is a scratch pad—any text typed into the notepad will be there next time the member logs in. This is most useful for members with administrative control panel access, as the notepad contents also appears on the right-hand side of the administrative control panel. The member control panel is very feature rich, allowing for a lot of functionality and configurability right out of the box. Members can send messages to other members, control what other members can see about them, and personalize settings such as their signature, avatar, or photo to suit their preferences.
The member list
Another option your members have access to is the member list. This can be used for members to browse other members and find their profiles or to send messages. 1. Click on Member List at the top-right of the member control panel or go to http://localhost/member/memberlist. Here, you are provided with a list of all active members. If there are lots of members, you can use filters or searches to find the person you are looking for.
[ 151 ]
Members
2. Click on a specific member and you can see the member profile, including any information the member may have personalized on their profile page.
3. Notice how the member's e-mail address is not publicly displayed. Click on the EMAIL button and you are brought to a form that you must fill in to send an e-mail. It is up to the recipient to decide whether they want to reply (and thereby reveal their e-mail address). With all this functionality, it is easy to build a website that members can use as a springboard to interact with other like-minded people. If you want to customize the member screens so that they share the same look and feel as the rest of your website, the templates can be edited in Design | Themes | Member Profile Templates and the corresponding files can be found in the /themes/profile_themes directory. (Note that it is best to make a backup of the templates before modifying them, in case you need to undo a change). Since each member page is made up of multiple templates, one technique (that you can see in the Agile Records templates) is to put an HTML comment in each template with the template name. In this way, you can view the source of the member pages and more clearly see which templates make up the page.
Linking to the member templates
As you have just seen, all the member functionality is pre-built. All you have to do is link to the pre-existing member URLs on your website and members can start registering and using your website.
[ 152 ]
Chapter 6
Next, you will set up the links in the sidebar on the right-hand side. If the visitor is logged out, there will be links to log in, register, or reset their password. If they are logged in, there will be links to log out, go to the member profile pages, or see the member list. 1. Log in to the control panel as a Super Admin. From the top-menu, select Design | Templates | Snippets. Select the website_sidebar snippet that you created in Chapter 5, Creating a Fully-Equipped Channel. 2. Add the following code to create the links immediately before the last in the snippet. Notice the use of the ExpressionEngine path variable (that you first saw in chapter 5)—this auto-generates a URL to the specific template group and template you specify. In this case, member is not a traditional template group, but rather the keyword you have defined in member preferences. If you do not feel like typing this in, remember that the finished code for each chapter can be downloaded at either http://www.packtpub. com/support or http://www.leonardmurphy.com/book2. Member Links
{if logged_out} - Login
- Forgot Password?
- Register
{/if} {if logged_in} - Profile
[ 153 ]
Members - Member list
- Logout
{/if}
3. Click Update and Finished and now visit the main website home page. Underneath Key Services, you should now see Member Links (depending on whether you are logged in or out will determine which links you see). Try the links to make sure they work.
You have now enabled the ability for visitors to register themselves on your website.
Introduction to member groups
By default, there are five member groups. You are already familiar with the Super Admins member group (which you are a member of). The Members member group is the group that approved members are put into (unless you have changed the default member group in the member preferences). By default, members in this group can do everything available on the member screens (such as sending private messages) as long as you have not disabled the option in the global Member Preferences. However, members cannot log into the control panel. The Pending members group is for members who have registered but have either not activated their membership via e-mail (if you allow self-activation by e-mail) or have not yet been manually approved (if you require members to be approved by an administrator). If you do allow self-activation by e-mail, it is a good idea to review the members of this group periodically and delete stale applicants (do this via Member | Activate Pending). [ 154 ]
Chapter 6
Members in the Banned member group cannot see your ExpressionEngine website, and the Guests member group is used for members who are not logged in. Since Super Admins can do anything and everything in ExpressionEngine and cannot be restricted, you should be very cautious about which members you assign to the Super Admin group. For example, while Ed & Eg need to be able to post and modify channel entries, it would be better not to give them access to templates, where they might accidentally change something. To accomplish this, you can create a new member group for Ed & Eg.
Creating a member group
In this section, you will create a new new member group called Editors for Ed & Eg. This will allow them to be able to log into the main control panel and publish or edit entries but will not allow them to view templates or change administrative preferences. After you create the member group, there will be two sets of options to configure. The first set of options applies to the member profile screens (and controls such things as whether they can send private messages). The second set of options control what the members can do within the control panel. For most members, you would not even allow them access to your control panel, so this second set would not apply. Throughout the configuration process, any options that you would not want to assign to someone you do not know and trust is bolded and colored red. 1. The first step is to create the member group. Log into the control panel as a Super Admin and go to Members | Member Groups. 2. Rather than creating a member group from scratch, you will base the new member group on the Super Admins member group. Underneath the member group listing is the option Create a new group based on an existing one. Select the Super Admins group from the drop-down box and click Submit.
[ 155 ]
Members
3. You will be brought to a new screen where you can give the new group the name Editors. Optionally, you can type in a description.
4. Continuing down the screen, the next option is Security Lock. If you allow groups, other than Super Admins, to administer members, you can control which member groups they can assign users to. As editors and owners of the website, you would want Ed & Eg to be able to approve and manage their members, but you would not want them to be able to assign members to the Super Admin or Editors group (for example). To accomplish this, leave this group Locked (meaning only Super Admins can assign members to the Editors group). To allow Ed & Eg to be able to assign members to the Members group, you would have to edit the Members group and adjust the group security lock to be Unlocked (by default, the Members group is locked, meaning only Super Admins can assign members to it).
5. The next option is Site Access. Since you would want Ed & Eg to have access to the website when it is offline, leave both options as Yes. (If you were creating a member group for members of the public, you would typically set this to No). [ 156 ]
Chapter 6
Within Admin | General Configuration, you can choose whether your system is on or not. You might choose to turn it off if you are doing updates and do not want members of the public to stumble across an incomplete site while the changes are in progress.
6. In the next option, Member Account Privileges, say No to allowing Ed & Eg to be able to delete their own account—if they accidentally did this, it would cause any content they had created to be deleted as well.
7. Comment Posting Privileges, Search Privileges, and Private Messaging Privileges allow you to control whether this member group can use these functions (and allows you to set member group-specific restrictions on their use). Since Ed & Eg own this website, do not make any changes to these screens.
[ 157 ]
Members
8. Control Panel Access is where you can allow (or prevent) the member group from accessing either the entire control panel or specific sections within the control panel. Since you want Ed & Eg to only have access to options they can safely use, say No to the following sections: DESIGN, add-ons (all five sections), ADMIN (all three sections), and say No to TOOLS (Utilities, Data, and Logs only). Leave the TOOLS section and the TOOLS: Communication set to Yes. Ed & Eg will only have access to the options set to yes here.
9. Under Control Panel Administration, say No to all the options except administrating member accounts, changing member groups, and banning users.
[ 158 ]
Chapter 6
10. Control Panel Email Privileges allows you to prevent Ed & Eg from sending e-mails through ExpressionEngine. Since there is no reason to do this, leave all the options as Yes. If you have a website where a large number of people will have control panel access (such as in a larger business), you might want to set this setting to No. 11. The Channel Posting Privileges allows you to decide what Ed & Eg can do with channel content (for example, if they can delete entries or edit other peoples' entries). Since Ed & Eg are the owners of the website, do not make any changes. 12. The Channel Assignment allows you to choose which channels Ed & Eg can publish to and edit. If you have Agile Records installed, you would want to ensure that Ed & Eg cannot see the Agile Record channels. Therefore, only say Yes to FAQs and Website—say No to Information Pages and News if they are there.
13. Comment Administration allows you to configure what comments Ed & Eg can view, moderate, edit, or delete. Leave all these options set to Yes. 14. Template Editing Privileges allows you to control which template groups Ed & Eg can edit. Since you do not want Ed & Eg editing any templates, say No to all of them. 15. Module Access Privileges allows you to control which modules Ed & Eg can access. Since you are not giving Ed & Eg access to the Add-On screens, you can say No to all modules (if there are any listed). 16. Click Submit to create the member group. You will be returned to the Member Groups page, where you will see your new member group in red and bold (because it has access to the control panel). You have now created an Editors member group, and all your changes have been saved. Next, you can log into the control panel as Ed or Eg and see what it looks like.
[ 159 ]
Members
Creating a member
Earlier in this chapter, you saw how to register yourself as a new member. Thankfully, as Super Admins, you can bypass this process and create new members directly in the control panel. In this section, you will create your first editor group member, Ed the Editor. 1. From the top menu, select Members | Register Member. 2. Fill in the username (edward), password, screen name (Ed), and e-mail address for your new member. (Remember that, by default, only one e-mail address can be used per member). Be sure to select the Editors member group as the member group assignment and then click Register a New Member.
3. You will be returned to a list of members in the Editors member group (right now, Ed is your first and only editor). Do not close this listing.
Logging in as Editor Ed
Another advantage of being a Super Admin is that you can log in as any other member without having to know that member's password. This allows you to see your website as they see it—which is helpful when you are developing new features or troubleshooting reported issues. 1. From the View / Search Members screen that you are on, click on the edward hyperlink.
[ 160 ]
Chapter 6
2. You will be taken to the member control panel for this member. From the left-hand side, select Login as Member (the second option from the bottom).
3. You can now choose which page of your website you want to see as Editor Ed. Select the Control Panel radio button and click Submit.
[ 161 ]
Members
4. You will then be logged in as Editor Ed. Although it looks like the control panel you have been working in so far, notice that there are far fewer options, both in the menu and on the main screen. Essentially, all Ed can do is publish new entries, edit existing entries, and administer members. ExpressionEngine has many options that allow you to decide how much access other people have to the control panel—you could set up a member group that can only post entries to a single channel or you could set up a member group that can do everything but post entries to a given channel. You can also set up member groups that do not have control panel access such as a trusted members group, which is exempt from comment moderation or that can search more frequently than regular members. You have now created a member group specifically for Ed & Eg to be able to create content without risk. However, there is one more area that can be customized by the member group: the Publish Page.
Modifying the Publish page layout
By default, the Publish page contains lots of options, spread across several tabs, some of which you will be unlikely to use for a given channel (such as the expiration date for an entry) and some of which you will intend to use, but will be liable to forget about (such as selecting the categories for an entry). Luckily, as a Super Admin, you can customize the Publish page so that the workflow better suits your needs. In the FAQs channel, you know you must select the category for a new entry, so instead of having the categories on a separate tab, you will move it to the bottom of the main tab so that you must scroll past it in order to submit your entry. In this way, you are less likely to forget to fill it in. 1. Log into the control panel as a Super Admin, and go to the Publish screen for the FAQs channel (Content | Publish | FAQs). 2. Towards the top-right (just to the left of the Notepad on the right-hand side), you should see an option that says show toolbar. Click this. (If you are not logged in as a Super Admin, you will not see this).
[ 162 ]
Chapter 6
3. A toolbar will appear with a list of fields, tabs, and authors. First, notice the eye on the right-hand side of each field name. If the eye is open, it means the field is visible. If the eye is closed, it means the field is not visible. (If there is no eye, it means the field is mandatory and cannot be made invisible). Click on the eye to toggle between open and closed. Close the following fields that Ed or Eg will be unlikely to modify on a per-entry basis in the FAQs channel: Expiration Date, Comment Expiration Date, Pings, Channel, and Options.
[ 163 ]
Members
4. The Tabs section allows you to delete tabs or create your own. For example, there are several tabs that have only one or two options on them. Rather than having all these tabs, you could delete all of them, and create a new tab for all your lesser-used options (such as the URL title and entry date, which you may want to alter for an entry, but not every entry). First, click Add a New Tab and call it Rarely-Used Options. Then click Add a Tab.
5. Next, click on the newly created tab and drag fields from the list of fields in the toolbar onto the main window in the position you would like them. Move the following fields: Entry Date, URL Title, Author, Status, and Revisions. If you do not see the revisions tab, you may not have enabled entry versioning while following chapter 5—to do so, go to Admin | Channel Preferences | Channels and then Edit Preferences for the FAQs channel. 6. Since Categories is something you always want Ed or Eg to select when they publish an FAQ (because the content is organized by category), click on the Publish tab and drag the Categories field from the toolbar onto the Publish tab. 7. Next, you can delete all the other tabs that you no longer need. Click on the trash can to the right of each tab name (other than Publish and Rarely-Used Options).
[ 164 ]
Chapter 6
Finally, each field on the main screen also has a little triangle at the bottom right and a little rectangular tab on the left. The triangle allows you to modify the size of the field (for example, so that it does not take up the entire width of the screen) and the rectangle allows you to modify the position of the field in relation to other fields. In this way, for example, you can put two smaller fields beside each other or you can reorder the fields as you see fit. 1. Now you can save your updated layout. At the bottom of the toolbar, check the boxes to apply the layout to both the Super Admins and the Editors member groups and then click Save Layout.
2. Now click hide toolbar to hide the toolbar, and you can see that the Publish page is substantially simplified. Instead of six tabs and lots of options you never use, there are two tabs—the first tab with options that you always want to set for a new entry, and the second tab with options that you rarely need to set, but might want to on occasion. To summarize, there are three ways to configure options on the Publish page: 1. The Member Group options allows you to configure which member groups can publish to which channels (or even whether a given member group with control panel access can publish to any channels). 2. The Custom Field options (reviewed in previous chapters) allows you to configure which options appear for each field—such as the HTML formatting buttons, write-mode, the spell-check, and so forth (and also whether the fields are mandatory or not). 3. The toolbar on the Publish page allows you to configure which options are visible on a per-channel, per-member group basis. This level of flexibility allows you to build a website for someone else to maintain, and to keep the interface uncluttered for that person, so that they only see the options they need to use. [ 165 ]
Members
Creating member-only content
So far you have seen the options available to you in the control panel for different member groups. For members with control panel access, the options are very comprehensive—you can disable entire sections (such as template editing) or disable individual items within a section (such as which template groups can be edited or which fields on the Publish page are visible). For members without control panel access, it is up to you how attractive you make the membership of your site, because any member-only feature has to be specifically coded that way in your templates. There are two ways you can restrict what nonmembers can see: 1. You can configure templates to not be viewable by certain member groups. If a person in an unauthorized member group attempts to access one of these templates, you can redirect them to a different template that says the content is for members only. From the Template Manager, where you would normally click to edit the template, click Access to change who can view the template and what template they should see instead. This can be useful if you are creating a new section to your website and want to allow certain member groups to try it out before going live to everyone.
[ 166 ]
Chapter 6
2. Alternatively, you can use conditional tags within templates to display different content. This allows you much more control and flexibility over what your visitors see—you can display different content depending on whether the member is logged in, depending on the member group of the member or based on any number of variables (for example, the username of the member or how many comments a member has posted). Read more about conditional tags at http://expressionengine.com/user_guide/ templates/globals/conditionals.html. Next, you are going to create a new custom status called Premium. If an FAQ is marked with a premium status, only registered members will be able to see the answer. Non-members will be able to browse all the FAQs, but if they select a premium FAQ, they will only see the question, along with a message encouraging them to register to see the answer.
Making content visible to members only
You have already seen the {if logged_in} and {if logged_out} tags to display different links, depending on whether a member is logged in or not. You will now use these same tags to determine whether or not to show them member-only content. WARNING: If you use conditional statements {if logged_in} and {if logged_out} inside the {exp:channel:entries} tag on a template, do not enable caching on that template or the conditionals will not work. The first person to visit the template will have their logged in state cached, meaning every subsequent visitor will be treated as if they have the same logged in state as that first visitor. Caching can be set for each template on the Template Manager screen by clicking on Edit Preferences for the template in question—by default, template caching is not enabled.
1. Before you can assign any channel entries to a premium status, you must first create the premium status by going to Admin | Channel Administration | Custom Status Groups. You currently only have one status group (statuses), so click Add/Edit Statuses.
[ 167 ]
Members
2. Next, click Create a New Status at the top right. (The Featured status you see in the screenshot will only exist if you installed Agile Records).
3. Call the new status Premium. Leave the Highlight Color blank. This controls the color of the status in the control panel—for example, if you typed red, the status would be in red text. Leave the specific groups who can access the status set to Yes. Click Submit.
The ability to restrict status to members of specific groups allows you to use statuses as a workflow on your website. For example, if you have a member group called authors, you could allow them to publish to a channel, but restrict what status they can assign the new entry so that their work is not open (for example they might only be able to publish to a 'needs review' status). You can then have another member group (such as editors) that do have the right to change the status from 'needs review' to 'open'—thereby ensuring that anything published on your website has been reviewed by a member of the editors group.
[ 168 ]
Chapter 6
4. Now post a new entry to the FAQs channel, and before clicking Submit, ensure that you set the status to Premium (on the Rarely-Used Options tab if you customized your Publish Page layout in the previous section, otherwise on the Options tab).
5. If you now visit http://localhost/faqs you will notice that your new entry does not appear. This is because you must specify in the {exp:channel:entries} tag in each template if you want entries to appear that have a status other than open. Modify the four templates (faqs/index, faqs/browse, faqs/rss, and faqs/atom) and the website_ faqs snippet to include the status="Open|Premium" parameter in the {exp:channel:entries} tag. The | means OR—as in, you want to entries that have either the Open or the Premium status. If you just specified status="Premium", then any entries with a status of open would not display. •
faqs/index: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Premium"}
•
faqs/browse (in HTML ): {exp:channel:entries channel="{my_channel}" disable="categories|category_fields|custom_fields|member_ data|pagination" status="Open|Premium"}{title}{/ exp:channel:entries} - Ed & Eg Financial Advisors title>
•
faqs/browse (after ): {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes" status="Open|Premium"}
•
faqs/rss: {exp:channel:entries channel="faqs" limit="10" dynamic_ start="on" disable="member_data" status="Open|Premium"}
•
faqs/atom: {exp:channel:entries channel="faqs" limit="15" dynamic_ start="on"disable="member_data" status="Open|Premium"} [ 169 ]
Members
•
website_faqs: {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off" status="Open|Premium"}
6. Now, modify the faqs/browse template and replace the line <strong>A: {faqs_answer}
with the following conditional statement. This says to display the answer if either the status is not Premium or if the visitor is logged in. If neither of these conditions are true (that is, the status is Premium and the visitor is not logged in), then do not display the answer. {if status!='Premium' OR logged_in} <strong>A: {faqs_answer}
{if:else} <strong>A: This answer is available to registered members only. If you are already a member, please login. Otherwise, consider registering for free & unlimited access to all our advice.
{/if}
7. Click Update and Finished, and now log out of the control panel (link in the upper-right-hand corner of the screen). 8. Now that you are not logged in, visit your premium content FAQ. Instead of seeing the answer, you should see a message telling you to log-in (as shown below). Verify that you can log in and see the answer.
[ 170 ]
Chapter 6
You have now given Ed & Eg the ability to make content Premium, encouraging visitors to register on the website. Although this is a simple example, ExpressionEngine's conditional statements are very flexible and very powerful. For example, you could show a promotion (5 percent off!) on your homepage, but only to registered members, or even only to registered members who have commented a set number of times. You could also show different content to different member groups. Each member group has a Group ID number, viewable under Members | Member Groups. Using this Group ID, you can use a condition such as {if member_group='6'} (where 6 is the Group ID of the Editors member group) and then create a draft status and allow Editors to see entries with a draft status, but keep them invisible to all other members and non-members. The choices are limitless.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. Try creating a new member group called Designers that can only be used to modify templates. Members of this group should not be able to post or modify any channel entries. 2. When a member registers for the first time, you have the option to collect additional information (beyond the username, name, and e-mail address) in Custom Member Fields. For example, if you have a motorcycle website, you could have a custom field to ask new members what make/model of motorcycle they have. Alternatively, if you give a free t-shirt to new members, you could ask for their t-shirt size. For this exercise, create a custom member field that asks "Are you an existing customer of Ed & Eg?" with possible answers being Yes or No. 3. On the right-hand side of your website is a box with a title of Promotion! that links to a Promotions page. Ed & Eg have decided that they want promotions to be visible only to registered members of the website. Modify the promotions/index template to display the promotion if a visitor is logged in, but otherwise display a message asking the visitor to register. (The promotions/index template is created as part of the challenges in Chapter 4, Moving a Website to ExpressionEngine).
[ 171 ]
Members
Summary
In this chapter, you learned all about member functionality in ExpressionEngine, including the built-in member control panel. You also looked at setting up new member groups and customizing the administrative control panel for different member groups (that have control panel access). Finally, you looked at how to use conditional statements in your templates in order to make membership attractive to visitors. The key points to remember after working through this chapter are as follows: •
You can control what all members can or cannot do in the Member | Preferences screens. You can also make exceptions on a member group basis in Members | Member Groups. So, for example, you can require that all comments are moderated, but make an exception for members in a specific group.
•
Be cautious about who you assign to the Super Admins member group. If someone needs control panel access, but does not need access to everything in the control panel, it is a better practice to set up a new member group with only the permissions that the member group needs.
•
If you are building a website for a client, remember that you can modify the Publish page to make it more intuitive. You can hide fields that are not relevant and at the same time make other fields more prominent.
•
How attractive membership is on your site is up to you. Using conditional statements, you can control what content members can see, displaying different content for different member groups or based on different conditions.
•
If you have a template that uses the conditional statements {if logged_in} or {if logged_out} inside the {exp:channel:entries} tag to display different content to different members, do not enable caching for that template.
[ 172 ]
Creating a Calendar Many organizations have events, and a calendar is a very visual way of indicating what is going on and when. The built-in ExpressionEngine calendar functionality is limited (for example, it does not allow recurring appointments). However, you can use it to display event titles with clickable links for more information. If a calendar is a key part of your website, you may be interested in checking out Solspace's calendar module (at the time of publication, it is not yet available for ExpressionEngine 2). http://www. solspace.com/software/detail/calendar/. The module contains support for more sophisticated calendar functionality such as recurring appointments.
In this chapter, you are going to use the built-in functionality of ExpressionEngine to build a simple events calendar that is easy to post to using the Publish page in the control panel. You will use the jQuery module to display more information when an event is clicked. Finally, you will also be introduced to the concept of Related Entries (relating the post from one channel to a post in another channel)—a useful tool to reduce repetition in channel entries.
Designing the calendar
Ed & Eg frequently host free seminars for customers and members of the community in their conference room. These seminars are usually sponsored by another organization. Ed & Eg would like a calendar on their website that shows each seminar on the date that it is to take place, along with a link so that visitors can read more about the topic of a given seminar as well as who the sponsor company is.
Creating a Calendar
One way you can design such a calendar is to create an events channel, which contains all the information regarding both the event and the event sponsor. This would work, but because a single event sponsor is often associated with more than one seminar, this design would result in you having to include the same information about the same sponsors in more than one channel entry. For example, if Anytown Bank sponsors five seminars, there would be five entries where you would have to provide information about Anytown Bank. Related Entries is a way to reduce repetition in channel entries. (Not to be confused with relating entries by category—which you did when you built the FAQs channel). Essentially, if you have two kinds of data (events and event sponsors), you can create two channels and then include the data from one channel in the other. In this way, you can have an event_sponsors channel, which contains all the pertinent information on the event sponsors (such as their name, location, opening hours, and services offered). The event channel itself will then only contain information about the event (such as the date, time, and topic). When Ed or Eg creates a new event, they can simply select the sponsor (such as Anytown Bank) from a drop-down list of sponsors in the event_sponsors channel, and all the information about the event sponsor will automatically populate for them—no retyping necessary.
Setting up your channels
To set up an event and an event sponsors channel, you will first create the custom fields, then create the channels, then populate the channels with example data, before finally creating the templates that you will use to display the channel data. When creating two channels that are to be related, it's best to start with the channel whose data will be included in the other channel—therefore, start with the event sponsors channel.
Creating custom fields for event sponsors 1. Select Admin | Channel Administration | Custom Fields.
2. Select Create a New Channel Field Group and call the field group event_ sponsors. Click Submit. 3. Now select Add/Edit Custom Fields for the event_sponsors field group. 4. For now, keep things simple and create only one field—a generic about field. (You could, of course, create as many fields as you want). Select Create a New Custom Field. [ 174 ]
Chapter 7
5. The field type will be Textarea. The field label will be About and the field name will be event_sponsors_about. The field will be required, will not be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. The event_sponsors field group is now ready to go. The next step is to create the event_sponsors channel.
Creating the event sponsors channel
By now, you should be familiar with the process of creating a channel. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Event Sponsors with a short name of event_sponsors. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and event_sponsors for the field group (the category group can be left as none, as you will not be using categories with this channel). Remember, if you do not select a Status Group when creating a new channel, then only Super Admins can post open entries. If any other member group posts an entry, it will be closed by default (and therefore not visible on your website).
3. Finally, select No to creating new templates and then click Submit. 4. Now, go to the Content | Publish | Event Sponsors and create a couple of example sponsors (for example, Anytown Houses, Anytown Bank, and Anytown Law Firm).
[ 175 ]
Creating a Calendar
Now that you have your sponsors channel set up with some sponsors, you can go ahead and create the events channel.
Creating the events custom fields
As before, you will first create your channel custom fields, before creating the channel, and then some example content. 1. Select Admin | Channel Administration | Custom Fields. 2. Select Create a New Channel Field Group and call the new field group events. Click Submit. 3. Now select Add/Edit Custom Fields for the events field group. 4. You will create two fields for your events—Description and Sponsor. Select Create a New Custom Field. Note that you will not create a custom field for the date or the time of the event. This is because you can change the date/time of the entry to reflect the date/time of the event.
5. The field type will be Textarea, the field label will be Description, and the field name will be events_description. The field will be required, will be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. 6. Next you can create the relationship field. Click Create a New Custom Field. 7. From the drop-down of Field Types, select Relationship. The Field Label will be Sponsor, and the Field Name will be events_sponsor.
8. The field will not be required (some events might not be sponsored) and the field will not be searchable. Say Yes to show the field by default. [ 176 ]
Chapter 7
9. In the Custom Field Options, select the Event Sponsors channel and leave the display criteria at the default setting (Sort by Title in Descending Order). Click Submit.
Now all you have to do before you can start creating events is create the events channel.
Creating the events channel
Creating the events channel is a fairly straightforward process. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Events with a channel name of events. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and events for the field group (the category group can be left as none, as you will not be using categories with this channel). 3. Finally, select No to creating new templates and then click Submit. 4. Your channel is created! Now, you can bring together your Events and Event Sponsors by creating some events.
Creating example events
The final step in setting up these channels is to post some example events, so that when you create the calendar on your website, you have some events to see how it is working. Your first event is going to be a seminar called Common Pitfalls of Home Buying, sponsored by Anytown Houses. 1. Select Content, Publish, and select the Events channel. 2. Type in the title, Common Pitfalls of Home Buying. In the description field, type in some example topics that will be covered.
[ 177 ]
Creating a Calendar
3. Select Anytown Houses as the sponsor. That is all you need to do to associate the sponsor with the event.
4. Before clicking submit, select the Date tab at the top of the screen and select a date for your entry and a time of 6 p.m.
[ 178 ]
Chapter 7
5. Click Submit. 6. Go ahead and create a few more events with different sponsors, dates, and times, so that when you create the calendar, you have a few entries to play with. Now that you have the channels built and have some example events too, you can go ahead and create the calendar!
Creating the calendar
For the rest of this chapter, it will be useful to refer to the official ExpressionEngine documentation on the calendar tag at http://www.expressionengine.com/user_ guide/modules/channel/calendar.html, where much of the code in this section is adapted from. The first steps in creating a calendar are to create a calendar template group, add the basic HTML to construct the page, build the outline of the calendar, and add CSS to make the calendar look good.
Creating a blank calendar template
1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group calendar. Do not duplicate a group and do not make the index template in this group your home page. Click Submit. 2. Copy and paste the code from the includes/404 template (or any template that has all the normal page components such as the header, sidebar, widebar, and footer). Paste the code into the new calendar/index template. At the top of the template, add a my_channel preload replace as follows: {preload_replace:my_channel="events"}
3. Change the page title from Page Not Found to Calendar. Calendar - Ed & Eg Financial Advisors
4. Change the h1 title to Seminar Calendar and delete the paragraph underneath that says the page does not exist (including the and
tags). The content section should look as follows: Seminar Calendar
[ 179 ]
Creating a Calendar
Now you have a blank Ed & Eg themed template (viewable at http://localhost/ calendar) that you can use for your calendar.
Creating the calendar
The next step is to create a blank calendar—it will not display any events just yet. This code is adapted from the ExpressionEngine documentation. 1. In the calendar/index template, add the following code after the Seminar Calendar
line. The first piece of code is the exp:channel:calendar tag. This is a pair of tags with a number of parameters. {exp:channel:calendar switch="calendarToday|calendarCell" channel="{my_channel}" show_future_entries="yes"} {/exp:channel:calendar}
The channel parameter specifies that the entries on the calendar are coming from {my_channel}, where {my_channel} is a Preload Text Replacement corresponding to the events channel. The parameter show_future_entries="yes" means that the calendar will show future entries. In most channel applications, if you set an entry date in the future, ExpressionEngine does not make that entry visible until that date. This is useful if (say), you are going away but want to schedule new content to appear at a certain time while you are gone. In this case, if a calendar only showed entries that have already happened, it would not be a very useful calendar. The switch parameter is used to switch between two different stylesheet styles (you will create the calendar stylesheet next). If the day being displayed is not today, then the stylesheet's style will be calendarCell. If the day being displayed is today, then the stylesheet's style will be calendarToday. This allows today's date to be styled differently.
2. The next step is to start displaying the calendar itself. A calendar is a table with seven columns (one for each day of the week) so you will use the HTML table tag to display it. In the following code, you define the first row. In the top left cell, you will display << that can be clicked to move to the previous month. Likewise, in the top-right cell, you will display >> to navigate to the next month. The middle five cells will contain the name of the current month being displayed. The style calendarBG will be defined in the stylesheet that you will create in the next section. Add the following code after the {exp:channel:calendar} tag and before the closing {/ exp:channel:calendar} tag. [ 180 ]
Chapter 7 << {date format="%F %Y"} >>
The previous and next path links both point to the current template (calendar/index). < is HTML for the < symbol and > is HTML for the > symbol. The format code to display the current month and year, %F %Y, is taken from ExpressionEngine's date formatting code, available at http:// expressionengine.com/user_guide/templates/date_ variable_formatting.html
3. Go to http://localhost/calendar and you can see the calendar beginning to take shape. Click on the arrows and you can see that the name of the month changes, as does the URL of the page. 4. The next row will display the weekdays. The code {lang:weekday_abrev} refers to the one letter weekdays. You could also use weekday_long or weekday_short to either spell out the entire weekday or the first few letters of the weekday respectively. This must be wrapped in a {calendar_ heading} variable pair. Insert the following code after the closing tag and before the closing tag. {calendar_heading} {lang:weekday_abrev} {/calendar_heading}
[ 181 ]
Creating a Calendar
5. The next row will display the actual dates. There is no way to know how many rows might be needed for a given month (February might only require four rows; October might require six). ExpressionEngine dynamically determines how many rows to display using the {calendar_rows} variable pair, which repeats for as many rows as are necessary. Each row starts with the command and ends with the closing command. For each calendar cell, there are three possibilities—there may be events for that date; there may not be events for that date; or it may be an empty cell before the first day of the month or after the last day of the month. You want to handle each of these situations differently, so you will use conditional statements to distinguish between these three possibilities, although, right now, you will simply be displaying the date in each. Notice that, for your empty cells, you use a different class so that you can style it differently in your stylesheet. Insert this code after the closing tag and before the closing tag. {calendar_rows} {row_start}{/row_start} {if entries} {day_number} {/if} {if not_entries} {day_number} {/if} {if blank} {day_number} {/if} {row_end} {/row_end} {/calendar_rows}
You now have the beginnings of a calendar, although it looks a little basic.
[ 182 ]
Chapter 7
Before you start displaying your events on this calendar, first create some CSS to make the calendar look a little more calendar-like.
Formatting the calendar with CSS
Rather than adding the calendar styles to your main site/site_css stylesheet, it makes sense to create a separate stylesheet just for the calendar styles. This is because the calendar styles are only needed on the calendar page and do not need to be included on any other page.
Creating the calendar CSS template
First, you will create the template for the calendar CSS. Then you will point the calendar/index template to this new template. 1. From Design | Templates | Template Manager, click the calendar template group and select New Template. Call the new template calendar_css and choose a Template Type of CSS. Click Create and Edit.
2. The first line in your new template will import the main site/site_css template (so that the page outside the calendar continues to be formatted correctly). After typing this, click Update and Finished. @import url({site_url}includes/site_css);
[ 183 ]
Creating a Calendar
The {site_url} variable, which you have seen before, is converted to the actual URL to the root directory of your site, as stored in Admin | General Configuration. Note that the URL in this setting should have a trailing / (for example, http://localhost/ as opposed to http:// localhost) or the link above will not work (for example, it will resolve to http://localhostincludes/site_css instead of htttp:// localhost/includes/site_css).
3. The next step is to point the existing calendar/index template to use this new CSS template in place of site/site_css. To do this, edit the calendar/ index template and modify the stylesheet line to read as follows:
Now you can add some styles to your CSS.
Adding styles to your calendar CSS
In the calendar/index code so far, you have defined several styles: • • • • • •
calendarBG is used to format the overall table calendarHeader is used to format the month heading calendarDayHeading is used to format the weekday headings calendarCell is used for the calendar cells, except for today's date calendarToday is used for the calendar cell that represents today's date calendarBlank is used for calendar cells that are not for the dates this month
Helpfully, EllisLab provides a suggested stylesheet in the ExpressionEngine documentation (http://expressionengine.com/user_guide/modules/channel/ calendar_css.txt), which you can start with and then adapt to your own needs. 1. Open the template calendar/calendar_css for editing. Copy and paste the example code from the URL above into the CSS stylesheet (below the @ import line) and click Update.
[ 184 ]
Chapter 7
2. Next, modify the three cell styles (calendarCell, calendarToday, and calendarBlank) to position the date in the top-left of the cell (so that there is room for your event text). To do this, modify the following two styles for .calendarCell and .calendarToday and add them to .calendarBlank: text-align: left; vertical-align: top;
3. Now modify the same three cell styles to have a fixed width. Otherwise, as events are added to your calendar, some columns will expand and other columns will shrink. Add the following styles to .calendarCell, .calendarToday, and .calendarBlank: width: 60px; height: 60px;
4. Finally, you can create some styles for displaying your events. You want to keep the font clear to read but small. The following code will give each event a border, so that if there are two events on the same day, the text will not run together. Since all the events will be links (for more information), this code will also change the background color of the event when the mouse moves over it to make it clear that it is clickable. Add the following to the end of the calendar_css stylesheet: .calendarEvent a{ font-family: Arial, Trebuchet MS, Tahoma, Verdana, Sansserif; [ 185 ]
Creating a Calendar font-size: 10px; font-weight: normal; letter-spacing: 0em; text-decoration: none; border: 1px solid #666; vertical-align: top; text-align: left; margin: 5px; padding: 5px; display: block; } .calendarEvent a:hover{ background-color: #ccc; }
You now have a pretty, but blank, calendar. You can, of course, go further and change the styles so that it suits your site. It is all easily configurable within the CSS. The next step is to start displaying events on your calendar. Since space on the calendar is limited, you will only display the title of the event on the calendar itself, with a clickable link for more information. (In fact, only the title field from the channel is available in the {exp:channel:calendar} tag—none of the custom field tags will work). The basic way to build the clickable link is to simply create a new, single-entry page template that you link to (just as you did with the FAQs channel). However, to keep things interesting, a new approach is called for. You will still create a single-entry page template, but rather than just linking to it directly, you will use the jQuery module combined with the FancyBox plug-in (http://fancybox.net/) to display the single-entry page in an iFrame lightbox that floats over the calendar. To accomplish this, you must first download the FancyBox tool and upload the files to your website. (FancyBox is also used in the next chapter on photo galleries). If you are removing the index.php from your URLs, then you will likely have to modify your .htaccess file so that you can access the FancyBox files. You can then create your single-entry template (and a corresponding, simplified CSS file). Finally, using the jQuery module and FancyBox, you can create a link to your single-entry template from your calendar.
[ 186 ]
Chapter 7
Note that although this chapter is using a third party jQuery plugin, the focus of this book is on using ExpressionEngine—not on learning jQuery (or FancyBox). For more information about jQuery, please visit http://jquery.com/.
Setting up FancyBox
You can download the latest version of FancyBox directly from http://fancybox. net/, or a copy of the latest version is included in the code for this chapter at either http://packtpub.com/support or http://www.leonardmurphy.com/book2/ chapter7. 1. First, download FancyBox and extract all the files from the compressed directory into a directory on your computer. 2. Once extracted, you should see a directory called fancybox, complete with a number of images, JavaScript files (.js), and a CSS file. Upload this entire directory to the root of your website. Note that for the purposes of this chapter, you do not need any of the example files that ship with FancyBox. 3. Next, if you are removing the index.php from your ExpressionEngine URLs using the exclude method, you will have to add this new directory to your .htaccess file (otherwise it will be treated as an ExpressionEngine template group, rendering it inaccessible). Open .htaccess and add FancyBox to the end of the list of real directories and files as follows (but do not create a second RewriteCond line—modify the line you already have). RewriteCond $1 !^(images|system|themes|index\.php|admin\.php|fancybox) [NC]
For an example of a complete .htaccess file using the exclude method, please see either http://packtpub.com/support or http://www. leonardmurphy.com/book2/chapter2. Your .htaccess file may include other files or directories that you have in the root directory of your website (such as robots.txt or favicon.ico) that you should leave in place. 4. To verify that your .htaccess file is not blocking access to the fancy box directory, open http://localhost/fancybox in your browser. If you see your ExpressionEngine 404 page, then your .htaccess file is treating the fancybox portion of your URL as an ExpressionEngine template group. Review your .htaccess file.
[ 187 ]
Creating a Calendar
Troubleshooting problems that are due to the .htaccess file can be challenging. Many times you set up a .htaccess file when you install ExpressionEngine and then forget that it exists, so you do not even think of the .htaccess file. Remember that EllisLab does not provide support for removing the index.php using a .htaccess file (because there are so many ways to do it and every server works a little bit differently). If you suspect your .htaccess file is causing problems, you can temporarily remove it and add the index.php back into your website URLs (in Admin | Configuration, under Name of your site's index page). If you do this, it will at least confirm whether the issue you are seeing is due to your .htaccess file or something else entirely.
5. Finally, if you are using Internet Explorer, you may want to modify fancybox/jquery.fancybox-1.3.1.css to include a / at the start of the AlphaImageLoader sources. (This tells Internet Explorer that FancyBox is a directory at the root of your website and therefore enables it to find the images it needs). The easiest way to do this is to do a find and replace and replace AlphaImageLoader(src='fancybox/ with AlphaImageLoader(src='/fancybox/
FancyBox is now in place and ready to go. Next, you will create your single-entry template, along with a pared-down CSS file.
Creating your single-entry template
First, you will create a pared down CSS file, before creating your single-entry template. Both will be much smaller versions of your regular templates/CSS (since you would not view this template on its own, but rather as an overlay on an existing page, you do not need the usual Ed & Eg header, sidebar, or footer. As a result, the template and the CSS are smaller). 1. Create a new template in the calendar template group called event_css. The template type will be CSS. Duplicate an existing template, namely, includes/site_css. Click Create and Edit. 2. Delete the input, textarea style. Further down, delete everything that appears after the /* Wrapper */ comment (including /* Wrapper */ itself). 3. Now update the body style to read as follows (essentially removing the background and adding in a four percent padding so that the text in the popup overlay will not touch the sides of the pop-up overlay box): body { font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; [ 188 ]
Chapter 7 font-size: 12px; color: #6B6B6B; padding: 4%; }
4. Finally, remove the h2 from the h1,h2 style (not the h1, h2, h3, h4 style) and instead, add it to the h3 style. The styles should end up looking as follows: h1 { font-size: 28px; } h2, h3 { font-size: 16px; font-weight: bold; }
5. Click Update and Finished to save this CSS template. 6. Next, you will create your event template. In the calendar template group, click New Template and name the template event. The template type will be Web Page. Select to duplicate the calendar/index template and click Create and Edit. This template will be visible at http://localhost/calendar/ event. 7. Delete everything between the and tags. Also, change the to be Calendar Event as follows: Calendar Event - Ed & Eg Financial Advisors
8. Next, change the stylesheet so that instead of pointing to calendar_css, it is pointing to the CSS stylesheet you just created (event_css).
9. Next, after the tag, add the following code to display the event information. {exp:channel:entries channel="{my_channel}" show_future_entries="yes" limit="1" require_entry="yes"} {if no_results} {redirect="404"} {/if} {title}
<strong>Join us on {entry_date format="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{events_description}
{/exp:channel:entries} [ 189 ]
Creating a Calendar
Notice that the show_future_entries parameter has to be included here, since this template is going to be displaying event entries that have an entry date after today's date. Also note the use of require_ entry and if no_results to ensure that only valid events can be displayed—all others will be redirected to your 404 page.
10. Next, you will display the sponsor information from the event_sponsors channel. Since you are displaying the content of the event_sponsors channel inside the events channel, ExpressionEngine needs a way to know which channel it is supposed to be displaying the data from (fields such as {title} could refer to either channel). To accomplish this, you wrap all your event_sponsors information in the tag {related_entries} using an ID that corresponds to the relationship field in the events channel (in this case, the events_sponsor custom field). You can then use the custom field names from the event_sponsors channel. The ID is a way for ExpressionEngine to support more than one relationship field in the same channel. Insert the following code after the {events_description}
line: {if events_sponsor} {related_entries id="events_sponsor"} More About {title}
{event_sponsors_about}
{/related_entries} {/if}
You have now completed this separate, pared-down single-entry template to show more information on your calendar entries. Although the plan is to only display this template in a pop-up overlay on your calendar page, you can see what the template looks like by itself by going to a URL like http://localhost/calendar/event/
common_pitfalls_of_home_buying.
[ 190 ]
Chapter 7
Notice how the information from the Event Sponsors channel is populated into the event information. Although you only have a few events right now, so the effort of creating two channels might not seem to outweigh the benefits, if you had tens or hundreds of events, all of which shared the same handful of sponsors, being able to simply select the sponsor information from the drop-down menu represents a significant time-savings over having to type in information about the sponsor in every event. The next step is to display these entries on your calendar.
Displaying events on your calendar
To display the event on your calendar, you will use an ordinary hyperlink to your single-entry template with a special class (pop-up). The pop-up class will correspond to JavaScript in your HTML header that will call upon the FancyBox jQuery plugin to display the single-entry template in an overlay dialog box. First, you need to enable the jQuery module in your template. 1. First, verify that the jQuery module is enabled. It is enabled by default if you have installed Agile Records. Select Add-Ons | Modules from the main menu and verify that jQuery is marked as installed. If not, click Install in the Status column to install it. 2. Edit the template calendar/index.
[ 191 ]
Creating a Calendar
3. The first change you are going to make is to activate the jQuery module. In the section of the template, add the following tag: {exp:jquery:script_tag}
When saving your template, if you see a warning that no closing tag was found, do not worry. The jQuery tag is a tag that does not require a closing tag.
4. Next, you are going to include the FancyBox jQuery files that are in the fancybox directory that you uploaded to the root of your website. You will link to the main FancyBox JavaScript files, plus the CSS file. Type this code in directly underneath the above tag. <script type="text/javascript" src="{site_url}fancybox/jquery.fancybox-1.3.1.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.mousewheel-3.0.2.pack.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.easing-1.3.pack.js">
Note that if you downloaded the newest version of FancyBox, then the filenames and the version numbers in each of the filenames are subject to change.
5. Now you are going to include the FancyBox code for the pop-up class. This tells FancyBox how you want the lightbox to work. You want the box to be 75 percent of the width and height of the page, with no margin or padding. OverlayOpacity means that you want the calendar page underneath to still be visible, but dimmed. The hideOnContentClick means that if you click anywhere off the lightbox, the lightbox will close. The iframe type means that the lightbox will display the contents of another URL (in this case, your single-entry template URL). For more information on all the FancyBox parameters, please visit http://www.fancybox.net/api. Type this code in directly underneath the above tags (still in the section). <script type="text/javascript"> $(document).ready(function() { $(".popup").fancybox({ 'width': '75%', 'height': '75%', [ 192 ]
Chapter 7 'titlePosition': 'outside', 'autoScale': true, 'margin': 0, 'padding': 0, 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none', 'type': 'iframe' }); });
6. Finally, add your link with the class of popup (that corresponds to the .popup used in the above JavaScript so that FancyBox knows that you want to use FancyBox, and not actually open the link like you normally would). Add the following code after {if entries}, deleting the existing {day_number} line. {day_number} {entries} {/entries}
7. As one date can contain multiple events, this variable pair {entries} applies to each entry. Since this hyperlink applies to each entry, you include it within the {entries} variable pair.
[ 193 ]
Creating a Calendar
8. Go to your calendar and navigate to a month that has events to verify that you can see the hyperlinks.
9. Finally, click on one of the events to verify that your single-entry template appears with the correct information in a FancyBox overlay. If your event does not appear in a pop-up window, but rather opens in a separate window or tab, there are a number of things you can check. First, verify that the fancybox directory is at the root of your website and that you can access the files in your browser (if not, check your .htaccess file). Next, verify that the paths in the calendar/ index template point to the script/CSS files in the fancybox directory and check the filenames for misspellings.
[ 194 ]
Chapter 7
Your calendar is now complete. As you can see, the calendar functionality in ExpressionEngine is limited in what it can do and is certainly not as flexible as specialized calendar applications. However, for simpler designs, it is quite functional.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. [ 195 ]
Creating a Calendar
1. Currently, your calendar displays the days of the week using single letters (for example, M, T, W). Modify this so that the first three letters of each weekday are displayed (for example, Mon, Tue, Wed). 2. Underneath your calendar, display the next event that is coming up (no matter what month is being displayed on the calendar).
Summary
In this chapter, you took a look at the calendar functionality in ExpressionEngine. You also got to see a working example of related entries and how it can help you reduce repetition in your channels. The calendar functionality can be daunting for beginners, as there is a lot of code involved. However, once mastered, the calendar is very flexible in terms of what you can display on it, how it is displayed, and how it all works together. The key points to remember after working through this chapter: •
The calendar functionality uses all the usual channel features that you know and love—custom fields, categories, status groups, and the Publish page. You can create channels with as many custom fields as you want, although you can only display the title field on the calendar itself.
•
Related Entries is when the contents of one channel are included in another channel. Although the events calendar was a natural choice, it could be used for any kind of channel. For example, if you have a recipes channel, you may have a second channel for common sub-recipes (such as making a pie-crust). In this way, you can have 14 different recipes that call for a pie-crust and you do not need to type out the instructions to make the pie-crust 14 times. Reducing repetition by using related entries also makes your website easier to maintain and update (for example, if you wanted to adjust your standard pie recipe, you only have to do it in one spot instead of in 14 places).
•
Related Categories has nothing to do with Related Entries. Related Categories is when two entries in a channel share a category and can therefore be considered to be related.
[ 196 ]
Chapter 7
•
The jQuery module allows you to use jQuery on your website without having to download it yourself (it comes included with ExpressionEngine). ExpressionEngine also masks where the jQuery file is, so it does not reveal the location of your system directory. Teaching jQuery is beyond the scope of this book, but when used thoughtfully, it can enhance the usability of a website.
In the next chapter, you will be building a photo gallery in ExpressionEngine.
[ 197 ]
Creating a Photo Gallery Although ExpressionEngine 2 does not come with a built-in photo gallery module, it does have many features designed to make working with photos easier. In this chapter, you will create a photo gallery channel, use file manager to manage your photos, and use jQuery to display the photos on your website. This chapter uses the FancyBox jQuery plugin that you set up in the previous chapter. If you did not follow the previous chapter, please follow the instructions in Chapter 7, Creating a Calendar under Setting up FancyBox
Although this chapter focuses on building a tool for Ed & Eg to share their personal photos, the techniques in this chapter will be useful in any situation where you want to display images—whether personal photos, a portfolio of your work or items for sale.
Designing your photo gallery
There are many different ways you can approach creating a photo gallery in ExpressionEngine. At the most basic level, you have a choice between each channel entry containing only one photo (and a description) or each channel entry containing a set of photos. If you allow only one photo per entry, you can use categories to organize the photos into galleries (and you can even include the same photo in more than one gallery). If you allow multiple photos per channel entry, each entry represents a photo gallery by itself. One way to accommodate multiple photos per entry is to create as many custom fields as the photos you think you will have in a gallery. For example, if you know each gallery will have a maximum of 20 photos, then you could create 20 custom fields for the photos and 20 custom fields for the descriptions. This solution works, but is not the most flexible (that is, to add 21 photos to a gallery, you would have to modify your custom fields and your templates).
Creating a Photo Gallery
An alternative approach to accommodate multiple photos per entry without creating an abundance of custom fields is to use a third party add-on such as Matrix by Pixel & Tonic (http://pixelandtonic. com/matrix). This add-on allows for tabular data in channel entries— you define the column headings (such as the photo and the description) and then add a row in the table for each photo. In each channel entry, you can create as many rows as you need. For example, you can create one entry with 12 photos and another entry with 25 photos.
Rather than creating lots of custom fields, or using a third party add-on, this chapter will show you a simple and elegant way to create a photo gallery using the one photo per entry design and then will use categories to organize the photos into galleries. Before you create your photo gallery channel, you first need to define where your photos will be stored.
File manager
The file manager is where you can upload new photos or crop, resize, rotate, or delete the images you have already uploaded; all from within the ExpressionEngine control panel. For this photo gallery, you will create a new upload destination—this is the directory on your server where ExpressionEngine will store your photos. 1. The first step in creating a new upload destination is to create the new directory on your server. Create a new directory called photos in /images. If you are following along on an actual web server, ensure that the new directory has 777 permissions (usually right-clicking on the directory in your FTP client will allow you to set permissions). If, instead of creating a new sub-directory inside the /images directory, you prefer to create a new top-level directory and you are using the .htaccess exclude method to remove the index.php from ExpressionEngine URLs, then be sure to add the new directory to your .htaccess file.
2. Next, you need to tell ExpressionEngine where this directory is. Inside the control panel, select Content and then File Manager.
[ 200 ]
Chapter 8
3. On the left-hand side of the screen, you will see the directory or directories where you can currently upload files to (if any), along with the files currently in each directory. In the toolbar on the right-hand side, underneath File Tools, select Create New Upload Destination.
4. Enter a descriptive name of Photo Gallery. The Server Path and URL may be pre-filled, however, you should make sure they point to the actual directory you just created (/images/photos). If you are following along in a localhost environment, the URL would be http://localhost/images/ photos. Leave Allowed File Types as Images only.
[ 201 ]
Creating a Photo Gallery
5. All the fields that begin with maximum can be left blank. These fields allow you to restrict the size, height, and width of photos. If you do enter values in here, and then later try to upload a file that exceeds these limits, you will see an error message such as The file you are attempting to upload is larger than the permitted size. 6. Set the Image Properties, Image Pre Formatting, and Image Post Formatting to be blank. These fields allow you to enter code that appears inside, before, and after the img tag. However, you can format your img tag as needed inside your template.
7. The File Properties, File Pre, and Post Formatting can be ignored for now as they only apply to non-image files that you upload (and you have specified that you are only allowing images in your photo gallery). 8. If desired, you can allow certain member groups to upload files. The member groups you see listed (if any) will depend on the member groups you have. Set all the member groups to Yes except for Members, which should be set No.
[ 202 ]
Chapter 8
9. Click Submit and your new upload destination will be ready to go. Go back to the file manager and you can see the new photo gallery upload destination with no files.
Creating your photo gallery channel
Now that you have created a place to store your photos, you can create your photo gallery channel. As with every other channel you have created in this book, you will follow the same basic steps—creating custom fields and categories, creating your channel, publishing some entries, and then building your templates.
Creating your custom fields
Since you are going to have one photo per channel entry, you have a lot of flexibility to create as many custom fields for each photo as you see fit—for example, you could have fields to capture the location of the photograph, the subject of the photo, the type of camera that was used, the name of the photographer, and so forth. However, to keep things simple, you will only create two custom fields right now—one for the photo itself and one for the description. 1. From the main menu of the control panel, select Admin, Channel Administration, and then Custom Fields. 2. Select Create a New Channel Field Group and call the new group photos. Click Submit. 3. Next to the new group, select Add/Edit Custom Fields and then select Create a New Custom Field.
[ 203 ]
Creating a Photo Gallery
4. The field type will be File. The field label will be Photo and the field name will be photos_photo (the first part representing the field group name). In the instructions for the field, indicate that photos in the photo gallery should be no more than 600x800 pixels (so that they fit on a typical computer screen without scrolling). You could also prevent photos that are bigger than 600x800 pixels from being uploaded by specifying the maximum width and height in the File Upload Preferences for the photo gallery upload destination. You have not done this here because it would prevent you from being able to upload a larger photo and then re-size it using file manager.
5. The field should be required, but not searchable, and should be shown by default. The field display order should be 1 and the file type should be Image. Click Submit. 6. Click Create a New Custom Field again. This time, the field type should be Textarea, the field label Caption, and the field name photos_caption. The field instructions can be left blank. Answer Yes to it being a required field, being searchable and being shown by default. The Field Display Order should be 2. 7. The number of rows can be left as 6 and the default text formatting should be set to Auto
(this will prevent unwanted whitespace in your captions due to extra paragraph tags being added, but will also allow multi-line captions). Say No to allowing an override on the Publish page. The text direction can be left as left-to-right. [ 204 ]
Chapter 8
8. Finally, say Yes to Formatting Buttons, Spellcheck, and Write mode. Say No to Smileys, Glossary, and the File Chooser. Click Submit to create the new field. Now that you have your custom fields, you can define your categories.
Creating your categories
As discussed at the beginning of this chapter, you are going to use categories to distinguish between photo galleries. To start with, you are going to create two photo galleries—one for vacation photos and one for local photos. You can always come back and add more galleries later. 1. Still in the control panel, select Admin, Channel Administration, and then Categories. 2. Select Create a New Category Group and name it Photo Categories. Select Allow All HTML in the category field formatting and check the boxes to allow other member groups to edit (or delete) categories as appropriate. (If you see a message saying that there are no member groups allowed to edit/ delete categories, this is fine too). Click Submit.
3. Back on the Category Management screen, select Add/Edit Categories for the Photo Categories category group.
[ 205 ]
Creating a Photo Gallery
4. Click Create a New Category. The first category will be called Local Photos. The Category URL will default to local_photos. Type in a category description (you will later display this on your website), leave the Category Image URL blank, leave the Category Parent set to None, and click Submit.
5. Select Create a New Category again. This time call the new category Vacation Photos, with a URL of vacation_photos. Type in a category description such as A selection of vacation photos taken by Ed & Eg. Leave the category image URL blank and the category parent as None. Click Submit.
Now that you have your category group and custom field group defined, you can go ahead and create your channel. [ 206 ]
Chapter 8
Creating your channel
The process of creating your channel is straightforward. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Photos with a short name of photos. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Photo Categories for the category group, Statuses for the status group, and photos for the field group.
3. Answer No to creating new templates and then click Submit. Your channel is created! Now you can start creating some content and displaying the photos on your website.
Uploading your first photos
There are three ways to upload photos to your website. Your first option is to go to File Manager (under the Content menu) and select File Upload on the right-hand toolbar. Alternatively, you can go to publish an entry in the Photos channel, click on Add File, and upload a file. Both of these options are convenient since they use the built-in ExpressionEngine file manager to upload your file—you never have to leave the control panel. However, you can upload only one photo at a time and you may run into issues if you try and upload very large photos (greater than 2 MB).
[ 207 ]
Creating a Photo Gallery
The third option for uploading photos is to do so directly, using FTP, just as you would upload any files to your website. Since this requires another tool, it is less convenient than uploading a single photo from within ExpressionEngine, but if you are uploading lots of photos, then using FTP is a lot faster to do. That is the method we will use here. The built-in file manager also allows you to crop, resize, and rotate images (although you can take advantage of these tools even if you do not use file manager to upload the files).
1. Download the example photos (local1.jpg through local8.jpg and vacation1.jpg through vacation8.jpg) from either the Packtpub support page at http://www.packtpub.com/support or from http://www. leonardmurphy.com/book2/chapter8. (Or you can substitute your own photos). 2. Copy or FTP the photos into the /images/photos directory that you created earlier in the chapter. 3. Back in the ExpressionEngine control panel, select Content | Publish and then select the Photos channel. 4. Type in a title of Fireworks and a caption Fireworks exploding with a bang. Then select Add File. 5. The first screen to appear in the Upload File screen. Since you have already uploaded the files, you can simply select the photo gallery option in the lefthand menu. If no photos appear under the photo gallery, or the files appear but no thumbnails appear, try logging out of the control panel and logging back in. (This helps to refresh ExpressionEngine so it recognizes the new files—the first time you access the files after uploading via FTP, ExpressionEngine has to create the thumbnails).
[ 208 ]
Chapter 8
6. Select local1.jpg.
7. On the Categories tab, select Local Photos. Then click Submit. 8. Now, repeat the same steps to create entries for the rest of the photos, using appropriate captions that describe the photos. Be sure to select a category for each photo. There are 16 example photos (eight local and eight vacation photos). Having several example photos in each category will demonstrate how the photo gallery works better.
Creating your templates
As with everything in ExpressionEngine, everything that appears on your website must be coded in a template. Your photo gallery is no exception. You will now create new templates in a design very similar to the one used by the FAQs channel—a single-entry template called comment so that visitors can leave comments on individual images, and a multiple-entry page where visitors can browse and view images by category. You will start with the single-entry page.
[ 209 ]
Creating a Photo Gallery
Creating the single-entry page
The single-entry page is where an individual photograph is displayed, along with the caption and any comments. In this section, you will create a new template group called photos and then create a new template called comment (since the primary reason to visit the single-entry template will be to view and post comments). 1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group photos. Do not duplicate a group and do not make the index template in this group your homepage. Click Submit. 2. Next, with the photos group highlighted on the left-hand side, select New Template. Call the template comment and leave the template type as Web Page. Since your single-entry page here will be very similar to the singleentry page you created for the FAQs channel, select Duplicate an existing template and then choose the faqs/browse template to duplicate. Click Create and Edit.
[ 210 ]
Chapter 8
If you did not follow Chapter 5, Creating a Fully-Equipped Channel completely and do not have an faqs/browse
template to duplicate, it can be downloaded from http:// www.packtpub.com/support or from the chapter 5 page at http://www.leonardmurphy.com/book2/chapter5.
3. Whenever you copy a template, the first thing to update is the Preload Text Replacements at the top. Update them to the following: {preload_replace:my_channel="photos"} {preload_replace:my_template_group="photos"} {preload_replace:my_single_entry_template="comment"}
4. Further down in the template, delete all the code between (but not including) the {title}
and the {/exp:channel:entries}. 5. Replace the deleted code with the following code to display your image and your image caption (centered), along with a link to your multiple-entry photos/index template (which is still blank):
<em>{photos_caption}
The limited class is defined in your site/site_css stylesheet as having the property max-width: 555px;. This value matches the width of the #content ID container. Although the channel field instructions ask that photos be no bigger than 600x800, they may still be too big to fit nicely into the #content area without overlapping the sidebar. The max-width property proportionally shrinks images if they are too big, but otherwise leaves the image alone.
6. A lot further down, underneath the line {/exp:comment:form}, remove the Other Questions Like This section: everything from the
to the {/exp:channel:entries} inclusive.
[ 211 ]
Creating a Photo Gallery
7. Click Update and visit an example photo (such as http://localhost/ photos/comment/fireworks). If you uploaded photos with different titles, then remember that because this is a single-entry page, the last part of the URL (in this case, fireworks) is actually the URL Title from the entry to be displayed. You can replace this with the URL Title of another entry in your channel, and that entry will appear instead. Refer to Chapter 5, Creating a FullyEquipped Channel for more information on single and multiple-entry pages and how they work. If something does not look right in your single-entry page page, compare your code with the final code for the template, downloadable at either http://www.packtpub.com/support or http://www. leonardmurphy.com/book2/chapter8.
[ 212 ]
Chapter 8
Your single-entry page is complete! Go ahead and try adding comments if you like— both as a member and a visitor. Next up, you will create your multiple-entry page where visitors will be able to browse photos by category.
Creating the multiple-entry page
The multiple-entry page needs to attractively display a series of photos so that your visitors can quickly browse to the photos they are most interested in. A visitor browsing your photo gallery will likely spend a lot of time on this page. Although you will use thumbnails to display the photos on your multiple-entry page, you do not have to force visitors to go to your single-entry page in order to view a larger image. Instead, you can use jQuery and the FancyBox plugin that you used in the previous chapter. When a visitor clicks on a photo, a full-size version will appear in a FancyBox overlay, complete with caption. Visitors will be able to quickly scroll through the larger images directly from the FancyBox plug-in. Underneath each thumbnail, a link can take visitors who wish to leave comments to the singleentry page where they can do so. If you did not follow the previous chapter, please, at least, follow the instructions under the heading Chapter 7, Creating a Calendar under the Setting up FancyBox section.
Rather than re-inventing the wheel, you can base the multiple-entry page template on the calendar/index template that you created in the last chapter. (If you did not follow the previous chapter, you can download the template from http:// www.packtpub.com/support or from http://www.leonardmurphy.com/book2/ chapter7). 1. In the ExpressionEngine control panel, copy the calendar/index template code and paste it into the photos/index template. You will see a message indicating that no closing tag was found for {exp:jquery. Ignore this message as this tag is one of those that do not require a closing tag. 2. Update the Preload text replacement at the top to the following: {preload_replace:my_channel="photos"}
3. Update the to be Photo Galleries as follows: Photo Galleries - Ed & Eg Financial Advisors
[ 213 ]
Creating a Photo Gallery
4. The calendar/index template used its own stylesheet with extra calendar formatting—since you do not need to do this, change the stylesheet back to includes/site_css:
5. Your calendar uses a pop-up class attribute to display links in a pop-up iFrame FancyBox. Since you will be displaying images rather than an entire page in this FancyBox, you can set different options. Specifically, you should remove the type of iFrame, display the caption inside the pop-up box (on the calendar you had it display outside so that it did not blend in with the iFrame content), and set cyclic to true—meaning that as someone cycles through the images, once they reach the end of the set, the images will loop back to the start. Finally, do not set any limitations on the width or height of the FancyBox—you can allow the pop-up to auto-size itself to the size of the image being displayed. To accomplish all this, replace everything currently between <script type="text/javascript"> and with the following (leave the <script> tags as-is): $(document).ready(function() { $("a.gallery").fancybox({ 'cyclic': true, 'titlePosition': 'inside', 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none' }); });
For more information on FancyBox, including what the different options mean, you can visit http://fancybox.net/.
6. Finally, remove all the code that appears between (and including) Seminar Calendar
and {/exp:channel:calendar}. This is where your photo gallery thumbnails will eventually go. Click Update to save your work so far. At this point, you have a blank page (with a relevant page title and a FancyBox script that is ready for you to start using). Now you can start adding content.
[ 214 ]
Chapter 8
Adding content to your multiple-entry page
There are going to be two ways to browse your photos—visitors may go to the main photos/index page, where they will see all your photos. Alternatively, they can go to a category-specific page, where they will only see photos that fall into that category. Just like you did with your faqs/index template, you are going to use conditional statements to distinguish between when a visitor is on a category browsing page versus when they are not. Remember that a category browsing page will have the word category in segment 2 of the URL. 1. Still in the photos/index template, add the following code after . If you are on a category browsing page, this code displays the category name, category description, and a link back to the non-category version of your multiple-entry template. If you are on the non-category browsing page, then it will display the generic title of photo galleries and some instructions on how to browse the photos. {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} {category_name}
{category_description}
Browse all photos
{/exp:channel:category_heading} {if:else} Photo Galleries
<strong>Instructions: Select a gallery to view or click on a photo to see enlarged. When viewing in enlarged mode, use your left & right arrow keys to scroll between photos and the escape key to exit enlarged mode.
{/if}
[ 215 ]
Creating a Photo Gallery
2. Next, you can create a drop-down category selector to allow visitors to jump quickly to a given category. This code is adapted from the Channel Categories Tag documentation viewable at http://expressionengine. com/user_guide/modules/channel/categories.html#dropdown. It essentially uses a standard HTML drop-down form, populated with options from the channel categories tag that link to the photos/index template (though you specify only the template group photos, ExpressionEngine knows you mean photos/index because the index template is the default template). Add the following immediately after the previous code:
3. Click Update and then visit your photo gallery (at http://localhost/ photos). Verify that you can browse between categories and that when you are on a category page, you see the category information, and when you are not, you see the generic instructions. JavaScript must be enabled in your browser for the drop-down menu to work.
[ 216 ]
Chapter 8
4. It makes sense to display the thumbnails in a table. Since every gallery could have a different number of thumbnails, it is impossible for you to know in advance how many rows your table might need. You will therefore use a suggestion from Mark Bowen in the ExpressionEngine wiki (http:// expressionengine.com/wiki/Entries_In_Table/) to use the {switch} variable to insert a row break () after every five photos. You will combine this with a conditional statement that checks to see if the current entry is the last entry, in order to prevent a superfluous row being added at the end of your table. Remember that the switch variable allows you to insert different code for different entries. Typically, it might be used to alternate the background color of entries (for example, {switch="blue|red"} would mean your first entry is blue, your second entry is red, and your third entry is blue again. The different pieces of code that are alternated are separated by a pipe (|). When there are more entries than pipes, ExpressionEngine starts again from the beginning. {switch="|||| "} means that on every fifth thumbnail the row will be ended and a new one started—there is no code between any of the other pipes. For more information on the switch parameter, please visit http:// expressionengine.com/user_guide/modules/channel/ variables.html#var_switch.
5. Add the following code immediately after the : {exp:channel:entries channel="{my_channel}"} ***Image will go here*** {if count!=total_results}{switch="|||| "}{/if} {/exp:channel:entries}
[ 217 ]
Creating a Photo Gallery
6. If you visit your website now, you will see a table where your images will go as well as some placeholder text. If you browse between the different galleries, you will see a different number of table rows depending on the number of images that are in that category.
7. The next step is to replace the placeholder text with actual thumbnails. When designing your custom fields, you did not include a field for a thumbnail. Whilst you could include the full-size image with a small width/height, your visitors would then have to download all the full-size images in order to see this page—significantly impacting page load times. Instead, you can use thumbnails that are automatically generated by ExpressionEngine. 8. Whether you upload photos via FTP or via file manager, ExpressionEngine automatically creates thumbnails of any photos in a _thumbs subdirectory (/ images/photos/_thumbs) when you first view them in file manager. These thumbnails are used internally by ExpressionEngine, but you can also use them on your visitor-facing pages. To do this, you will use the custom File field (photos_photo) as a tag pair instead of as a single tag. This allows you to access the different components of each file (the path, the filename, and the extension) in each entry separately. By doing this, you can then insert the _thumbs subdirectory to the end of the path, and prefix the filename with the thumbs_ prefix that is automatically added to the thumbnails.
[ 218 ]
Chapter 8
For more information about using the File custom field as a tag pair instead of as a single tag, please visit http:// expressionengine.com/user_guide/modules/ channel/custom_fields.html#file_fields
9. Replace the ***Image will go here*** placeholder text with the following code:
If, after doing this, you have some thumbnails that are not showing up, you may need to log into ExpressionEngine, edit the entry in question, and re-add the photo using file manager. Make sure you can see the thumbnail in your entry before you submit it.
10. Visit your website again, and you will see thumbnails instead of the placeholder text you had before. Additionally, if you click an image, it will pop up in a FancyBox lightbox, with the caption underneath. This is because you gave the link a class attribute of gallery (which matches the class attribute you used in your FancyBox script). You can scroll through the photos in the FancyBox by clicking the left and right arrows or by using your mouse scroll wheel—this is because all the photos on the page have the same rel attribute, letting FancyBox know this is an image gallery. FancyBox treats whatever is in the title attribute as a caption—in this case, you included the {photos_caption} caption.
[ 219 ]
Creating a Photo Gallery
If your image does not appear in a pop-up overlay, but rather opens in a separate window or tab, you can check for a number of things. First, verify that the FancyBox directory is at the root of your website and that you can access the FancyBox files in your browser (if not, check your .htaccess file). Next, verify that the paths in the photos/index template point to the script/CSS files in the FancyBox directory and check the filenames for misspellings. Then, compare the photo/index template you have created with the photo/index template that is available for download from http://www.packtpub.com/support or http://www.leonardmurphy.com/book2/chapter8. Look carefully for any spelling mistakes or typos, especially in the code and <script> sections, as well as in the link code for the thumbnails. Finally, ensure that JavaScript is enabled in your browser.
11. The final step is to include a link to your single-entry page for visitors who want to leave comments. This can be accomplished by using a hyperlink underneath each photo that will mention how many comments have already been made. Add the following code immediately before the in your template:
{if comment_total=="1"}1 comment{if:else}{comment_total} comments{/if}
12. Now visit your photo gallery page and you will find the new hyperlinks. Click on one to confirm that you are taken to the single-entry page. Add a comment and verify the total increments correctly. If you have comment moderation turned on, you will have to mark the comments as open before they will be included in these counts (although if you are logged in as a Super Admin, you will be able to see the comments on the single-entry page). To mark a comment as open, select Recent Comments from the View section of the control panel home page, click on the comment you wish to open and then click View Comments. Here you can check all the comments you wish to open, and from the drop-down box, select Open Selected and click Submit.
[ 220 ]
Chapter 8
Your photo gallery is complete. You now have an easy way for visitors to browse your photos quickly, either from the main photos/index page or by gallery. It is also easy to see which photos already have comments and for visitors to add their own.
Image editing features
Now that you have gone through the process of creating a photo gallery, uploading images, and creating the corresponding templates, it is a good time to discuss how photos can be cropped, resized, and rotated all from within ExpressionEngine. 1. From the Content menu in the control panel, select File Manager. 2. If you have multiple upload destinations, it is good to know that if you click on the title of one (such as About), it will collapse the list of files. If you click again, the file list will expand. This can help reduce screen clutter. 3. If you select a filename (such as local6.jpg), a FancyBox pop-up will appear with the full size image. (Press escape or click the x in the top-right to close). 4. For the photo local6.jpg, select Edit (in the fifth column from the left).
[ 221 ]
Creating a Photo Gallery
5. At the top-right, there are three modes (Crop, Resize, and Rotate). Select Crop Mode.
6. The picture on the left will darken. To crop the photo, you can drag the rectangle over the picture until the part of the picture you want is framed. The rectangle can be resized or repositioned as needed. On the right-hand side, you can see information about the width, height, and X/Y coordinates of your crop.
[ 222 ]
Chapter 8
7. Once the rectangle is placed, click Save Image on the right-hand side to save your changes. 8. You can also resize the photo by clicking on the Resize option. In this case, setting a width will automatically adjust the height so the photo stays in proportion (and setting the height will automatically change the width). This feature is extremely useful if you want to upload a full-sized image, but then manually adjust it so the width is no more than a certain size (for example). When you upload a photo for the first time from the Publish page, you also have the option to resize an image. In this way, you can upload full-size images directly, and resize them on the fly in ExpressionEngine, rather than shrinking them in advance or uploading them and using the file manager to resize them.
Rotate mode is also fairly self-explanatory. However, be aware that selecting a different rotation (or flipping the image horizontally or vertically) automatically saves the image.
Photo gallery add-ons
In this chapter, you have walked through how to build a photo gallery in ExpressionEngine without using any third party add-ons. As you can see, the functionality in ExpressionEngine is very robust and flexible out of the box. That said, there are times when an add-on can be useful—especially if images are a large part of the content of your website. Pixel & Tonic's Matrix was already mentioned at the beginning of the chapter as a useful add-on for designing a photo gallery with multiple photos per channel entry. In addition, the following add-ons are specific to editing photos (though they are by no means representative of all the add-ons that are available. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available.).
Image sizer
http://devot-ee.com/add-ons/image-sizer/
Written by David Rencher, this plugin takes a large image, dynamically resizes it, and caches the resized image (to reduce page load times). Using this add-on in your template saves you from having to manually resize every image you upload (and eliminates the risk of breaking your page layout if you forget). Instead, images are resized on the fly. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available. [ 223 ]
Creating a Photo Gallery
Channel Images
http://devot-ee.com/add-ons/channel-images/
For a small fee, Channel Images by DevDemon allows you to batch-upload multiple files from within the ExpressionEngine control panel and simplifies image management on the Publish page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. Since the photo gallery uses the same tools as all the other sections of your website, these exercises are not so much specific to photo galleries, but are a good reminder of the techniques learnt in previous chapters. 1. The main page of the photo gallery works great when there are only a handful of photos. However, over time, you could end up with hundreds and hundreds of photos in your channel, all of which would get displayed on your main page. Change the main page so that it limits the number of photos that are displayed and randomizes which photos are shown. 2. ExpressionEngine has the ability to track how many times a channel entry has been viewed on a single-entry page (Entry Views). Using a conditional statement, indicate on your multiple-entry template which photos are ***popular*** photos, based on the number of single-entry page views. For now, consider more than ten single-entry page views to be a sign of a popular photo. 3. The form for submitting comments and the code for displaying comments on your single-entry page are almost identical to the form for submitting comments and the code for displaying comments on your FAQs channel. In the spirit of reducing repetition, choose between a Preload Text Replacement, a Global Variable, a Snippet, or an Embedded Template and extract the code from both photos/comment and faqs/browse, so that both templates use the same code for submitting and displaying comments.
[ 224 ]
Chapter 8
Summary
In this chapter, you took a look at how to adapt the channel functionality of ExpressionEngine to a photo gallery. The lack of a formal photo-gallery module can make ExpressionEngine seem less functional. However, as you can quite clearly see, the standard channel functionality is more than adequate for the task, and indeed allows for a lot more flexibility than a separate photo gallery module might offer— with unlimited custom fields, a multitude of ways that you can organize photos within your channel (using categories and/or status groups), and with no restriction on how you can build your templates, the sky is the limit. This chapter wraps up the step-by-step introduction to ExpressionEngine. By now, you should be fairly comfortable with the basics of ExpressionEngine—channels, templates, tags, custom fields, categories, status groups, and so on. In the next chapter, you will be introduced to some more specialized first party modules that you may find useful.
[ 225 ]
Beyond the Basics So far, this book has introduced the basic concepts and the most commonly used features of ExpressionEngine. Many of the same basic skills have been used time and again such as setting up custom fields and categories, creating a new channel, posting entries to the channel, and building templates with HTML/CSS and ExpressionEngine tags. ExpressionEngine comes bundled with many other modules that may or may not be useful, given your website. The modules range from the simple to the complex—the simplest create additional tags that you can use in your templates, while the most complex include their own configuration pages and library of tags. This chapter looks at some of the offerings, including: •
The Search module
•
The Mailing List module
•
The Email module (create a contact form or a tell-a-friend form)
•
The Moblog module (submit new channel entries via e-mail)
•
The Wiki module The Mailing List and the Email modules rely on ExpressionEngine being able to send e-mails. If you are following along in a localhost environment such as WampServer, XAMPP, or MAMP, you will find that ExpressionEngine cannot send e-mails. This is because a localhost environment does not include an e-mail server. You can either follow along on an actual website server, or if you choose to follow along in your localhost environment, be aware that in places where you would expect ExpressionEngine to send an e-mail, you will not see such an e-mail.
Beyond the Basics
The Search module
ExpressionEngine comes with a pre-built search tool to allow visitors to search your site. Although technically a module, the search functionality comes pre-installed and does not have any special setup. This means that you can start using the search tags right away. There are two parts to enabling search on your website, namely: •
Creating a form that allows visitors to type in and submit search terms (this could be as simple as a search box that appears in your sidebar or it could be an entire template dedicated to an advanced search).
•
Creating templates to display the search results (or that there are no results). The Search functionality only searches channels. The Discussion Forum module and the Wiki module both have separate search functions.
When you design your search forms, you can use parameters to control what is searched. By doing this, you can limit searches to particular channels, status groups, or categories. You can also determine whether you want the search to include expired or future entries (this is important if you are searching a channel, like an events calendar, where all the entries might be in the future). Finally, you can set whether you want to search for words only in channel titles, in all the custom fields of a channel, or in the channel title, custom fields, and comments. Be very cautious if you enable your search to include future entries and the search form searches more than one channel. While one channel might routinely have entries in the future that you want to be searchable, another channel might have future-dated entries that you want to keep hidden until that date/time. The parameters you set for your search form (such as whether to include future-dated entries) apply to all channels that you allow to be searched from that form.
In addition to the search tags, there are three settings in the control panel that control how the search behaves:
[ 228 ]
Chapter 9
1. Is the field searchable? Each custom field in ExpressionEngine can be set to either be searchable or not searchable. Having this field set incorrectly on your custom fields can mean entries not being found that otherwise would be. As a general rule, fields that contain content such as sentences and paragraphs should be set to searchable, but fields such as drop-down boxes or files should not be searchable. To change the searchable setting for any individual field, go to Admin | Channel Administration | Custom Fields, and then select the field group and the field you wish to edit. You could create a custom field on a channel that is searchable, but that is not displayed on your website. This field could then be used to store likely search-terms for each individual entry that might not otherwise appear in the article (such as variations in spelling), thus improving the possibility that meaningful results are returned for people searching your website.
2. Search Page URL. Each channel has a path that is used to link the search results to the actual entries that were found. If this path is set incorrectly, clicking on a given search result will send the visitor to a wrong page. The field should be set to the single-entry template for the channel. (For example, the Photos channel should be set to http://localhost/photos/ comment). To change this setting for a given channel, go to Admin | Channel Administration | Channels, then click Edit Preferences for a specific channel, and look under Path Settings. 3. Which field should be used for search excerpt? This is also found under Channel Preferences, under Administrative Preferences. This defines the custom field from which the excerpt displayed on the results page comes from. To demonstrate the search functionality, you will create a search box in the sidebar that searches both the FAQs and the Photos channels. Before you begin, ensure that the Search Page URLs for these two channels are set to http://localhost/faqs/ browse and http://localhost/photos/comment respectively.
Adding a search box to your site
In this section, you will create a search box in the sidebar for Ed & Eg's website, thus allowing visitors to start a search from any page they like. 1. Go to Design | Templates | Snippets and edit the website_sidebar snippet.
[ 229 ]
Beyond the Basics
2. In the snippet, add the following code immediately after the final and before the final . Notice the parameters—the channel parameter restricts the search to the FAQs and Photos channels. The search_ in="everywhere" parameter means that you want the search to include titles, custom fields, and comments. The where="any" parameter means that entries containing any of the searched-for words will be returned (as opposed to requiring an exact match). The status parameter means that you will include entries with a status of open or premium (the premium status was one that you created in Chapter 6, Members, and if you did not include it explicitly, only entries with an open status would be searched). Finally, the result_page and no_result_page define which templates should be used when there are results or when there are no results (in this case, the search/ index and search/noresults templates, which you are yet to create). The rest of the code is a standard HTML form (although the input box must have the name="keywords" attribute for the search form to work). For more information on each of these parameters, including alternative settings for them and additional parameters not included here, please visit http://expressionengine.com/user_guide/modules/ search/simple.html. {exp:search:simple_form channel="faqs|photos" search_in="everywhere" status="open|premium" where="all" result_page="search" no_result_page="search/noresults"}
{/exp:search:simple_form}
3. If you visit the home page of your website, you should now see the search box on the right-hand side. If you have the Agile Records example website template groups still installed, searching will result in the Agile Records themed advanced search template being returned—otherwise, you would get a 404 page. You will create the search result templates next.
[ 230 ]
Chapter 9
Creating a search results template
The search results template is specified in the parameters of the search form as search, which translates to the search/index template. Had you not defined a specific template, the search results template would be set to search/results. If Agile Records is installed, then you are likely to already have a search template group which you can adapt to display your results. Otherwise, go ahead and create a search template group now. 1. The first step is to start with your basic site outline (header, sidebar, and so on). You can accomplish this by copying the includes/404 template into the search/index template. Edit the search/index template and paste in a copy of the code from includes/404. 2. Change the title of the page to be: Search Results - Ed & Eg Financial Advisors
3. Change the heading to be Search Results: Search Results
4. Replace the next paragraph (that talks about the page not existing) with the following. The {exp:search:keywords} tag displays the keywords used for the search.
You searched for <em>{exp:search:keywords}.
If you see a warning about there not being a closing tag when you save your template, ignore it. The {exp:search:keywords} tag is one of those that does not have a corresponding closing tag.
[ 231 ]
Beyond the Basics
5. Underneath the preceding paragraph, insert the following code (adapted from the code found at http://expressionengine.com/user_guide/ modules/search/results.html). This displays your search results in a two-column table. The first column will have the entry title and the second column will have an excerpt from the entry (the first 50 words from the field designated as the search excerpt field in your channel preferences). First create the table and the header row.
Title Excerpt
{if paginate} <span>{page_count} {paginate} {/if}
The pagination code at the end works similarly to channel pagination—allowing a long list of results to span multiple pages.
6. The following code uses the {exp:search:search_results} tag to display the actual results. This tag loops through once for each result you have. In this case, a new table row is created for each result. The switch tag makes the first row light-gray, the next white, the third light-gray, and so on. (Remember from the photo gallery chapter that the switch tag uses the first switch for the first result, the second switch for the second result, and so on, until it runs out of switches, when it starts over). Prior to the entry title, the channel name (such as Photos: or FAQs:) is added to make it clearer what kind of entry is being linked. Underneath the entry title, the number of comments that the entry has received is displayed. Add this code after the closing of the header row, within the table you created earlier: [ 232 ]
Chapter 9 {exp:search:search_results} <strong>{channel}: {title}
{if comment_total=="1"} 1 Comment {if:else} {comment_total} Comments {/if} {excerpt} {/exp:search:search_results}
Within the {exp:search:search_results} tag, there are some special variable tags you can use, including {auto_path} and {excerpt}. {auto_path} creates a path to the entry using the Search Page URL, defined in the channel preferences, and {excerpt} displays the first 50 characters of the excerpt field defined in the channel preferences. You can also use tags (such as {comment_total}, {author}, or {entry_date}), which are normally available in the {exp:channel:entries} tag. More information on search resultspecific tags can be found at http://expressionengine.com/user_ guide/modules/search/results.html and information on channel entry tag variables can be found at http://expressionengine.com/ user_guide/modules/channel/variables.html.
[ 233 ]
Beyond the Basics
7. Now click Update and Finished, go to your website, and search for something (for example, money). Your results will be displayed.
The no-results template
One other template you defined in your website_sidebar snippet was a no_ result_page of search/noresults. This can be a simple template that uses {exp:search:keywords} to display the search term and indicates that no results were found.
1. In the Search template group, create a new web page template called noresults. If you already have a results and a no_results template in the search template group, you can go ahead and delete these. 2. When creating the template, select to duplicate an existing template and duplicate search/index. Click Create and Edit. 3. Delete all the code from (and including) the
immediately above the opening tag down to (and including) the closing {/if} statement of the {if paginate} block of code. 4. Modify the You searched for… paragraph to read as follows:
[ 234 ]
Chapter 9 You searched for <em>{exp:search:keywords}. Unfortunately, nothing matching that search was found.
5. Click Update and Finished (ignoring any warnings about there being no closing tag) and now try searching for something that you know is not part of your website (for example, monkey). You will be redirected to your search/ noresults template.
Advanced search
In addition to the {exp:search:simple_form} that you used in your sidebar snippet, you also have the option of creating an advanced search form using the {exp:search:advanced_form} tag. The advanced search form allows visitors to select many of the settings that you set in the parameters of the simple search form. For example, on the simple search form, you specified which channels could be searched, whereas on the advanced search form, you can allow visitors to select which channels they can search in (although you can limit the choices they see by using parameters, just as you did with the simple search form).
[ 235 ]
Beyond the Basics
To build an advanced search form, you can create a template, such as search/ advanced, and then adapt the code from http://expressionengine.com/user_ guide/modules/search/advanced.html. This form looks much more complex than the simple_form, but most of that complexity comes from building all the form fields—how the form works is the same. Although an advanced search form on a small website like Ed & Eg would be overkill, an advanced search tool can enable power users to find what they are looking for on websites that have large amounts of content.
The Mailing List module
ExpressionEngine comes with a Mailing List module included. It is a very straightforward module that allows you to quickly and easily send e-mails to visitors who have signed up to receive e-mails or to specific member groups. You can have as many mailing lists as you want. Remember that if you are using a localhost environment such as WampServer or MAMP, ExpressionEngine will not be able to send outgoing e-mails. You will be able to follow the steps to set up a mailing list and make the sign-up box available on your website, but you will not be able to use the Mailing List module to send e-mails.
Setting up the Mailing List
The Mailing List module is included with ExpressionEngine, but is not installed by default. Installing it is easy. The following steps will show you how to do it: 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Mailing List and then click Install. 3. The Mailing List module name will turn into a clickable link. Click it to enter the Mailing List Manager. 4. To start with, there is one mailing list set up called Default Mailing List. You can change the name of the mailing list by clicking Edit next to the mailing list. You can also create multiple mailing lists by clicking Create New Mailing List at the top right.
[ 236 ]
Chapter 9
5. Click Edit Template to edit how the e-mails will look. By default, each e-mail has a footer with the unsubscribe URL (auto-generated by the Mailing List module for each e-mail address the e-mail is sent to). You can customize how this footer is worded or add text above the {message_text} variable in order to create a header for all your Mailing List e-mails. The conditionals {if plain_email} and {if html_email} allow you to distinguish between plain-text and HTML versions of an outgoing e-mail, so that people reading the e-mail in plain text do not see the HTML mark-up. For now, leave the default e-mail template as-is. 6. Also, within the Mailing List Manager, you can batch subscribe or unsubscribe people (for example, if you were transferring over a Mailing List from another application). You can also set up an administrator e-mail address, so when someone new subscribes to a Mailing List, the administrator gets notified. (Click Mailing List Preferences to do this). 7. To see who is signed up for any given Mailing List, click View next to the Mailing List name.
[ 237 ]
Beyond the Basics
Now that you have a mailing list defined, there are two more things you must do: 1. Allow people to subscribe to your mailing list 2. Send e-mails to people on your mailing list
Allowing members to sign-up
To allow visitors to sign themselves up to the mailing list, you are going to add an option to your sidebar snippet. 1. Modify the snippet called website_sidebar. 2. In the snippet, add the following code immediately after the final li> and before the final . This code is adapted from the mailing list documentation at http://expressionengine.com/user_guide/modules/ mailinglist/index.html. Notice that in the {exp:mailinglist:form} tag, you have a parameter called list that is used to determine which mailing list the member will be signed up for (in this case, default). The e-mail input box value is set to {email}, which is a global variable referring to the e-mail address of the currently logged in member. In this way, if a member wishes to register for the mailing list, they do not need to re-type their e-mail address. Mailing List
{exp:mailinglist:form list="default"}
{/exp:mailinglist:form}
3. Click Update and Finished. Visit Ed & Eg's home page and you will see the option to sign up for a mailing list. Note that any new visitors who sign up will receive an e-mail with a link which they must click within 48 hours in order to actually sign-up (remember that if you are using a localhost environment, you will not receive this e-mail). The mailing list is strictly an opt-in feature, with an opt-out link included in every e-mail that you send.
[ 238 ]
Chapter 9
You have set up your mailing list so that visitors can sign themselves up to it. Note that if you wanted to have multiple mailing lists, all you would need to do is change the list parameter to reflect the short-name of the mailing list that the person is signing up for. Of course, now that you have a mailing list with subscribers, how do you send them e-mails?
Sending e-mails
Before trying to send an e-mail, review your e-mail settings in Admin | Email Configuration. Here, you can define not only how e-mails are sent (PHP Mail, Send Mail, or SMTP), but you can also define which e-mail address they come from. If, for any reason, ExpressionEngine is not sending e-mails, you can also turn on Email Debugging, which will then display the error message explaining what is stopping the e-mail from being sent. The settings on this page apply to all e-mails sent by ExpressionEngine, including automated e-mails such as those that are sent as part of new member registration or when you sign up for a mailing list.
[ 239 ]
Beyond the Basics
To send e-mails, you must use the Communicate tool (under Tools in the main menu). This tool can be used in conjunction with the Mailing List module to send e-mails to people who have subscribed to a given mailing list, or it can be used on a standalone basis to send e-mails to certain member groups or specific e-mail addresses. Remember that if you are following along in a localhost environment, you will not actually be able to send outgoing e-mails.
The Communicate tool has lots of options, most of which are fairly self-explanatory. At the very top, there is a link to see previously sent e-mails. Underneath the message, you can choose between sending a plain-text or an HTML e-mail. If you choose HTML, you can optionally include a plain text alternative for recipients who cannot read HTML e-mails. On the right-hand side, you can choose which mailing lists or member groups get the e-mail (or manually type in your own recipients' e-mail addresses). If you are handtyping e-mail addresses, it is recommended that you use the BCC field so that you do not expose the e-mail addresses of recipients to other recipients. You can also define who the e-mail comes from (so that it is less likely to be treated as spam).
A checkbox at the very bottom allows you to suppress e-mails to members who have requested not to receive e-mails from administrators in their control panel settings—respecting this setting is recommended. [ 240 ]
Chapter 9
The Mailing List module is designed to make it easy to send e-mails to multiple recipients at once. If you want to send an e-mail to an individual member, you can also do so via the e-mail console, provided you have enabled this functionality for the member group you are in. Click on the Email button from either the individual member's profile or from the member list at http://localhost/member/list to access the e-mail console. See Chapter 6, Members for more information on member-facing functionality.
The Email module
The Email module gives you the ability to easily create contact forms (so that your visitors can e-mail you) and tell-a-friend forms (so that your visitors can e-mail their friends). In this section, you will see how to set up both of these forms for your website. If you installed the Agile Records example site, then the Email module will already be installed. Otherwise, it can be easily installed by going to Add-Ons | Modules and clicking Install.
Creating a contact form
Ed & Eg currently have an FAQs section, where they answer frequently asked questions from their customers and visitors. However, there is no easy way for visitors to submit their questions to Ed & Eg. In this section, you will create a new contact form so that visitors can submit their questions for Ed & Eg to answer. As you have done before, you will base the contact form template on the includes/404 template (which has the site header and other layout components, but does not have much in the way of content that needs to be changed). 1. From Template Manager, select the faqs member group and click New Template. 2. The new template will be called submit. The template type should be Web Page. Check the option to duplicate another template and select the includes/404 template to duplicate. Click Create and Edit. 3. Change the HTML to the following: Submit a Question - Ed & Eg Financial Advisors
[ 241 ]
Beyond the Basics
4. Change the title from Page Not Found to Submit a Question. 5. Delete the paragraph underneath the tag. 6. The following code is adapted from the example provided in the ExpressionEngine documentation for this module at http://
expressionengine.com/user_guide/modules/email/contact_form. html. The {exp:email:contact_form} tag displays your contact form. This tag has a parameter called recipients that allows you to specify the e-mail
address you want the final e-mail to be sent to—your visitors will not be able to see or change this address. The rest of the form is a standard HTML form with some values filled in, based on ExpressionEngine variables (the e-mail address of the member, their name, and the date/time). Add the following code underneath the header in the template, changing the recipient's e-mail address to match your own:
{exp:email:contact_form user_recipients="false" recipients="[email protected]" charset="utf-8"}
{/exp:email:contact_form}
7. Although the form is complete as-is, you can also add code to display a CAPTCHA. Even if you are not using the CAPTCHA system now, it does not hurt to put this code in; in case you want to use it in the future, you can quickly enable it (under Admin | Email Configuration) without changing your templates. You can do this because the {if captcha} conditional prevents the CAPTCHA from displaying, unless it is set to be required. Insert this code immediately before the Submit button (after the
) within the contact form: {if captcha} {captcha} [ 242 ]
Chapter 9
{/if}
8. Click Update and now visit your submission form at http://localhost/ faqs/submit. If ExpressionEngine is configured to send e-mails, visitors will be able to use the form to send you e-mails easily and seamlessly from within your website.
For more information about the parameters of this form and how they can be set, please see the ExpressionEngine documentation at http://expressionengine. com/user_guide/modules/email/contact_form.html. The documentation includes useful tips in case your server host does not allow e-mails to be sent from your domain with a "from e-mail address" that is not yours. [ 243 ]
Beyond the Basics
Creating a tell-a-friend form
The tell-a-friend form works very much like the Contact form, except that instead of e-mailing a person you specify, the person can e-mail a friend of their choice. The risk with this form is that spammers might use it to e-mail advertising or other junk to third parties. To prevent this, there are several options—you can restrict this functionality to signed-in members who have activated their membership via e-mail (and then pre-fill the From field with that member's e-mail address). You can fix the message text yourself so that it cannot be edited (visitors can either send or not send the message as-is). Finally, you can require CAPTCHAs (in Admin | Email Configuration) for visitors e-mailing a friend. You may also wish to consider independent social media solutions, such as adding Facebook's Like button to your website, which allows visitors to easily share that they like your website, without the concerns that the tell-a-friend form brings. Check out http://developers.facebook. com/docs/guides/web for more information.
For this example, you will create a tell-a-friend form for the FAQs channel that is only available to members. The From e-mail address will be set as the e-mail address of the logged-in member and the message will also not be editable.
Creating the tell-a-friend template
The tell-a-friend template will be based on the faqs/submit template, which you had created for your contact form. If you did not follow the steps to create a Contact form, remember that you can download the source code from either http://www. leonardmurphy.com/book2/chapter9 or from http://www.packtpub.com/support. 1. Create a new template in the FAQs template group called friend. When prompted to duplicate an existing template, select faqs/submit as the template to duplicate. Click Create and Edit. The tell-a-friend form can also be added to the bottom of the singleentry template for your channel (in this case, faqs/browse).
2. Change the HTML to: Tell a Friend - Ed & Eg Financial Advisors
3. Change the title to Tell a Friend. [ 244 ]
Chapter 9
4. Replace everything from {exp:email:contact_form} to {/ exp:email:contact_form} with the following conditional, which checks to see if the visitor is logged in. If they are not logged in, they will not be able to tell-a-friend. {if logged_out}
Sorry, you must be logged in to tell-afriend.
{if:else} {/if}
5. After the {if:else} and before the {/if}, insert the following tell_a_ friend form (adapted from http://expressionengine.com/user_guide/ modules/email/tellafriend.html). The tell-a-friend form is necessarily longer than the Contact form because there are more fields (for the send-to e-mail address and the name of the person the e-mail is coming from). Also, notice that some of the fields in the following code are read-only because the values are being populated from ExpressionEngine. {exp:email:tell_a_friend charset="utf-8" allow_html='no' status="open|premium"}
{/exp:email:tell_a_friend}
In this example, you use the {faqs_question} custom field to display data from your entry in the message. Indeed, ExpressionEngine is versatile enough that you can create a single tell-a-friend form for multiple channels, even if they have different custom fields. ExpressionEngine will suppress any custom fields that do not apply, based on the channel that is being sent to a friend. The status="open|premium" is because there are some entries that might have a premium status rather than open. Without this setting, any status that is not open would not render the tell-a-friend form.
6. As with the Contact form, add the following CAPTCHA code immediately before the Submit button (after the
) {if captcha} {captcha}
{/if}
7. Now you need to create a link to the tell-a-friend form. Edit the faqs/browse template and add the following link next to the Back to FAQs link. Like the form itself, this link will only be visible to members who are logged in. {if logged_in}Tell-aFriend | {/if}Back to FAQs
[ 246 ]
Chapter 9
8. Now if you visit a FAQs channel entry and click the Tell a Friend form, you will be brought to the faqs/friend form, where you can send an e-mail to a friend.
Word-of-mouth is one of the best marketing strategies available, and the tell-a-friend functionality allows visitors to share an entry on your site without having to a draft a special e-mail. Although this example is very locked-down, you can make it more flexible (such as by allowing visitors to edit the message). Before making changes such as that, always think of how easy it might be for a malicious person to use the form to send advertising or phishing e-mails to third parties.
[ 247 ]
Beyond the Basics
The Moblog module
So far, whenever you wanted to create content, you have had to log into the control panel and publish a new entry. The Moblog module provides a way to upload files to your website and create content directly from your Internet-enabled smart phone. The basic concept involves setting up an e-mail address which ExpressionEngine can access. When you e-mail from your phone to the e-mail address, the content can either be turned into a channel entry, or attached files can be saved to an upload location without a channel entry being created (making it an easy way to upload files to your website without FTP). The module includes ways to prevent spam or other e-mails that might also be sent to the same e-mail address from being published to your site. Unfortunately, the Moblog module can only add new content to text area custom fields. Since channels will often have other types of custom fields, does this mean that you cannot use the Moblog module? No. Take, for example, the Photos channel. There is one text area custom field (caption), but the photo itself is a File custom field. Although you cannot publish an entry to the photo channel without a photo, you can still use the Moblog module to create a closed entry with the caption you desire, and upload the photo(s) attached to your e-mail to the photo gallery upload destination. Then, when you log in to the control panel, all you have to do is edit the entry, select the photo from the file manager, and change the entry status to open. For the Moblog module to work, you must have an e-mail address that ExpressionEngine can access via POP3. Typically, an e-mail address associated with your website domain or your internet provider (ISP) would have POP3 access, but a free web-based e-mail service may or may not. Since ExpressionEngine is only reading incoming e-mails (and not sending e-mails), the Moblog module can be set up and tested even in a localhost environment.
Setting up the Moblog module
As with other modules, the Moblog module is not installed by default. Installing it is easy. 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Moblog and then click Install. 3. The Moblog module name will turn into a clickable link. Click it to enter the Moblog control panel. 4. When you first enter the control panel, no Moblogs exist. Click Create New Moblog. [ 248 ]
Chapter 9
5. First, the general settings need to be defined. Enter a full name of Photos Moblog and a short name of photos_moblog (remember that the short name is what will be used in templates). Leave the time between checks set at 15 minutes. This does not mean that the e-mail address will be checked every 15 minutes, but that if you set up a template with an {exp:moblog:check} tag, and someone visits that template and more than 15 minutes has passed since the last check, then the e-mail address will be checked. Set Moblog Enabled? to Yes and set File Archive Mode to No (File Archive Mode is where files attached to your e-mail are uploaded, but no channel entry is created).
[ 249 ]
Beyond the Basics
6. Next, choose the channel you want to post to—in this case, Photos. You can also select a default category, field, status, and author. This can be useful if, for example, you want your mobile photos to be in their own gallery or to have their own status. For this example, use a default category of None. Use a default field of Caption, a default status of Closed (since you do not want your entries to be visible until you have updated the File custom field with the photo), and a default author of you.
7. Say No to making the entry sticky (meaning that it always appears first on a multi-entry page) and Yes to allowing overrides in e-mail. This means that if you want to set the category or status differently as compared to the default, you can do so by using a special code in your e-mail—for a list of possible overrides, see http://expressionengine.com/user_guide/modules/ moblog/email_contents.html. 8. Select Photo Gallery as the upload directory. 9. The Moblog templates allow you to define exactly what will happen with your e-mails. The default is to display the text first, then any images in an img tag, and any other files as a Download File link—all within your text area. Since you do not want your images to be part of the caption, change the template to remove the {images} section as follows: {text} {files match="audio|files|movie"} Download File {/files}
[ 250 ]
Chapter 9
For more information on the different tags and parameters that are available, please visit: http://expressionengine.com/user_ guide/modules/moblog/control_panel/email_template.html.
10. Next up, you can define your e-mail settings. The e-mail server must support POP3—typically e-mail addresses associated with your website domain would have POP3 access, as would e-mail addresses from your ISP. Free e-mail services may or may not include support for POP3 access. If you already download your e-mail to your e-mail software using POP3, then the same settings that are in your e-mail client (server name, username, and password) would go here. Since the Moblog module is scanning for incoming e-mails and does not send e-mails, the Moblog module will work even if you are using a localhost environment. Simply set the settings to the e-mail address you want to scan.
11. Further down, you can specify a word or phrase that must appear in the subject of your Moblog e-mails. This allows ExpressionEngine to distinguish between a Moblog e-mail and all the other e-mails you may receive. The default setting is moblog:, meaning that any e-mail you want posted to your Photos channel needs to have moblog: in the subject. (When setting the title of the entry, this phrase will be stripped out and the rest of the subject will be used; for example, Moblog: Flower will result in an entry called Flower.) Changing the subject prefix is useful when you want multiple Moblogs to use the same e-mail address. However, for the purposes of this example, leave it set as moblog:. 12. For security, you can also set your Moblog e-mails to be from a certain e-mail address (or addresses) and you can require authentication (meaning your control panel username and password must be included in your Moblog e-mails). It is recommended to at least limit the e-mail addresses that can send Moblog e-mails. 13. The next option allows you to prevent certain text that might be included in your e-mails (such as your signature) from appearing in your channel entry.
[ 251 ]
Beyond the Basics
14. Next, you can set the parameters for any images you attach—you can require images to display with a certain height or width, you can resize, you can upload images automatically, and you can also create thumbnail images if desired. For now, say Yes to resize images on import, and resize any images to have a width of 555. Leave the height set to 0 to keep the image in proportion.
15. Finally, click Submit to create your Moblog.
Setting up your template
If you were using the Moblog module to post content directly to your website, you could set up a template to check for new Moblog entries automatically whenever it is accessed by a visitor. With the following tag, ExpressionEngine will check to see if 15 minutes have elapsed since the last check, and if so, ExpressionEngine will check again:
silent="true" means that the Moblog check will be invisible to the person viewing your template. For troubleshooting purposes, you could temporarily set this to false. If you do set this to be false, having the tag wrapped within an HTML comment, as shown, means that you can see any error messages by viewing the HTML source (by clicking View Source from your browser), while visitors see nothing unusual. [ 252 ]
Chapter 9
Since you are setting up your Moblog to act as an easy way to create entries without publishing them right away, this step does not apply.
Sending a Moblog e-mail
Now that the Moblog module is configured, you can try sending your first Moblog e-mail. 1. First, send an e-mail to the e-mail address you specified with an image attached. Be sure that the e-mail has a subject prefix as defined (moblog:) and comes from an e-mail address that is allowed to post Moblog entries. Do not forget the attachment!
2. Next, log into the control panel and select Add-Ons | Modules and then select Moblog. Click Check Moblog. If the Moblog module finds valid e-mails, you will see a green check mark at the top of the screen (which you can click to see more information).
[ 253 ]
Beyond the Basics
3. Now select Content | Edit and look for an entry with a title that matches the subject of the e-mail, a date/time of the current date/time, and a status of closed. Click the entry to edit it and you can see the body of your e-mail in the caption field.
4. Click Add File, select the Photo Gallery, and click on the file you uploaded. 5. Click on the Options tab and change the status to Open. Then click Submit. 6. Visit the photo album (http://localhost/photos) to see your new entry. Notice how the image was automatically resized to be 555 pixels wide, as specified in the Moblog preferences.
[ 254 ]
Chapter 9
The Wiki module
A wiki is an area of the website where visitors themselves can edit the content or create new content. One of the most famous wiki's on the web is Wikipedia (http://www. wikipedia.org/)—an online encyclopedia that anyone can contribute content to. Another example wiki is the ExpressionEngine wiki, located at http:// expressionengine.com/wiki/—a great tool for sharing how-tos and more with other ExpressionEngine users.
At first glance, it can be difficult to see the use for a wiki (especially for a website like Ed & Eg's). However, if you think of it as a collection of documents that can be shared among a group of people of any size, and updated in real time by the same group of people that actually use the content, the business advantages start to become clearer. As with any tool that requires active participation from others, it helps if you already have a group of people that is willing to participate. A wiki, more so than other tools (such as comments or a discussion forum), requires an unusually high commitment from end-users—first to build the content and then to be willing to edit and add to other people's content. To demonstrate how the Wiki module works, you will create a wiki for visitors to exchange money-saving tips and ideas. The Freelancer license does not include the Wiki module, so this section will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing.
Setting up the wiki
As with other modules, the Wiki module is not installed by default. Installing it is easy. 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Wiki and then click Install. 3. The Wiki module's name will turn into a clickable link. Click it to enter the wiki control panel. 4. Click on Create Wiki. 5. Change the full wiki name to Money Saving Wiki and change the short name to money_saving_wiki.
[ 255 ]
Beyond the Basics
6. Leave the text formatting as Xhtml, but Allow only safe HTML (meaning that people can use standard HTML tags to mark-up their content). 7. Choose a File Upload Directory where files associated with the wiki will be stored. (You may want to create a new directory under Content | File Manager that is specifically for wiki files). If you do not select a destination, uploading files will not be possible. 8. Select which member groups can administer the Wiki module, and which member groups can use it. Administrators can delete content, mark an article as locked (so that no-one can edit it), or mark an article as moderated (meaning that users can edit it but an administrator must approve the change before it becomes visible to others). Select Super Admins as your administrating member group, and select all your member groups as users. 9. You can set up how many revisions you keep for each article and how many edits a single individual can do in a single day. For now, leave these at their defaults. 10. Set up an e-mail address as the e-mail to receive notifications when an article marked as moderated is changed. 11. You can optionally set up a namespace for you to group articles. The main advantage to using a namespace rather than a category is to set up different member groups as administrators and users. For example, Ed & Eg cater to both businesses and individuals, so if they wanted, they could have created two namespaces so that their business articles and individual articles were separated. They could then have two member groups and allow members of the business member groups to add/edit content to articles in the Business namespace but not articles in the Individual namespace. For now, leave the namespace fields blank. 12. Click Update to create the wiki. 13. The final step is to create a new template and template group for your wiki. Go to Design | Templates | Edit | Create Group and call the new template group wiki. 14. Edit the index template of the wiki template group and add the following code. You do not need to include any other HTML or ExpressionEngine tags, as this tag will create the entire wiki. {exp:wiki base_path="wiki/index" wiki="money_saving_wiki" theme="azure"}
[ 256 ]
Chapter 9
If you use a different template group or template name, change the base_path parameter accordingly. The wiki parameter is the short name of the wiki. The theme can be either default or azure. You can also create your own themes by creating a new directory in your / themes/wiki_themes/ directory and copying and modifying the files from an existing theme. See http://expressionengine.com/user_ guide/modules/wiki/wiki_templates.html for more information.
15. Now view this template in a browser (http://localhost/wiki).
How does the wiki work? The next step is to create some content.
1. On the first page of the wiki, click Edit (at the top) to edit the page.
[ 257 ]
Beyond the Basics
2. You can type in whatever text you wish, using HTML for basic text formatting. To create a link to a new article, enclose the new article's name in double square brackets. For example: Welcome to our Money Saving Wiki. Here are some moneysaving ideas: <strong>[[Shopping]] Don't buy the name-brand of everything. Pick one or two items that you like, and for everything else, buy the store brand. Sometimes spending the extra 30 cents for the name-brand doesn't sound like much, but saving 30 cents on 30 items in a single trip, and doing 40 trips a year, will save you $360 this year!
For more money-saving tips when [[shopping]], click on the word [[shopping]].
3. In the notes section, write a brief description of the change you are making, such as "Added Tip on saving money when shopping". (This will show in the history log). Then click Submit.
4. You can now click on any one of the shopping links to be brought to a new article where you can create a new page with more text. Notice how you can have multiple links to the same article. Remember that a wiki is a multi-user environment. The intent is not to have one person create all the content, but for it to be a collaborative effort (although you may prefer to have one person add some content and develop the structure before making it more generally available).
5. The ExpressionEngine wiki also supports the use of categories. Use the following code anywhere in an article to assign the article to a Shopping category. [[Category:Shopping]] [ 258 ]
Chapter 9
You can assign an article to multiple categories. You can also assign articles to subcategories using a format such as: [[Category:Shopping:Store Brands]]
6. If enabled, you can also upload images, diagrams, and documents by clicking on File Upload on the left-hand menu. You can then embed uploaded files using either [[File:filename.txt]] (to create a link) or [[Image:image. jpg]] (to embed a picture). For more information on wiki syntax, visit http://expressionengine.com/user_ guide/modules/wiki/wiki_syntax.html.
Other ExpressionEngine modules
There are several other free modules that ExpressionEngine has which have not been covered here. •
The Discussion Forum is a module written by EllisLab but sold separately from ExpressionEngine (although it requires ExpressionEngine to run). The module leverages ExpressionEngine's Member module features, but has its own templating system and is styled via separate CSS. The best example of a discussion forum in action is the ExpressionEngine support forums (at http://expressionengine.com/forums).
•
Simple Commerce allows you to mark posts in channel entries as being for sale. You can create a channel of items for sale, set the price for each item and then accept payments through PayPal. All payment information is transferred directly between the visitor and PayPal—at no point does your website or ExpressionEngine handle payment information. Although Simple Commerce is not a fully-fledged e-commerce module, for smaller websites that do not need the complexity of a complete payment processing solution, Simple Commerce will likely meet your needs.
•
Blacklist/Whitelist is a spam prevention tool that allows you to block visitors by IP address, URL, or User-Agent. You can either block specific IP Addresses, URLs, or User-Agents, or you can enter a partial string to block anything that matches that string. You can also add items to your white-list (meaning that you could blacklist a certain IP address pattern, but make an exception for an IP address that you know is not spam). EllisLab provides a Blacklist and a Whitelist that you can download periodically to keep known spammers away.
[ 259 ]
Beyond the Basics
•
IP to Nation allows you to determine which country an IP address is associated with, and then ban visitors from that country from seeing your website (or display a flag next to comments or entries from visitors that come from that country).
•
Query is a very useful module for more advanced users, allowing you to run SQL queries against the ExpressionEngine database directly. Although it requires some familiarity with the ExpressionEngine database structure and with SQL syntax, it can allow you to display ExpressionEngine data in unique ways that might not otherwise be possible. See http:// expressionengine.com/user_guide/modules/query/index.html for examples of how to use this module within a template.
•
Referrer allows you to track which websites have links to your website that people are using to arrive at your site.
•
Statistics allows you to display certain facts about your website on a template (such as the number of people who are logged in, the date of the most recent comment, and the total number of comments that have been left on your site).
Multiple Site Manager
EllisLab also offers Multiple Site Manager for people who run multiple websites. Multiple Site Manager adds the ability to manage multiple websites from the same ExpressionEngine login (up to three sites are included with the initial purchase price, with the option to buy more if needed). The key licensing criterion is that you must be the owner of all the websites you manage. Each website is distinct in terms of templates, channels, and preferences, but addons, members, and member groups are shared across all three sites. In this way, members only have to register once for all the websites, as each of your websites can share the same modules and other add-ons (saving you from installing and configuring the same modules over and over again) and you can conveniently manage all your websites from the same control panel. Although not appropriate for everyone, Multiple Site Manager is a very powerful tool, making maintaining your websites much easier and at a lower cost than purchasing three separate licenses. More information can be found at http:// expressionengine.com/user_guide/cp/sites/index.html.
[ 260 ]
Chapter 9
Summary
In this chapter, you took a look at many of the modules that come bundled with ExpressionEngine. Some modules come pre-installed, some are included but not installed, and some have to be downloaded and installed separately. A typical module has a configuration screen (accessible via Add-Ons | Modules) and tags that can be used in templates to access the modules functionality. In the next chapter, you will be introduced to the other types of add-ons, including Accessories, Extensions, Fieldtypes, and Plugins. You will also learn about third party add-ons. Finally, you will learn key tips for running an ExpressionEngine website, including how to do database backups and version upgrades.
[ 261 ]
Extending ExpressionEngine So far, this book has taken a step-by-step approach to implementing the most popular modules in ExpressionEngine. In this chapter, you will not be building content for Ed & Eg's website, but rather looking at what else goes into maintaining an ExpressionEngine website. First, you will learn about essential maintenance tasks such as backups, restores, and upgrades. You will then be introduced to many of the most highly-rated addons that are available for ExpressionEngine before finally getting an overview of ExpressionEngine's spam controls, as well as ways to fine-tune ExpressionEngine. After completing this chapter (and the book), you will feel confident creating and maintaining an ExpressionEngine-powered website.
Backups and restores
ExpressionEngine is a database-driven application. So to back it up, you need to back up both the individual files on your web server and the database itself.
Backups
To back up ExpressionEngine, you need a tool such as phpMyAdmin. If your website is hosted by a website hosting provider, contact them and ask if phpMyAdmin or another tool is installed that will allow you to do MySQL database backups. If necessary, phpMyAdmin can be downloaded from http://www. phpmyadmin.net/. phpMyAdmin is included with local development environments, including WampServer, XAMPP, and MAMP, usually at an address such as http:// localhost/phpmyadmin (all in lower-case).
Extending ExpressionEngine
1. The first step to doing a backup is to clear all the unnecessary data from the database (such as cached templates). Log in to the control panel and select Tools | Data | Clear Caching. Select All caches and click Submit.
2. Access the phpMyAdmin control panel.
3. On the left-hand side, select the ExpressionEngine database (such as ee). After selecting the database, you are brought to a screen that shows all the ExpressionEngine tables on the left-hand side (beginning with exp). 4. In the main window, select Export from the top menu.
[ 264 ]
Chapter 10
5. On the Export page, at the top of the left column, verify that all the tables are selected.
6. All the options on the right-hand side can be left at their default settings. At the bottom, check the box Save as file. Select a Compression method of either zipped or gzipped and then select Go.
7. You are then prompted to save the file; save it to a safe place. Note that while phpMyAdmin is sufficient for smaller databases, the backup may time out when backing up very large databases. One option to work around this is to split out the database backup so that not all the tables are backed up into a single file. Another option is to look at the command line MySQL code or a utility such as My SQL Dumper (http://www.mysqldumper.de/en/).
In addition to backing up the MySQL database, it is also prudent to back up all the files on your web server, including any themes, language packs, and add-ons that may have been installed as well as any files that may have been uploaded to your File Upload Destinations (such as the /images directory).
[ 265 ]
Extending ExpressionEngine
Database restores
A backup is only useful if it is usable, and the only way to know if a backup is usable is to restore it. To test a database restore, it helps to have a second database created in phpMyAdmin (if your hosting package includes two databases). Alternatively, you can test a restore to a localhost environment. Testing a database restore using a different database or a localhost server is easy enough, but bringing up an entire ExpressionEngine website on a different database or server is more complicated. The guidelines on how you can accomplish this can be found in the ExpressionEngine wiki at http://www.expressionengine.com/wiki/.
1. If you are restoring a database to a test database, you can follow the instructions at the beginning of Chapter 1, Getting Installed to create a second database. 2. If you are restoring over the top of an existing ExpressionEngine database, you first have to delete the existing tables. In phpMyAdmin, select the database you are restoring to and select Structure from the menu at the top of the main window. Scroll all the way down and select Check All to check all the tables. In the drop-down box, select Drop. A confirmation window will appear—click Yes. Before doing this, be very sure that the database is well backed up or that losing all the data in all the tables will not be a problem.
3. Next, in the empty database, select Import from the menu in the top window. 4. Browse to the location where the database backup was saved. Leave all the other options at their defaults and click Go. [ 266 ]
Chapter 10
5. When the import is complete, there will be a message that says Import has been successfully finished.
6. If you are restoring to the same database/server that the backup was made from, make sure that the corresponding files have also been restored (including the /system directory).
Upgrading ExpressionEngine
EllisLab is always working on new versions of ExpressionEngine. These versions are often packed full of new features as well as security updates and bug fixes. Occasionally, EllisLab will put a price on a new feature (such as the discussion forum). However, the prices are very fair, and reflect the cost of development and support. Doing this keeps the cost of ExpressionEngine itself lower for those users who have no interest in the new feature.
There are two types of releases that ExpressionEngine goes through: •
A new build contains bug fixes or minor updates. It is generally not necessary to upgrade to a new build unless it contains a bug fix that you have been waiting for. Builds are numbered by date, and you can see what build you have in the footer of any page in the control panel.
•
A new version contains new features and improvements to existing functionality. A new version will include all the bug fixes and minor updates of any intermittent builds. Versions are numbered sequentially (such as 2.0.0, 2.0.1, 2.0.2, 2.1.0, and so on).
[ 267 ]
Extending ExpressionEngine
When a new version is released, ExpressionEngine will indicate this prominently on the control panel home page.
When upgrading, you can skip builds, but it is not recommended to skip too many versions. Not only will you miss out on security updates, bug fixes and new features, but if you seek support in the forums and there are significant changes between your version and the current version, you may be asked to upgrade. The instructions for updating to the latest build can be found at http://www. expressionengine.com/user_guide/installation/update_build.html and the instructions for updating to the latest version can be found at http:// www.expressionengine.com/user_guide/installation/update.html. The
instructions are basically the same, except that for a new build, you do not have to run the server update wizard. The basic instructions for upgrading to a new version are as follows: 1. Download the latest version of ExpressionEngine. Read the version update notes (step 5 at http://www.expressionengine.com/user_guide/ installation/update.html) to verify there are no changes that might have a big impact on the specific website that is being updated—for example, a compatibility issue with an add-on that is used. 2. Perform a backup of the database and ideally back up your entire website, including the system, themes, and images directories as well as the index. php file (located in the root directory of your website—though it may have been renamed as part of the ExpressionEngine installation in Chapter 1, Introduction to ExpressionEngine). 3. Take your website offline. ExpressionEngine includes an offline.html template in the /system/expressionengine/utilities/ directory that you can modify and copy to the root of your website. Rename your index. php to index_old.php and then rename offline.html to index.php. 4. If you chose to rename index.php as part of your ExpressionEngine installation, then replace the renamed file with the offline.html template instead.
[ 268 ]
Chapter 10
5. Clear your cached data. Log in to the control panel and select Tools | Data | Clear Caching. Select All caches, and click Submit. 6. On your website, rename your system and themes directories to system_old and themes_old. By keeping the directories on the server for now, it makes it easier to roll back the update if, for some reason, an issue is encountered. The official update instructions recommend renaming the new files being uploaded first, then renaming the existing files after the new files are uploaded, and finally renaming the new files to the names of the original files. This is equally effective and potentially minimizes downtime (if you wanted to keep the website up while the new files are being uploaded).
7. Upload the system and themes directories from the new ExpressionEngine version to your website. You will upload the index.php file right before the upgrade so that, for now, your website continues to reflect that it is offline. If you use additional control panel themes, such as Corporate, Fruit, or the Mobile theme, you will also need to download these themes from http://www.expressionengine.com/ and upload them to the /themes/cp_themes/ directory.
8. From the backup of your old system directory, upload the following directories to your new system directory: /system/expressionengine/third_party/ /system/expressionengine/config/ /system/expressionengine/templates/
9. Set the file permissions for /system/expressionengine/config/config. php and /system/expressionengine/config/database.php to 666 (writeable). Set /system/expressionengine/cache to 777 (writeable). 10. Now upload the index.php file, overwriting the offline template that you earlier saved as index.php. [ 269 ]
Extending ExpressionEngine
11. If this is a version update rather than a build update, point your browser to / system (for example, http://localhost/system or http://www.example. com/system) and follow the on-screen instructions to perform the update to the latest version.
12. After you see a message saying that you are running the most current version of ExpressionEngine, delete the /system/installer directory. 13. If you renamed your system directory, you will need to edit the newly uploaded index.php and update the $system_path = './system'; line towards the top of the file to reflect your renamed system directory. 14. If you mask the location of your control panel by accessing your control panel from a URL other than http://localhost/system/index.php (such as http://localhost/admin.php), you will also have to copy /system/ index.php and replace your masked-access file (such as /admin.php). Once you have done this, you will also have to update the $system_path = ''; line towards the top of the file to reflect the path to your system directory. 15. Follow the Version Specific Notes for any versions between the version you are updating to and the version you are updating from. The Version Specific Notes will contain details on any changes that need to be made above and beyond the normal upgrade changes just listed. For example, if additional files need to be uploaded, a theme or language pack has been updated, or if a new setting in the control panel needs to be defined, the Version Specific Notes is where you will find that out. If you have customized your own themes and the Version Specific Notes indicate that a theme was updated, you will have to manually update your theme with the same changes that were made to the built-in themes. Luckily, EllisLab is very good at identifying these changes in a version upgrade and at outlining what needs to be done.
16. Verify that your website is working as expected, and then delete the system_ old and themes_old directories, as well as the index_old.php file at the root of your website. [ 270 ]
Chapter 10
When you first log into the control panel, you will be warned that one or more core files have been changed—click to accept these changes. You may also receive an e-mail saying the same thing.
17. Finally, in addition to ExpressionEngine itself, modules you install (such as the Discussion Forum and Multiple Site Manager) can also be subject to new versions. For example, the discussion forum version update instructions can be found at http://expressionengine.com/user_guide/modules/forum/ forum_update.html.
ExpressionEngine add-ons
Although not open source software, ExpressionEngine has many ways in which both EllisLab and the members of the ExpressionEngine community can add to it. ExpressionEngine 2 is built on CodeIgnitor—an open source PHP web application framework also by EllisLab. CodeIgnitor is a popular framework for PHP developers, allowing rapid development of PHP web applications. For ExpressionEngine users, this means that add-on developers have the ability to build more complex add-ons (even entire applications) for ExpressionEngine by using CodeIgnitor. It also means that there is a much larger base of developers who can build ExpressionEngine add-ons. More developers building more and more complex add-ons for ExpressionEngine can only mean one thing. If there is something you need to do that is not supported natively, there is likely an add-on for it. The add-on market has grown hugely in the last few years and there are now several companies that have either started or been able to branch into developing and selling ExpressionEngine add-ons. Although this means that some add-ons come at a cost, it also means those same add-ons are likely to be high-quality, reliable tools to expand the functionality of ExpressionEngine. The best resource for ExpressionEngine add-ons is http://www.devot-ee.com/—an official EllisLab community partner.
Types of add-ons
ExpressionEngine add-ons come in five flavors, namely, modules, accessories, extensions, fieldtypes, and plugins. All add-ons are managed through the Add-Ons menu in the control panel—here you can install, uninstall, or access the configuration screens (if applicable). [ 271 ]
Extending ExpressionEngine
Modules
Throughout this book, you have been working with ExpressionEngine modules, including the Channel module, the Member module, the Comment module, and the jQuery module. A module can be simple and focused (that is, do one thing and do it well), or they can be close to applications in their own right, complete with their own control panel configuration screens and their own library of tags. Some modules are aimed at control panel users and do not add any visible functionality to the frontend of your website—an example is the Blacklist/Whitelist module, which allows you to block spammers from your website but does not change anything on your website. Other modules are designed specifically to add functionality to your website—they provide tags that can be used within templates so that you can control where this functionality appears and how it looks. The Search module works like this—it does not add any functionality to the control panel, but it allows you to add integrated searching capabilities to your website. Finally, there are modules that add functionality to both the control panel and your website. For example, the Mailing List module provides a control panel configuration screen where you can set up mailing lists and manage subscribers, and it also provides tags that you can use in templates to allow visitors to sign themselves up. Modules can read and write data to your database, making them a very powerful tool in an ExpressionEngine installation.
Accessories
Accessories are new in ExpressionEngine 2. They are the tabs that appear on the bottom of each control panel page.
ExpressionEngine comes bundled with the ExpressionEngine Info accessory installed and three other accessories that are included but not installed (Learning EE, News and Stats, and Quick Tips).
[ 272 ]
Chapter 10
To install a new accessory, you can go to Add-Ons | Accessories, and then click Install on the accessory (or accessories) of your choice (third-party accessories must be uploaded to the /system/expressionengine/third_party/ directory before they appear in this list to install). Once installed, clicking on an accessory name will open a preferences page where you can define which member groups can see the accessory and on what control panel pages the accessory appears. In this way, an accessory that is useful when creating templates (for example) can be set to appear only on Design pages of the control panel, and only to member groups that would be working with templates.
Building your own accessory is a great way to start getting into ExpressionEngine add-on development. One use for an accessory (if you build websites for clients) is that it can be used to provide easily accessible help and tips to your client, right inside the ExpressionEngine control panel.
Extensions
Extensions are a type of add-on that uses hooks within ExpressionEngine to modify how ExpressionEngine itself works. Unlike modules, extensions do not have tags that are used in templates. Instead, they modify aspects of how ExpressionEngine works. For example, there are extensions that allow you to change how CAPTCHA works, that allow you to change the page ExpressionEngine loads after a member logs in, and that allow you to change system messages so that they use a regular template instead of the template found under Design | Message Pages | User Messages. [ 273 ]
Extending ExpressionEngine
Like accessories, third-party extensions need to be uploaded to /system/ expressionengine/third_party/ before they can be enabled from the Add-Ons | Extensions control panel page. Most extensions will come with instructions on how to install them. ExpressionEngine does not come bundled with any extensions that are ready to go, but extensions are a very common type of add-on.
Field types
ExpressionEngine comes bundled with several different types of fields that can be used in entries. Throughout this book, you have used Text Input and Textarea extensively. You used File when building the photo gallery and you also used the Relationship field when building the calendar so that you could relate events in one channel to event sponsors in another. Fieldtype add-ons allow you to expand the range of fields that you can use for your channels.
Plugins
Plugins are the most basic form of add-on for ExpressionEngine. Unlike a module, plugins cannot store data in the database (though they may still query the database), and do not have their own control panels. Unlike an extension, plugins do not change the functionality of ExpressionEngine itself. A plugin works by making one or more tags available that can then be used in templates. Like other add-ons, third-party plugin directories need to be uploaded to /system/ expressionengine/third_party/ before they can be enabled from the Add-Ons |
Plugins control panel page. Clicking on the title of an installed plug-in will give you instructions on how to use it.
[ 274 ]
Chapter 10
Plugins exist for lots of nifty purposes—replacing text with other text, creating random text, converting kilograms to pounds, the list is endless. For EE2 compatible plugins and other add-ons, please visit http://www.devot-ee.com/.
Third-party add-ons and add-on developers
While there are far too many add-ons to list them all, what follows are some prominent add-on developers whose add-ons are worth knowing. This is not a comprehensive list, and it can be expected that different people would have different ideas regarding which add-ons are the most useful. Devot:ee is the best place on the web to find up-to-date information about add-ons, and EE Insider (http://www.eeinsider.com/) is another good site to follow for tips, information, and interviews on all things ExpressionEngine.
Pixel & Tonic http://www.pixelandtonic.com/
Although Pixel & Tonic is a relatively new company, Brandon Kelly has been building add-ons for many years, including the FieldFrame extension that became the basis of the Fieldtype add-on in ExpressionEngine 2. Several of Pixel & Tonic's add-ons are considered essential by ExpressionEngine developers, including: •
•
•
Matrix: This adds the ability to have tables in your channel entries. This is a huge improvement over using repeated textarea and text input fields for as many "rows" as you are likely to need. With Matrix, you can define the columns and in each entry, create as many rows as you need. Matrix can be used whenever tabular data is involved. One common use is to create photo galleries where each channel entry represents a gallery containing multiple photos (one per row) as opposed to having one photo per-entry (like you did when building the photo gallery in Chapter 8, Creating a Photo Gallery). Playa: This is a field type that works very similarly to the Relationship field that is built into ExpressionEngine, but instead of only allowing you to relate only one entry in another channel to your entry, Playa allows you to relate multiple entries in many other channels to your entry. Using the calendar example from Chapter 7, Creating a Calendar, you could have multiple sponsors for each calendar event, instead of being limited to picking just one (or having to create multiple Relationship fields). Wygwam: This adds WYSIWYG (What You See Is What You Get) functionality to ExpressionEngine's publish page. Instead of plain-text fields on the Publish page, Wygwam allows you to create content using wordprocessor-like functionality—you can add images, format, and layout the text just like you would in a word processor. [ 275 ]
Extending ExpressionEngine
Solspace http://www.solspace.com/
Solspace is a leading add-on developer for ExpressionEngine. Their work includes: •
Tag: A module that allows you to tag channel entries and organize your content by tag. You can also build a tag cloud.
•
FreeForm: A module that makes it easy to create and manage forms that collect information from your visitors.
•
User: A module that overhauls ExpressionEngine's native member functionality, bringing the default member templates into regular templates and making them much easier to customize and brand.
•
Facebook Connect: A module that adds Facebook SSO (Single Sign-On) capabilities to your website.
•
Super Search: This is a module that overhauls ExpressionEngine's native search functionality, improving the performance and allowing results to be sorted by relevance.
•
Friends: A module that updates the member functionality to be more like a social network. Members can invite each other to become friends, they can restrict their profile so that it is only visible to their friends and they can post status updates similar to Facebook or LinkedIn (at the time of writing, this module was not yet compatible with EE2).
•
Calendar: A full-featured calendar that goes far beyond what is possible with ExpressionEngine's built-in calendar functionality (the main improvement being the addition of recurring events—a key requirement of most calendar applications) (at the time of writing, this module was not yet compatible with EE2).
Newism (Leevi Graham) http://www.expressionengine-addons.com/
Newism is the author of many very popular ExpressionEngine 1 add-ons. Newism's add-ons include: •
NSM Addon Updater (previously LG Addon Updater): This accessory works with other compatible add-ons to let you know when a new version of the add-on is released. Each compatible add-on is listed in an accessory tab, along with the installed version and the latest available version.
[ 276 ]
Chapter 10
•
NSM Better Meta (previously LG Better Meta): This extension makes it easy for you to generate unique HTML meta tags for each entry without having to create custom fields in each of your channels for the meta tags (such as description, keywords, author, and so on). By having unique meta tags on your pages, your website is more search-engine friendly, potentially making it easier for people to find you through search engines. The extension can also generate search engine XML sitemaps.
•
NSM TinyMCE (previously LG TinyMCE): This is a free WYSIWYG custom field type, similar to Wygwam.
•
NSM Transplant (previously LG Replace): When creating new entries on the Publish page, this plugin allows you to insert the contents of one custom field inside the contents of another custom field. For example, if you have one or more image fields and a textarea field, you could insert a tag (called a needle) inside the text area so that the images appear within your text. (In your template, you can only place custom fields before or after each other, not inside each other).
•
NSM Live Look (previously LG Live Look): This extension allows you to view what your entry will look like on your website, directly from the Publish page.
Low (Lodewijk Schutte) http://www.loweblog.com/software/
Low has created many ExpressionEngine add-ons, including Low NoSpam, which will check comments, forum posts, and wiki articles submitted to your site against a service such as Akismet or TypePad AntiSpam to see if the submission is spam. Low Variables is another add-on that builds upon and improves ExpressionEngine's native variable management, allowing you to hide variables from other control panel users on a per-variable basis, as well as allowing you to group, sort, and label them.
nGen works http://www.ngenworks.com/software/ee/
nGen Works have built a number of ExpressionEngine add-ons, of which one of the most popular is Structure (http://www.buildwithstructure.com/). Structure bypasses the template structure of the standard ExpressionEngine website and instead allows you to define static and dynamic pages in an easy-to-use site-map view.
[ 277 ]
Extending ExpressionEngine
Other notable add-ons
The following add-ons can also be useful when building ExpressionEngine websites: •
Template Variables (by Matthew Krivanek) is a third-party accessory that displays the custom field names, snippets, and global variables that are on your site, so that you never again forget what you called a particular field, snippet or variable. The accessory includes quick links to add or edit custom fields, snippets, and global variables. Clicking a name copies the syntax onto the clipboard for easy pasting into a template (http://www.devot-ee.com/ add-ons/template-variables/).
•
Image Sizer (by David Rencher) is plugin that makes a template tag available which, when wrapped around an HTML tag, will resize the corresponding image to the size specified in the parameters and cache the resized image. This means that instead of having to require images to be of a certain size when they are uploaded to ExpressionEngine, they can be dynamically resized from within the template the first time the template is accessed. The plugin has won Devot:ee's AcademEE Plugin of the Year award multiple times (http://www.devot-ee.com/add-ons/imagesizer/).
•
First Timer (by Ryan Irelan) is an extension that allows you to alter where members are redirected to after they log in (http://www.devot-ee.com/ add-ons/first-timer/).
•
Backup (by Thomas Myer) is a module that makes it easy to do a database backup and download the file right from within the ExpressionEngine control panel—no logging into phpMyAdmin needed (http://www.devotee.com/add-ons/backup/).
•
Accessible Captcha (by Greg Salt) is an extension that changes the graphic CAPTCHA to a random question & answer system that plays well with screen-readers in a way that image-based CAPTCHAs do not. It works in much the same way as a regular CAPTCHA—making it easy for a person to complete the question, but making it difficult for an automated script to do so (http://www.devot-ee.com/add-ons/accessible-captcha/).
•
MD Detect Page Type (by Ryan Masuga) is a plugin that can be used in a template to detect what type of page is being rendered. This makes it easy to build conditional statements based on whether a page is a basic multipleentry page, a category page, a paginated page, an archive page or a singleentry page, and therefore makes it easier to use a single template for some or all of these scenarios (http://www.devot-ee.com/add-ons/md-detectpage-type/).
[ 278 ]
Chapter 10
•
Custom System Messages (by Brian Litzinger) is an extension that allows you to change the template that system messages are displayed with, allowing your system messages to share the same layout as the rest of your website and allowing you to use the full range of ExpressionEngine tags on the page (http://www.devot-ee.com/add-ons/custom-systemmessages/).
•
Channel Images (by DevDemon) is a module/extension that improves upon ExpressionEngine's native file manager functionality, including features such as multi-select image uploads from the control panel (http://www.devotee.com/add-ons/channel-images/).
•
Search Results (by Planet/EE) is a module that improves upon ExpressionEngine's default search capabilities, allowing you to group and sort search results, highlight search terms, use custom fields in search results, and more (http://www.devot-ee.com/add-ons/search-results/).
•
Cartthrob (by Chris Newton) and FoxEE (by HCC Development) are both full-featured shopping cart modules. (At the time of writing, they are not yet available for ExpressionEngine 2; http://www.devot-ee.com/add-ons/ cartthrob/ and http://www.devot-ee.com/add-ons/foxee/).
There are many more add-ons available for ExpressionEngine—more than can possibly be listed here. If there is something you wish ExpressionEngine could do (or could do differently), search the add-on library at http://www.devot-ee.com/ first.
Optimizing ExpressionEngine
Out-of-the-box, ExpressionEngine works very well, but on larger sites that attract more traffic, there are several options to fine-tune that can help you keep ExpressionEngine humming.
[ 279 ]
Extending ExpressionEngine
Spam
One downside of any website that allows members of the public to submit content is spam. Spam can take many forms, including comment spam, forum spam, and member registration spam (where spammers register as new members on your site and then place links in their profile pages), Luckily, ExpressionEngine has several tools you can use to combat spam, many of which are outlined in the ExpressionEngine documentation at http://www.expressionengine.com/user_ guide/general/spam_protection.html. Suggestions include: •
Use the blacklist/whitelist module to keep known spammers from your website and prevent content (in comments or member profile fields) that matches anything in the blacklist from being submitted. There is a oneclick option to download the latest blacklist from ExpressionEngine and you can also add items to the blacklist/whitelist that may be unique to you (downloading the list will not overwrite anything you add manually). The bottom line is that there is no reason not to use this module. (This module can be found in Addons | Modules in the control panel).
•
Require all comments to be moderated, require membership in order to post comments, or enable CAPTCHA for comment postings. If nothing else, you should ensure that you are set up to receive e-mails whenever comments are posted. All these settings can be found under Admin | Channel Administration | Channels for each channel.
•
Enable membership CAPTCHA (under Members | Preferences) or require all new member registrations to be activated manually by an administrator (though even administrators may not be able to spot spam registrations).
•
Disable New Member Registrations entirely (under Members | Preferences) if you do not plan to use the member features of ExpressionEngine. Remember that this feature is enabled by default, meaning that even if your website does not link to the member URLs, the member URLs are active. [ 280 ]
Chapter 10
•
Use Word Censoring (under Admin | Security and Privacy | Word Censoring), which allows you to replace any user-submitted word (or partial word) with the # symbol (or a word of your choice).
•
Apply Rank Denial (under Admin | Security and Privacy | Security and Sessions). This makes your website less attractive to spammers because user-submitted links point to a redirect page on your own site rather than pointing directly to the spammer's site. This means that any links posted to your website will not improve the spammers search engine page rank.
•
To prevent Denial of Service attacks, ExpressionEngine has Throttling Preferences (under Admin | Security and Privacy) that allow you to set how many pages can be downloaded in a given time period by a single person before that person is temporarily locked out.
•
Other recommendations in the documentation include setting a longer Comment Time Interval in the preferences for each channel (to prevent spammers from submitting hundreds of comments in a short space of time), using Secure Form Mode in the Security and Session preferences to prevent the same form being submitted multiple times without being refreshed and Deny Duplicate Data (also in the Security and Session preferences) to prevent the same comment being made more than once.
•
Finally, in addition to ExpressionEngine's built-in features, there are also several add-ons including Accessible CAPTCHA, Low NoSpam, and No Follow, all designed to make your website less attractive to spammers. Search for these and others at http://www.devot-ee.com/.
In summary, none of these options are a perfect solution, and there is certainly a trade-off between functionality and anti-spam controls. For example, requiring membership to post comments does not prevent a member from posting spam in comments but it at least provides an extra layer of protection.
Performance
ExpressionEngine is database-driven, and for most websites, the performance is excellent out of the box. With that said, if you are expecting high traffic volumes, it is worth being aware of (and following) good design practices as you build your website. The most fundamental technique that you can use to reduce template load times is reducing the number of ExpressionEngine tags in a template. A template that uses multiple embedded templates, nested conditionals, add-ons, and so forth involves more database queries and so will take longer for ExpressionEngine to render than a simple template with only a handful of standard ExpressionEngine tags. [ 281 ]
Extending ExpressionEngine
Other techniques to reduce page load times include the following: •
Use embedded templates, snippets, and global variables appropriately. An embedded template comes with all the overhead of rendering a template, whereas a snippet does not. So, if a snippet can be used instead of an embedded template, it should be.
•
Use the Disable Parameter liberally. By default, the {exp:channel:entries} tag fetches all the information about the channel entry that is stored in your database (including category information, member data, and the data in the custom fields). In many cases, you do not use all this data, so there is no point in retrieving it from the database. The disable parameter allows you to reduce the number of database queries by turning off queries for certain types of data. For example, you used this parameter when retrieving the entry title for the HTML in your single-entry templates. Since you only needed the title of the entry (which is not a custom field), disabling all the extra database queries made sense: disable="categories|category_fields|custom_fieldsmember_ data|pagination".
For more information on the disable parameter, visit http://www. expressionengine.com/user_guide/modules/channel/ parameters.html#par_disable.
•
Use Simple Conditionals instead of complex conditionals. A simple conditional is an if statement that evaluates one condition and does not have any if:else clauses. A simple conditional is parsed early, meaning that any ExpressionEngine tags within the simple conditional are ignored if the condition is false. More complex conditional statements (involving multiple conditions or multiple else clauses) are parsed later, meaning any ExpressionEngine tags within them are parsed, even if the condition turns out to be false.
•
Consider enabling GZIP output. This option (under Admin | System Adminstration | Output and Debugging Preferences) compresses website pages (which are then decompressed seamlessly by most modern browsers). This can result in faster download speeds.
•
Optimize ExpressionEngine's SQL tables. Under Admin | Utilities | SQL Manager, select Manage Database Tables, select all tables, and click Optimize. When run from time to time, this can help make database queries faster by eliminating database fragmentation.
[ 282 ]
Chapter 10
ExpressionEngine also includes a variety of different types of caching that can help improve performance by minimizing the number of queries needed to render a template. The benefits of enabling these options can vary depending on the server the website is hosted on (if the server already has caching enabled, then enabling caching within ExpressionEngine may cause double-caching and therefore an increase in load). More information can be found at http://www. expressionengine.com/user_guide/general/caching.html. ExpressionEngine caching is useful to reduce the number of database queries that a specific URL creates (such as your home page). However, caching is done by URL, meaning that for each new URL, a new cache is created, even if the elements on the pages at two different URLs come from the same template. Given that a single template can be the basis of hundreds or thousands of URLs (depending on the number of channel pages), websites with a lot of traffic spread over a large number of URLs may not see much benefit in page load times by caching, even if the traffic is concentrated on a small number of templates.
For sites with high traffic loads, the documentation also includes information on how to further optimize ExpressionEngine by turning off tracking and minimizing Disk I/O. Please see http://www.expressionengine.com/user_guide/general/ handling_extreme_traffic.html for more information. Solspace offers a Site Performance Evaluation for ExpressionEngine sites (http://www.solspace.com/development/ performance/) that may be worth considering for large, high-traffic websites.
Summary
In this chapter, you learned about the routine maintenance tasks that come with running a powerful database-driven website (such as database backups and software upgrades). You learned about the different types of add-ons that ExpressionEngine accommodates, and about specific add-ons and add-on developers that are worth being aware of. Finally, you learned about optimizing ExpressionEngine to fight spam and improve page-load times. The key points to remember after working through this chapter (and the book) are: •
Back up your website, including the database.
•
Upgrade ExpressionEngine when new versions are released (or at least every few versions). If you continue to use an older version, you will not have all the latest features and bug-fixes, and newer add-ons may not be compatible. [ 283 ]
Extending ExpressionEngine
•
ExpressionEngine is highly extensible, and many of the add-ons are highquality commercial grade pieces of software. If there is something you wish ExpressionEngine could do, research the add-on library first.
•
The ExpressionEngine documentation is an excellent resource—clear, concise, accurate, and with plenty of examples. It is a great way to learn about a new feature (or to learn more about a feature you are already familiar with).
•
Visit the ExpressionEngine support forums often (http://www. expressionengine.com/forums). If there is something you are trying to accomplish, the chances are good that someone else has tried the same thing. A quick search can often reveal lots of ideas. The how-to forum is a great place to get ideas, seek advice, or even get feedback.
[ 284 ]
Installing WampServer In this appendix, you will walk through downloading, installing, and setting up WampServer. This will allow you to run ExpressionEngine on your own computer. If you already have WampServer installed (or an alternative product such as XAMPP or MAMP for Mac OS X), then you can skip these instructions. WampServer is a free package that includes an easy-to-set up web server (Apache), database server (MySQL), and server-side scripting language (PHP), all of which are requirements of ExpressionEngine. Installing WampServer lets you experiment with ExpressionEngine on your own computer instead of a live website. Setting up each piece of an Apache, MySQL, and PHP (AMP) environment individually can be complicated, but with WampServer, the system comes pre-configured and ready to go, so you can concentrate on learning ExpressionEngine. You are installing WampServer as a development (or testing) environment only. You will not be using WampServer to build a live server that presents your website to the outside world. Setting up and securing a production web and database server is a topic beyond the scope of this text.
WampServer is a Windows only package. If you are using Mac OS X, MAMP is a good alternative (http://www.mamp.info). XAMPP is another alternative that is available for Windows, Linux, Mac OS X, and Solaris. If you choose to use an alternative package, the installation instructions for that package are going to be different and there may be some differences when you install and configure ExpressionEngine on your server in Chapter 2, Getting Installed. However, ExpressionEngine itself will work exactly the same.
Installing WampServer
WampServer is free to download, and the package contains the following: •
The AMP environment of Apache, MySQL, and PHP (needed to install ExpressionEngine)
•
phpMyAdmin, which is the leading web-based interface to MySQL (needed to manage the ExpressionEngine database)
Installing WAMPServer First, you must download WampServer:
1. Visit http://www.wampserver.com/en 2. On that page, there will be a link to the download page of WampServer. Select it and you should see a link to download WampServer. 3. Clicking the download link will take you to SourceForge.net where you can download the file. The file download should begin automatically, but if it does not start, there should be a direct link that you can use to start the download. If you have Internet Explorer 7 or higher, it may block the site from downloading files to your computer. A warning will appear in a small bar at the top of your browser screen. Click on it and select Download File.
4. Next you will be prompted to save the file. Save it to your Downloads, Desktop, or My Documents area. Depending on the speed of your Internet connection, the file may take some time to download. Now that you have downloaded the software, the next step is to install it. If you are running the Skype VOIP application, or IIS Server, you will need to exit them before proceeding. Apache cannot start as a service if Skype or IIS is also running as they all use port 80. If you have Skype, you can set it to no longer use port 80 by going into the Advanced page of the options screen in Skype.
1. Double-click on the file that you downloaded in order to run it. If you get a Windows security warning, click on Run. 2. A welcome screen will display. Click on Next.
[ 286 ]
Appendix A
3. A license agreement screen will display. WampServer is an open source software package released under the GNU General Public License. Accept the license agreement. 4. WAMPServer, by default, installs in C:\wamp, and that is where this book will assume it is installed.
5. Select whether you would like a Quick Launch or Desktop icon, then click on Next. 6. A summary screen will display, showing where WampServer will be installed. Click on Install.
[ 287 ]
Installing WampServer
7. The installation will take a few minutes to run, during which you will see all the files being extracted. After all the files have extracted, a dialog box will appear asking you to pick your default browser (this is used by WampServer to know what browser to use when you use WampServer shortcuts to open your website; it does not prevent you from using other browsers installed on your machine if you later wish to do so). If you have Firefox installed, it will ask if you wish to use Firefox. If you do not, browse to Internet Explorer (typically located in C:\Program Files\Internet Explorer\iexplore. exe). Click on Open.
8. The installation will run for a little longer, and then you will be prompted for your PHP mail parameters. Although ExpressionEngine does make use of e-mail (for example, when registering new members), it is not an essential part of this book. If you have an SMTP server you can use, feel free to enter the information, otherwise accept the default settings. Click on Next.
[ 288 ]
Appendix A
9. Finally, leave the checkbox to launch WampServer checked and click on Finish.
WampServer is now installed and running.
Using WampServer
When WampServer is running, you should see a new icon on your taskbar next to the clock. Clicking on this will produce a menu with useful links. (If you do not see the icon, try launching WampServer again by clicking on start WampServer under WampServer in your Start menu).
[ 289 ]
Installing WampServer
Localhost will launch your website (you can also access your website by visiting http://localhost/ in your browser). phpMyAdmin is used to manage your website databases, and we will use it in Chapter 2 to set up the database that ExpressionEngine will use. www directory will open C:\wamp\www in Windows Explorer. Any files placed in this directory will be visible on your website. This directory is therefore where you will place your ExpressionEngine installation files. The other options allow us to control the different services individually. You can stop and start services individually (or stop and start all services). You can also switch between versions and change settings specific to each service. By default, when you visit http://localhost/, you will see a WampServer home page. If you are using Internet Explorer and see a message at the top of your screen that says Intranet settings are now turned off by default, left-click on it and select Don't show this message again.
In order for us to develop our website, you should delete this welcome page.
[ 290 ]
Appendix A
This welcome page displays configuration information about your PHP installation. A comprehensive view of the same information can be accessed from within the ExpressionEngine control panel (under Tools | Utilities | PHP Info).
1. Navigate to C:\wamp\www and delete the file index.php. 2. In your browser, navigate to http://localhost/, and you should now see an empty directory listing.
Allowing .htaccess files to be used
To take advantage of some features in ExpressionEngine (such as removing the index. php from ExpressionEngine URLs), you need to use a .htaccess file, which requires the Apache module mod_rewrite to be enabled. 1. Left-click the WampServer task bar icon, click Apache | Apache Modules, and then scroll down the list of modules until you see the rewrite_module. Left-click on the rewrite_module option to enable it.
[ 291 ]
Installing WampServer
It will take a few seconds for it to enable, but then your .htaccess files will be recognized; you will be using them in Chapter 2, Getting Installed.
Summary
In this appendix, you walked through the installation of WampServer, one of several products available for simulating an Apache, MySQL, and PHP environment on your computer. Other alternatives include XAMPP and MAMP (for Mac OS X). The key points to remember after working through this appendix: •
Your website can be accessed in a browser at http://localhost/.
•
To upload files to your local website, you have to save them in C:\wamp\www.
[ 292 ]
Solutions to Exercises Most of the exercises throughout this book have more than one solution. The following are the example solutions to some of the exercises in this book. Where a solution has not been provided, the instructions in the chapter can be adapted to complete the exercise. Chapter 3, Exercise 1 To limit the entries that are displayed to 2, you need to edit the channel tag to read as follows: {exp:channel:entries channel="news" limit="2"}
Chapter 3, Exercise 2 To post a new entry to a channel, log into the control panel at http://localhost/ admin.php (or http://localhost/system/index.php), and select Content from
the menu at the top of the screen. Highlight Publish and then select the channel you wish to post to (in this case, News), and type in the new entry. Select an image and then click Submit when you are done. Chapter 3, Exercise 3 To edit an entry, you can either select Content from the main menu, then select Edit, or you can select Entry under Modify or delete. Click on the entry you wish to edit and then edit away.
Solutions to Exercises
Chapter 3, Exercise 4 Try searching for html css tutorials in your favorite search engine. A couple of good resources include: • •
http://www.htmldog.com/guides/ http://www.w3.org/Style/Examples/011/firstcss
If you prefer learning from a book, pop down to your local bookstore's Computing & Technology section, and you will find plenty of books. Look for ones that focus on HTML and CSS, rather than other software applications (such as Dreamweaver). Chapter 4, Exercise 1 To create new pages, select Content | Publish | Website and copy in the text from the corresponding static HTML file. Add in HTML tags for the headings (), links (using {site_url}), and italic (<em>) where appropriate, and remember that you can choose the previously uploaded picture, rather than uploading the picture again. Make sure that the URL title for each entry matches the URL title in the table below. Next, create the following template groups and select to duplicate the site template group. Then edit the index template of each group and adjust the url_title parameter to be as follows: Template Group Name
URL Title
business
small_business
contact
get_in_touch
promotion
promotion
Notice how when you enter e-mail addresses into the Contact Us entry, they are automatically converted to links on your page. The links are automatically encrypted using JavaScript to make it harder to harvest by spambots.
Chapter 5, Exercise 1 To set the amount of time to show a comment, go to Admin | Channel Administration | Channels. Select the FAQs weblog and click Edit Preferences. Select Comment Posting Preferences and change the Comment Expiration field to 60. Optionally, check the box to update existing comments with this setting and then click Update.
[ 294 ]
Appendix B
Chapter 5, Exercise 2 To include the author and the date of a post, update the line of code that reads
<strong>Q: <em>{faqs_question}
in both the faqs/ index and faqs/browse templates to read as follows: <strong>Q: <em>{faqs_question}
<strong>Posted by {author} on {entry_date format="%m/%d"} p>
More information about the different types of dates that you can display in your entries can be found at http://www.expressionengine. com/user_guide/modules/channel/variables.html#date_ variables. More information about date formatting code can be found at http://www.expressionengine.com/user_guide/ templates/date_variable_formatting.html.
Chapter 5, Exercise 3 If your installation included Agile Records, then you will already have a custom status called Featured. If you are using the blank installation, then you will need to create such a custom status. To create it, go to Admin | Channel Administration | Custom Status Groups, click Add/Edit Statuses, and then click Create a New Status on the top right. Call the new status Featured and click Submit. Before you update your snippet, you should first make at least three of the entries in your channel Featured entries. To do this, edit an entry and select the Options tab. Under Status, change the status to Featured. Next, update the snippet code to include a new parameter which says that the status must be featured in order to display. {exp:channel:entries channel="faqs" limit="3" orderby="random" dy namic="off" status="featured"}
[ 295 ]
Solutions to Exercises
Finally, you have to update the faqs/index, faqs/browse (both in the title and in the body of the page), faqs/rss and faqs/atom to display featured entries in these templates. By default, ExpressionEngine will only display entries with an open status—if you want to display entries with a different status, you have to explicitly tell ExpressionEngine to do so. Modify any {exp:channel:entries} tags in these templates to have the status="Open|Featured" parameter as in this example: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Featured"}
Chapter 6, Exercise 1 To create a new member group that can only modify templates, go to Members | Member Groups and select Create a New Member Group. Call the new member group Designers. Click on Control Panel Access and say Yes to accessing the control panel, and Yes to the design section. Under Template Editing Privileges, select which templates can be edited (business, contact, faqs, includes, individual, promotion, and site). Click Submit. Next, select Members | Register Member and create a new member in the Designers member group. Log in as the new member and verify that it works as expected. Chapter 6, Exercise 2 To create a custom member field, you go to Members | Custom Member Fields. Select Create a New Member Field. Choose a field name of existing_customer and a field label of Are you an existing customer of Ed & Eg?. Change the field type to Select List and enter two options (one on each line)—Yes and No. Leave Text Formatting set to None. Say Yes to this being a required field, No to the field being visible in public profiles, and Yes to being visible in registration pages. Click Submit. Log out of the control panel, then visit your website and click Register. You should see the new field on the registration screen.
[ 296 ]
Appendix B
Chapter 6, Exercise 3 Copy the includes/404 template code and then edit the promotion/index template (created as part of the exercises in Chapter 4, Moving a Website to ExpressionEngine). At the top of the template, add a line of code that says {if logged_in}. Underneath the {embed} line, add in another line of code that says {if:else}. Underneath this, paste in the code from includes/404. Then modify the
and the to reflect that you are on the Promotions page rather than the 404 page and modify the paragraph of text to indicate that promotions are available to members who are logged in only. Finally, at the very end of the template, add a closing {/if} tag. The overall template structure will be as follows: {if logged_in} {embed="includes/.website_page" url_title="promotion"} {if:else} [Modified template code from includes/404] {/if}
Chapter 7, Exercise 1 To modify how the days of the week in the calendar are displayed, you need to edit the code in between the calendar_heading tags in the calendar/index template to read as follows: {calendar_heading}
{lang:weekday_short} {/calendar_heading}
Another alternative is to use {lang:weekday_long}, which will output the full name
of the day (such as Friday). Chapter 7, Exercise 2
To display the next event that is coming up underneath your calendar, you need to use the {exp:channel:entries} tag with two parameters, namely, dynamic="off" and start_on="{current_time format='%Y-%m-%d %H:%i'}".
[ 297 ]
Solutions to Exercises
The dynamic="off" parameter decouples the channel entries being displayed at the URL. By default, the channel tag will look at the URL of the page you are on to determine the entries to display. So, if you were viewing May 2012 (and the URL was http://localhost/calendar/2012/05), your {exp:channel:entries} tag would also only display entries from May 2012. dynamic="off" means that the channel will display any entry from your channel, regardless of the URL. The second parameter is start_on="{current_time format='%Y-%m-%d %H:%i'}". The current_time is a system global variable for the current time on the server. The start_on parameter says that you only want to display channel entries with an entry date on or after the date you provide—in this case, the current date. This means that events in the past will not be displayed—you will only display events that are yet to happen. Read more about global variables at http://www. expressionengine.com/user_guide/templates/globals/ single_variables.html and read more about the start_on parameter at http://www.expressionengine.com/user_ guide/modules/channel/parameters.html#par_start_on
Insert the following code after the {/exp:channel:calendar} tag and immediately before the tag in the calendar/index template: Upcoming Event
{exp:channel:entries channel="{my_channel}" limit="1" re quire_entry="yes" show_future_entries="yes" sort="asc" dynamic="off" start_on="{current_time format='%Y-%m-%d %H:%i'}"} {if no_results}
No Upcoming Events
{/if} <strong>{title}
<em>{entry_date for mat="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{if events_description} {events_description}
{/if} {if events_sponsor} {related_entries id="events_sponsor"} More About Our Sponsor: {title}
{if event_sponsors_about} {event_sponsors_about}
{/if} {/related_entries} {/if} {/exp:channel:entries} [ 298 ]
Appendix B
Chapter 8, Exercise 1 Limiting the number of photos and randomizing them simply requires adding parameters to the {exp:channel:entries} tag in the photos/index template. This also limits the number of photos that will display in each category, so you want to be sure not to add more photos in a given category than the limit you set here. Alternatively, you can use pagination so that if there are more photos than the limit, they display on separate pages. {exp:channel:entries channel="{my_channel}" or derby="random" limit="10"}
Chapter 8, Exercise 2 To track the number of single-entry page views, you must first add a parameter to the {exp:channel:entries} tag in your single-entry page template (photos/ comment). ExpressionEngine offers four view counters that can be added to different single-entry pages, helpfully numbered one through four. Since you only have one single-entry page, you can use view counter one. {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes" status="Open|Premium" track_views="one"}
Next, add a conditional statement to your multiple-entry page (photos/index), immediately after the code that displays how many comments there are and before the :
{if view_count_one>="10"}***Popular***{/if}
The second
helps keep the photo thumbnails aligned, when some are considered popular and some are not.
Note that the view counter is not incremented when a photo is viewed in the lightbox because the lightbox is displaying the actual image file and not the single-entry template.
[ 299 ]
Solutions to Exercises
For channel entry view tracking to work, it must be enabled in Admin | Security and Privacy | Tracking Preferences (by default, it is enabled). The single-entry template in question must also not have caching enabled (by default, caching is disabled). To change the caching preferences of a template, select Preferences from either the Template Manager or the Edit Template screens. For more information on entry view tracking, please see http://www.expressionengine.com/ user_guide/modules/channel/entry_tracking.html.
Chapter 8, Exercise 3 When extracting code that is repeated, you must decide on the best tool to use. In this case, since you use this repeated code in more than one template, Preload Text Replacements are automatically ruled out (since they can only be used in the template in which they are defined). Global variables are also not an option here because the code contains ExpressionEngine tags such as {exp:comment:form}. The choice, therefore, comes down to Snippets or Embedded Templates. Snippets are preferable if the code is identical, regardless of which template might be using it. Embedded Templates are useful if you need to pass in variables to account for small variances in the code. In this case, the {exp:comment:form} requires you to define the preview template. Since this is different for the FAQs channel versus the Photos channel, you will need to use an Embedded Template and pass in the preview template information as a variable. First, create a template called .comment in the includes template group. The preceding dot means that the template is hidden and cannot be accessed directly. The template type should be Web Page. In the .comment template, copy in all the code from photos/comment from Comments
all the way down to {/exp:comment:form}. Change the {exp:comment:form} line to read {my_template_group} and {my_single_entry_ template} as embedded variables rather than Preload Text Replacements: {exp:comment:form pre view="{embed:my_template_group}/{embed:my_single_entry_template}"}
Click Submit to save the new template. Now edit faqs/browse and photos/ comment and replace all the code from Comments
all the way down to {/ exp:comment:form} with the following: {embed="includes/.comment" my_template_group="{my_template_group}" my_single_entry_template="{my_single_entry_template}"}
[ 300 ]
Appendix B
Both the faq/browse and photos/comment templates have Preload Text Replacements for {my_template_group} and {my_single_entry_template}. This line simply passes these text replacements to the embedded template. In this way, even though both the Photos and FAQs channel are using the same chunk of code to display comments, if a member chooses to preview their comment, they are redirected to the appropriate template based on the channel. Visit both the FAQs and Photo sections of your website, and you should see no difference in the functionality of viewing, previewing, and posting comments. The only difference is that now your single entry templates contain a lot less code and if you ever want to change the comment form, you can do so in one template, instead of having to go through multiple templates. Reducing repetition in this way is a powerful feature of ExpressionEngine, and it makes websites easier to maintain.
[ 301 ]
Index Symbols 404 Page improving 140 404 Page not found 98 {exp:search:advanced_form} tag 235 .htaccess files allowing, to be used 291, 292 {site_url} variable 87
A Accessible Captcha extension 278 accessories 272, 273 add-ons, ExpressionEngine about 271 accessible Captcha extension 278 accessories 272, 273 add-on developers 275 backup module 278 Cartthrob module 279 channel images add-ons 279 channel images module/extension 279 custom system messages extension 279 extensions 273 field types 274 first timer extension 278 FoxEE module 279 image sizer plug-in 278 Low (Lodewijk Schutte) 277 MD detect page type plugin 278 modules 272 Newism (Leevi Graham) 276 nGen works 277 notable add-ons 278, 279 Pixel & Tonic 275
plugins 274, 275 resources, URL 271 search results module 279 Solspace 276 template variables accessory 278 third-party add-ons 275 types 271 advanced search form, Search module 235, 236 Agile Records website 37 Atom feed about 136 and RSS feed, differences 139 creating 139 setting up 136-139
B backup module 278 backups, ExpressionEngine 263-265 banned member group 155 Blacklist/Whitelist module 259 blank calendar template creating 179 Body field 46 build release 267
C caching 283 calendar blank calendar template, creating 179 calendar CSS template, creating 183, 184 creating 179-182 designing 173, 174 events, displaying 191-195 exercise 196
formatting, with CSS 183 solution 297 styles, adding to calendar CSS 184-187 weblog, creating 207 calendar CSS styles, adding to 184-186 calendar CSS template creating 183, 184 Calendar module, Solspace 276 calendar template blank calendar template, creating 210 blank calendar, creating 182 CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) 123 Cartthrob module 279 categories about 64 browsing page, distinguishing 132, 133 creating 108-111 data, organizing 129, 130 displaying, with entries 130, 131 related entries, displaying by 133, 134 categories, photo gallery channel creating 205, 206 category browsing page distinguishing 132, 133 channel categories 64 categories, creating 108-111 content, creating 75-77 creating 63 custom channel fields, creating 105-107 custom field group, creating 65 custom fields 64, 65 custom fields for event sponsors, creating 174, 175 custom statuses 64 designing 104, 105 events custom fields, creating 176, 177 event sponsors channel, creating 175, 176 example events, creating 177-179 first custom field, creating 66 Information Pages channel 45 new channel, creating 73, 74 new channel. creating 111, 112 News channel 45
setting up 174 templates, pointing to 82, 83 channel images module/extension 279 channel images, photo gallery add-ons 224 comments allowing, on entries 120 form, creating 125-128 previewing, by visitors 128, 129 spam, preventing 120-125 Constrain Proportions checkbox 49 contact form, Email module 241-243 content about 44 Body field 46 Constrain Proportions checkbox 49 Extended text field 48 Information Pages channel 45 new content, creating 45 News channel 45 selecting, from top menu 45 URL title 46 View Entry page 50 Write Mode 47 content management system (CMS) 7, 9 control panel, ExpressionEngine about 38 administrative control panel access 39 Corporate theme 44 Default Control Panel Theme 43 ExpressionEngine Info tab 39 Fruit theme 44 hide sidebar link 39 home icon 39 home page 39 logging into 29, 30 navigation 39 notepad 41 profile 39 Quick Links Manager link 42 Quick Links section 39 reveal sidebar 39 tab manager 40, 41 themes 42 website 39 CSS calendar, formatting with 183 custom field group
[ 304 ]
creating 65 custom fields about 64, 65 creating 66, 70, 71, 105-107 creating, for event sponsors 174, 175 options 72 custom fields, photo gallery channel creating 203-205 custom statuses 64 custom system messages extension 279
D data organizing, with categories 129, 130 Default Control Panel Theme 43 design, photo gallery changing 209, 210 single-entry page layout, creating 210 Devot-ee 275 Discussion Forum module 259 Duplicate an Existing Template Group option 53
E Ed & Eg 61, 62 Editors 155 Email module about 241 contact form, creating 241-243 tell-a-friend form, creating 244 tell-a-friend template, creating 244-247 embedded template 96-98 entries categories, displaying with 130, 131 editing, solution 293 limiting, solution 293 posting to channel, solution 293 events displaying, on calendar 191-194 solution 297, 298 events channel creating 177 events custom fields creating 176, 177 event sponsors custom fields, creating for 174, 175
event sponsors channel creating 175, 176 example events creating 177, 179 exercises solutions 293-301 ExpressionEngine 404 Page, improving 140 .htaccess files, allowing to be used 291, 292 about 9, 11 accessories 272, 273 add-ons 271 Agile Records website 37 assumptions 20 backups 263, 264, 265 business case 12 calendar 173 CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) 123 channel, designing 104, 105 control panel 38, 39 control panel, logging into 29, 30 database restores 266, 267 database, setting up 21, 22 documentation, URL 15 Email module 241 extensions 273 field types 274 file manager 200-203 files, downloading 22, 23 files, uploading 23, 24 image editing, features 221-223 installing, steps 24-28 Mailing List module 236 members, types 39 Moblog module 248 modules 272 official installation guide, URL 19 photo gallery channel, creating 203 photo gallery, designing 199, 200 phpMyAdmin 21 repetition, reducing 90, 91 requisites 20 resources, URL 16, 17 search box, adding to site 229, 230 Search module 228 [ 305 ]
technical case 12 templates, creating 209 templates 50 updating 19 upgrading 267 upgrading, steps 268-271 user-friendly URLs, creating 31 WampServer 21, 285 WampServer, downloading 286, 287 WampServer, installing 288, 289 wiki module 255 ExpressionEngine 2 15 ExpressionEngine database setting up 21, 22 ExpressionEngine documentation, URL 15 ExpressionEngine modules Blacklist/Whitelist 259 Discussion Forum 259 IP to Nation 260 Query 260 Referrer 260 ExpressionEngine modulesSimple Commerce 259 Statistics 260 ExpressionEngine, optimizing performance 281-283 spam 280, 281 ExpressionEngine page index.php 31 ExpressionEngine URLs index.php, hiding 32, 33 index.php, renaming 34, 35 Extended text field 48 extensions 273
F Facebook Connect module, Solspace 276 FancyBox setting up 187, 188 FAQ snippet 134-136 FAQ template creating 114-118 single-entry page, creating 118-120 field types, ExpressionEngine about 274 checkboxes 67
date 67 file 67 multi select 67 radio buttons 67 relationship 67 select dropdown 67 textarea 67 text input 67 file manager 200-203 first timer extension 278 FoxEE module 279 FreeForm module, Solspace 276 Friends module, Solspace 276
G guests member group 155
H hide sidebar link, ExpressionEngine control panel 39
I image editing features 221- 223 image sizer, photo gallery add-ons 223 image sizer plugin 278 includes, template group 78 index.php hiding, in ExpressionEngine URLs 32, 33 renaming, in ExpressionEngine URLs 34, 35 Information Pages channel 45 installing photo gallery 203 installing, ExpressionEngine files, downloading 22, 23 files, uploading 23, 24 steps 24-28 IP to Nation module 260
J jQuery module 173
[ 306 ]
L Low (Lodewijk Schutte) 277 Low NoSpam 277 Low Variables 277
M Mailing List module about 236 e-mails, sending 239, 240 mailing list, setting up 236, 237 member registration, allowing 238, 239 Make the index template in this group your site's home page? box 53 MAMP 285 Matrix 275 MD Detect Page Type URL 141 MD Detect Page Type plugin 278 member groups about 154 banned member group 155 Channel Assignment 159 Channel Posting Privileges 159 Comment Administration 159 configuring, options 155, 156 control panel access 158 Control Panel Email Privileges 159 creating, solution 296 custom member field, solution 296 editor member group, creating 155 guests member group 155 members member group 154 Module Access Privileges 159 new member group, creating 159 pending member group 154 site access 156 Template Editing Privileges 159 member-only content content, making visible to members 167-170 creating 166, 167 members creating 160 Editor Ed, logging in as 160-162 list 151, 152 member groups 154 member-only content, creating 166
new member, registering as 147-149 profile 149-151 templates, linking to 152-154 types 143, 144 with administrative control panel access 144 without administrative control panel access 144 membership designing 143 member groups 144, 154 member, list 151, 152 member, profile 149,-151 member templates, linking to 152-154 new member, registering as 147-149 preferences 144-147 members member group 154 menu, snippets creating 95, 96 Moblog e-mail, Moblog module sending 253, 254 Moblog module about 248 Moblog e-mail, sending 253, 254 setting up 248-252 template, setting up 252, 253 modules about 272 multiple-entry page content, adding 215-221 creating 213, 214 Multiple Site Manager 260
N Newism (Leevi Graham) NSM Addon Updater 276 NSM Better Meta 277 NSM TinyMCE 277 NSM Transplant 277 News channel 45 nGen works 277 no-results template 235 no-results template, Search module 234 notepad, control panel 41 NSM Addon Updater, Newism (Leevi Graham) 276
[ 307 ]
NSM Live Look, Newism (Leevi Graham 277 NSM TinyMCE, Newism (Leevi Graham) 277 NSM Transplant, Newism (Leevi Graham) 277
O official installation guide URL 19
P page load times reducing, techniques 282 pages adding 84, 85 creating, solution 294 second page, publishing 86, 87 second template, creating 88-90 Pages module URL 85 pending member group 154 photo gallery add-ons 223 advanced features 221 channel, creating 203 design, changing 209, 210 designing 199, 200 installing 203 photo gallerysolution 299 setting up 205 photo gallery, add-ons channel images 224 image sizer 223 photo gallery channel categories, creating 205, 206 creating 203, 207 custom fields, creating 203-205 photos, uploading 207-209 photos direct upload 208 uploading, to website 207 phpMyAdmin 21, 290 Pixel & Tonic about 275 Matrix 275 Playa field type 275
Wygwam 275 URL 200 Playa field type 275 plugins 274, 275 Pluralism 62 preload text replacements 91, 92 Publish page layout modifying 162-164 options, configuring 165
Q Query module 260 question set publishing 112, 113 Quick Links Manager, control panel 42
R Referrer module 260 repetition preload text replacements 91, 92 reducing, ways 90, 91 user-defined global variables 92, 93 resources ExpressionEngine documentation, URL 15 URL 17 restores, ExpressionEngine build release 267 database restores 266 releases, types 267 version release 267 RSS feed about 136 and Atom feed, differences 139 setting up 136-139
S search box Search module adding, to site 230 search box, Search module adding, to site 229 Search module advanced search 235 no-results template 234, 235 search results template, creating 231-233 search results module 279 [ 308 ]
setting up 252, 253 templates, ExpressionEngine about 10, 50 Access section 54 as files 99-101 content displaying, tags used 55-58 content, adding to multiple-entry page 215-221 creating 78-82, 290 Duplicate an Existing Template Group option 53 editing 54 group, creating 53, 54 index template 52, 55 Make the index template in this group your site's home page? box 53 multiple-entry page, creating 213, 214 pointing, to channel 82, 83 Preferences section 54 second template, creating 88 single-entry page, creating 210-213 tag 56 tag pair 57 Template Notes section 54 URL, relationship 52 URLs, relating to 51, 52 template variables accessory 278 themes, control panel corporate theme 44 Default Control Panel Theme 43 downloading 42 fruit theme 44 mobile theme 43 switching 43
search results template, Search module creating 231-233 Simple Commerce module 259 single-entry page creating 210-213 single-entry page, FAQ template creating 118-120 solution 299 single-entry page layout, photo gallery creating 210 photo comments, displaying 213 single-entry template creating 188-191 snippets about 93-95 menu, creating 95, 96 Solspace about 276 Calendar module 276 Facebook Connect module 276 FreeForm module 276 Friends module 276 Super Search module 276 Tag module 276 User module 276 solutions to exercises 293-301 spam 280, 281 Statistics module 260 styles adding, to calendar CSS 184-186 Super Search module, Solspace 276
T tab manager, control panel Template Manager screen 40, 41 Tag module, Solspace 276 tag pair 57 tags about 10, 56 used, to display content in templates 55-58 tell-a-friend form, Email module creating 244 tell-a-friend template, Email module creating 244-247 template, Moblog module
U upgrading, ExpressionEngine steps 268-71 URL title 46 user-defined global variables 92, 93 user-friendly URLs, ExpressionEngine creating 31 index.php, hiding 32, 33 index.php, renaming 34, 35 User module, Solspace 276
[ 309 ]
V version release 267 View Entry page 50 visitors allowing, to preview comments 128, 129
W WampServer about 285 downloading 286, 287 home page, URL 290 installing 288, 289 Localhost 290 package 286 using 289 welcome page, deleting 290 www directory 290 WampServer, package AMP environment 286 phpMyAdmin 286 website converting into ExpressionEngine, approaches 62, 63 wiki module about 255 wiki, setting up 255, 256 wiki, working 257-259 Write Mode 47 Wygwam 275
X XAMPP 285
[ 310 ]
Thank you for buying Building Websites with ExpressionEngine 2
About Packt Publishing
Packt, pronounced 'packed', published its first book "Mastering phpMyAdmin for Effective MySQL Management" in April 2004 and subsequently continued to specialize in publishing highly focused books on specific technologies and solutions. Our books and publications share the experiences of your fellow IT professionals in adapting and customizing today's systems, applications, and frameworks. Our solution based books give you the knowledge and power to customize the software and technologies you're using to get the job done. Packt books are more specific and less general than the IT books you have seen in the past. Our unique business model allows us to bring you more focused information, giving you more of what you need to know, and less of what you don't. Packt is a modern, yet unique publishing company, which focuses on producing quality, cutting-edge books for communities of developers, administrators, and newbies alike. For more information, please visit our website: www.packtpub.com.
Writing for Packt
We welcome all inquiries from people who are interested in authoring. Book proposals should be sent to author@packtpub.com. If your book idea is still at an early stage and you would like to discuss it first before writing a formal book proposal, contact us; one of our commissioning editors will get in touch with you. We're not just looking for published authors; if you have strong technical skills but no writing experience, our experienced editors can help you develop a writing career, or simply get some additional reward for your expertise.
CodeIgniter 1.7 Professional Development ISBN: 978-1-849510-90-5
Paperback: 300 pages
Become a CodeIgniter expert with professional tools, techniques and extended libraries 1.
Learn expert CodeIgniter techniques and move beyond the realms of the User Guide
2.
Create mini-applications that teach you a technique and allow you to easily build extras on top of them
3.
Create CodeIgniter Libraries to minimize code bloat and allow for easy transitions across multiple projects
CodeIgniter 1.7 ISBN: 978-1-847199-48-5
Paperback: 300 pages
Improve your PHP coding productivity with the free compact open-source MVC CodeIgniter framework! 1.
Clear, structured tutorial on working with CodeIgniter for rapid PHP application development
2.
Careful explanation of the basic concepts of CodeIgniter and its MVC architecture
3.
Use CodeIgniter with databases, HTML forms, files, images, sessions, and email
4.
Full of ideas and examples with instructions making it ideal for beginners to CodeIgniter
Please check www.PacktPub.com for information on our titles
jQuery 1.4 Reference Guide ISBN: 978-1-849510-04-2
Paperback: 336 pages
A comprehensive exploration of the popular JavaScript library 1.
Quickly look up features of the jQuery library
2.
Step through each function, method, and selector expression in the jQuery library with an easy-to-follow approach
3.
Understand the anatomy of a jQuery script
4.
Write your own plug-ins using jQuery's powerful plug-in architecture
Drupal 6 Content Administration ISBN: 978-1-847198-56-3
Paperback: 196 pages
Maintain, add to, and edit content of your Drupal site with ease 1.
Keep your Drupal site up to date: easily edit, add to, and maintain your site's content, even if you've never used Drupal before!
2.
Covers the full range of content that you might want on your site: richly formatted text, images, videos, as well as blog posts, calendar events, and more
3.
Get to grips with managing users, slaying spam, and other activities that will help you maintain a content-rich site
4.
Concise, targeted information with easy-tofollow hands-on examples
Please check www.PacktPub.com for information on our titles
Recommend Documents
Building Websites with ExpressionEngine 2
A step-by-step guide to ExpressionEngine: the web-publishing system used by ...
Building Websites with ExpressionEngine 2
A step-by-step guide to ExpressionEngine: the web-publishing system used by ...
Building Websites with XOOPS A step-by-step Tutorial
Get your XOOPS website up fast using this easy-to-follow guide
S...
Building Websites with Joomla! A step by step tutorial to getting your Joomla! CMS website up fast
Hagen Graf
BIRMING...
Building Websites with Joomla! A step by step tutorial to getting your Joomla! CMS website up fast
Hagen Graf
BIRMING...
Building Websites with XOOPS A step-by-step Tutorial
Get your XOOPS website up fast using this easy-to-follow guide
S...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Sign In
Our partners will collect data and use cookies for ad personalization and measurement. Learn how we and our ad partner Google, collect and use data. Agree & close
User-defined global variables
User-defined global variables can be used for any code that is repeated and that does not contain ExpressionEngine tags. Unlike Preload text replacements, a global variable can contain multiple lines of text and can be used in any template. The site name at the top of each page is a good example of this—although it's only three lines and it does not contain any ExpressionEngine tags. However, it will be needed in every template, so it's worth extracting into a global variable. This way, if Ed & Eg ever change their site name, the update only has to happen in one place and the entire website will be updated. 1. In the control panel, select Design | Templates | Global Variables from the top menu. 2. You will see that there are already some global variables that have been defined. These are being used by the Agile Records website. Click on Create a New Global Variable at the top right. 3. Call your new variable website_sitename. 4. The variable content will be as follows.
Ed & Eg Financial Advisors
5. Click Update to save the global variable.
[ 92 ]
Chapter 4
6. Now go back to the includes/.website_page template and replace the section of code that displays the site name, starting with
7. Visit your website and you should see no difference. Reducing repetition is something that makes the website easier to maintain for you, but does not change anything for your visitors.
Snippets
Snippets are ideal for code that is repeated and that contains ExpressionEngine tags. For this example, you will convert the sidebar that appears on the right-hand side of each page into a snippet. Although the sidebar does not currently have any ExpressionEngine tags, meaning you could use a global variable, you will be adding additional functionality into the sidebar as you progress through the book. In anticipation of this, it therefore makes sense to convert the sidebar into a snippet, rather than a global variable.
[ 93 ]
Moving a Website to ExpressionEngine
1. In the control panel, select Design | Templates | Snippets from the top menu. 2. You will see that there are already some snippets that have been defined for the Agile Records website. Agile Records uses snippets prefixed with global for items that appear on every page (like the footer) and snippets prefixed with the template group name for items that only appear in templates in that group. We are going to create a new snippet, so click on Create a New Snippet at the top right. 3. Call your new snippet website_sidebar, using website instead of global to distinguish this snippet from the Agile Records snippets. 4. To save typing, copy the following code from the includes/.website_page template:
-
Promotion!
From now until the end of the year, Ed & Eg are offering a <strong>free initial 90 minute consultation, plus <strong>25% off your first return visit. Learn More…
-
Key Services
- -Budgeting
- -Debt Management
- -Investing
- -Financial Planning
- -Tax Services
- -Book-keeping & Cash Flow
- -Accounts Preparation
- -Payroll Services
5. Before saving this snippet, update the link that appears in the Promotion! box from promotion.html to {site_url}promotion. (Although you have not yet created a promotion template group and a corresponding website channel entry, when you do, this link will work). [ 94 ]
Chapter 4
6. Click on Update and Finished to save the snippet.
7. Now go to the includes/.website_page template and replace the sidebar code you just copied into the snippet with the snippet tag {website_ sidebar}. The four lines after should now look as follows. When you are done, click Update. {website_sidebar}
8. If you now visit your website, you should not see much change. The only difference that indicates the sidebar is now coming from your snippet rather than from the template is the link in the Promotions! box that points to http://localhost/promotion instead of promotion.html.
Creating a menu
Another good candidate for a snippet is the site menu that appears at the top of every page. Creating the menu as a snippet (rather than a global variable) allows you to use the ExpressionEngine variable {site_url} in place of your domain name, just like you did when creating the link to the promotions page within the Individual/ Family entry. Although you have not yet created all the entries (and template groups) for the following page links to work, you can create this menu snippet in anticipation of creating the corresponding pages later (as part of the exercises at the end of this chapter). [ 95 ]
Moving a Website to ExpressionEngine
1. In the control panel, select Design | Templates | Snippets from the top menu and click on Create a New Snippet at the top right. 2. Call your new snippet website_menu. 3. Type in the following code:
4. Click on Update and Finished to save your new snippet. 5. Now go to the includes/.website_page template and replace the menu code that starts with
6. If you now visit your website, you should see that your menu links have all changed. Verify that you can successfully click between the Homepage and the Individual/Family pages you have already created.
Embedded templates
You have already seen an example of an embedded template. An embedded template can do everything a snippet can do with two main differences: 1. Embedded templates can be passed variables, and the output can then vary based on those variables.
[ 96 ]
Chapter 4
2. An embedded template is a template. ExpressionEngine has many different options that can be defined on a per-template basis (different templates can have different access controls, different caching preferences and different PHP settings) whereas snippets have the same settings as the template they are in. Furthermore, you can restrict certain template groups so that other administrative control panel users cannot see them, but with snippets, you can only give other administrative control panel users access to all snippets or none of them. Note that when using embedded templates, you can define as many or as few variables as you wish. Simply listing the variables and their values in the tag creates the variables, for example, {embed="template group/template" variable1="dog" variable2="cat"}. If you do not want any variables, then the tag is simply {embed="template group/template"}.
Now that you have seen examples of Preload text replacements, global variables, snippets, and embedded templates, you can certainly go further and extract even more repeated code into these tools. The page footer could be a global variable, as could the widebar. However, it is important to strike a balance between reducing repetition and writing code that you will understand a year or two later. Although only you can know where that balance lies for you, here are some recommendations: •
•
Keep custom tags descriptive as to what the code is that they represent (for example, instead of {widget}, use a name that makes it obvious to you what the tag represents). As you start out, avoid putting opening tags (such as a
•
Do not bundle unrelated parts of your page into the same global variable, snippet, or embedded template. While you could use one snippet for the entire footer, including the FAQs and the copyright notice, it would cause problems if, on one page, you only need the copyright notice, but not the FAQs. [ 97 ]
Moving a Website to ExpressionEngine
For an example of just how far you can take these techniques, check out Derek Jones' official ExpressionEngine blog series 'Behind the Curtains' that talks about how EllisLab uses ExpressionEngine on their own websites. (Note that the series was written in 2007, before snippets existed): http://expressionengine.com/blog/ article_list/category/behind_the_curtain/
Creating a 404 Page not found
A 404 Page is an essential part of any website, and working through this chapter, you may have noticed that your 404 Page is still themed like the Agile Records website. In this section, you will take advantage of all the repetition-reduction you have done as you create a new 404 Page. 1. Select Design | Templates | Template Manager, select the Includes template group, and then select New Template. Call the new template 404. The Template Type will be Web Page, select Duplicate an Existing Template, and finally select the includes/.website_page template to copy from. Click on Create and Edit. 2. Since the 404 Page content does not come from a channel, delete the line that reads {preload_replace:my_channel="website"}. 3. Change the
Replace everything from
Page not Found (404)
The page you were looking for does not exist. There may be a spelling mistake in the URL in the address bar, or we may have removed this page inadvertently. Please use the menu at the top to visit a page that does exist.
4. Click Update to save the changes. 5. Now that you have a 404 Page that is consistent with your site design, you can define this page to appear when a page is not found. Select Design | Templates | Global Preferences from the top menu. 6. Under 404 Page, select includes/404 as the template to display. At the same time, make sure Enable Strict URLs is set to Yes (or your 404 Page will not work). Click Update. [ 98 ]
Chapter 4
Now, when you visit an invalid URL (such as http://localhost/toast), you will see your 404 page instead of the Agile Records 404 page.
Templates as files
While working with templates within the web-based control panel interface works well, it does have limitations. If you are used to coding HTML files using your favorite text editor, you may wish to continue using that text editor and FTP the files to your website instead. In ExpressionEngine, this is entirely doable. 1. If you are following along on an actual website, you will need to ensure that the directory permissions for /system/expressionengine/ templates are set to 777. If you are using a localhost environment, this is not necessary. This directory is where your template files will be saved. [ 99 ]
Moving a Website to ExpressionEngine
2. In the control panel, select Design | Templates | Global Preferences from the top menu. 3. Set Allow Templates to be Saved as Files to Yes. The likelihood is that the Basepath to Template File Directory is already set to the full server path for / system/expressionengine/templates, but if it is not, you will need to set it.
4. Click Update to save your changes. 5. Although this option allows you to start creating templates as files, it does not automatically go back and create files for your existing templates. To do this, you have to mark each template to save as a file. Edit each template in the site, individual, and includes template groups in turn, check the box marked Save Template as File (just above the Update button), and then click Update and Finished.
6. You will now see your template files in system/expressionengine/ templates in a sub-directory called default_site. You can now edit your template code by editing these files directly. You can easily create new templates and new template groups without using the control panel by putting new files and directories in this directory. When creating new templates and new template groups, there are certain conventions to be aware of: template groups are separate directories with the name of the group followed by a .group extension. Webpage templates end in .html and CSS templates end in .css. You can edit templates in the control panel and in the files interchangeably. When opening a template in the control panel, ExpressionEngine will look to see if the file is newer than the database version, and if so, load the file. Updating your template will then update the ExpressionEngine database and file simultaneously (unless you uncheck the box to save it as a file). [ 100 ]
Chapter 4
Know that when displaying pages to visitors, ExpressionEngine will always use the file before using the template saved in the ExpressionEngine database. This means that you can feel confident updating the files outside of the control panel, knowing that the changes will immediately reflect on your website. Occasionally, when using templates as files, you may find that a file for a template has gone missing. ExpressionEngine has a utility to synchronize the templates periodically to ensure that the templates in the database match the content of the files and that there are files for every template. To run this, you can go to Design | Templates | Synchronize Templates. The screen will summarize whether the templates are in sync or if the files are newer than the database templates. If any are not in sync, check which templates you want to sync and click on Submit to update the database with the updated files (as well as recreate any template files that may have accidentally gone missing). For more information on templates as files, see the ExpressionEngine documentation at http://expressionengine.com/user_guide/templates/flat_file_ templates.html
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. In this chapter, you only created the home page and the Individual/Family page. Go ahead and create the Small Business, Contact Us, and Promotions page. Leave out the Frequently Asked Questions page. You will convert this page in the next chapter.
Summary
In this chapter, you have seen how to build a complete website using ExpressionEngine. You have taken advantage of many of ExpressionEngine's features to reduce repetition and make your website as simple to maintain as possible. In the next chapter, you will learn more about channels and how you can use ExpressionEngine to turn the Frequently Asked Questions page of Ed & Eg's website into a more interactive experience for your visitors. [ 101 ]
Moving a Website to ExpressionEngine
The key points to remember after working through this chapter are: •
Custom fields, categories, and statuses can all be customized on a perchannel basis (or different channels can share the same custom fields, categories, or statuses). This lends itself to enormous flexibility in how you design your channel (but also means there is usually more than one way to accomplish anything in ExpressionEngine).
•
When creating a new channel, you create custom fields/statuses and categories for the new channel (optional), create the channel itself, create content inside the channel, and create or modify templates to display the channel content. These steps can be completed in any order and are usually iterative.
•
Preload text replacements are useful as constants, allowing you to take a line of text that is repeated throughout a template, such as the channel name, and define it in one place.
•
Global variables can be used for static text, HTML, or scripts that are used in more than one template. Therefore, by using this, if you want to make a change, you only have to update the global variable, rather than every template that might be using that code.
•
Snippets are like global variables, except that they also allow ExpressionEngine code and tags.
•
Embedded templates are like snippets, except that they allow variables to be passed to them to dynamically vary the output.
[ 102 ]
Creating a Fully-Equipped Channel So far you have used ExpressionEngine to create a website where you can easily edit the content through the Publish screen in ExpressionEngine and where it is easy to add new pages, should you wish to. In this chapter, you are going to take your ExpressionEngine-powered (but still static) website and enhance it to make it interactive. The Frequently Asked Questions page is an ideal candidate for this. Currently, there are only two questions on the page. However, Ed & Eg would like to start posting new questions and answers regularly. The frequently updated content would encourage visitors to keep coming back to the site. Although Ed & Eg is the example in this chapter, the concepts could easily be applied to any regularly updated content that you would want to post on your website; including a regular blog, book reviews, recipes, or products that you are selling. You will be: •
Displaying multiple entries
•
Allowing visitors to browse entries and select the ones that interest them
•
Allowing visitors to comment on entries, just like they might comment on a blog posting
•
Creating a feed to allow visitors to keep up with new entries using their favorite news reader (such as Google Reader)
From what you learned in the last chapter, you should now be familiar with the process of creating a channel, creating custom fields, posting content, and creating a template to display the content. You will follow that same process in this chapter.
Creating a Fully-Equipped Channel
Designing your channel
One of the biggest benefits to using ExpressionEngine is the ability to customize your channel fields. This allows you to really tailor the fields to the content that will be in the channel. In this case, you are creating a channel for Ed & Eg's Frequently Asked Questions. You will need two text fields—one for the question and one for the answer. By splitting up the question and answer fields in this way, you gain the ability to display the question separately from the answer—a design you will take full advantage of. You will create a multiple-entry page where visitors can see the various questions that have been asked and (hopefully) be tempted to click to find out the answers. When they click on a given question, the visitor will be taken to a single-entry page where the question and the answer will be displayed, along with comments from other visitors, with the ability to add their own comments. This design of single and multiple-entry pages is actually fundamental to ExpressionEngine. The key differences between the two types of pages are: 1. A multiple-entry page displays the content from more than one entry in your channel. You can choose to display all the information from the channel or just a teaser (such as only the question, but not the answer). You have control over how many entries are displayed on a page and how they are displayed. A multiple-entry page can change frequently—if a visitor bookmarks a multiple-entry page and returns at a later date, the page will likely reflect new content. 2. A single-entry page displays the content from only one entry in your channel. The content does not change over time (unless you edit the entry in question). This means that a visitor can bookmark the URL or e-mail it to a friend, and when they return, they will see the same content that they originally saw (plus any new comments). A single-entry page is required to accept comments for a specific entry and to display those comments. The URL for a single-entry page is determined by the URL Title on the Publish screen for the entry. A single-entry page URL typically takes the format of http:// localhost/template_group/template/entry_url_title, whereas a multiple-entry page URL would not have the entry_url_title at the end. ExpressionEngine uses the URL to dynamically determine what content to display using each template. If the URL has the URL Title of an entry in it, ExpressionEngine will only display that entry. If the URL does not have the URL Title of an entry in it, ExpressionEngine will return as many entries as meet the criteria in the parameters of the {exp:channel:entries} tag. [ 104 ]
Chapter 5
The includes/.website_page template that is used to display content from the website channel is actually an example of a multipleentry page. However, you used the parameter url_title to limit the number of entries to one specific entry.
In general, not all channels need both single and multiple-entry pages. However, it's good practice to have single-entry pages for channels with content that a visitor might want to bookmark and return to. Furthermore, if your channel allows visitors to leave comments on your posts, a single-entry page is required. Whether or not to allow comments is, in fact, a design decision in itself. Although it can encourage visitors to engage with your brand, having a website that allows comments but does not have any can be worse than not allowing comments at all. Ed & Eg have a plan to ensure their website will receive comments once it goes live.
Creating your custom channel fields The custom fields you are going to create are: • •
faqs_question faqs_answer
The question and answer fields will be Textarea fields with Auto
formatting. This formatting will put line breaks between paragraphs in the answer, but will not wrap the question and answer in paragraph tags. The benefit to doing this is that you can put an A: at the beginning of each answer in your template and know that the first paragraph of the answer will be on the same line. 1. From the top menu of the control panel, select Admin | Channel Administration | Custom Fields. Now select Create a New Channel Field Group.
[ 105 ]
Creating a Fully-Equipped Channel
2. Use a Field Group Name of faqs, as this field group will only be suitable for the Frequently Asked Questions channel. Click Submit. 3. Select Add/Edit Custom Fields for your faqs field group, and then select Create a New Custom Field.
4. The first field to create is the Question field. The Field Type will be Textarea. Give it a Field Label of Question and a Field Name of faqs_question. Leave the Field Instructions blank (these appear only on the Publish page).
5. This will be a required field and will be searchable. Say Yes to show this field by default and do not change the value of the Field Display Order. 6. The Textarea Rows can be left at 6. Set the Default Text Formatting to Auto
and say No to allowing an override on the Publish page. Leave the Text Direction as Left to Right and say Yes to show the Formatting Buttons, Smileys, Spellcheck, Writemode and File Chooser. Leave everything else set to No.
[ 106 ]
Chapter 5
7. Click Submit. 8. Go ahead and create the field Answer (faqs_answer) with the same settings as the faqs_question field. 9. Once your fields have been created, your Field Group should look as follows:
That's it! Your custom fields have been created and you can now move on to creating some custom categories.
[ 107 ]
Creating a Fully-Equipped Channel
Creating your categories
In the last chapter, when you created the website channel, you did not create categories because there was no need to organize your content by category. In this chapter, since the number of questions in your channel could quickly become numerous, it makes sense to use categories to relate questions to each other (and hopefully keep your visitors browsing longer). 1. To create a new category group, go to Admin | Channel Administration and then Categories.
2. Select Create a New Category Group. 3. Call the new category group FAQ Categories and select Allow ALL HTML from the formatting drop-down box. Ignore the options about editing and deleting categories—if you had other member groups with administrative control panel access, you could have granted them permission to edit and/ or delete categories in this category group. ExpressionEngine automatically recognizes that no other member groups have administrative control panel access at the moment.
[ 108 ]
Chapter 5
4. Click Submit. 5. You have now created a category group, but you have not yet created any categories. From the Category Management screen, select Add/Edit Categories for the FAQ Categories group. 6. At the top right, select Create a New Category.
7. For now, you will have two parent categories (Life Events and General Advice) as well as a number of sub-categories. Name this first category Life Events. The Category URL Title will default to life_events. Leave the Category Description blank and do not assign an image to your category. Leave the Category Parent set to None and click Submit.
8. Back on the FAQ Categories screen, select Create a New Category again.
[ 109 ]
Creating a Fully-Equipped Channel
9. Your first sub-category will be Going to College (with a URL title of going_ to_college). Type in a short category description such as Questions relating to college/university. Under Category Parent, select Life Events. Do not select a Category Image. Click Submit.
10. The rest of the categories will be set up similar to the two already created (except that the names, URLs, and descriptions will be different). Create the following categories/sub-categories and go ahead and make up your own descriptions; later, you will display the descriptions on your website, so be sure they are full sentences. Category Name
Category URL Title
Category Parent
Getting Married
getting_married
Life Events
Having a Baby
having_a_baby
Life Events
Changing Jobs
changing_jobs
Life Events
Retiring
retiring
Life Events
General Advice
general_advice
None
Budgeting
budgeting
General Advice
Buying a Car
buying_a_car
General Advice
Buying a Home
buying_a_home
General Advice
Debt
debt
General Advice
Savings
savings
General Advice
Investments
investments
General Advice
[ 110 ]
Chapter 5
Your categories have been created. If you want to, you could use the arrows on the left-hand side to re-order the fields (currently, they are ordered alphabetically).
Now that you have created your custom categories, the next step is to create your FAQ channel. Note that you could create your channel first and then create your categories and your custom fields afterwards. However, if you do this, you would then have to go back and edit your channel to associate it with your custom fields/categories. By creating your categories/custom fields first, you can associate the category/custom field group when you create your channel.
Creating your new channel
As you have previously seen, a channel contains content. In this chapter, the questions Ed & Eg get asked and their answers are your content. You have already built new custom fields and a new category group for your channel. You do not need a new custom status group; the open and closed statuses that are in the pre-existing Statuses status group are all you need. 1. From the control panel top menu, select Admin, then Channel Administration, and then Channels. Now select Create a New Channel. [ 111 ]
Creating a Fully-Equipped Channel
2. The Full Name for your channel will be FAQs and the Channel Name will be faqs. Do not duplicate an existing channel's preferences, but say Yes to editing the group preferences.
3. Under Edit Group Preferences, choose a Category Group of FAQ Categories, a Status Group of Statuses, and a Field Group of faqs.
4. Further down, say No to creating new templates for this channel (you will do this later). Finally, click Submit. Your channel has now been created!
Publishing your first set of questions
You have a channel created, complete with custom fields and categories. The next step is to publish some entries so that there are some entries to work with when you start building the templates that will display your channel content. Take the initial questions from the existing questions.html page in the original Ed & Eg website that you downloaded in chapter 4. 1. From the top menu, select Content, Publish, and then FAQs. Title your first question Living Paycheck to Paycheck with a URL Title of living_ paycheck_to_paycheck.
[ 112 ]
Chapter 5
2. Open questions.html in your browser and copy the text of the question and the answer into your channel. Do not copy any of the HTML (such as paragraph tags). Also, do not copy the Q: or A: and do not worry about putting the question in italics—this can be done at the template level to save you from having to remember to do it for each and every question. Do go ahead and apply any italics in the answer by highlighting the words to italicize and then clicking the i button above the field.
3. Select the Categories tab at the top and check the appropriate categories for this entry (such as Budgeting, Debt, and Savings). Next click Submit.
[ 113 ]
Creating a Fully-Equipped Channel
4. Repeat all these steps for the second question called Giving Gifts. Select a category for this entry of Budgeting and click Submit. You now have your first entries published, but before you can see them on your website, you will need to create some templates.
Creating your FAQ templates
Earlier in the chapter, you learned about single-entry versus multiple-entry pages. However, in reality, a channel with more than a handful of entries needs more than one multiple-entry page to keep the number of entries on each page down to a digestible number for your visitors. ExpressionEngine, therefore, offers you three ways to organize your multiple-entry page content: 1. By Category: Organizing your entries by category involves having a category page for each category. On that page, only the entries in that category are displayed. 2. By Date: Organizing your content by date creates an archive page for each month, with only the entries in each month displayed. This technique can be combined with a mini-calendar so that visitors can select a month or even a specific day and see only the entries from that timeframe. 3. By Pagination (showing 10 entries per page): There are two types of pagination—one that shows how many pages there are and allows you to jump to a specific page (including the last page). The other is a simple Next/ Previous link that your visitors can use to traverse through your pages oneby-one. Pagination can be combined with organizing by category so that categories that have a lot of entries are paginated. You can choose one or more of the preceding techniques to organize your content. You can even use all the techniques together, paginating your multiple-entry page while also providing links for visitors to filter either by date or by category should they wish to do so. For Ed & Eg's website, the content is such that it makes more sense to organize by category than it does by date. (A new visitor to Ed & Eg is going to care less about when each FAQ was posted and care more about whether the FAQ is relevant to them). It also makes sense to use pagination to keep the number of entries on each page to a reasonable number. You will therefore create two templates—one for the multiple-entry pages (faqs/ index) so that a visitor can browse the FAQs and one for the single-entry page (faqs/browse) where visitors can read an individual FAQ and post their own comments. Within the multiple-entry page template, you will use conditional statements to identify whether the page being displayed is the main multiple-entry page (with no filtering by category) or a category-specific multiple-entry page. [ 114 ]
Chapter 5
It is possible to go even further and combine the single-entry page and the multiple-entry page into a single template using conditional statements based on the URL. However, your template quickly becomes complicated when doing this, particularly if you are organizing your entries by category, by date, or by pagination, since each of these techniques results in different URLs which have to be accounted for. If this is something you are interested in doing, then a plugin such as MD Detect Page Type (http://devot-ee. com/add-ons/plugins/md-detect-page-type/) will help.
You will start by creating a basic multiple-entry page template with pagination (you will add the category archiving later). 1. First, since you are creating a new section for your website, it makes sense to create a new template group to house it in. In the control panel, click on Design, Templates, and then Template Manager. Select New Group and call the new template group faqs. Do not duplicate a group and do not make the index template in this group your site's home page. (You still want the site template group to be the site's home page). Click Submit. 2. Next, copy the includes/404 template (created in the previous chapter, or can be downloaded from http://www.packtpub.com/support or from the chapter 4 page at http://www.leonardmurphy.com/book2/chapter4) into the faqs/index template. Remove the
heading and the following paragraph so that there is nothing between the and the closing . Click on Update. This will result in a page at http:// localhost/faqs with a header, sidebar and footer, but no content.
[ 115 ]
Creating a Fully-Equipped Channel
3. At the top of the template, create three new Preload Text Replacements (below). The first represents the channel name, the second represents the template group, and the third represents the single-entry template that you will create next. Each of these will be used in multiple-places throughout the template, so they are good candidates for Preload Text Replacements. {preload_replace:my_channel="faqs"} {preload_replace:my_template_group="faqs"} {preload_replace:my_single_entry_template="browse"}
4. Update the HTML attribute as follows (this is the title that appears at the top of the window): Frequently Asked Questions - Ed & Eg Financial Advisors
5. Next, write the code to display the Frequently Asked Questions' introduction. After the line, insert the following: Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
6. Now you are going to write the code to display up to ten questions on a page using pagination. This first piece of code displays the title of each entry. The limit parameter is what determines how many entries to display on each page, and the paginate parameter indicates where you would like the pagination links to appear (the choices are top, bottom, or both). Within the paginate variable pair, a conditional statement makes sure that there is more than one page of entries before displaying in order to display the pagination links. (This means that, initially, since you do not have more than ten entries, you will not see these pagination links). Insert the following code just before the line that appears immediately above : [ 116 ]
Chapter 5 {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom"} {title}
{paginate} {if "{total_pages}" != 1}
Page {current_page} of {total_pages} pages {pagination_links}
{/if} {/paginate} {/exp:channel:entries}
7. If you click Update and then visit http://localhost/faqs, you will see the titles for the channel entries you have already submitted.
8. Now you can add the questions for each entry, along with a link to read the answers. Insert the following code after the header:
<strong>Q: <em>{faqs_question}
<strong>A: Read the answer here!
[ 117 ]
Creating a Fully-Equipped Channel
The permalink tag generates an HTML link to the URL for the single-entry page for each entry. A permalink is so called because it is a permanent link to that entry. For example, the multiple-entry page http://localhost/faqs may display different FAQs in different orders at different times, but the permalink http://localhost/ faqs/browse/living_paycheck_to_paycheck will always be a link to the Living Paycheck to Paycheck entry. (Note that you have not yet created the browse single-entry template). The permalink tag includes one parameter, which is the template group and the template to use to display the entry. It then dynamically adds the URL title for you. In this case, you are linking to the browse template of the faqs template group (although you are using Preload Text Replacements instead of referencing faqs/browse directly).
Now visit http://localhost/faqs and you can see the questions along with links to read the answers. The links do not work yet since you have not yet created your single-entry template. You will do this next.
You are done with your multiple-entry page template! Next, you have to create the single-entry page.
Creating your single-entry page
As previously explained, you are going to use the faqs/browse template for your single-entry pages. 1. In the control panel, go to Design, Templates, and then click on Template Manager. Highlight the faqs template group and select New Template. [ 118 ]
Chapter 5
2. Name the new template browse. Leave the template type as Web Page. Under Default Template Data, highlight Duplicate an Existing Template and select faqs/index as the template to duplicate. Click Create and Edit.
3. The first change you are going to make is the HTML that appears in the browser title bar. In the includes/.website_page template in Chapter 4, Moving a Website to ExpressionEngine, you used the {exp:channel:entries} tag to get the title of the entry from the channel and use it as part of your HTML title. You will now do this again. Remember that the disable parameter cuts down on unnecessary database queries given that you are just retrieving the title of the entry and nothing else. Change the to read as follows: {exp:channel:entries channel="{my_channel}" disable="categories|category_fields|custom_fields|member_data|pagi nation"}{title}{/exp:channel:entries} - Ed & Eg Financial Advisors
4. Underneath the line , delete the entire block of code from the down to (and including) the {/exp:channel:entries} tag. 5. Now add the following code in the section instead. This code is very similar to the code for your browsing page, except that you are displaying the answer and instead of links to the single-entry page, you have a link back to the main browsing page. {exp:channel:entries channel="{my_channel}"} {title}
<strong>Q: <em>{faqs_question}
<strong>A: {faqs_answer}
[ 119 ]
Creating a Fully-Equipped Channel {/exp:channel:entries}
Note the use of the path variable to provide a link back to the index template of the faqs template group. If you wanted a link to a template that was not index, you would have to write it as: {path=template_ group/template}. The difference between the permalink variable used to link to the single-entry page and the path variable used to link back is that the permalink variable automatically adds the URL Title of the entry to the template specified (so you are taken to the URL specific to the entry), whereas the path variable does no such thing (it simply takes you to the template group and template specified).
You now have a FAQs page that displays all your faqs (with built-in pagination once you post enough entries). You can also click on individual questions to see the answer. The next step is to add some user interactivity to the single-entry page by allowing visitors to leave comments or add their own suggestions to each question.
Allowing comments on your entries
Comments are one of the easiest ways for visitors to interact with your site. They are also an easy way to attract spammers, who will be glad to leave hundreds of comments linking to websites of dubious quality. Luckily, ExpressionEngine includes features designed to prevent abuse.
Preventing comment spam
1. Comment preferences are set on a per-channel basis, allowing you to have different preferences for different channels (although when you create a new channel, you can copy the preferences from an existing channel to make things simpler). Go to Admin | Channel Administration | Channels and select Edit Preferences for the FAQs channel. [ 120 ]
Chapter 5
2. Here are all the aspects of the channel that you can fine-tune, organized into expandable groups. The General Channel Preferences were set when you created the channel, and include the channel name and short name.
3. Click on Path Settings. The path settings are the URLs that are unique to this channel. When creating links in your templates, ExpressionEngine will use these settings to know what URL to link to. Set your Channel URL to http://localhost/faqs and set your Comment Page URL and Search Results URL both to http://localhost/faqs/browse. You have not yet created an RSS template, but you can set your RSS Feed URL to be http:// localhost/faqs/rss in anticipation. The Ping Return URL does not apply to this channel.
When the Live Look Template is set, you will see a new Live Look link after publishing a new entry, as well as a new View link on the Content | Edit page. When you click one of these links, you will be taken to the livelook template to see the entry. A live-look template is coded exactly like an ordinary single-entry page template, and although you can define your single-entry template to be your live-look template, the true power comes into play when you define a live-look template that displays entries that would not be visible in your single-entry page template (either because they are future-dated or because they do not have an open status). This allows you to draft an entry with a closed status, for example, and view what it will look like on your website before you publish it with an open status.
[ 121 ]
Creating a Fully-Equipped Channel
4. The Administrative Preferences sets up defaults for each entry. For example, if you know the channel does not have comments, instead of having to click No to Allow Comments on each entry, you can set the default for every new entry to be no here (leave it set to Yes right now). The field for the search excerpt allows you to define which custom field is displayed when a member searches your site—the excerpt will automatically strip out any HTML formatting. For now, leave this set to Question. 5. The Channel Posting Preferences determines what to do with URLs inside a channel entry—you can either automatically link to them or leave them as plain text. Since only trusted people (such as yourself, Ed & Eg) will be able to post to this channel, you can Allow ALL HTML and say Yes to allowing images as well as to converting URLs into links. If your channel will involve lots of example HTML code, you could Convert HTML into character entities, meaning that any HTML entered as part of an entry will display on screen as-is and not be interpreted by the browser. At this time, no changes are needed. 6. Next, click on Versioning Preferences and set Enable Entry Versioning to Yes. By doing this, you can keep old versions of a channel entry saved. This is useful as it provides a quick undo feature for edits which were made erroneously. Enabling this option creates a new Revisions tab on your channel Publish page where you can load previous revisions. This option is not a substitute for doing a full database backup at regular intervals. [ 122 ]
Chapter 5
7. Select Notification Preferences. These preferences allow you to set up individuals to receive e-mails whenever a new entry or comment is posted. Setting this is essential if you require a moderator to approve all comments but can also be useful if you do not moderate your comments, as a means to monitor comments for comment spam. If you are using a localhost environment, outgoing e-mails may not work. So for now, leave all the notification options set to No. 8. Select Comment Posting Preferences. This is where you can either lock down or open up who can post comments and how many hoops they have to jump through in order to do so. Right now, say Yes to allow comments and No to requiring membership in order to post comments. As you are not requiring membership, say Yes to enabling a CAPTCHA for comment posting and say Yes to requiring an e-mail address to be entered when a reader tries to post a comment, but say No to moderating comments. Comment moderation means that an administrator, such as you, must approve every comment before it actually appears on your website. CAPTCHA stands for a Completely Automated Public Turing test to tell Computers and Humans Apart and is a puzzle that is easy for a human to solve, but not easy for a computer to solve. It is designed to filter out real people posting comments from automated scripts that are posting comment spam. ExpressionEngine's CAPTCHA technology relies on an image of letters with a background that makes it difficult for a computer to identify the letters. The person submitting the comment must type in the letters from the image correctly in order to post their comment. The downside to using an image in CAPTCHA technology is that it is not very accessible for visually-impaired visitors who might be relying on screen-readers to navigate your website. There are add-ons that provide a solution to this, such as Accessible Captcha (available at http://devotee.com/add-ons/extensions/accessible-captcha/). This addon changes the graphic to a user-defined question and answer, such as 2+2. A human could easily answer 4, but an automated spam program would not be able to do so. Search for CAPTCHA at http://devotee.com/ for other add-ons [ 123 ]
Creating a Fully-Equipped Channel
9. Leave the Maximum number of characters allowed in comments at 5,000, but set a comment re-submission time interval of 30 seconds. This option prevents an automated script from submitting more than one comment every 30 seconds. It can be useful as a deterrent against comment spam (especially if you are not moderating your comments or using CAPTCHA technology). Leave the comment expiration setting at 0 (meaning comments do not expire). If desired, you can use this setting to stop accepting comments on entries after a certain number of days. This can be useful to reduce the number of places on your website where comment spam can be posted. For the Comment Text Formatting, select XHTML but Allow only safe HTML. This means that formatting HTML, such as <strong> and <em>, will work, but more complex HTML will be rendered in plain text rather than being interpreted by a browser (thereby preventing malicious code being executed on your website). Do not allow image URLs in comments and do not automatically turn URLs and e-mail addresses into links (these options discourage spammers because their comments do not become links that could drive traffic to their website).
[ 124 ]
Chapter 5
10. Finally, the Publish Page Customization allows you to set a default entry title or URL title prefix that will apply to all new entries. This can be useful if you want all your entries to have the same prefix. Right now, leave these blank. Also, leave the Display Rich Formatting Buttons option set to Yes. Setting this to No would turn off the HTML formatting buttons (such as bold and italics) on all your custom fields, regardless of each individual custom field setting. 11. Click on Update and Finished to save all your settings. The settings you have just seen are useful in combating comment spam, especially from automated scripts, and it's recommended to consider them carefully before enabling comments. Using some combination of either requiring membership to post comments, enabling CAPTCHA technology, and/or enabling comment moderation along with setting an administrator up to receive notifications of new comments allows you to minimize comment spam as much as possible and quickly identify it when it does occur. You are now ready to create a form to accept comments. More information on all of these preferences can be found in the ExpressionEngine documentation at http://expressionengine. com/user_guide/cp/admin/content_admin/channel_edit_ preferences.html.
Creating a comment form
The first step in accepting comments is to create a form where visitors can write and submit their comments. Comments have to be tied to a specific channel entry, and therefore, the comment form can only appear on single-entry pages. Therefore, you will add your comment form to the faqs/browse template. 1. Open the browse template in the faqs template group for editing and type in the following code after {/exp:channel:entries}. This code displays the comments that other people have submitted. The title of the section is Comments. Comments
{exp:comment:entries} {if comments} {comment}
Posted by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/if} [ 125 ]
Creating a Fully-Equipped Channel {if no_results} There are no comments at this time - be the first to share your thoughts!
{/if} {/exp:comment:entries}
2. Next, add the code to create a comment form. Add this after the {/ exp:comment:entries} tag. First, this creates the fields for the visitors name and e-mail address. Since you would already have the name and e-mail address of any member who is logged in, you only need to ask for this information if the visitor is logged out. {exp:comment:form} Post Your Own Comment
{if logged_out}
{/if}
{if logged_out}
{/if}
{if captcha} {captcha}
[ 126 ]
Chapter 5
{/if}
{/exp:comment:form}
You can also add fields for a visitor's location or website. Use the same format as the email field in the previous code, but replace the word email with either location or url.
3. Now try posting your first comment. In order to see the website as a visitor will see it, log out of the control panel by clicking on Logout at the top-right and confirming you want to log out. (Closing the control panel without logging out will leave you logged in). Now visit http://localhost/faqs and click on a question. 4. Fill in your name, e-mail, type in a comment, and leave the box to remember your personal information, and the box to notify you of follow-up comments unchecked. If you check Remember my Personal Information, then the next time you see a comment form, your name and e-mail address will be pre-filled. Note that if you are logged in when you visit this page (for example, if you were previously logged into the control panel), then you will not see the fields for the name or e-mail and you will not see the CAPTCHA.
5. Enter the CAPTCHA word. Notice that each time you refresh the page, a different image with a different word is shown for your CAPTCHA. When you have completely filled in the comment form, click Submit.
[ 127 ]
Creating a Fully-Equipped Channel
Note that currently the Preview button will not work as you have not yet set up a preview template. If you are using a localhost environment, posting comments can be more difficult than when using an installation on a real website. If you are unable to post comments in the localhost environment, try changing the setting Require IP Address and User Agent for Login to No. This setting can be found in the control panel under Admin | Security and Privacy | Security and Sessions.
6. The page will auto-refresh, and you should now see the comment that you submitted.
Allowing visitors to preview comments
One final aspect of comments that hasn't yet been covered is the ability to preview the comment before publishing. You may have noticed the Preview button on the comment form that does not work yet. 1. First, modify the faqs/browse template to include the following code after the {/exp:comment:entries} and before the {exp:comment:form} line. Notice how the code is almost exactly the same as the code to display an actual comment, except that you are using the {exp:comment:preview} tag instead of the {exp:comment:entries} tag. This means that the look and feel of the previewed comment is identical to how it would look if it were an actual comment. {exp:comment:preview} {comment}
Being previewed by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/exp:comment:preview}
[ 128 ]
Chapter 5
2. Next, change the line {exp:comment:form} to include the preview parameter as follows. This parameter tells the form which template to load if the preview button is clicked. {exp:comment:form preview="{my_template_group}/{my_single_entry_template}"}
3. Now go to the FAQs page, type in a comment, and click Preview instead of Submit. You can see that the comment appears and looks exactly as if you had submitted it, except that instead of Posted by in the footnote, it says Being previewed by. You can keep editing the text and clicking on Preview as often as you like.
Organizing your data with categories
Although you have created custom categories and assigned your entries to some of your categories, you haven't yet used categories to help visitors browse the FAQs. You will now do this, but first set ExpressionEngine to use category names rather than ID numbers in the URL. This means that instead of category browsing pages having a URL such as http://localhost/faqs/C8, the category URL will be more like http://localhost/faqs/category/getting_married 1. In the control panel, go to Admin, Channel Administration, and then Global Preferences.
[ 129 ]
Creating a Fully-Equipped Channel
2. Say Yes to using category URL titles in links. Leave the Category URL Indicator as category. (If you do change this, bear in mind that whatever word you use here becomes a reserved word and cannot be used as a template name).
3. While you are on this page, also select No to auto-assigning category parents and click on Submit. Later in the chapter, you will use categories to show visitors who are viewing one question other related questions from the same categories. If all questions have the same two parent categories autoassigned, the related questions that are displayed are going to be less tightly coupled to the question being viewed.
Displaying categories with your entries
To encourage visitors to browse by category, it makes sense to display the categories that each entry belongs to underneath the questions on the faqs/index page. For this, you will use the channel {categories} tag, which allows you to list the categories, along with the {comment_total} tag to show how many comments each entry has and the {comment_url_title_auto_path} tag to link to your single-entry page for comments. Note that the {comment_url_title_auto_path} tag autogenerates the URL to your category template, as defined in Admin | Channel Administration | Channels, under Edit Preferences for the FAQs channel, then under Path Settings. The option Comment Page URL should be set to http://localhost/faqs/browse.
1. Edit the faqs/index page and add the following code underneath the Read the answer here! permalink and above the {paginate} line. <strong>Categories: [ 130 ]
Chapter 5 {categories backspace="3"}{category_name} | {/categories}Comments ({comment_total})
Everything between the {categories} opening tag and the {/ categories} closing tag is repeated for each category that the channel entry is assigned to. In this code, there is a vertical bar (|) after the category name and before the next category name to separate the categories. To prevent this vertical bar appearing after the last category, we use the backspace parameter. This parameter removes the specified number of characters from the end of our code after the last category name only (in this case, the | and the surrounding two spaces). This parameter is specifically designed to remove separators or other code that it makes sense to have between categories, but not after the last category.
2. Click on Update and Finished and then visit the FAQs page. You should now see underneath each answer—a piped list of categories that the entry belongs to. Clicking on one of the categories takes you to a category browsing page where you can see other entries that have the same category. At the moment, given that you only have two entries right now, namely, your category browsing pages and your main multiple-entry page, it will not be substantially different unless you pick a category that is unique to just one entry. Once the number of entries starts getting higher, browsing by category will be a much faster way of finding related questions than simply browsing through all the questions.
[ 131 ]
Creating a Fully-Equipped Channel
Distinguishing your category browsing page
Currently your category browsing page and your main multiple-entry page look identical—they have the same page title and the same introduction. Within the faqs/ index template, you can tell if you are on the main multiple-entry page or a category browsing page by looking at the URL. If segment_2 (the part of the URL after faqs) is category, you are on a category browsing page. You can, therefore, use this condition to display slightly different content accordingly. 1. First update the HTML title (which appears on the title bar of the window). To do this, edit the faqs/index template and replace the
Frequently Asked Questions - Ed & Eg Financial Advisors with the following: {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} Questions About {category_name} - Ed & Eg Financial Advisors {/exp:channel:category_heading} {if:else} Frequently Asked Questions - Ed & Eg Financial Advisors {/if}
2. Next, you can replace the code appearing after down to, but not including, the exp:channel:entries tag with the following: {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} Questions About {category_name}
{category_description}
{/exp:channel:category_heading} {if:else} Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
{/if}
[ 132 ]
Chapter 5
This code says that if you are on a category-browsing page, then the page heading should be Questions About {category_name} and the introductory text should be the category description. To edit the category descriptions, you have to edit the individual category in question. Go to Admin | Channel Administration | Categories, then click on Add/Edit Categories for the FAQ Categories group, and edit the category you want.
Now your category browsing pages look markedly different to your main multipleentry browsing page. However, this setup still requires your visitors to deliberately click on a category that interests them in order to find other FAQs that might be of interest. A different approach would be to display, at the end of the single-entry page, a list of other FAQs that have the same category (and therefore, are likely to be of interest to the visitor). In this way, the visitor is encouraged to keep browsing without ever realizing they are using categories.
Displaying related entries by category
To display other entries in the same category on your single-entry page, you need to make use of the ExpressionEngine parameter related_categories_mode. This looks at the URL of your single-entry page and then brings back the data of other entries that are in the same category as the page you are on. 1. Edit the faqs/browse template. Insert the following code after the line {/ exp:comment:form}: Other Questions Like This
{exp:channel:entries channel="{my_channel}" limit="5" related_categories_mode="yes" custom_fields="yes" orderby="random"} {if no_results} There are no questions like this currently – check back soon though...we're always adding more!
{/if} <strong>Q: <em>{faqs_question}
[ 133 ]
Creating a Fully-Equipped Channel <strong>A: Read the answer here!
{/exp:channel:entries}
Here you are bringing back up to five entries that are in the same categories as the question being viewed. To ensure variety, the entries are displayed in a random order, meaning that if you have more than five entries, no two sets of related questions will be the same.
2. If you now visit http://localhost/faqs and click on an entry, you should see a link to the entry you did not click on at the bottom of the single-entry page. If you do not see a link to your entry, it means the entry you are viewing is the only one in that category.
Now, as Ed & Eg go through and start adding hundreds of questions and answers, ExpressionEngine will dynamically organize the content. In this way, you may catch a visitor's eye with a question they want to know the answer to, and then keep them hooked by dynamically showing them other questions that are similar to the question they initially clicked on.
The FAQ snippet
The final step in getting visitors into the Frequently Asked Questions section of the website is to display Frequently Asked Questions in the widebar at the bottom of each page. Currently, there are two, static FAQs that are displayed in the widebar. In this section, you will update the widebar to display three random entries from the FAQs channel. To do this, it makes sense to use a snippet. Why a snippet? If you recall from Chapter 4, a snippet is used when you want to reduce repetition. In this case, since the widebar will be used on lots of templates, it is a great candidate for becoming a snippet. Why not a global variable? Remember that global variables do not support ExpressionEngine tags. Since you are planning to show data from an ExpressionEngine channel, a snippet is required. [ 134 ]
Chapter 5
In this section, you are choosing to display three random entries in your widebar. If you wanted more control over which FAQs were displayed at the bottom of every page, you could manually set the status of three entries to a custom status such as Featured (instead of open). Then, in your snippet, you could specify in the {exp:channel:entries} tag that you only want to include entries where status="Featured". You would also have to add a parameter status="open|featured" to the {exp:channel:entries} tags in all your other templates that use the FAQs channel. ExpressionEngine does not display entries that do not have a status of open, by default.
1. In the control panel, click on Design, then Templates, and finally Snippets. Then click on Create a New Snippet. 2. Call the snippet website_faqs and type in the following code to display your random entries. Note the use of the switch parameter—this essentially says that for the first entry, use colA as the div id. The second entry should use colB and the third entry should use colC. If you were displaying more than three entries, the fourth entry would use colA again, which, in this case, does not make sense to do. {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off"} Frequently Asked Question
{faqs_question} Find out…
{/exp:channel:entries}
Remember that ExpressionEngine uses the URL to dynamically determine whether you are on a single-entry page or a multiple-entry page. (If the URL has the url_title of a specific entry after the template name, then ExpressionEngine recognizes that you are on single-entry page and will only display content from that entry). This means that you cannot display content from another entry (or another channel) on a single-entry page unless you tell ExpressionEngine to ignore the fact that you are on a single-entry page. This is what the dynamic="off" parameter does.
[ 135 ]
Creating a Fully-Equipped Channel
3. Next, edit all your existing templates that show the widebar (includes/. website_page, includes/404, faqs/index, and faqs/browse) and replace the widebar code with a reference to this snippet instead. For each template, delete all the code including and between to and replace it with {website_faqs}.
Your work with the FAQ page is almost complete. The next step is to provide a way for visitors to be notified about new FAQs, without having to constantly re-visit your website. For this, you will use a feed.
Setting up an RSS or Atom feed
RSS or Atom feeds are an alternative way of allowing visitors to keep up-to-date on your website. Essentially, the visitor subscribes to your feed through their e-mail software, browser, or other news readers, and then they get notified when you post new entries. This saves them from having to periodically revisit your website to see if there is new content or not. Having a feed available can make the difference between a visitor being someone who visited your website and liked it (but does not come back) and someone who visited your website and now reads every new post. When building a feed, the easiest approach is to start with a pre-built ExpressionEngine feed template. This will take care of the top portion of the feed (containing meta-information such as the date, the URL of the entry, and so forth), meaning you only have to make a few customizations so that the feed displays the content from your custom fields. An RSS 2.0 template can be found at http://expressionengine.com/wiki/RSS_ Template_for_EE2/. However, since Agile Records comes with both an RSS 2.0
and an Atom 1.0 template, you can also base your template on theirs. If you did not install Agile Records, using the template from the wiki will have the same results. 1. From the Template Manager, select the FAQs template group and create a new template called rss. The template type should be RSS Page and you should duplicate a template, namely, the news/rss template. Click on Create and Edit. [ 136 ]
Chapter 5
2. On the first line, change {exp:rss:feed channel="news"} to {exp:rss:feed channel="faqs"}. (If you are starting from the wiki template, then the channel on the first line is howto, but should still be changed to faqs). 3. About half-way down, you will see a familiar {exp:channel:entries} tag. In this tag, change news to faqs. The limit parameter limits the number of results to 10 and the disable parameter tells ExpressionEngine not to query the database for member data (reducing the amount of data that is queried). Finally, every time a news-reader polls your website for new entries, it provides the last date/time that it checked. The dynamic_start parameter tells ExpressionEngine to only return entries (if any) that have been posted since that particular last date/time. {exp:channel:entries channel="faqs" limit="10" dynamic_start="on" disable="member_data"}
4. Even further down, look for the XML tag <description>. On that line, you will see an ExpressionEngine tag {news_body} (or {body} if you are starting from the wiki template). This is a custom field, so you should change this line to use your own custom field—{faqs_question}. You could display both the question and the answer in the feed. However, in this example, you are going to display only the question, followed by a link to the answer page (using code you have already used on your multiple-entry page). <description>{faqs_question}]]>
[ 137 ]
Creating a Fully-Equipped Channel
5. Click on Update and Finished. If you now browse to the RSS template (http://localhost/faqs/rss), your browser will likely recognize it as an RSS feed.
If you get an error, you may not have set the template to be an RSS Page. Check the template preferences for your RSS template.
6. Now all you have to do is link to the feed from your FAQs page so that people know it is there. Edit the faqs/index template and add the following after the introductory paragraph and before the {/if}: Don't forget to subscribe to our RSS feed to stay up-to-date with new FAQs as they are posted.
[ 138 ]
Chapter 5
You can now use your favorite RSS reader to view the content. If you do not have a favorite RSS reader, your e-mail client will likely already support it. For example, Mozilla Thunderbird 1.0 and greater and Outlook 2007 and greater, both have builtin support for feeds. Alternatively, Google Reader is a popular and free web-based alternative (http://www.google.com/reader). If you are following along in a localhost environment, then web-based feed readers will not be able to access your feed.
The instructions for creating an Atom feed are almost identical to those for creating an RSS feed: 1. Create a template faqs/atom and duplicate the news/atom template from the Agile Records example site into your new template. (The template type should still be RSS Page). 2. Change the feed channel on the first line to faqs. {exp:rss:feed channel="faqs"}
3. Change the channel in the exp:channel:entries tag to faqs. {exp:channel:entries channel="faqs" limit="15" dynamic_start="on" disable="member_data"}
4. Unique to Atom feeds, change the scheme to point to the single-entry template where the entry is: scheme="{path=faqs/browse}"
5. Change the custom fields inside the CDATA[] tag to reflect the content that you want to display inside your feed: {faqs_question} ]]>
6. Save your template and verify that you can subscribe to your new feed (http://localhost/faqs/atom). What is the difference between an RSS and an Atom feed? RSS 2.0 is the older and more established feed. Atom 1.0 was designed as a modern alternative to RSS. For practical purposes, news readers can read either feed, so which one you choose is up to you or you can use both types of feed and let your visitors pick whichever they prefer.
[ 139 ]
Creating a Fully-Equipped Channel
Improving your 404 Page
In the last chapter, you created a 404 Page for your site. ExpressionEngine allows for great flexibility with URLs and the downside of that is that invalid URLs can often return valid content. As an example, if you type in an entry URL that does not exist (such as http:// localhost/faqs/browse/ihatetoast, you see an actual page with content instead of your 404 template. This can be confusing to visitors if they mistype the URL. Luckily, there are options available to fix this. ExpressionEngine comes with a redirect tag that you can use to redirect visitors to another template, based on a conditional. Typically, the syntax of this tag would be {redirect="template_group/template"}. However, when redirecting to a 404 Page, rather than redirecting to "includes/404", you can redirect to "404". This will return the template that you defined in chapter 4 as your 404 template (if you have not yet defined this template, you can do so in Design | Templates | Global Preferences). The difference between a redirect to the template directly and a redirect to 404 is that, if you redirect to just 404, the redirect also includes 404 Page headers, meaning that search engines visiting that URL will recognize it as invalid and will not index it. 1. First edit the browse template of the faqs template group. Change the HTML to read {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes"}. This change means that if the URL does not match up to the URL of an entry, it will not display any content from the channel. 2. Next, between the opening {exp:channel:entries} tag and the closing {/ exp:channel:entries} tag, add the following code. This change says that if there is not an entry to display, then show your 404 Page instead. {if no_results} {redirect="404"} {/if}
3. Now visit http://localhost/faqs/browse/ihatetoast and you can see that your 404 template is now returned. 4. You can go one step further with your redirect. For example, you know that there should not be a segment in the URL after the URL of the entry (that is, http://localhost/faqs/browse/living_paycheck_to_paycheck is a valid URL, but http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus is not). Right now, the hippopotamus URL will still display your entry. If you add the following code to your faqs/browse template, immediately after the code you added above, it will cause a 404 redirect to take place instead: [ 140 ]
Chapter 5 {if segment_4!=""} {redirect="404"} {/if}
5. Now visit isit http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus and you will see a 404 Page instead. What about your multiple-entry page? For example, a URL of http://localhost/ faqs/rubbish should return a 404 Page, but it currently displays your multiple-
entry page. If you were not using categories or pagination, you could safely say that there should not be a segment 2, and if there is, redirect to 404. However, category URLs (such as http://localhost/faqs/category/debt) also use the faqs/index template, so you would need to build in logic to say that if segment 2 is category, then do not redirect to a 404. However, this logic gets more complicated. Once you have more than 10 entries, your entries will paginate over different pages, and the URLs for the pages will also be category 2 segments (for example, http://localhost/faqs/P0). Entries can also be archived by date. For example, a URL of http://localhost/ faqs/2011/11 will only display entries from November 2011. If you are organizing your entries by date in this way, then any year could appear in segment 2. One solution is to use an add-on such as MD Detect Page Type (http://devot-ee. com/add-ons/plugins/md-detect-page-type/), which makes it easy to tell if
you are on a category page, paginated page, or archive page, and therefore makes it much easier to build a conditional statement to display a 404 Page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. You have suddenly started getting spam comments on old FAQs. Set the comments on the FAQ channel so that after 60 days, no more comments are accepted. 2. Your FAQs currently have no indication of when they were posted or who posted them. On both the single-entry and multiple-entry pages, modify the question to include who posted the question and the date of the post (although this is something that might not make sense on the FAQs channel, in most situations where articles are being posted regularly, displaying the date of the post is a common requirement). to include the date of the post. [ 141 ]
Creating a Fully-Equipped Channel
3. Update the snippet that displays the three FAQs on every page of your website so that instead of displaying three random entries, it displays three featured entries (based on a custom status of "Featured").
Summary
In this chapter, you got more practice in using custom fields, channels, and templates. You also got introduced to categories, comments, and feeds. In the next chapter, you will get an in-depth look at the built-in membership module, including registering members, managing members, setting member privileges and permissions, and creating parts of your website that only members can see. The key points to remember after working through this chapter: •
You used a FAQ example in this chapter. However, all the functionality covered in this chapter would equally apply to any dynamic content that your site might have—whether it's a blog, news articles, recipes, or the products you sell.
•
ExpressionEngine contains many options to help you control and filter comments. You can use CAPTCHAs, you can moderate all comments, and you can require membership for comments. You can also set it up so that you get e-mailed when new comments are posted.
•
Feeds are a great option to encourage repeat visitors—they are easy to set up and give people an alternative way to keep up with your website.
•
Preload Text Replacements, Global Variables, Snippets, and Embedded Templates are incredibly useful—it is definitely worth becoming comfortable using them.
•
Conditional {if} statements are also a powerful tool, allowing you to account for different situations in a single template such as redirecting to a 404 Page if there are no entries or displaying category-specific information if the URL segment is a category.
[ 142 ]
Members You have now used ExpressionEngine to build a fully-functional website for Ed & Eg. So far, however, you are the only one who has logged into ExpressionEngine on your website and the only one who has been making any changes. Now is a good time to explore the member functionality of ExpressionEngine. The Freelancer license does not include member management, so this chapter will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing. In this chapter, you will: •
Allow visitors to register on your website and see what they see
•
Create a member group for Ed & Eg, so they can log into the control panel and publish and edit entries (but not edit template code or change administrative options like you can)
•
Use conditional statements to create content that only members can see
First, however, it makes sense to review how membership management works in ExpressionEngine and what all your options are.
Designing your membership ExpressionEngine allows two types of members:
1. Members who can log in to your website, but not into the administrative control panel. These members can see any content that you have coded in your templates as member-only as well as perform any actions that you have set to require membership (such as post comments).
Members
2. Members who can log into your website and also the administrative control panel. Depending on the permissions you give these members, they may be able to complete tasks such as creating or modifying channel content, creating or modifying templates, or changing global settings. If you have an ExpressionEngine-powered website, allowing members is not a requirement. If you do not intend to support members on your website, it is recommended to turn off new member registrations completely (the first option under Members | Preferences in the main menu). Membership in ExpressionEngine is based on member groups, which are what determine the permissions a member has. Each member can only be in a single member group. For members with administrative control panel access, ExpressionEngine offers a huge amount of granularity over what the members can see and do inside the control panel. You can define which channels they can post to (if any), which template groups they can modify (if any), and much more. For members without administrative control panel access, ExpressionEngine offers a member control panel, where members can post a profile, see other members' profiles, as well as send an e-mail or a private message to another member. As with the administrative control panel, you have control over what different member groups can actually do. To make joining your website attractive, you can make some or all of your content member-only by using conditional statements in your templates. You can look to see if a member is logged in and then display different content based on that, or you can display different content to different member groups. In this chapter, you will create a new member group for Ed & Eg that allows them to edit and post channel entries, but that does not allow them to edit templates. Then, to encourage members to join your website, you will update the FAQs channel so that some FAQs are viewable only to members. First, though, you will explore the membership preferences, and then explore the member profile screens as if you were a new member.
Membership preferences
There are many options you can set for your members on a global level that will impact their experience on your site. 1. First, log in to the control panel (http://localhost/admin.php) with your administrator login. [ 144 ]
Chapter 6
Note that you are also assigned to a member group—the Super Admins group. This group gives you access to everything. ExpressionEngine also comes with a Members member group, which does not have administrative control panel access, but can do everything in the member control panel. The permissions of the Members member group can be modified in Members | Member Groups, but the Super Admins group cannot be altered.
2. From the top menu, select Members and then select Preferences. 3. The first section is called General Configuration. Here, you can set whether you want members to be able to register themselves or not and the hoops they have to jump through in order to register. For example, you can require member account activation. If you do not require this, then any new members automatically become assigned to the Default Member Group (which is Members, but can be changed further down). If you require activation (either by an administrator or by requiring the new member to click on a link in their e-mail), then members will be placed into a Pending member group until they are actually activated (by selecting Members | Activate Pending from the main menu). For now, if you are using a localhost environment, say Yes to allow new members and select No activation required (since a localhost environment does not include an e-mail server and so cannot send activation e-mails). If you are following along on an actual website, it is recommended that you require activation of some kind.
4. Further down, you can require new members to accept a terms of service (if you say No, the terms of service will still display) or to complete a CAPTCHA form when they register. You can also allow members to set their own localization preferences (that is, members can set what time zone they are in and then see all times in their local time zone). Ensure that all these are set to Yes.
[ 145 ]
Members
5. Further down, you can set the member group that new members are assigned to (for now, leave this set to Members). You can also change the Default Member Profile Theme. You have two choices: Agile Records or Default. Since the Agile Records theme is designed specifically for the Agile Records website, select Default here. Finally, you can change the Profile Triggering Word, which changes the URL for the member control panel. (For example, if you changed this to guest, then all member control panel URLs would include the word guest instead of member). Leave this set to member for now and click Update. If you do not see any options for the default member profile theme (not even default), then you may be using the Freelancer license, which does not include member management.
6. The Member List Preferences allows you to change the default sort and order of your public member list page (which lists all the members on your site). Do not make any changes right now. 7. The Notification Preferences allows you to receive an e-mail whenever a new member registers at your site. This can be useful if you require an administrator to activate all new member registrations, or if you simply want to monitor new member registrations. If you are using a localhost testing environment, do not make any changes to this screen right now (as the localhost environment does not include an e-mail server, meaning such e-mails cannot be sent). If you are following along on a live website, type in your e-mail address here.
[ 146 ]
Chapter 6
8. ExpressionEngine includes functionality to allow members to contact each other via your website through Private Messages. The Private Messaging Preferences allows you to restrict the number of characters or the size of the attachments that can be attached to private messages. 9. ExpressionEngine includes the ability for members to associate an avatar (image) with themselves, which you can then display next to comments or forum posts that the member makes. The Avatar Preferences allows you to control whether avatars are enabled and whether members can upload their own images. 10. You can also choose whether you want to allow members to upload photos of themselves (which are then displayed on their profile). 11. Finally, you can choose whether or not you want to allow signatures, which appear after every forum post. Signatures are enabled by default, though signature images are turned off. 12. If you have not already done so, click Update to save any changes you have made. Now that you have made these modifications, the next step is to walk through registering as a member and explore the member control panel.
Registering as a new member
The membership functionality in ExpressionEngine is very rich, so rather than having to design your own membership templates from scratch, ExpressionEngine comes with pre-built member templates that you can use for members to login, register, share profiles, change settings, and send e-mails/private messages to other members. When following along in this section, remember that you are a member of your own website. This means that in order to register as a new member, you must first log out of the control panel by clicking Logout at the top right. 1. After logging out of the control panel, visit http://localhost/member/ register. (Remember, if you have the Freelancer license, this URL will not work). 2. You will be presented with a standard Member Registration screen, complete with a generic terms of service. Fill in the form with settings different than the administrator login that you have been using up to this point.
[ 147 ]
Members
Note that, by default, there can only be one username per e-mail address, so you cannot use the same e-mail address for this member as you did for your administrator login. This setting can be changed in Admin | Security and Privacy | Security and Sessions, although it is recommended not to change this setting as it can cause issues if a member with two accounts associated with their e-mail address forgets their password.
3. Select the check box to agree to the terms of service, fill in the CAPTCHA, and click Submit.
[ 148 ]
Chapter 6
4. As long as there were no errors with the information provided, you should be presented with a registration complete message and a link to go back to the main website. You are now registered as a new member!
The member profile
Now that you have walked through registering as a new member, you can see what the member control panel looks like. For this section, you can either be logged in as the member you just created or logged in using your Super Admin username. 1. Go to http://localhost/member/profile. If you are prompted to log in, log in first. 2. You should see a screen with your account statistics: your e-mail address, when you became a member, when you last visited the website, how many channel entries you have posted, and how many comments you have made. Along the top are links to log out or to see the member list. Along the left are links that allow the member to modify and personalize their account.
3. Click Edit Profile on the left-hand side and you can change what other members see about you. Go ahead and fill it in so that when you later visit your profile screen, you can see how it looks. 4. As mentioned earlier, Edit Signature and Edit Avatar are more relevant if you have purchased the forum module. If enabled, members can set their signature and avatar here. ExpressionEngine comes with a default set of avatars that members can select from. [ 149 ]
Members
5. With Edit Photo, you can also associate a member photo that other members can see when they visit your profile (although this option is not enabled by default).
6. Select Email Settings from the left-hand side. This allows members to finetune what notification e-mails they receive. By default, ExpressionEngine allows members to e-mail other members—a member can turn this off here. You can also change your e-mail address on this page. 7. Username and Password allows you to change your username, your screen name, or your password. 8. Edit Preferences allows members to determine whether avatars, signatures, or smiley images are displayed. Members can also prevent Private Messages from being sent to them on this screen.
[ 150 ]
Chapter 6
9. The Localization Settings allow a member to specify their Time Zone, their Time Formatting (US or European), and their Language (if you have multiple language packs installed). By selecting a different time zone, the member can see times in their local time zone. If the times on your website do not appear correct, it may be that either the server timezone or the daylight savings (summer) time setting has been set wrongly. These can be set in Admin | Localization Settings.
10. If a member has posted comments and selected to be notified of follow-up comments, then they are considered subscribed to that channel post. The Subscription Manager shows which posts a member is subscribed to and allows them to unsubscribe if desired. 11. The Ignore List allows members to ignore other members. As a result, any forum posts made by them will not display. 12. The Private Messages section is where members can send private messages to each other and view the ones they have received. 13. Finally, the Notepad is a scratch pad—any text typed into the notepad will be there next time the member logs in. This is most useful for members with administrative control panel access, as the notepad contents also appears on the right-hand side of the administrative control panel. The member control panel is very feature rich, allowing for a lot of functionality and configurability right out of the box. Members can send messages to other members, control what other members can see about them, and personalize settings such as their signature, avatar, or photo to suit their preferences.
The member list
Another option your members have access to is the member list. This can be used for members to browse other members and find their profiles or to send messages. 1. Click on Member List at the top-right of the member control panel or go to http://localhost/member/memberlist. Here, you are provided with a list of all active members. If there are lots of members, you can use filters or searches to find the person you are looking for.
[ 151 ]
Members
2. Click on a specific member and you can see the member profile, including any information the member may have personalized on their profile page.
3. Notice how the member's e-mail address is not publicly displayed. Click on the EMAIL button and you are brought to a form that you must fill in to send an e-mail. It is up to the recipient to decide whether they want to reply (and thereby reveal their e-mail address). With all this functionality, it is easy to build a website that members can use as a springboard to interact with other like-minded people. If you want to customize the member screens so that they share the same look and feel as the rest of your website, the templates can be edited in Design | Themes | Member Profile Templates and the corresponding files can be found in the /themes/profile_themes directory. (Note that it is best to make a backup of the templates before modifying them, in case you need to undo a change). Since each member page is made up of multiple templates, one technique (that you can see in the Agile Records templates) is to put an HTML comment in each template with the template name. In this way, you can view the source of the member pages and more clearly see which templates make up the page.
Linking to the member templates
As you have just seen, all the member functionality is pre-built. All you have to do is link to the pre-existing member URLs on your website and members can start registering and using your website.
[ 152 ]
Chapter 6
Next, you will set up the links in the sidebar on the right-hand side. If the visitor is logged out, there will be links to log in, register, or reset their password. If they are logged in, there will be links to log out, go to the member profile pages, or see the member list. 1. Log in to the control panel as a Super Admin. From the top-menu, select Design | Templates | Snippets. Select the website_sidebar snippet that you created in Chapter 5, Creating a Fully-Equipped Channel. 2. Add the following code to create the links immediately before the last in the snippet. Notice the use of the ExpressionEngine path variable (that you first saw in chapter 5)—this auto-generates a URL to the specific template group and template you specify. In this case, member is not a traditional template group, but rather the keyword you have defined in member preferences. If you do not feel like typing this in, remember that the finished code for each chapter can be downloaded at either http://www.packtpub. com/support or http://www.leonardmurphy.com/book2. Member Links
{if logged_out} - Login
- Forgot Password?
- Register
{/if} {if logged_in} - Profile
[ 153 ]
Members - Member list
- Logout
{/if}
3. Click Update and Finished and now visit the main website home page. Underneath Key Services, you should now see Member Links (depending on whether you are logged in or out will determine which links you see). Try the links to make sure they work.
You have now enabled the ability for visitors to register themselves on your website.
Introduction to member groups
By default, there are five member groups. You are already familiar with the Super Admins member group (which you are a member of). The Members member group is the group that approved members are put into (unless you have changed the default member group in the member preferences). By default, members in this group can do everything available on the member screens (such as sending private messages) as long as you have not disabled the option in the global Member Preferences. However, members cannot log into the control panel. The Pending members group is for members who have registered but have either not activated their membership via e-mail (if you allow self-activation by e-mail) or have not yet been manually approved (if you require members to be approved by an administrator). If you do allow self-activation by e-mail, it is a good idea to review the members of this group periodically and delete stale applicants (do this via Member | Activate Pending). [ 154 ]
Chapter 6
Members in the Banned member group cannot see your ExpressionEngine website, and the Guests member group is used for members who are not logged in. Since Super Admins can do anything and everything in ExpressionEngine and cannot be restricted, you should be very cautious about which members you assign to the Super Admin group. For example, while Ed & Eg need to be able to post and modify channel entries, it would be better not to give them access to templates, where they might accidentally change something. To accomplish this, you can create a new member group for Ed & Eg.
Creating a member group
In this section, you will create a new new member group called Editors for Ed & Eg. This will allow them to be able to log into the main control panel and publish or edit entries but will not allow them to view templates or change administrative preferences. After you create the member group, there will be two sets of options to configure. The first set of options applies to the member profile screens (and controls such things as whether they can send private messages). The second set of options control what the members can do within the control panel. For most members, you would not even allow them access to your control panel, so this second set would not apply. Throughout the configuration process, any options that you would not want to assign to someone you do not know and trust is bolded and colored red. 1. The first step is to create the member group. Log into the control panel as a Super Admin and go to Members | Member Groups. 2. Rather than creating a member group from scratch, you will base the new member group on the Super Admins member group. Underneath the member group listing is the option Create a new group based on an existing one. Select the Super Admins group from the drop-down box and click Submit.
[ 155 ]
Members
3. You will be brought to a new screen where you can give the new group the name Editors. Optionally, you can type in a description.
4. Continuing down the screen, the next option is Security Lock. If you allow groups, other than Super Admins, to administer members, you can control which member groups they can assign users to. As editors and owners of the website, you would want Ed & Eg to be able to approve and manage their members, but you would not want them to be able to assign members to the Super Admin or Editors group (for example). To accomplish this, leave this group Locked (meaning only Super Admins can assign members to the Editors group). To allow Ed & Eg to be able to assign members to the Members group, you would have to edit the Members group and adjust the group security lock to be Unlocked (by default, the Members group is locked, meaning only Super Admins can assign members to it).
5. The next option is Site Access. Since you would want Ed & Eg to have access to the website when it is offline, leave both options as Yes. (If you were creating a member group for members of the public, you would typically set this to No). [ 156 ]
Chapter 6
Within Admin | General Configuration, you can choose whether your system is on or not. You might choose to turn it off if you are doing updates and do not want members of the public to stumble across an incomplete site while the changes are in progress.
6. In the next option, Member Account Privileges, say No to allowing Ed & Eg to be able to delete their own account—if they accidentally did this, it would cause any content they had created to be deleted as well.
7. Comment Posting Privileges, Search Privileges, and Private Messaging Privileges allow you to control whether this member group can use these functions (and allows you to set member group-specific restrictions on their use). Since Ed & Eg own this website, do not make any changes to these screens.
[ 157 ]
Members
8. Control Panel Access is where you can allow (or prevent) the member group from accessing either the entire control panel or specific sections within the control panel. Since you want Ed & Eg to only have access to options they can safely use, say No to the following sections: DESIGN, add-ons (all five sections), ADMIN (all three sections), and say No to TOOLS (Utilities, Data, and Logs only). Leave the TOOLS section and the TOOLS: Communication set to Yes. Ed & Eg will only have access to the options set to yes here.
9. Under Control Panel Administration, say No to all the options except administrating member accounts, changing member groups, and banning users.
[ 158 ]
Chapter 6
10. Control Panel Email Privileges allows you to prevent Ed & Eg from sending e-mails through ExpressionEngine. Since there is no reason to do this, leave all the options as Yes. If you have a website where a large number of people will have control panel access (such as in a larger business), you might want to set this setting to No. 11. The Channel Posting Privileges allows you to decide what Ed & Eg can do with channel content (for example, if they can delete entries or edit other peoples' entries). Since Ed & Eg are the owners of the website, do not make any changes. 12. The Channel Assignment allows you to choose which channels Ed & Eg can publish to and edit. If you have Agile Records installed, you would want to ensure that Ed & Eg cannot see the Agile Record channels. Therefore, only say Yes to FAQs and Website—say No to Information Pages and News if they are there.
13. Comment Administration allows you to configure what comments Ed & Eg can view, moderate, edit, or delete. Leave all these options set to Yes. 14. Template Editing Privileges allows you to control which template groups Ed & Eg can edit. Since you do not want Ed & Eg editing any templates, say No to all of them. 15. Module Access Privileges allows you to control which modules Ed & Eg can access. Since you are not giving Ed & Eg access to the Add-On screens, you can say No to all modules (if there are any listed). 16. Click Submit to create the member group. You will be returned to the Member Groups page, where you will see your new member group in red and bold (because it has access to the control panel). You have now created an Editors member group, and all your changes have been saved. Next, you can log into the control panel as Ed or Eg and see what it looks like.
[ 159 ]
Members
Creating a member
Earlier in this chapter, you saw how to register yourself as a new member. Thankfully, as Super Admins, you can bypass this process and create new members directly in the control panel. In this section, you will create your first editor group member, Ed the Editor. 1. From the top menu, select Members | Register Member. 2. Fill in the username (edward), password, screen name (Ed), and e-mail address for your new member. (Remember that, by default, only one e-mail address can be used per member). Be sure to select the Editors member group as the member group assignment and then click Register a New Member.
3. You will be returned to a list of members in the Editors member group (right now, Ed is your first and only editor). Do not close this listing.
Logging in as Editor Ed
Another advantage of being a Super Admin is that you can log in as any other member without having to know that member's password. This allows you to see your website as they see it—which is helpful when you are developing new features or troubleshooting reported issues. 1. From the View / Search Members screen that you are on, click on the edward hyperlink.
[ 160 ]
Chapter 6
2. You will be taken to the member control panel for this member. From the left-hand side, select Login as Member (the second option from the bottom).
3. You can now choose which page of your website you want to see as Editor Ed. Select the Control Panel radio button and click Submit.
[ 161 ]
Members
4. You will then be logged in as Editor Ed. Although it looks like the control panel you have been working in so far, notice that there are far fewer options, both in the menu and on the main screen. Essentially, all Ed can do is publish new entries, edit existing entries, and administer members. ExpressionEngine has many options that allow you to decide how much access other people have to the control panel—you could set up a member group that can only post entries to a single channel or you could set up a member group that can do everything but post entries to a given channel. You can also set up member groups that do not have control panel access such as a trusted members group, which is exempt from comment moderation or that can search more frequently than regular members. You have now created a member group specifically for Ed & Eg to be able to create content without risk. However, there is one more area that can be customized by the member group: the Publish Page.
Modifying the Publish page layout
By default, the Publish page contains lots of options, spread across several tabs, some of which you will be unlikely to use for a given channel (such as the expiration date for an entry) and some of which you will intend to use, but will be liable to forget about (such as selecting the categories for an entry). Luckily, as a Super Admin, you can customize the Publish page so that the workflow better suits your needs. In the FAQs channel, you know you must select the category for a new entry, so instead of having the categories on a separate tab, you will move it to the bottom of the main tab so that you must scroll past it in order to submit your entry. In this way, you are less likely to forget to fill it in. 1. Log into the control panel as a Super Admin, and go to the Publish screen for the FAQs channel (Content | Publish | FAQs). 2. Towards the top-right (just to the left of the Notepad on the right-hand side), you should see an option that says show toolbar. Click this. (If you are not logged in as a Super Admin, you will not see this).
[ 162 ]
Chapter 6
3. A toolbar will appear with a list of fields, tabs, and authors. First, notice the eye on the right-hand side of each field name. If the eye is open, it means the field is visible. If the eye is closed, it means the field is not visible. (If there is no eye, it means the field is mandatory and cannot be made invisible). Click on the eye to toggle between open and closed. Close the following fields that Ed or Eg will be unlikely to modify on a per-entry basis in the FAQs channel: Expiration Date, Comment Expiration Date, Pings, Channel, and Options.
[ 163 ]
Members
4. The Tabs section allows you to delete tabs or create your own. For example, there are several tabs that have only one or two options on them. Rather than having all these tabs, you could delete all of them, and create a new tab for all your lesser-used options (such as the URL title and entry date, which you may want to alter for an entry, but not every entry). First, click Add a New Tab and call it Rarely-Used Options. Then click Add a Tab.
5. Next, click on the newly created tab and drag fields from the list of fields in the toolbar onto the main window in the position you would like them. Move the following fields: Entry Date, URL Title, Author, Status, and Revisions. If you do not see the revisions tab, you may not have enabled entry versioning while following chapter 5—to do so, go to Admin | Channel Preferences | Channels and then Edit Preferences for the FAQs channel. 6. Since Categories is something you always want Ed or Eg to select when they publish an FAQ (because the content is organized by category), click on the Publish tab and drag the Categories field from the toolbar onto the Publish tab. 7. Next, you can delete all the other tabs that you no longer need. Click on the trash can to the right of each tab name (other than Publish and Rarely-Used Options).
[ 164 ]
Chapter 6
Finally, each field on the main screen also has a little triangle at the bottom right and a little rectangular tab on the left. The triangle allows you to modify the size of the field (for example, so that it does not take up the entire width of the screen) and the rectangle allows you to modify the position of the field in relation to other fields. In this way, for example, you can put two smaller fields beside each other or you can reorder the fields as you see fit. 1. Now you can save your updated layout. At the bottom of the toolbar, check the boxes to apply the layout to both the Super Admins and the Editors member groups and then click Save Layout.
2. Now click hide toolbar to hide the toolbar, and you can see that the Publish page is substantially simplified. Instead of six tabs and lots of options you never use, there are two tabs—the first tab with options that you always want to set for a new entry, and the second tab with options that you rarely need to set, but might want to on occasion. To summarize, there are three ways to configure options on the Publish page: 1. The Member Group options allows you to configure which member groups can publish to which channels (or even whether a given member group with control panel access can publish to any channels). 2. The Custom Field options (reviewed in previous chapters) allows you to configure which options appear for each field—such as the HTML formatting buttons, write-mode, the spell-check, and so forth (and also whether the fields are mandatory or not). 3. The toolbar on the Publish page allows you to configure which options are visible on a per-channel, per-member group basis. This level of flexibility allows you to build a website for someone else to maintain, and to keep the interface uncluttered for that person, so that they only see the options they need to use. [ 165 ]
Members
Creating member-only content
So far you have seen the options available to you in the control panel for different member groups. For members with control panel access, the options are very comprehensive—you can disable entire sections (such as template editing) or disable individual items within a section (such as which template groups can be edited or which fields on the Publish page are visible). For members without control panel access, it is up to you how attractive you make the membership of your site, because any member-only feature has to be specifically coded that way in your templates. There are two ways you can restrict what nonmembers can see: 1. You can configure templates to not be viewable by certain member groups. If a person in an unauthorized member group attempts to access one of these templates, you can redirect them to a different template that says the content is for members only. From the Template Manager, where you would normally click to edit the template, click Access to change who can view the template and what template they should see instead. This can be useful if you are creating a new section to your website and want to allow certain member groups to try it out before going live to everyone.
[ 166 ]
Chapter 6
2. Alternatively, you can use conditional tags within templates to display different content. This allows you much more control and flexibility over what your visitors see—you can display different content depending on whether the member is logged in, depending on the member group of the member or based on any number of variables (for example, the username of the member or how many comments a member has posted). Read more about conditional tags at http://expressionengine.com/user_guide/ templates/globals/conditionals.html. Next, you are going to create a new custom status called Premium. If an FAQ is marked with a premium status, only registered members will be able to see the answer. Non-members will be able to browse all the FAQs, but if they select a premium FAQ, they will only see the question, along with a message encouraging them to register to see the answer.
Making content visible to members only
You have already seen the {if logged_in} and {if logged_out} tags to display different links, depending on whether a member is logged in or not. You will now use these same tags to determine whether or not to show them member-only content. WARNING: If you use conditional statements {if logged_in} and {if logged_out} inside the {exp:channel:entries} tag on a template, do not enable caching on that template or the conditionals will not work. The first person to visit the template will have their logged in state cached, meaning every subsequent visitor will be treated as if they have the same logged in state as that first visitor. Caching can be set for each template on the Template Manager screen by clicking on Edit Preferences for the template in question—by default, template caching is not enabled.
1. Before you can assign any channel entries to a premium status, you must first create the premium status by going to Admin | Channel Administration | Custom Status Groups. You currently only have one status group (statuses), so click Add/Edit Statuses.
[ 167 ]
Members
2. Next, click Create a New Status at the top right. (The Featured status you see in the screenshot will only exist if you installed Agile Records).
3. Call the new status Premium. Leave the Highlight Color blank. This controls the color of the status in the control panel—for example, if you typed red, the status would be in red text. Leave the specific groups who can access the status set to Yes. Click Submit.
The ability to restrict status to members of specific groups allows you to use statuses as a workflow on your website. For example, if you have a member group called authors, you could allow them to publish to a channel, but restrict what status they can assign the new entry so that their work is not open (for example they might only be able to publish to a 'needs review' status). You can then have another member group (such as editors) that do have the right to change the status from 'needs review' to 'open'—thereby ensuring that anything published on your website has been reviewed by a member of the editors group.
[ 168 ]
Chapter 6
4. Now post a new entry to the FAQs channel, and before clicking Submit, ensure that you set the status to Premium (on the Rarely-Used Options tab if you customized your Publish Page layout in the previous section, otherwise on the Options tab).
5. If you now visit http://localhost/faqs you will notice that your new entry does not appear. This is because you must specify in the {exp:channel:entries} tag in each template if you want entries to appear that have a status other than open. Modify the four templates (faqs/index, faqs/browse, faqs/rss, and faqs/atom) and the website_ faqs snippet to include the status="Open|Premium" parameter in the {exp:channel:entries} tag. The | means OR—as in, you want to entries that have either the Open or the Premium status. If you just specified status="Premium", then any entries with a status of open would not display. •
faqs/index: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Premium"}
•
faqs/browse (in HTML ): {exp:channel:entries channel="{my_channel}" disable="categories|category_fields|custom_fields|member_ data|pagination" status="Open|Premium"}{title}{/ exp:channel:entries} - Ed & Eg Financial Advisors title>
•
faqs/browse (after ): {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes" status="Open|Premium"}
•
faqs/rss: {exp:channel:entries channel="faqs" limit="10" dynamic_ start="on" disable="member_data" status="Open|Premium"}
•
faqs/atom: {exp:channel:entries channel="faqs" limit="15" dynamic_ start="on"disable="member_data" status="Open|Premium"} [ 169 ]
Members
•
website_faqs: {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off" status="Open|Premium"}
6. Now, modify the faqs/browse template and replace the line <strong>A: {faqs_answer}
with the following conditional statement. This says to display the answer if either the status is not Premium or if the visitor is logged in. If neither of these conditions are true (that is, the status is Premium and the visitor is not logged in), then do not display the answer. {if status!='Premium' OR logged_in} <strong>A: {faqs_answer}
{if:else} <strong>A: This answer is available to registered members only. If you are already a member, please login. Otherwise, consider registering for free & unlimited access to all our advice.
{/if}
7. Click Update and Finished, and now log out of the control panel (link in the upper-right-hand corner of the screen). 8. Now that you are not logged in, visit your premium content FAQ. Instead of seeing the answer, you should see a message telling you to log-in (as shown below). Verify that you can log in and see the answer.
[ 170 ]
Chapter 6
You have now given Ed & Eg the ability to make content Premium, encouraging visitors to register on the website. Although this is a simple example, ExpressionEngine's conditional statements are very flexible and very powerful. For example, you could show a promotion (5 percent off!) on your homepage, but only to registered members, or even only to registered members who have commented a set number of times. You could also show different content to different member groups. Each member group has a Group ID number, viewable under Members | Member Groups. Using this Group ID, you can use a condition such as {if member_group='6'} (where 6 is the Group ID of the Editors member group) and then create a draft status and allow Editors to see entries with a draft status, but keep them invisible to all other members and non-members. The choices are limitless.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. Try creating a new member group called Designers that can only be used to modify templates. Members of this group should not be able to post or modify any channel entries. 2. When a member registers for the first time, you have the option to collect additional information (beyond the username, name, and e-mail address) in Custom Member Fields. For example, if you have a motorcycle website, you could have a custom field to ask new members what make/model of motorcycle they have. Alternatively, if you give a free t-shirt to new members, you could ask for their t-shirt size. For this exercise, create a custom member field that asks "Are you an existing customer of Ed & Eg?" with possible answers being Yes or No. 3. On the right-hand side of your website is a box with a title of Promotion! that links to a Promotions page. Ed & Eg have decided that they want promotions to be visible only to registered members of the website. Modify the promotions/index template to display the promotion if a visitor is logged in, but otherwise display a message asking the visitor to register. (The promotions/index template is created as part of the challenges in Chapter 4, Moving a Website to ExpressionEngine).
[ 171 ]
Members
Summary
In this chapter, you learned all about member functionality in ExpressionEngine, including the built-in member control panel. You also looked at setting up new member groups and customizing the administrative control panel for different member groups (that have control panel access). Finally, you looked at how to use conditional statements in your templates in order to make membership attractive to visitors. The key points to remember after working through this chapter are as follows: •
You can control what all members can or cannot do in the Member | Preferences screens. You can also make exceptions on a member group basis in Members | Member Groups. So, for example, you can require that all comments are moderated, but make an exception for members in a specific group.
•
Be cautious about who you assign to the Super Admins member group. If someone needs control panel access, but does not need access to everything in the control panel, it is a better practice to set up a new member group with only the permissions that the member group needs.
•
If you are building a website for a client, remember that you can modify the Publish page to make it more intuitive. You can hide fields that are not relevant and at the same time make other fields more prominent.
•
How attractive membership is on your site is up to you. Using conditional statements, you can control what content members can see, displaying different content for different member groups or based on different conditions.
•
If you have a template that uses the conditional statements {if logged_in} or {if logged_out} inside the {exp:channel:entries} tag to display different content to different members, do not enable caching for that template.
[ 172 ]
Creating a Calendar Many organizations have events, and a calendar is a very visual way of indicating what is going on and when. The built-in ExpressionEngine calendar functionality is limited (for example, it does not allow recurring appointments). However, you can use it to display event titles with clickable links for more information. If a calendar is a key part of your website, you may be interested in checking out Solspace's calendar module (at the time of publication, it is not yet available for ExpressionEngine 2). http://www. solspace.com/software/detail/calendar/. The module contains support for more sophisticated calendar functionality such as recurring appointments.
In this chapter, you are going to use the built-in functionality of ExpressionEngine to build a simple events calendar that is easy to post to using the Publish page in the control panel. You will use the jQuery module to display more information when an event is clicked. Finally, you will also be introduced to the concept of Related Entries (relating the post from one channel to a post in another channel)—a useful tool to reduce repetition in channel entries.
Designing the calendar
Ed & Eg frequently host free seminars for customers and members of the community in their conference room. These seminars are usually sponsored by another organization. Ed & Eg would like a calendar on their website that shows each seminar on the date that it is to take place, along with a link so that visitors can read more about the topic of a given seminar as well as who the sponsor company is.
Creating a Calendar
One way you can design such a calendar is to create an events channel, which contains all the information regarding both the event and the event sponsor. This would work, but because a single event sponsor is often associated with more than one seminar, this design would result in you having to include the same information about the same sponsors in more than one channel entry. For example, if Anytown Bank sponsors five seminars, there would be five entries where you would have to provide information about Anytown Bank. Related Entries is a way to reduce repetition in channel entries. (Not to be confused with relating entries by category—which you did when you built the FAQs channel). Essentially, if you have two kinds of data (events and event sponsors), you can create two channels and then include the data from one channel in the other. In this way, you can have an event_sponsors channel, which contains all the pertinent information on the event sponsors (such as their name, location, opening hours, and services offered). The event channel itself will then only contain information about the event (such as the date, time, and topic). When Ed or Eg creates a new event, they can simply select the sponsor (such as Anytown Bank) from a drop-down list of sponsors in the event_sponsors channel, and all the information about the event sponsor will automatically populate for them—no retyping necessary.
Setting up your channels
To set up an event and an event sponsors channel, you will first create the custom fields, then create the channels, then populate the channels with example data, before finally creating the templates that you will use to display the channel data. When creating two channels that are to be related, it's best to start with the channel whose data will be included in the other channel—therefore, start with the event sponsors channel.
Creating custom fields for event sponsors 1. Select Admin | Channel Administration | Custom Fields.
2. Select Create a New Channel Field Group and call the field group event_ sponsors. Click Submit. 3. Now select Add/Edit Custom Fields for the event_sponsors field group. 4. For now, keep things simple and create only one field—a generic about field. (You could, of course, create as many fields as you want). Select Create a New Custom Field. [ 174 ]
Chapter 7
5. The field type will be Textarea. The field label will be About and the field name will be event_sponsors_about. The field will be required, will not be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. The event_sponsors field group is now ready to go. The next step is to create the event_sponsors channel.
Creating the event sponsors channel
By now, you should be familiar with the process of creating a channel. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Event Sponsors with a short name of event_sponsors. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and event_sponsors for the field group (the category group can be left as none, as you will not be using categories with this channel). Remember, if you do not select a Status Group when creating a new channel, then only Super Admins can post open entries. If any other member group posts an entry, it will be closed by default (and therefore not visible on your website).
3. Finally, select No to creating new templates and then click Submit. 4. Now, go to the Content | Publish | Event Sponsors and create a couple of example sponsors (for example, Anytown Houses, Anytown Bank, and Anytown Law Firm).
[ 175 ]
Creating a Calendar
Now that you have your sponsors channel set up with some sponsors, you can go ahead and create the events channel.
Creating the events custom fields
As before, you will first create your channel custom fields, before creating the channel, and then some example content. 1. Select Admin | Channel Administration | Custom Fields. 2. Select Create a New Channel Field Group and call the new field group events. Click Submit. 3. Now select Add/Edit Custom Fields for the events field group. 4. You will create two fields for your events—Description and Sponsor. Select Create a New Custom Field. Note that you will not create a custom field for the date or the time of the event. This is because you can change the date/time of the entry to reflect the date/time of the event.
5. The field type will be Textarea, the field label will be Description, and the field name will be events_description. The field will be required, will be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. 6. Next you can create the relationship field. Click Create a New Custom Field. 7. From the drop-down of Field Types, select Relationship. The Field Label will be Sponsor, and the Field Name will be events_sponsor.
8. The field will not be required (some events might not be sponsored) and the field will not be searchable. Say Yes to show the field by default. [ 176 ]
Chapter 7
9. In the Custom Field Options, select the Event Sponsors channel and leave the display criteria at the default setting (Sort by Title in Descending Order). Click Submit.
Now all you have to do before you can start creating events is create the events channel.
Creating the events channel
Creating the events channel is a fairly straightforward process. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Events with a channel name of events. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and events for the field group (the category group can be left as none, as you will not be using categories with this channel). 3. Finally, select No to creating new templates and then click Submit. 4. Your channel is created! Now, you can bring together your Events and Event Sponsors by creating some events.
Creating example events
The final step in setting up these channels is to post some example events, so that when you create the calendar on your website, you have some events to see how it is working. Your first event is going to be a seminar called Common Pitfalls of Home Buying, sponsored by Anytown Houses. 1. Select Content, Publish, and select the Events channel. 2. Type in the title, Common Pitfalls of Home Buying. In the description field, type in some example topics that will be covered.
[ 177 ]
Creating a Calendar
3. Select Anytown Houses as the sponsor. That is all you need to do to associate the sponsor with the event.
4. Before clicking submit, select the Date tab at the top of the screen and select a date for your entry and a time of 6 p.m.
[ 178 ]
Chapter 7
5. Click Submit. 6. Go ahead and create a few more events with different sponsors, dates, and times, so that when you create the calendar, you have a few entries to play with. Now that you have the channels built and have some example events too, you can go ahead and create the calendar!
Creating the calendar
For the rest of this chapter, it will be useful to refer to the official ExpressionEngine documentation on the calendar tag at http://www.expressionengine.com/user_ guide/modules/channel/calendar.html, where much of the code in this section is adapted from. The first steps in creating a calendar are to create a calendar template group, add the basic HTML to construct the page, build the outline of the calendar, and add CSS to make the calendar look good.
Creating a blank calendar template
1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group calendar. Do not duplicate a group and do not make the index template in this group your home page. Click Submit. 2. Copy and paste the code from the includes/404 template (or any template that has all the normal page components such as the header, sidebar, widebar, and footer). Paste the code into the new calendar/index template. At the top of the template, add a my_channel preload replace as follows: {preload_replace:my_channel="events"}
3. Change the page title from Page Not Found to Calendar. Calendar - Ed & Eg Financial Advisors
4. Change the h1 title to Seminar Calendar and delete the paragraph underneath that says the page does not exist (including the and
tags). The content section should look as follows: Seminar Calendar
[ 179 ]
Creating a Calendar
Now you have a blank Ed & Eg themed template (viewable at http://localhost/ calendar) that you can use for your calendar.
Creating the calendar
The next step is to create a blank calendar—it will not display any events just yet. This code is adapted from the ExpressionEngine documentation. 1. In the calendar/index template, add the following code after the Seminar Calendar
line. The first piece of code is the exp:channel:calendar tag. This is a pair of tags with a number of parameters. {exp:channel:calendar switch="calendarToday|calendarCell" channel="{my_channel}" show_future_entries="yes"} {/exp:channel:calendar}
The channel parameter specifies that the entries on the calendar are coming from {my_channel}, where {my_channel} is a Preload Text Replacement corresponding to the events channel. The parameter show_future_entries="yes" means that the calendar will show future entries. In most channel applications, if you set an entry date in the future, ExpressionEngine does not make that entry visible until that date. This is useful if (say), you are going away but want to schedule new content to appear at a certain time while you are gone. In this case, if a calendar only showed entries that have already happened, it would not be a very useful calendar. The switch parameter is used to switch between two different stylesheet styles (you will create the calendar stylesheet next). If the day being displayed is not today, then the stylesheet's style will be calendarCell. If the day being displayed is today, then the stylesheet's style will be calendarToday. This allows today's date to be styled differently.
2. The next step is to start displaying the calendar itself. A calendar is a table with seven columns (one for each day of the week) so you will use the HTML table tag to display it. In the following code, you define the first row. In the top left cell, you will display << that can be clicked to move to the previous month. Likewise, in the top-right cell, you will display >> to navigate to the next month. The middle five cells will contain the name of the current month being displayed. The style calendarBG will be defined in the stylesheet that you will create in the next section. Add the following code after the {exp:channel:calendar} tag and before the closing {/ exp:channel:calendar} tag. [ 180 ]
Chapter 7 << {date format="%F %Y"} >>
The previous and next path links both point to the current template (calendar/index). < is HTML for the < symbol and > is HTML for the > symbol. The format code to display the current month and year, %F %Y, is taken from ExpressionEngine's date formatting code, available at http:// expressionengine.com/user_guide/templates/date_ variable_formatting.html
3. Go to http://localhost/calendar and you can see the calendar beginning to take shape. Click on the arrows and you can see that the name of the month changes, as does the URL of the page. 4. The next row will display the weekdays. The code {lang:weekday_abrev} refers to the one letter weekdays. You could also use weekday_long or weekday_short to either spell out the entire weekday or the first few letters of the weekday respectively. This must be wrapped in a {calendar_ heading} variable pair. Insert the following code after the closing tag and before the closing tag. {calendar_heading} {lang:weekday_abrev} {/calendar_heading}
[ 181 ]
Creating a Calendar
5. The next row will display the actual dates. There is no way to know how many rows might be needed for a given month (February might only require four rows; October might require six). ExpressionEngine dynamically determines how many rows to display using the {calendar_rows} variable pair, which repeats for as many rows as are necessary. Each row starts with the command and ends with the closing command. For each calendar cell, there are three possibilities—there may be events for that date; there may not be events for that date; or it may be an empty cell before the first day of the month or after the last day of the month. You want to handle each of these situations differently, so you will use conditional statements to distinguish between these three possibilities, although, right now, you will simply be displaying the date in each. Notice that, for your empty cells, you use a different class so that you can style it differently in your stylesheet. Insert this code after the closing tag and before the closing tag. {calendar_rows} {row_start}{/row_start} {if entries} {day_number} {/if} {if not_entries} {day_number} {/if} {if blank} {day_number} {/if} {row_end} {/row_end} {/calendar_rows}
You now have the beginnings of a calendar, although it looks a little basic.
[ 182 ]
Chapter 7
Before you start displaying your events on this calendar, first create some CSS to make the calendar look a little more calendar-like.
Formatting the calendar with CSS
Rather than adding the calendar styles to your main site/site_css stylesheet, it makes sense to create a separate stylesheet just for the calendar styles. This is because the calendar styles are only needed on the calendar page and do not need to be included on any other page.
Creating the calendar CSS template
First, you will create the template for the calendar CSS. Then you will point the calendar/index template to this new template. 1. From Design | Templates | Template Manager, click the calendar template group and select New Template. Call the new template calendar_css and choose a Template Type of CSS. Click Create and Edit.
2. The first line in your new template will import the main site/site_css template (so that the page outside the calendar continues to be formatted correctly). After typing this, click Update and Finished. @import url({site_url}includes/site_css);
[ 183 ]
Creating a Calendar
The {site_url} variable, which you have seen before, is converted to the actual URL to the root directory of your site, as stored in Admin | General Configuration. Note that the URL in this setting should have a trailing / (for example, http://localhost/ as opposed to http:// localhost) or the link above will not work (for example, it will resolve to http://localhostincludes/site_css instead of htttp:// localhost/includes/site_css).
3. The next step is to point the existing calendar/index template to use this new CSS template in place of site/site_css. To do this, edit the calendar/ index template and modify the stylesheet line to read as follows:
Now you can add some styles to your CSS.
Adding styles to your calendar CSS
In the calendar/index code so far, you have defined several styles: • • • • • •
calendarBG is used to format the overall table calendarHeader is used to format the month heading calendarDayHeading is used to format the weekday headings calendarCell is used for the calendar cells, except for today's date calendarToday is used for the calendar cell that represents today's date calendarBlank is used for calendar cells that are not for the dates this month
Helpfully, EllisLab provides a suggested stylesheet in the ExpressionEngine documentation (http://expressionengine.com/user_guide/modules/channel/ calendar_css.txt), which you can start with and then adapt to your own needs. 1. Open the template calendar/calendar_css for editing. Copy and paste the example code from the URL above into the CSS stylesheet (below the @ import line) and click Update.
[ 184 ]
Chapter 7
2. Next, modify the three cell styles (calendarCell, calendarToday, and calendarBlank) to position the date in the top-left of the cell (so that there is room for your event text). To do this, modify the following two styles for .calendarCell and .calendarToday and add them to .calendarBlank: text-align: left; vertical-align: top;
3. Now modify the same three cell styles to have a fixed width. Otherwise, as events are added to your calendar, some columns will expand and other columns will shrink. Add the following styles to .calendarCell, .calendarToday, and .calendarBlank: width: 60px; height: 60px;
4. Finally, you can create some styles for displaying your events. You want to keep the font clear to read but small. The following code will give each event a border, so that if there are two events on the same day, the text will not run together. Since all the events will be links (for more information), this code will also change the background color of the event when the mouse moves over it to make it clear that it is clickable. Add the following to the end of the calendar_css stylesheet: .calendarEvent a{ font-family: Arial, Trebuchet MS, Tahoma, Verdana, Sansserif; [ 185 ]
Creating a Calendar font-size: 10px; font-weight: normal; letter-spacing: 0em; text-decoration: none; border: 1px solid #666; vertical-align: top; text-align: left; margin: 5px; padding: 5px; display: block; } .calendarEvent a:hover{ background-color: #ccc; }
You now have a pretty, but blank, calendar. You can, of course, go further and change the styles so that it suits your site. It is all easily configurable within the CSS. The next step is to start displaying events on your calendar. Since space on the calendar is limited, you will only display the title of the event on the calendar itself, with a clickable link for more information. (In fact, only the title field from the channel is available in the {exp:channel:calendar} tag—none of the custom field tags will work). The basic way to build the clickable link is to simply create a new, single-entry page template that you link to (just as you did with the FAQs channel). However, to keep things interesting, a new approach is called for. You will still create a single-entry page template, but rather than just linking to it directly, you will use the jQuery module combined with the FancyBox plug-in (http://fancybox.net/) to display the single-entry page in an iFrame lightbox that floats over the calendar. To accomplish this, you must first download the FancyBox tool and upload the files to your website. (FancyBox is also used in the next chapter on photo galleries). If you are removing the index.php from your URLs, then you will likely have to modify your .htaccess file so that you can access the FancyBox files. You can then create your single-entry template (and a corresponding, simplified CSS file). Finally, using the jQuery module and FancyBox, you can create a link to your single-entry template from your calendar.
[ 186 ]
Chapter 7
Note that although this chapter is using a third party jQuery plugin, the focus of this book is on using ExpressionEngine—not on learning jQuery (or FancyBox). For more information about jQuery, please visit http://jquery.com/.
Setting up FancyBox
You can download the latest version of FancyBox directly from http://fancybox. net/, or a copy of the latest version is included in the code for this chapter at either http://packtpub.com/support or http://www.leonardmurphy.com/book2/ chapter7. 1. First, download FancyBox and extract all the files from the compressed directory into a directory on your computer. 2. Once extracted, you should see a directory called fancybox, complete with a number of images, JavaScript files (.js), and a CSS file. Upload this entire directory to the root of your website. Note that for the purposes of this chapter, you do not need any of the example files that ship with FancyBox. 3. Next, if you are removing the index.php from your ExpressionEngine URLs using the exclude method, you will have to add this new directory to your .htaccess file (otherwise it will be treated as an ExpressionEngine template group, rendering it inaccessible). Open .htaccess and add FancyBox to the end of the list of real directories and files as follows (but do not create a second RewriteCond line—modify the line you already have). RewriteCond $1 !^(images|system|themes|index\.php|admin\.php|fancybox) [NC]
For an example of a complete .htaccess file using the exclude method, please see either http://packtpub.com/support or http://www. leonardmurphy.com/book2/chapter2. Your .htaccess file may include other files or directories that you have in the root directory of your website (such as robots.txt or favicon.ico) that you should leave in place. 4. To verify that your .htaccess file is not blocking access to the fancy box directory, open http://localhost/fancybox in your browser. If you see your ExpressionEngine 404 page, then your .htaccess file is treating the fancybox portion of your URL as an ExpressionEngine template group. Review your .htaccess file.
[ 187 ]
Creating a Calendar
Troubleshooting problems that are due to the .htaccess file can be challenging. Many times you set up a .htaccess file when you install ExpressionEngine and then forget that it exists, so you do not even think of the .htaccess file. Remember that EllisLab does not provide support for removing the index.php using a .htaccess file (because there are so many ways to do it and every server works a little bit differently). If you suspect your .htaccess file is causing problems, you can temporarily remove it and add the index.php back into your website URLs (in Admin | Configuration, under Name of your site's index page). If you do this, it will at least confirm whether the issue you are seeing is due to your .htaccess file or something else entirely.
5. Finally, if you are using Internet Explorer, you may want to modify fancybox/jquery.fancybox-1.3.1.css to include a / at the start of the AlphaImageLoader sources. (This tells Internet Explorer that FancyBox is a directory at the root of your website and therefore enables it to find the images it needs). The easiest way to do this is to do a find and replace and replace AlphaImageLoader(src='fancybox/ with AlphaImageLoader(src='/fancybox/
FancyBox is now in place and ready to go. Next, you will create your single-entry template, along with a pared-down CSS file.
Creating your single-entry template
First, you will create a pared down CSS file, before creating your single-entry template. Both will be much smaller versions of your regular templates/CSS (since you would not view this template on its own, but rather as an overlay on an existing page, you do not need the usual Ed & Eg header, sidebar, or footer. As a result, the template and the CSS are smaller). 1. Create a new template in the calendar template group called event_css. The template type will be CSS. Duplicate an existing template, namely, includes/site_css. Click Create and Edit. 2. Delete the input, textarea style. Further down, delete everything that appears after the /* Wrapper */ comment (including /* Wrapper */ itself). 3. Now update the body style to read as follows (essentially removing the background and adding in a four percent padding so that the text in the popup overlay will not touch the sides of the pop-up overlay box): body { font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; [ 188 ]
Chapter 7 font-size: 12px; color: #6B6B6B; padding: 4%; }
4. Finally, remove the h2 from the h1,h2 style (not the h1, h2, h3, h4 style) and instead, add it to the h3 style. The styles should end up looking as follows: h1 { font-size: 28px; } h2, h3 { font-size: 16px; font-weight: bold; }
5. Click Update and Finished to save this CSS template. 6. Next, you will create your event template. In the calendar template group, click New Template and name the template event. The template type will be Web Page. Select to duplicate the calendar/index template and click Create and Edit. This template will be visible at http://localhost/calendar/ event. 7. Delete everything between the and tags. Also, change the to be Calendar Event as follows: Calendar Event - Ed & Eg Financial Advisors
8. Next, change the stylesheet so that instead of pointing to calendar_css, it is pointing to the CSS stylesheet you just created (event_css).
9. Next, after the tag, add the following code to display the event information. {exp:channel:entries channel="{my_channel}" show_future_entries="yes" limit="1" require_entry="yes"} {if no_results} {redirect="404"} {/if} {title}
<strong>Join us on {entry_date format="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{events_description}
{/exp:channel:entries} [ 189 ]
Creating a Calendar
Notice that the show_future_entries parameter has to be included here, since this template is going to be displaying event entries that have an entry date after today's date. Also note the use of require_ entry and if no_results to ensure that only valid events can be displayed—all others will be redirected to your 404 page.
10. Next, you will display the sponsor information from the event_sponsors channel. Since you are displaying the content of the event_sponsors channel inside the events channel, ExpressionEngine needs a way to know which channel it is supposed to be displaying the data from (fields such as {title} could refer to either channel). To accomplish this, you wrap all your event_sponsors information in the tag {related_entries} using an ID that corresponds to the relationship field in the events channel (in this case, the events_sponsor custom field). You can then use the custom field names from the event_sponsors channel. The ID is a way for ExpressionEngine to support more than one relationship field in the same channel. Insert the following code after the {events_description}
line: {if events_sponsor} {related_entries id="events_sponsor"} More About {title}
{event_sponsors_about}
{/related_entries} {/if}
You have now completed this separate, pared-down single-entry template to show more information on your calendar entries. Although the plan is to only display this template in a pop-up overlay on your calendar page, you can see what the template looks like by itself by going to a URL like http://localhost/calendar/event/
common_pitfalls_of_home_buying.
[ 190 ]
Chapter 7
Notice how the information from the Event Sponsors channel is populated into the event information. Although you only have a few events right now, so the effort of creating two channels might not seem to outweigh the benefits, if you had tens or hundreds of events, all of which shared the same handful of sponsors, being able to simply select the sponsor information from the drop-down menu represents a significant time-savings over having to type in information about the sponsor in every event. The next step is to display these entries on your calendar.
Displaying events on your calendar
To display the event on your calendar, you will use an ordinary hyperlink to your single-entry template with a special class (pop-up). The pop-up class will correspond to JavaScript in your HTML header that will call upon the FancyBox jQuery plugin to display the single-entry template in an overlay dialog box. First, you need to enable the jQuery module in your template. 1. First, verify that the jQuery module is enabled. It is enabled by default if you have installed Agile Records. Select Add-Ons | Modules from the main menu and verify that jQuery is marked as installed. If not, click Install in the Status column to install it. 2. Edit the template calendar/index.
[ 191 ]
Creating a Calendar
3. The first change you are going to make is to activate the jQuery module. In the section of the template, add the following tag: {exp:jquery:script_tag}
When saving your template, if you see a warning that no closing tag was found, do not worry. The jQuery tag is a tag that does not require a closing tag.
4. Next, you are going to include the FancyBox jQuery files that are in the fancybox directory that you uploaded to the root of your website. You will link to the main FancyBox JavaScript files, plus the CSS file. Type this code in directly underneath the above tag. <script type="text/javascript" src="{site_url}fancybox/jquery.fancybox-1.3.1.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.mousewheel-3.0.2.pack.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.easing-1.3.pack.js">
Note that if you downloaded the newest version of FancyBox, then the filenames and the version numbers in each of the filenames are subject to change.
5. Now you are going to include the FancyBox code for the pop-up class. This tells FancyBox how you want the lightbox to work. You want the box to be 75 percent of the width and height of the page, with no margin or padding. OverlayOpacity means that you want the calendar page underneath to still be visible, but dimmed. The hideOnContentClick means that if you click anywhere off the lightbox, the lightbox will close. The iframe type means that the lightbox will display the contents of another URL (in this case, your single-entry template URL). For more information on all the FancyBox parameters, please visit http://www.fancybox.net/api. Type this code in directly underneath the above tags (still in the section). <script type="text/javascript"> $(document).ready(function() { $(".popup").fancybox({ 'width': '75%', 'height': '75%', [ 192 ]
Chapter 7 'titlePosition': 'outside', 'autoScale': true, 'margin': 0, 'padding': 0, 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none', 'type': 'iframe' }); });
6. Finally, add your link with the class of popup (that corresponds to the .popup used in the above JavaScript so that FancyBox knows that you want to use FancyBox, and not actually open the link like you normally would). Add the following code after {if entries}, deleting the existing {day_number} line. {day_number} {entries} {/entries}
7. As one date can contain multiple events, this variable pair {entries} applies to each entry. Since this hyperlink applies to each entry, you include it within the {entries} variable pair.
[ 193 ]
Creating a Calendar
8. Go to your calendar and navigate to a month that has events to verify that you can see the hyperlinks.
9. Finally, click on one of the events to verify that your single-entry template appears with the correct information in a FancyBox overlay. If your event does not appear in a pop-up window, but rather opens in a separate window or tab, there are a number of things you can check. First, verify that the fancybox directory is at the root of your website and that you can access the files in your browser (if not, check your .htaccess file). Next, verify that the paths in the calendar/ index template point to the script/CSS files in the fancybox directory and check the filenames for misspellings.
[ 194 ]
Chapter 7
Your calendar is now complete. As you can see, the calendar functionality in ExpressionEngine is limited in what it can do and is certainly not as flexible as specialized calendar applications. However, for simpler designs, it is quite functional.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. [ 195 ]
Creating a Calendar
1. Currently, your calendar displays the days of the week using single letters (for example, M, T, W). Modify this so that the first three letters of each weekday are displayed (for example, Mon, Tue, Wed). 2. Underneath your calendar, display the next event that is coming up (no matter what month is being displayed on the calendar).
Summary
In this chapter, you took a look at the calendar functionality in ExpressionEngine. You also got to see a working example of related entries and how it can help you reduce repetition in your channels. The calendar functionality can be daunting for beginners, as there is a lot of code involved. However, once mastered, the calendar is very flexible in terms of what you can display on it, how it is displayed, and how it all works together. The key points to remember after working through this chapter: •
The calendar functionality uses all the usual channel features that you know and love—custom fields, categories, status groups, and the Publish page. You can create channels with as many custom fields as you want, although you can only display the title field on the calendar itself.
•
Related Entries is when the contents of one channel are included in another channel. Although the events calendar was a natural choice, it could be used for any kind of channel. For example, if you have a recipes channel, you may have a second channel for common sub-recipes (such as making a pie-crust). In this way, you can have 14 different recipes that call for a pie-crust and you do not need to type out the instructions to make the pie-crust 14 times. Reducing repetition by using related entries also makes your website easier to maintain and update (for example, if you wanted to adjust your standard pie recipe, you only have to do it in one spot instead of in 14 places).
•
Related Categories has nothing to do with Related Entries. Related Categories is when two entries in a channel share a category and can therefore be considered to be related.
[ 196 ]
Chapter 7
•
The jQuery module allows you to use jQuery on your website without having to download it yourself (it comes included with ExpressionEngine). ExpressionEngine also masks where the jQuery file is, so it does not reveal the location of your system directory. Teaching jQuery is beyond the scope of this book, but when used thoughtfully, it can enhance the usability of a website.
In the next chapter, you will be building a photo gallery in ExpressionEngine.
[ 197 ]
Creating a Photo Gallery Although ExpressionEngine 2 does not come with a built-in photo gallery module, it does have many features designed to make working with photos easier. In this chapter, you will create a photo gallery channel, use file manager to manage your photos, and use jQuery to display the photos on your website. This chapter uses the FancyBox jQuery plugin that you set up in the previous chapter. If you did not follow the previous chapter, please follow the instructions in Chapter 7, Creating a Calendar under Setting up FancyBox
Although this chapter focuses on building a tool for Ed & Eg to share their personal photos, the techniques in this chapter will be useful in any situation where you want to display images—whether personal photos, a portfolio of your work or items for sale.
Designing your photo gallery
There are many different ways you can approach creating a photo gallery in ExpressionEngine. At the most basic level, you have a choice between each channel entry containing only one photo (and a description) or each channel entry containing a set of photos. If you allow only one photo per entry, you can use categories to organize the photos into galleries (and you can even include the same photo in more than one gallery). If you allow multiple photos per channel entry, each entry represents a photo gallery by itself. One way to accommodate multiple photos per entry is to create as many custom fields as the photos you think you will have in a gallery. For example, if you know each gallery will have a maximum of 20 photos, then you could create 20 custom fields for the photos and 20 custom fields for the descriptions. This solution works, but is not the most flexible (that is, to add 21 photos to a gallery, you would have to modify your custom fields and your templates).
Creating a Photo Gallery
An alternative approach to accommodate multiple photos per entry without creating an abundance of custom fields is to use a third party add-on such as Matrix by Pixel & Tonic (http://pixelandtonic. com/matrix). This add-on allows for tabular data in channel entries— you define the column headings (such as the photo and the description) and then add a row in the table for each photo. In each channel entry, you can create as many rows as you need. For example, you can create one entry with 12 photos and another entry with 25 photos.
Rather than creating lots of custom fields, or using a third party add-on, this chapter will show you a simple and elegant way to create a photo gallery using the one photo per entry design and then will use categories to organize the photos into galleries. Before you create your photo gallery channel, you first need to define where your photos will be stored.
File manager
The file manager is where you can upload new photos or crop, resize, rotate, or delete the images you have already uploaded; all from within the ExpressionEngine control panel. For this photo gallery, you will create a new upload destination—this is the directory on your server where ExpressionEngine will store your photos. 1. The first step in creating a new upload destination is to create the new directory on your server. Create a new directory called photos in /images. If you are following along on an actual web server, ensure that the new directory has 777 permissions (usually right-clicking on the directory in your FTP client will allow you to set permissions). If, instead of creating a new sub-directory inside the /images directory, you prefer to create a new top-level directory and you are using the .htaccess exclude method to remove the index.php from ExpressionEngine URLs, then be sure to add the new directory to your .htaccess file.
2. Next, you need to tell ExpressionEngine where this directory is. Inside the control panel, select Content and then File Manager.
[ 200 ]
Chapter 8
3. On the left-hand side of the screen, you will see the directory or directories where you can currently upload files to (if any), along with the files currently in each directory. In the toolbar on the right-hand side, underneath File Tools, select Create New Upload Destination.
4. Enter a descriptive name of Photo Gallery. The Server Path and URL may be pre-filled, however, you should make sure they point to the actual directory you just created (/images/photos). If you are following along in a localhost environment, the URL would be http://localhost/images/ photos. Leave Allowed File Types as Images only.
[ 201 ]
Creating a Photo Gallery
5. All the fields that begin with maximum can be left blank. These fields allow you to restrict the size, height, and width of photos. If you do enter values in here, and then later try to upload a file that exceeds these limits, you will see an error message such as The file you are attempting to upload is larger than the permitted size. 6. Set the Image Properties, Image Pre Formatting, and Image Post Formatting to be blank. These fields allow you to enter code that appears inside, before, and after the img tag. However, you can format your img tag as needed inside your template.
7. The File Properties, File Pre, and Post Formatting can be ignored for now as they only apply to non-image files that you upload (and you have specified that you are only allowing images in your photo gallery). 8. If desired, you can allow certain member groups to upload files. The member groups you see listed (if any) will depend on the member groups you have. Set all the member groups to Yes except for Members, which should be set No.
[ 202 ]
Chapter 8
9. Click Submit and your new upload destination will be ready to go. Go back to the file manager and you can see the new photo gallery upload destination with no files.
Creating your photo gallery channel
Now that you have created a place to store your photos, you can create your photo gallery channel. As with every other channel you have created in this book, you will follow the same basic steps—creating custom fields and categories, creating your channel, publishing some entries, and then building your templates.
Creating your custom fields
Since you are going to have one photo per channel entry, you have a lot of flexibility to create as many custom fields for each photo as you see fit—for example, you could have fields to capture the location of the photograph, the subject of the photo, the type of camera that was used, the name of the photographer, and so forth. However, to keep things simple, you will only create two custom fields right now—one for the photo itself and one for the description. 1. From the main menu of the control panel, select Admin, Channel Administration, and then Custom Fields. 2. Select Create a New Channel Field Group and call the new group photos. Click Submit. 3. Next to the new group, select Add/Edit Custom Fields and then select Create a New Custom Field.
[ 203 ]
Creating a Photo Gallery
4. The field type will be File. The field label will be Photo and the field name will be photos_photo (the first part representing the field group name). In the instructions for the field, indicate that photos in the photo gallery should be no more than 600x800 pixels (so that they fit on a typical computer screen without scrolling). You could also prevent photos that are bigger than 600x800 pixels from being uploaded by specifying the maximum width and height in the File Upload Preferences for the photo gallery upload destination. You have not done this here because it would prevent you from being able to upload a larger photo and then re-size it using file manager.
5. The field should be required, but not searchable, and should be shown by default. The field display order should be 1 and the file type should be Image. Click Submit. 6. Click Create a New Custom Field again. This time, the field type should be Textarea, the field label Caption, and the field name photos_caption. The field instructions can be left blank. Answer Yes to it being a required field, being searchable and being shown by default. The Field Display Order should be 2. 7. The number of rows can be left as 6 and the default text formatting should be set to Auto
(this will prevent unwanted whitespace in your captions due to extra paragraph tags being added, but will also allow multi-line captions). Say No to allowing an override on the Publish page. The text direction can be left as left-to-right. [ 204 ]
Chapter 8
8. Finally, say Yes to Formatting Buttons, Spellcheck, and Write mode. Say No to Smileys, Glossary, and the File Chooser. Click Submit to create the new field. Now that you have your custom fields, you can define your categories.
Creating your categories
As discussed at the beginning of this chapter, you are going to use categories to distinguish between photo galleries. To start with, you are going to create two photo galleries—one for vacation photos and one for local photos. You can always come back and add more galleries later. 1. Still in the control panel, select Admin, Channel Administration, and then Categories. 2. Select Create a New Category Group and name it Photo Categories. Select Allow All HTML in the category field formatting and check the boxes to allow other member groups to edit (or delete) categories as appropriate. (If you see a message saying that there are no member groups allowed to edit/ delete categories, this is fine too). Click Submit.
3. Back on the Category Management screen, select Add/Edit Categories for the Photo Categories category group.
[ 205 ]
Creating a Photo Gallery
4. Click Create a New Category. The first category will be called Local Photos. The Category URL will default to local_photos. Type in a category description (you will later display this on your website), leave the Category Image URL blank, leave the Category Parent set to None, and click Submit.
5. Select Create a New Category again. This time call the new category Vacation Photos, with a URL of vacation_photos. Type in a category description such as A selection of vacation photos taken by Ed & Eg. Leave the category image URL blank and the category parent as None. Click Submit.
Now that you have your category group and custom field group defined, you can go ahead and create your channel. [ 206 ]
Chapter 8
Creating your channel
The process of creating your channel is straightforward. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Photos with a short name of photos. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Photo Categories for the category group, Statuses for the status group, and photos for the field group.
3. Answer No to creating new templates and then click Submit. Your channel is created! Now you can start creating some content and displaying the photos on your website.
Uploading your first photos
There are three ways to upload photos to your website. Your first option is to go to File Manager (under the Content menu) and select File Upload on the right-hand toolbar. Alternatively, you can go to publish an entry in the Photos channel, click on Add File, and upload a file. Both of these options are convenient since they use the built-in ExpressionEngine file manager to upload your file—you never have to leave the control panel. However, you can upload only one photo at a time and you may run into issues if you try and upload very large photos (greater than 2 MB).
[ 207 ]
Creating a Photo Gallery
The third option for uploading photos is to do so directly, using FTP, just as you would upload any files to your website. Since this requires another tool, it is less convenient than uploading a single photo from within ExpressionEngine, but if you are uploading lots of photos, then using FTP is a lot faster to do. That is the method we will use here. The built-in file manager also allows you to crop, resize, and rotate images (although you can take advantage of these tools even if you do not use file manager to upload the files).
1. Download the example photos (local1.jpg through local8.jpg and vacation1.jpg through vacation8.jpg) from either the Packtpub support page at http://www.packtpub.com/support or from http://www. leonardmurphy.com/book2/chapter8. (Or you can substitute your own photos). 2. Copy or FTP the photos into the /images/photos directory that you created earlier in the chapter. 3. Back in the ExpressionEngine control panel, select Content | Publish and then select the Photos channel. 4. Type in a title of Fireworks and a caption Fireworks exploding with a bang. Then select Add File. 5. The first screen to appear in the Upload File screen. Since you have already uploaded the files, you can simply select the photo gallery option in the lefthand menu. If no photos appear under the photo gallery, or the files appear but no thumbnails appear, try logging out of the control panel and logging back in. (This helps to refresh ExpressionEngine so it recognizes the new files—the first time you access the files after uploading via FTP, ExpressionEngine has to create the thumbnails).
[ 208 ]
Chapter 8
6. Select local1.jpg.
7. On the Categories tab, select Local Photos. Then click Submit. 8. Now, repeat the same steps to create entries for the rest of the photos, using appropriate captions that describe the photos. Be sure to select a category for each photo. There are 16 example photos (eight local and eight vacation photos). Having several example photos in each category will demonstrate how the photo gallery works better.
Creating your templates
As with everything in ExpressionEngine, everything that appears on your website must be coded in a template. Your photo gallery is no exception. You will now create new templates in a design very similar to the one used by the FAQs channel—a single-entry template called comment so that visitors can leave comments on individual images, and a multiple-entry page where visitors can browse and view images by category. You will start with the single-entry page.
[ 209 ]
Creating a Photo Gallery
Creating the single-entry page
The single-entry page is where an individual photograph is displayed, along with the caption and any comments. In this section, you will create a new template group called photos and then create a new template called comment (since the primary reason to visit the single-entry template will be to view and post comments). 1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group photos. Do not duplicate a group and do not make the index template in this group your homepage. Click Submit. 2. Next, with the photos group highlighted on the left-hand side, select New Template. Call the template comment and leave the template type as Web Page. Since your single-entry page here will be very similar to the singleentry page you created for the FAQs channel, select Duplicate an existing template and then choose the faqs/browse template to duplicate. Click Create and Edit.
[ 210 ]
Chapter 8
If you did not follow Chapter 5, Creating a Fully-Equipped Channel completely and do not have an faqs/browse
template to duplicate, it can be downloaded from http:// www.packtpub.com/support or from the chapter 5 page at http://www.leonardmurphy.com/book2/chapter5.
3. Whenever you copy a template, the first thing to update is the Preload Text Replacements at the top. Update them to the following: {preload_replace:my_channel="photos"} {preload_replace:my_template_group="photos"} {preload_replace:my_single_entry_template="comment"}
4. Further down in the template, delete all the code between (but not including) the {title}
and the {/exp:channel:entries}. 5. Replace the deleted code with the following code to display your image and your image caption (centered), along with a link to your multiple-entry photos/index template (which is still blank):
<em>{photos_caption}
The limited class is defined in your site/site_css stylesheet as having the property max-width: 555px;. This value matches the width of the #content ID container. Although the channel field instructions ask that photos be no bigger than 600x800, they may still be too big to fit nicely into the #content area without overlapping the sidebar. The max-width property proportionally shrinks images if they are too big, but otherwise leaves the image alone.
6. A lot further down, underneath the line {/exp:comment:form}, remove the Other Questions Like This section: everything from the
to the {/exp:channel:entries} inclusive.
[ 211 ]
Creating a Photo Gallery
7. Click Update and visit an example photo (such as http://localhost/ photos/comment/fireworks). If you uploaded photos with different titles, then remember that because this is a single-entry page, the last part of the URL (in this case, fireworks) is actually the URL Title from the entry to be displayed. You can replace this with the URL Title of another entry in your channel, and that entry will appear instead. Refer to Chapter 5, Creating a FullyEquipped Channel for more information on single and multiple-entry pages and how they work. If something does not look right in your single-entry page page, compare your code with the final code for the template, downloadable at either http://www.packtpub.com/support or http://www. leonardmurphy.com/book2/chapter8.
[ 212 ]
Chapter 8
Your single-entry page is complete! Go ahead and try adding comments if you like— both as a member and a visitor. Next up, you will create your multiple-entry page where visitors will be able to browse photos by category.
Creating the multiple-entry page
The multiple-entry page needs to attractively display a series of photos so that your visitors can quickly browse to the photos they are most interested in. A visitor browsing your photo gallery will likely spend a lot of time on this page. Although you will use thumbnails to display the photos on your multiple-entry page, you do not have to force visitors to go to your single-entry page in order to view a larger image. Instead, you can use jQuery and the FancyBox plugin that you used in the previous chapter. When a visitor clicks on a photo, a full-size version will appear in a FancyBox overlay, complete with caption. Visitors will be able to quickly scroll through the larger images directly from the FancyBox plug-in. Underneath each thumbnail, a link can take visitors who wish to leave comments to the singleentry page where they can do so. If you did not follow the previous chapter, please, at least, follow the instructions under the heading Chapter 7, Creating a Calendar under the Setting up FancyBox section.
Rather than re-inventing the wheel, you can base the multiple-entry page template on the calendar/index template that you created in the last chapter. (If you did not follow the previous chapter, you can download the template from http:// www.packtpub.com/support or from http://www.leonardmurphy.com/book2/ chapter7). 1. In the ExpressionEngine control panel, copy the calendar/index template code and paste it into the photos/index template. You will see a message indicating that no closing tag was found for {exp:jquery. Ignore this message as this tag is one of those that do not require a closing tag. 2. Update the Preload text replacement at the top to the following: {preload_replace:my_channel="photos"}
3. Update the to be Photo Galleries as follows: Photo Galleries - Ed & Eg Financial Advisors
[ 213 ]
Creating a Photo Gallery
4. The calendar/index template used its own stylesheet with extra calendar formatting—since you do not need to do this, change the stylesheet back to includes/site_css:
5. Your calendar uses a pop-up class attribute to display links in a pop-up iFrame FancyBox. Since you will be displaying images rather than an entire page in this FancyBox, you can set different options. Specifically, you should remove the type of iFrame, display the caption inside the pop-up box (on the calendar you had it display outside so that it did not blend in with the iFrame content), and set cyclic to true—meaning that as someone cycles through the images, once they reach the end of the set, the images will loop back to the start. Finally, do not set any limitations on the width or height of the FancyBox—you can allow the pop-up to auto-size itself to the size of the image being displayed. To accomplish all this, replace everything currently between <script type="text/javascript"> and with the following (leave the <script> tags as-is): $(document).ready(function() { $("a.gallery").fancybox({ 'cyclic': true, 'titlePosition': 'inside', 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none' }); });
For more information on FancyBox, including what the different options mean, you can visit http://fancybox.net/.
6. Finally, remove all the code that appears between (and including) Seminar Calendar
and {/exp:channel:calendar}. This is where your photo gallery thumbnails will eventually go. Click Update to save your work so far. At this point, you have a blank page (with a relevant page title and a FancyBox script that is ready for you to start using). Now you can start adding content.
[ 214 ]
Chapter 8
Adding content to your multiple-entry page
There are going to be two ways to browse your photos—visitors may go to the main photos/index page, where they will see all your photos. Alternatively, they can go to a category-specific page, where they will only see photos that fall into that category. Just like you did with your faqs/index template, you are going to use conditional statements to distinguish between when a visitor is on a category browsing page versus when they are not. Remember that a category browsing page will have the word category in segment 2 of the URL. 1. Still in the photos/index template, add the following code after . If you are on a category browsing page, this code displays the category name, category description, and a link back to the non-category version of your multiple-entry template. If you are on the non-category browsing page, then it will display the generic title of photo galleries and some instructions on how to browse the photos. {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} {category_name}
{category_description}
Browse all photos
{/exp:channel:category_heading} {if:else} Photo Galleries
<strong>Instructions: Select a gallery to view or click on a photo to see enlarged. When viewing in enlarged mode, use your left & right arrow keys to scroll between photos and the escape key to exit enlarged mode.
{/if}
[ 215 ]
Creating a Photo Gallery
2. Next, you can create a drop-down category selector to allow visitors to jump quickly to a given category. This code is adapted from the Channel Categories Tag documentation viewable at http://expressionengine. com/user_guide/modules/channel/categories.html#dropdown. It essentially uses a standard HTML drop-down form, populated with options from the channel categories tag that link to the photos/index template (though you specify only the template group photos, ExpressionEngine knows you mean photos/index because the index template is the default template). Add the following immediately after the previous code:
3. Click Update and then visit your photo gallery (at http://localhost/ photos). Verify that you can browse between categories and that when you are on a category page, you see the category information, and when you are not, you see the generic instructions. JavaScript must be enabled in your browser for the drop-down menu to work.
[ 216 ]
Chapter 8
4. It makes sense to display the thumbnails in a table. Since every gallery could have a different number of thumbnails, it is impossible for you to know in advance how many rows your table might need. You will therefore use a suggestion from Mark Bowen in the ExpressionEngine wiki (http:// expressionengine.com/wiki/Entries_In_Table/) to use the {switch} variable to insert a row break () after every five photos. You will combine this with a conditional statement that checks to see if the current entry is the last entry, in order to prevent a superfluous row being added at the end of your table. Remember that the switch variable allows you to insert different code for different entries. Typically, it might be used to alternate the background color of entries (for example, {switch="blue|red"} would mean your first entry is blue, your second entry is red, and your third entry is blue again. The different pieces of code that are alternated are separated by a pipe (|). When there are more entries than pipes, ExpressionEngine starts again from the beginning. {switch="|||| "} means that on every fifth thumbnail the row will be ended and a new one started—there is no code between any of the other pipes. For more information on the switch parameter, please visit http:// expressionengine.com/user_guide/modules/channel/ variables.html#var_switch.
5. Add the following code immediately after the : {exp:channel:entries channel="{my_channel}"} ***Image will go here*** {if count!=total_results}{switch="|||| "}{/if} {/exp:channel:entries}
[ 217 ]
Creating a Photo Gallery
6. If you visit your website now, you will see a table where your images will go as well as some placeholder text. If you browse between the different galleries, you will see a different number of table rows depending on the number of images that are in that category.
7. The next step is to replace the placeholder text with actual thumbnails. When designing your custom fields, you did not include a field for a thumbnail. Whilst you could include the full-size image with a small width/height, your visitors would then have to download all the full-size images in order to see this page—significantly impacting page load times. Instead, you can use thumbnails that are automatically generated by ExpressionEngine. 8. Whether you upload photos via FTP or via file manager, ExpressionEngine automatically creates thumbnails of any photos in a _thumbs subdirectory (/ images/photos/_thumbs) when you first view them in file manager. These thumbnails are used internally by ExpressionEngine, but you can also use them on your visitor-facing pages. To do this, you will use the custom File field (photos_photo) as a tag pair instead of as a single tag. This allows you to access the different components of each file (the path, the filename, and the extension) in each entry separately. By doing this, you can then insert the _thumbs subdirectory to the end of the path, and prefix the filename with the thumbs_ prefix that is automatically added to the thumbnails.
[ 218 ]
Chapter 8
For more information about using the File custom field as a tag pair instead of as a single tag, please visit http:// expressionengine.com/user_guide/modules/ channel/custom_fields.html#file_fields
9. Replace the ***Image will go here*** placeholder text with the following code:
If, after doing this, you have some thumbnails that are not showing up, you may need to log into ExpressionEngine, edit the entry in question, and re-add the photo using file manager. Make sure you can see the thumbnail in your entry before you submit it.
10. Visit your website again, and you will see thumbnails instead of the placeholder text you had before. Additionally, if you click an image, it will pop up in a FancyBox lightbox, with the caption underneath. This is because you gave the link a class attribute of gallery (which matches the class attribute you used in your FancyBox script). You can scroll through the photos in the FancyBox by clicking the left and right arrows or by using your mouse scroll wheel—this is because all the photos on the page have the same rel attribute, letting FancyBox know this is an image gallery. FancyBox treats whatever is in the title attribute as a caption—in this case, you included the {photos_caption} caption.
[ 219 ]
Creating a Photo Gallery
If your image does not appear in a pop-up overlay, but rather opens in a separate window or tab, you can check for a number of things. First, verify that the FancyBox directory is at the root of your website and that you can access the FancyBox files in your browser (if not, check your .htaccess file). Next, verify that the paths in the photos/index template point to the script/CSS files in the FancyBox directory and check the filenames for misspellings. Then, compare the photo/index template you have created with the photo/index template that is available for download from http://www.packtpub.com/support or http://www.leonardmurphy.com/book2/chapter8. Look carefully for any spelling mistakes or typos, especially in the code and <script> sections, as well as in the link code for the thumbnails. Finally, ensure that JavaScript is enabled in your browser.
11. The final step is to include a link to your single-entry page for visitors who want to leave comments. This can be accomplished by using a hyperlink underneath each photo that will mention how many comments have already been made. Add the following code immediately before the in your template:
{if comment_total=="1"}1 comment{if:else}{comment_total} comments{/if}
12. Now visit your photo gallery page and you will find the new hyperlinks. Click on one to confirm that you are taken to the single-entry page. Add a comment and verify the total increments correctly. If you have comment moderation turned on, you will have to mark the comments as open before they will be included in these counts (although if you are logged in as a Super Admin, you will be able to see the comments on the single-entry page). To mark a comment as open, select Recent Comments from the View section of the control panel home page, click on the comment you wish to open and then click View Comments. Here you can check all the comments you wish to open, and from the drop-down box, select Open Selected and click Submit.
[ 220 ]
Chapter 8
Your photo gallery is complete. You now have an easy way for visitors to browse your photos quickly, either from the main photos/index page or by gallery. It is also easy to see which photos already have comments and for visitors to add their own.
Image editing features
Now that you have gone through the process of creating a photo gallery, uploading images, and creating the corresponding templates, it is a good time to discuss how photos can be cropped, resized, and rotated all from within ExpressionEngine. 1. From the Content menu in the control panel, select File Manager. 2. If you have multiple upload destinations, it is good to know that if you click on the title of one (such as About), it will collapse the list of files. If you click again, the file list will expand. This can help reduce screen clutter. 3. If you select a filename (such as local6.jpg), a FancyBox pop-up will appear with the full size image. (Press escape or click the x in the top-right to close). 4. For the photo local6.jpg, select Edit (in the fifth column from the left).
[ 221 ]
Creating a Photo Gallery
5. At the top-right, there are three modes (Crop, Resize, and Rotate). Select Crop Mode.
6. The picture on the left will darken. To crop the photo, you can drag the rectangle over the picture until the part of the picture you want is framed. The rectangle can be resized or repositioned as needed. On the right-hand side, you can see information about the width, height, and X/Y coordinates of your crop.
[ 222 ]
Chapter 8
7. Once the rectangle is placed, click Save Image on the right-hand side to save your changes. 8. You can also resize the photo by clicking on the Resize option. In this case, setting a width will automatically adjust the height so the photo stays in proportion (and setting the height will automatically change the width). This feature is extremely useful if you want to upload a full-sized image, but then manually adjust it so the width is no more than a certain size (for example). When you upload a photo for the first time from the Publish page, you also have the option to resize an image. In this way, you can upload full-size images directly, and resize them on the fly in ExpressionEngine, rather than shrinking them in advance or uploading them and using the file manager to resize them.
Rotate mode is also fairly self-explanatory. However, be aware that selecting a different rotation (or flipping the image horizontally or vertically) automatically saves the image.
Photo gallery add-ons
In this chapter, you have walked through how to build a photo gallery in ExpressionEngine without using any third party add-ons. As you can see, the functionality in ExpressionEngine is very robust and flexible out of the box. That said, there are times when an add-on can be useful—especially if images are a large part of the content of your website. Pixel & Tonic's Matrix was already mentioned at the beginning of the chapter as a useful add-on for designing a photo gallery with multiple photos per channel entry. In addition, the following add-ons are specific to editing photos (though they are by no means representative of all the add-ons that are available. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available.).
Image sizer
http://devot-ee.com/add-ons/image-sizer/
Written by David Rencher, this plugin takes a large image, dynamically resizes it, and caches the resized image (to reduce page load times). Using this add-on in your template saves you from having to manually resize every image you upload (and eliminates the risk of breaking your page layout if you forget). Instead, images are resized on the fly. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available. [ 223 ]
Creating a Photo Gallery
Channel Images
http://devot-ee.com/add-ons/channel-images/
For a small fee, Channel Images by DevDemon allows you to batch-upload multiple files from within the ExpressionEngine control panel and simplifies image management on the Publish page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. Since the photo gallery uses the same tools as all the other sections of your website, these exercises are not so much specific to photo galleries, but are a good reminder of the techniques learnt in previous chapters. 1. The main page of the photo gallery works great when there are only a handful of photos. However, over time, you could end up with hundreds and hundreds of photos in your channel, all of which would get displayed on your main page. Change the main page so that it limits the number of photos that are displayed and randomizes which photos are shown. 2. ExpressionEngine has the ability to track how many times a channel entry has been viewed on a single-entry page (Entry Views). Using a conditional statement, indicate on your multiple-entry template which photos are ***popular*** photos, based on the number of single-entry page views. For now, consider more than ten single-entry page views to be a sign of a popular photo. 3. The form for submitting comments and the code for displaying comments on your single-entry page are almost identical to the form for submitting comments and the code for displaying comments on your FAQs channel. In the spirit of reducing repetition, choose between a Preload Text Replacement, a Global Variable, a Snippet, or an Embedded Template and extract the code from both photos/comment and faqs/browse, so that both templates use the same code for submitting and displaying comments.
[ 224 ]
Chapter 8
Summary
In this chapter, you took a look at how to adapt the channel functionality of ExpressionEngine to a photo gallery. The lack of a formal photo-gallery module can make ExpressionEngine seem less functional. However, as you can quite clearly see, the standard channel functionality is more than adequate for the task, and indeed allows for a lot more flexibility than a separate photo gallery module might offer— with unlimited custom fields, a multitude of ways that you can organize photos within your channel (using categories and/or status groups), and with no restriction on how you can build your templates, the sky is the limit. This chapter wraps up the step-by-step introduction to ExpressionEngine. By now, you should be fairly comfortable with the basics of ExpressionEngine—channels, templates, tags, custom fields, categories, status groups, and so on. In the next chapter, you will be introduced to some more specialized first party modules that you may find useful.
[ 225 ]
Beyond the Basics So far, this book has introduced the basic concepts and the most commonly used features of ExpressionEngine. Many of the same basic skills have been used time and again such as setting up custom fields and categories, creating a new channel, posting entries to the channel, and building templates with HTML/CSS and ExpressionEngine tags. ExpressionEngine comes bundled with many other modules that may or may not be useful, given your website. The modules range from the simple to the complex—the simplest create additional tags that you can use in your templates, while the most complex include their own configuration pages and library of tags. This chapter looks at some of the offerings, including: •
The Search module
•
The Mailing List module
•
The Email module (create a contact form or a tell-a-friend form)
•
The Moblog module (submit new channel entries via e-mail)
•
The Wiki module The Mailing List and the Email modules rely on ExpressionEngine being able to send e-mails. If you are following along in a localhost environment such as WampServer, XAMPP, or MAMP, you will find that ExpressionEngine cannot send e-mails. This is because a localhost environment does not include an e-mail server. You can either follow along on an actual website server, or if you choose to follow along in your localhost environment, be aware that in places where you would expect ExpressionEngine to send an e-mail, you will not see such an e-mail.
Beyond the Basics
The Search module
ExpressionEngine comes with a pre-built search tool to allow visitors to search your site. Although technically a module, the search functionality comes pre-installed and does not have any special setup. This means that you can start using the search tags right away. There are two parts to enabling search on your website, namely: •
Creating a form that allows visitors to type in and submit search terms (this could be as simple as a search box that appears in your sidebar or it could be an entire template dedicated to an advanced search).
•
Creating templates to display the search results (or that there are no results). The Search functionality only searches channels. The Discussion Forum module and the Wiki module both have separate search functions.
When you design your search forms, you can use parameters to control what is searched. By doing this, you can limit searches to particular channels, status groups, or categories. You can also determine whether you want the search to include expired or future entries (this is important if you are searching a channel, like an events calendar, where all the entries might be in the future). Finally, you can set whether you want to search for words only in channel titles, in all the custom fields of a channel, or in the channel title, custom fields, and comments. Be very cautious if you enable your search to include future entries and the search form searches more than one channel. While one channel might routinely have entries in the future that you want to be searchable, another channel might have future-dated entries that you want to keep hidden until that date/time. The parameters you set for your search form (such as whether to include future-dated entries) apply to all channels that you allow to be searched from that form.
In addition to the search tags, there are three settings in the control panel that control how the search behaves:
[ 228 ]
Chapter 9
1. Is the field searchable? Each custom field in ExpressionEngine can be set to either be searchable or not searchable. Having this field set incorrectly on your custom fields can mean entries not being found that otherwise would be. As a general rule, fields that contain content such as sentences and paragraphs should be set to searchable, but fields such as drop-down boxes or files should not be searchable. To change the searchable setting for any individual field, go to Admin | Channel Administration | Custom Fields, and then select the field group and the field you wish to edit. You could create a custom field on a channel that is searchable, but that is not displayed on your website. This field could then be used to store likely search-terms for each individual entry that might not otherwise appear in the article (such as variations in spelling), thus improving the possibility that meaningful results are returned for people searching your website.
2. Search Page URL. Each channel has a path that is used to link the search results to the actual entries that were found. If this path is set incorrectly, clicking on a given search result will send the visitor to a wrong page. The field should be set to the single-entry template for the channel. (For example, the Photos channel should be set to http://localhost/photos/ comment). To change this setting for a given channel, go to Admin | Channel Administration | Channels, then click Edit Preferences for a specific channel, and look under Path Settings. 3. Which field should be used for search excerpt? This is also found under Channel Preferences, under Administrative Preferences. This defines the custom field from which the excerpt displayed on the results page comes from. To demonstrate the search functionality, you will create a search box in the sidebar that searches both the FAQs and the Photos channels. Before you begin, ensure that the Search Page URLs for these two channels are set to http://localhost/faqs/ browse and http://localhost/photos/comment respectively.
Adding a search box to your site
In this section, you will create a search box in the sidebar for Ed & Eg's website, thus allowing visitors to start a search from any page they like. 1. Go to Design | Templates | Snippets and edit the website_sidebar snippet.
[ 229 ]
Beyond the Basics
2. In the snippet, add the following code immediately after the final and before the final . Notice the parameters—the channel parameter restricts the search to the FAQs and Photos channels. The search_ in="everywhere" parameter means that you want the search to include titles, custom fields, and comments. The where="any" parameter means that entries containing any of the searched-for words will be returned (as opposed to requiring an exact match). The status parameter means that you will include entries with a status of open or premium (the premium status was one that you created in Chapter 6, Members, and if you did not include it explicitly, only entries with an open status would be searched). Finally, the result_page and no_result_page define which templates should be used when there are results or when there are no results (in this case, the search/ index and search/noresults templates, which you are yet to create). The rest of the code is a standard HTML form (although the input box must have the name="keywords" attribute for the search form to work). For more information on each of these parameters, including alternative settings for them and additional parameters not included here, please visit http://expressionengine.com/user_guide/modules/ search/simple.html. {exp:search:simple_form channel="faqs|photos" search_in="everywhere" status="open|premium" where="all" result_page="search" no_result_page="search/noresults"}
{/exp:search:simple_form}
3. If you visit the home page of your website, you should now see the search box on the right-hand side. If you have the Agile Records example website template groups still installed, searching will result in the Agile Records themed advanced search template being returned—otherwise, you would get a 404 page. You will create the search result templates next.
[ 230 ]
Chapter 9
Creating a search results template
The search results template is specified in the parameters of the search form as search, which translates to the search/index template. Had you not defined a specific template, the search results template would be set to search/results. If Agile Records is installed, then you are likely to already have a search template group which you can adapt to display your results. Otherwise, go ahead and create a search template group now. 1. The first step is to start with your basic site outline (header, sidebar, and so on). You can accomplish this by copying the includes/404 template into the search/index template. Edit the search/index template and paste in a copy of the code from includes/404. 2. Change the title of the page to be: Search Results - Ed & Eg Financial Advisors
3. Change the heading to be Search Results: Search Results
4. Replace the next paragraph (that talks about the page not existing) with the following. The {exp:search:keywords} tag displays the keywords used for the search.
You searched for <em>{exp:search:keywords}.
If you see a warning about there not being a closing tag when you save your template, ignore it. The {exp:search:keywords} tag is one of those that does not have a corresponding closing tag.
[ 231 ]
Beyond the Basics
5. Underneath the preceding paragraph, insert the following code (adapted from the code found at http://expressionengine.com/user_guide/ modules/search/results.html). This displays your search results in a two-column table. The first column will have the entry title and the second column will have an excerpt from the entry (the first 50 words from the field designated as the search excerpt field in your channel preferences). First create the table and the header row.
Title Excerpt
{if paginate} <span>{page_count} {paginate} {/if}
The pagination code at the end works similarly to channel pagination—allowing a long list of results to span multiple pages.
6. The following code uses the {exp:search:search_results} tag to display the actual results. This tag loops through once for each result you have. In this case, a new table row is created for each result. The switch tag makes the first row light-gray, the next white, the third light-gray, and so on. (Remember from the photo gallery chapter that the switch tag uses the first switch for the first result, the second switch for the second result, and so on, until it runs out of switches, when it starts over). Prior to the entry title, the channel name (such as Photos: or FAQs:) is added to make it clearer what kind of entry is being linked. Underneath the entry title, the number of comments that the entry has received is displayed. Add this code after the closing of the header row, within the table you created earlier: [ 232 ]
Chapter 9 {exp:search:search_results} <strong>{channel}: {title}
{if comment_total=="1"} 1 Comment {if:else} {comment_total} Comments {/if} {excerpt} {/exp:search:search_results}
Within the {exp:search:search_results} tag, there are some special variable tags you can use, including {auto_path} and {excerpt}. {auto_path} creates a path to the entry using the Search Page URL, defined in the channel preferences, and {excerpt} displays the first 50 characters of the excerpt field defined in the channel preferences. You can also use tags (such as {comment_total}, {author}, or {entry_date}), which are normally available in the {exp:channel:entries} tag. More information on search resultspecific tags can be found at http://expressionengine.com/user_ guide/modules/search/results.html and information on channel entry tag variables can be found at http://expressionengine.com/ user_guide/modules/channel/variables.html.
[ 233 ]
Beyond the Basics
7. Now click Update and Finished, go to your website, and search for something (for example, money). Your results will be displayed.
The no-results template
One other template you defined in your website_sidebar snippet was a no_ result_page of search/noresults. This can be a simple template that uses {exp:search:keywords} to display the search term and indicates that no results were found.
1. In the Search template group, create a new web page template called noresults. If you already have a results and a no_results template in the search template group, you can go ahead and delete these. 2. When creating the template, select to duplicate an existing template and duplicate search/index. Click Create and Edit. 3. Delete all the code from (and including) the
immediately above the opening tag down to (and including) the closing {/if} statement of the {if paginate} block of code. 4. Modify the You searched for… paragraph to read as follows:
[ 234 ]
Chapter 9 You searched for <em>{exp:search:keywords}. Unfortunately, nothing matching that search was found.
5. Click Update and Finished (ignoring any warnings about there being no closing tag) and now try searching for something that you know is not part of your website (for example, monkey). You will be redirected to your search/ noresults template.
Advanced search
In addition to the {exp:search:simple_form} that you used in your sidebar snippet, you also have the option of creating an advanced search form using the {exp:search:advanced_form} tag. The advanced search form allows visitors to select many of the settings that you set in the parameters of the simple search form. For example, on the simple search form, you specified which channels could be searched, whereas on the advanced search form, you can allow visitors to select which channels they can search in (although you can limit the choices they see by using parameters, just as you did with the simple search form).
[ 235 ]
Beyond the Basics
To build an advanced search form, you can create a template, such as search/ advanced, and then adapt the code from http://expressionengine.com/user_ guide/modules/search/advanced.html. This form looks much more complex than the simple_form, but most of that complexity comes from building all the form fields—how the form works is the same. Although an advanced search form on a small website like Ed & Eg would be overkill, an advanced search tool can enable power users to find what they are looking for on websites that have large amounts of content.
The Mailing List module
ExpressionEngine comes with a Mailing List module included. It is a very straightforward module that allows you to quickly and easily send e-mails to visitors who have signed up to receive e-mails or to specific member groups. You can have as many mailing lists as you want. Remember that if you are using a localhost environment such as WampServer or MAMP, ExpressionEngine will not be able to send outgoing e-mails. You will be able to follow the steps to set up a mailing list and make the sign-up box available on your website, but you will not be able to use the Mailing List module to send e-mails.
Setting up the Mailing List
The Mailing List module is included with ExpressionEngine, but is not installed by default. Installing it is easy. The following steps will show you how to do it: 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Mailing List and then click Install. 3. The Mailing List module name will turn into a clickable link. Click it to enter the Mailing List Manager. 4. To start with, there is one mailing list set up called Default Mailing List. You can change the name of the mailing list by clicking Edit next to the mailing list. You can also create multiple mailing lists by clicking Create New Mailing List at the top right.
[ 236 ]
Chapter 9
5. Click Edit Template to edit how the e-mails will look. By default, each e-mail has a footer with the unsubscribe URL (auto-generated by the Mailing List module for each e-mail address the e-mail is sent to). You can customize how this footer is worded or add text above the {message_text} variable in order to create a header for all your Mailing List e-mails. The conditionals {if plain_email} and {if html_email} allow you to distinguish between plain-text and HTML versions of an outgoing e-mail, so that people reading the e-mail in plain text do not see the HTML mark-up. For now, leave the default e-mail template as-is. 6. Also, within the Mailing List Manager, you can batch subscribe or unsubscribe people (for example, if you were transferring over a Mailing List from another application). You can also set up an administrator e-mail address, so when someone new subscribes to a Mailing List, the administrator gets notified. (Click Mailing List Preferences to do this). 7. To see who is signed up for any given Mailing List, click View next to the Mailing List name.
[ 237 ]
Beyond the Basics
Now that you have a mailing list defined, there are two more things you must do: 1. Allow people to subscribe to your mailing list 2. Send e-mails to people on your mailing list
Allowing members to sign-up
To allow visitors to sign themselves up to the mailing list, you are going to add an option to your sidebar snippet. 1. Modify the snippet called website_sidebar. 2. In the snippet, add the following code immediately after the final li> and before the final . This code is adapted from the mailing list documentation at http://expressionengine.com/user_guide/modules/ mailinglist/index.html. Notice that in the {exp:mailinglist:form} tag, you have a parameter called list that is used to determine which mailing list the member will be signed up for (in this case, default). The e-mail input box value is set to {email}, which is a global variable referring to the e-mail address of the currently logged in member. In this way, if a member wishes to register for the mailing list, they do not need to re-type their e-mail address. Mailing List
{exp:mailinglist:form list="default"}
{/exp:mailinglist:form}
3. Click Update and Finished. Visit Ed & Eg's home page and you will see the option to sign up for a mailing list. Note that any new visitors who sign up will receive an e-mail with a link which they must click within 48 hours in order to actually sign-up (remember that if you are using a localhost environment, you will not receive this e-mail). The mailing list is strictly an opt-in feature, with an opt-out link included in every e-mail that you send.
[ 238 ]
Chapter 9
You have set up your mailing list so that visitors can sign themselves up to it. Note that if you wanted to have multiple mailing lists, all you would need to do is change the list parameter to reflect the short-name of the mailing list that the person is signing up for. Of course, now that you have a mailing list with subscribers, how do you send them e-mails?
Sending e-mails
Before trying to send an e-mail, review your e-mail settings in Admin | Email Configuration. Here, you can define not only how e-mails are sent (PHP Mail, Send Mail, or SMTP), but you can also define which e-mail address they come from. If, for any reason, ExpressionEngine is not sending e-mails, you can also turn on Email Debugging, which will then display the error message explaining what is stopping the e-mail from being sent. The settings on this page apply to all e-mails sent by ExpressionEngine, including automated e-mails such as those that are sent as part of new member registration or when you sign up for a mailing list.
[ 239 ]
Beyond the Basics
To send e-mails, you must use the Communicate tool (under Tools in the main menu). This tool can be used in conjunction with the Mailing List module to send e-mails to people who have subscribed to a given mailing list, or it can be used on a standalone basis to send e-mails to certain member groups or specific e-mail addresses. Remember that if you are following along in a localhost environment, you will not actually be able to send outgoing e-mails.
The Communicate tool has lots of options, most of which are fairly self-explanatory. At the very top, there is a link to see previously sent e-mails. Underneath the message, you can choose between sending a plain-text or an HTML e-mail. If you choose HTML, you can optionally include a plain text alternative for recipients who cannot read HTML e-mails. On the right-hand side, you can choose which mailing lists or member groups get the e-mail (or manually type in your own recipients' e-mail addresses). If you are handtyping e-mail addresses, it is recommended that you use the BCC field so that you do not expose the e-mail addresses of recipients to other recipients. You can also define who the e-mail comes from (so that it is less likely to be treated as spam).
A checkbox at the very bottom allows you to suppress e-mails to members who have requested not to receive e-mails from administrators in their control panel settings—respecting this setting is recommended. [ 240 ]
Chapter 9
The Mailing List module is designed to make it easy to send e-mails to multiple recipients at once. If you want to send an e-mail to an individual member, you can also do so via the e-mail console, provided you have enabled this functionality for the member group you are in. Click on the Email button from either the individual member's profile or from the member list at http://localhost/member/list to access the e-mail console. See Chapter 6, Members for more information on member-facing functionality.
The Email module
The Email module gives you the ability to easily create contact forms (so that your visitors can e-mail you) and tell-a-friend forms (so that your visitors can e-mail their friends). In this section, you will see how to set up both of these forms for your website. If you installed the Agile Records example site, then the Email module will already be installed. Otherwise, it can be easily installed by going to Add-Ons | Modules and clicking Install.
Creating a contact form
Ed & Eg currently have an FAQs section, where they answer frequently asked questions from their customers and visitors. However, there is no easy way for visitors to submit their questions to Ed & Eg. In this section, you will create a new contact form so that visitors can submit their questions for Ed & Eg to answer. As you have done before, you will base the contact form template on the includes/404 template (which has the site header and other layout components, but does not have much in the way of content that needs to be changed). 1. From Template Manager, select the faqs member group and click New Template. 2. The new template will be called submit. The template type should be Web Page. Check the option to duplicate another template and select the includes/404 template to duplicate. Click Create and Edit. 3. Change the HTML to the following: Submit a Question - Ed & Eg Financial Advisors
[ 241 ]
Beyond the Basics
4. Change the title from Page Not Found to Submit a Question. 5. Delete the paragraph underneath the tag. 6. The following code is adapted from the example provided in the ExpressionEngine documentation for this module at http://
expressionengine.com/user_guide/modules/email/contact_form. html. The {exp:email:contact_form} tag displays your contact form. This tag has a parameter called recipients that allows you to specify the e-mail
address you want the final e-mail to be sent to—your visitors will not be able to see or change this address. The rest of the form is a standard HTML form with some values filled in, based on ExpressionEngine variables (the e-mail address of the member, their name, and the date/time). Add the following code underneath the header in the template, changing the recipient's e-mail address to match your own:
{exp:email:contact_form user_recipients="false" recipients="[email protected]" charset="utf-8"}
{/exp:email:contact_form}
7. Although the form is complete as-is, you can also add code to display a CAPTCHA. Even if you are not using the CAPTCHA system now, it does not hurt to put this code in; in case you want to use it in the future, you can quickly enable it (under Admin | Email Configuration) without changing your templates. You can do this because the {if captcha} conditional prevents the CAPTCHA from displaying, unless it is set to be required. Insert this code immediately before the Submit button (after the
) within the contact form: {if captcha} {captcha} [ 242 ]
Chapter 9
{/if}
8. Click Update and now visit your submission form at http://localhost/ faqs/submit. If ExpressionEngine is configured to send e-mails, visitors will be able to use the form to send you e-mails easily and seamlessly from within your website.
For more information about the parameters of this form and how they can be set, please see the ExpressionEngine documentation at http://expressionengine. com/user_guide/modules/email/contact_form.html. The documentation includes useful tips in case your server host does not allow e-mails to be sent from your domain with a "from e-mail address" that is not yours. [ 243 ]
Beyond the Basics
Creating a tell-a-friend form
The tell-a-friend form works very much like the Contact form, except that instead of e-mailing a person you specify, the person can e-mail a friend of their choice. The risk with this form is that spammers might use it to e-mail advertising or other junk to third parties. To prevent this, there are several options—you can restrict this functionality to signed-in members who have activated their membership via e-mail (and then pre-fill the From field with that member's e-mail address). You can fix the message text yourself so that it cannot be edited (visitors can either send or not send the message as-is). Finally, you can require CAPTCHAs (in Admin | Email Configuration) for visitors e-mailing a friend. You may also wish to consider independent social media solutions, such as adding Facebook's Like button to your website, which allows visitors to easily share that they like your website, without the concerns that the tell-a-friend form brings. Check out http://developers.facebook. com/docs/guides/web for more information.
For this example, you will create a tell-a-friend form for the FAQs channel that is only available to members. The From e-mail address will be set as the e-mail address of the logged-in member and the message will also not be editable.
Creating the tell-a-friend template
The tell-a-friend template will be based on the faqs/submit template, which you had created for your contact form. If you did not follow the steps to create a Contact form, remember that you can download the source code from either http://www. leonardmurphy.com/book2/chapter9 or from http://www.packtpub.com/support. 1. Create a new template in the FAQs template group called friend. When prompted to duplicate an existing template, select faqs/submit as the template to duplicate. Click Create and Edit. The tell-a-friend form can also be added to the bottom of the singleentry template for your channel (in this case, faqs/browse).
2. Change the HTML to: Tell a Friend - Ed & Eg Financial Advisors
3. Change the title to Tell a Friend. [ 244 ]
Chapter 9
4. Replace everything from {exp:email:contact_form} to {/ exp:email:contact_form} with the following conditional, which checks to see if the visitor is logged in. If they are not logged in, they will not be able to tell-a-friend. {if logged_out}
Sorry, you must be logged in to tell-afriend.
{if:else} {/if}
5. After the {if:else} and before the {/if}, insert the following tell_a_ friend form (adapted from http://expressionengine.com/user_guide/ modules/email/tellafriend.html). The tell-a-friend form is necessarily longer than the Contact form because there are more fields (for the send-to e-mail address and the name of the person the e-mail is coming from). Also, notice that some of the fields in the following code are read-only because the values are being populated from ExpressionEngine. {exp:email:tell_a_friend charset="utf-8" allow_html='no' status="open|premium"}
{/exp:email:tell_a_friend}
In this example, you use the {faqs_question} custom field to display data from your entry in the message. Indeed, ExpressionEngine is versatile enough that you can create a single tell-a-friend form for multiple channels, even if they have different custom fields. ExpressionEngine will suppress any custom fields that do not apply, based on the channel that is being sent to a friend. The status="open|premium" is because there are some entries that might have a premium status rather than open. Without this setting, any status that is not open would not render the tell-a-friend form.
6. As with the Contact form, add the following CAPTCHA code immediately before the Submit button (after the
) {if captcha} {captcha}
{/if}
7. Now you need to create a link to the tell-a-friend form. Edit the faqs/browse template and add the following link next to the Back to FAQs link. Like the form itself, this link will only be visible to members who are logged in. {if logged_in}Tell-aFriend | {/if}Back to FAQs
[ 246 ]
Chapter 9
8. Now if you visit a FAQs channel entry and click the Tell a Friend form, you will be brought to the faqs/friend form, where you can send an e-mail to a friend.
Word-of-mouth is one of the best marketing strategies available, and the tell-a-friend functionality allows visitors to share an entry on your site without having to a draft a special e-mail. Although this example is very locked-down, you can make it more flexible (such as by allowing visitors to edit the message). Before making changes such as that, always think of how easy it might be for a malicious person to use the form to send advertising or phishing e-mails to third parties.
[ 247 ]
Beyond the Basics
The Moblog module
So far, whenever you wanted to create content, you have had to log into the control panel and publish a new entry. The Moblog module provides a way to upload files to your website and create content directly from your Internet-enabled smart phone. The basic concept involves setting up an e-mail address which ExpressionEngine can access. When you e-mail from your phone to the e-mail address, the content can either be turned into a channel entry, or attached files can be saved to an upload location without a channel entry being created (making it an easy way to upload files to your website without FTP). The module includes ways to prevent spam or other e-mails that might also be sent to the same e-mail address from being published to your site. Unfortunately, the Moblog module can only add new content to text area custom fields. Since channels will often have other types of custom fields, does this mean that you cannot use the Moblog module? No. Take, for example, the Photos channel. There is one text area custom field (caption), but the photo itself is a File custom field. Although you cannot publish an entry to the photo channel without a photo, you can still use the Moblog module to create a closed entry with the caption you desire, and upload the photo(s) attached to your e-mail to the photo gallery upload destination. Then, when you log in to the control panel, all you have to do is edit the entry, select the photo from the file manager, and change the entry status to open. For the Moblog module to work, you must have an e-mail address that ExpressionEngine can access via POP3. Typically, an e-mail address associated with your website domain or your internet provider (ISP) would have POP3 access, but a free web-based e-mail service may or may not. Since ExpressionEngine is only reading incoming e-mails (and not sending e-mails), the Moblog module can be set up and tested even in a localhost environment.
Setting up the Moblog module
As with other modules, the Moblog module is not installed by default. Installing it is easy. 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Moblog and then click Install. 3. The Moblog module name will turn into a clickable link. Click it to enter the Moblog control panel. 4. When you first enter the control panel, no Moblogs exist. Click Create New Moblog. [ 248 ]
Chapter 9
5. First, the general settings need to be defined. Enter a full name of Photos Moblog and a short name of photos_moblog (remember that the short name is what will be used in templates). Leave the time between checks set at 15 minutes. This does not mean that the e-mail address will be checked every 15 minutes, but that if you set up a template with an {exp:moblog:check} tag, and someone visits that template and more than 15 minutes has passed since the last check, then the e-mail address will be checked. Set Moblog Enabled? to Yes and set File Archive Mode to No (File Archive Mode is where files attached to your e-mail are uploaded, but no channel entry is created).
[ 249 ]
Beyond the Basics
6. Next, choose the channel you want to post to—in this case, Photos. You can also select a default category, field, status, and author. This can be useful if, for example, you want your mobile photos to be in their own gallery or to have their own status. For this example, use a default category of None. Use a default field of Caption, a default status of Closed (since you do not want your entries to be visible until you have updated the File custom field with the photo), and a default author of you.
7. Say No to making the entry sticky (meaning that it always appears first on a multi-entry page) and Yes to allowing overrides in e-mail. This means that if you want to set the category or status differently as compared to the default, you can do so by using a special code in your e-mail—for a list of possible overrides, see http://expressionengine.com/user_guide/modules/ moblog/email_contents.html. 8. Select Photo Gallery as the upload directory. 9. The Moblog templates allow you to define exactly what will happen with your e-mails. The default is to display the text first, then any images in an img tag, and any other files as a Download File link—all within your text area. Since you do not want your images to be part of the caption, change the template to remove the {images} section as follows: {text} {files match="audio|files|movie"} Download File {/files}
[ 250 ]
Chapter 9
For more information on the different tags and parameters that are available, please visit: http://expressionengine.com/user_ guide/modules/moblog/control_panel/email_template.html.
10. Next up, you can define your e-mail settings. The e-mail server must support POP3—typically e-mail addresses associated with your website domain would have POP3 access, as would e-mail addresses from your ISP. Free e-mail services may or may not include support for POP3 access. If you already download your e-mail to your e-mail software using POP3, then the same settings that are in your e-mail client (server name, username, and password) would go here. Since the Moblog module is scanning for incoming e-mails and does not send e-mails, the Moblog module will work even if you are using a localhost environment. Simply set the settings to the e-mail address you want to scan.
11. Further down, you can specify a word or phrase that must appear in the subject of your Moblog e-mails. This allows ExpressionEngine to distinguish between a Moblog e-mail and all the other e-mails you may receive. The default setting is moblog:, meaning that any e-mail you want posted to your Photos channel needs to have moblog: in the subject. (When setting the title of the entry, this phrase will be stripped out and the rest of the subject will be used; for example, Moblog: Flower will result in an entry called Flower.) Changing the subject prefix is useful when you want multiple Moblogs to use the same e-mail address. However, for the purposes of this example, leave it set as moblog:. 12. For security, you can also set your Moblog e-mails to be from a certain e-mail address (or addresses) and you can require authentication (meaning your control panel username and password must be included in your Moblog e-mails). It is recommended to at least limit the e-mail addresses that can send Moblog e-mails. 13. The next option allows you to prevent certain text that might be included in your e-mails (such as your signature) from appearing in your channel entry.
[ 251 ]
Beyond the Basics
14. Next, you can set the parameters for any images you attach—you can require images to display with a certain height or width, you can resize, you can upload images automatically, and you can also create thumbnail images if desired. For now, say Yes to resize images on import, and resize any images to have a width of 555. Leave the height set to 0 to keep the image in proportion.
15. Finally, click Submit to create your Moblog.
Setting up your template
If you were using the Moblog module to post content directly to your website, you could set up a template to check for new Moblog entries automatically whenever it is accessed by a visitor. With the following tag, ExpressionEngine will check to see if 15 minutes have elapsed since the last check, and if so, ExpressionEngine will check again:
silent="true" means that the Moblog check will be invisible to the person viewing your template. For troubleshooting purposes, you could temporarily set this to false. If you do set this to be false, having the tag wrapped within an HTML comment, as shown, means that you can see any error messages by viewing the HTML source (by clicking View Source from your browser), while visitors see nothing unusual. [ 252 ]
Chapter 9
Since you are setting up your Moblog to act as an easy way to create entries without publishing them right away, this step does not apply.
Sending a Moblog e-mail
Now that the Moblog module is configured, you can try sending your first Moblog e-mail. 1. First, send an e-mail to the e-mail address you specified with an image attached. Be sure that the e-mail has a subject prefix as defined (moblog:) and comes from an e-mail address that is allowed to post Moblog entries. Do not forget the attachment!
2. Next, log into the control panel and select Add-Ons | Modules and then select Moblog. Click Check Moblog. If the Moblog module finds valid e-mails, you will see a green check mark at the top of the screen (which you can click to see more information).
[ 253 ]
Beyond the Basics
3. Now select Content | Edit and look for an entry with a title that matches the subject of the e-mail, a date/time of the current date/time, and a status of closed. Click the entry to edit it and you can see the body of your e-mail in the caption field.
4. Click Add File, select the Photo Gallery, and click on the file you uploaded. 5. Click on the Options tab and change the status to Open. Then click Submit. 6. Visit the photo album (http://localhost/photos) to see your new entry. Notice how the image was automatically resized to be 555 pixels wide, as specified in the Moblog preferences.
[ 254 ]
Chapter 9
The Wiki module
A wiki is an area of the website where visitors themselves can edit the content or create new content. One of the most famous wiki's on the web is Wikipedia (http://www. wikipedia.org/)—an online encyclopedia that anyone can contribute content to. Another example wiki is the ExpressionEngine wiki, located at http:// expressionengine.com/wiki/—a great tool for sharing how-tos and more with other ExpressionEngine users.
At first glance, it can be difficult to see the use for a wiki (especially for a website like Ed & Eg's). However, if you think of it as a collection of documents that can be shared among a group of people of any size, and updated in real time by the same group of people that actually use the content, the business advantages start to become clearer. As with any tool that requires active participation from others, it helps if you already have a group of people that is willing to participate. A wiki, more so than other tools (such as comments or a discussion forum), requires an unusually high commitment from end-users—first to build the content and then to be willing to edit and add to other people's content. To demonstrate how the Wiki module works, you will create a wiki for visitors to exchange money-saving tips and ideas. The Freelancer license does not include the Wiki module, so this section will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing.
Setting up the wiki
As with other modules, the Wiki module is not installed by default. Installing it is easy. 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Wiki and then click Install. 3. The Wiki module's name will turn into a clickable link. Click it to enter the wiki control panel. 4. Click on Create Wiki. 5. Change the full wiki name to Money Saving Wiki and change the short name to money_saving_wiki.
[ 255 ]
Beyond the Basics
6. Leave the text formatting as Xhtml, but Allow only safe HTML (meaning that people can use standard HTML tags to mark-up their content). 7. Choose a File Upload Directory where files associated with the wiki will be stored. (You may want to create a new directory under Content | File Manager that is specifically for wiki files). If you do not select a destination, uploading files will not be possible. 8. Select which member groups can administer the Wiki module, and which member groups can use it. Administrators can delete content, mark an article as locked (so that no-one can edit it), or mark an article as moderated (meaning that users can edit it but an administrator must approve the change before it becomes visible to others). Select Super Admins as your administrating member group, and select all your member groups as users. 9. You can set up how many revisions you keep for each article and how many edits a single individual can do in a single day. For now, leave these at their defaults. 10. Set up an e-mail address as the e-mail to receive notifications when an article marked as moderated is changed. 11. You can optionally set up a namespace for you to group articles. The main advantage to using a namespace rather than a category is to set up different member groups as administrators and users. For example, Ed & Eg cater to both businesses and individuals, so if they wanted, they could have created two namespaces so that their business articles and individual articles were separated. They could then have two member groups and allow members of the business member groups to add/edit content to articles in the Business namespace but not articles in the Individual namespace. For now, leave the namespace fields blank. 12. Click Update to create the wiki. 13. The final step is to create a new template and template group for your wiki. Go to Design | Templates | Edit | Create Group and call the new template group wiki. 14. Edit the index template of the wiki template group and add the following code. You do not need to include any other HTML or ExpressionEngine tags, as this tag will create the entire wiki. {exp:wiki base_path="wiki/index" wiki="money_saving_wiki" theme="azure"}
[ 256 ]
Chapter 9
If you use a different template group or template name, change the base_path parameter accordingly. The wiki parameter is the short name of the wiki. The theme can be either default or azure. You can also create your own themes by creating a new directory in your / themes/wiki_themes/ directory and copying and modifying the files from an existing theme. See http://expressionengine.com/user_ guide/modules/wiki/wiki_templates.html for more information.
15. Now view this template in a browser (http://localhost/wiki).
How does the wiki work? The next step is to create some content.
1. On the first page of the wiki, click Edit (at the top) to edit the page.
[ 257 ]
Beyond the Basics
2. You can type in whatever text you wish, using HTML for basic text formatting. To create a link to a new article, enclose the new article's name in double square brackets. For example: Welcome to our Money Saving Wiki. Here are some moneysaving ideas: <strong>[[Shopping]] Don't buy the name-brand of everything. Pick one or two items that you like, and for everything else, buy the store brand. Sometimes spending the extra 30 cents for the name-brand doesn't sound like much, but saving 30 cents on 30 items in a single trip, and doing 40 trips a year, will save you $360 this year!
For more money-saving tips when [[shopping]], click on the word [[shopping]].
3. In the notes section, write a brief description of the change you are making, such as "Added Tip on saving money when shopping". (This will show in the history log). Then click Submit.
4. You can now click on any one of the shopping links to be brought to a new article where you can create a new page with more text. Notice how you can have multiple links to the same article. Remember that a wiki is a multi-user environment. The intent is not to have one person create all the content, but for it to be a collaborative effort (although you may prefer to have one person add some content and develop the structure before making it more generally available).
5. The ExpressionEngine wiki also supports the use of categories. Use the following code anywhere in an article to assign the article to a Shopping category. [[Category:Shopping]] [ 258 ]
Chapter 9
You can assign an article to multiple categories. You can also assign articles to subcategories using a format such as: [[Category:Shopping:Store Brands]]
6. If enabled, you can also upload images, diagrams, and documents by clicking on File Upload on the left-hand menu. You can then embed uploaded files using either [[File:filename.txt]] (to create a link) or [[Image:image. jpg]] (to embed a picture). For more information on wiki syntax, visit http://expressionengine.com/user_ guide/modules/wiki/wiki_syntax.html.
Other ExpressionEngine modules
There are several other free modules that ExpressionEngine has which have not been covered here. •
The Discussion Forum is a module written by EllisLab but sold separately from ExpressionEngine (although it requires ExpressionEngine to run). The module leverages ExpressionEngine's Member module features, but has its own templating system and is styled via separate CSS. The best example of a discussion forum in action is the ExpressionEngine support forums (at http://expressionengine.com/forums).
•
Simple Commerce allows you to mark posts in channel entries as being for sale. You can create a channel of items for sale, set the price for each item and then accept payments through PayPal. All payment information is transferred directly between the visitor and PayPal—at no point does your website or ExpressionEngine handle payment information. Although Simple Commerce is not a fully-fledged e-commerce module, for smaller websites that do not need the complexity of a complete payment processing solution, Simple Commerce will likely meet your needs.
•
Blacklist/Whitelist is a spam prevention tool that allows you to block visitors by IP address, URL, or User-Agent. You can either block specific IP Addresses, URLs, or User-Agents, or you can enter a partial string to block anything that matches that string. You can also add items to your white-list (meaning that you could blacklist a certain IP address pattern, but make an exception for an IP address that you know is not spam). EllisLab provides a Blacklist and a Whitelist that you can download periodically to keep known spammers away.
[ 259 ]
Beyond the Basics
•
IP to Nation allows you to determine which country an IP address is associated with, and then ban visitors from that country from seeing your website (or display a flag next to comments or entries from visitors that come from that country).
•
Query is a very useful module for more advanced users, allowing you to run SQL queries against the ExpressionEngine database directly. Although it requires some familiarity with the ExpressionEngine database structure and with SQL syntax, it can allow you to display ExpressionEngine data in unique ways that might not otherwise be possible. See http:// expressionengine.com/user_guide/modules/query/index.html for examples of how to use this module within a template.
•
Referrer allows you to track which websites have links to your website that people are using to arrive at your site.
•
Statistics allows you to display certain facts about your website on a template (such as the number of people who are logged in, the date of the most recent comment, and the total number of comments that have been left on your site).
Multiple Site Manager
EllisLab also offers Multiple Site Manager for people who run multiple websites. Multiple Site Manager adds the ability to manage multiple websites from the same ExpressionEngine login (up to three sites are included with the initial purchase price, with the option to buy more if needed). The key licensing criterion is that you must be the owner of all the websites you manage. Each website is distinct in terms of templates, channels, and preferences, but addons, members, and member groups are shared across all three sites. In this way, members only have to register once for all the websites, as each of your websites can share the same modules and other add-ons (saving you from installing and configuring the same modules over and over again) and you can conveniently manage all your websites from the same control panel. Although not appropriate for everyone, Multiple Site Manager is a very powerful tool, making maintaining your websites much easier and at a lower cost than purchasing three separate licenses. More information can be found at http:// expressionengine.com/user_guide/cp/sites/index.html.
[ 260 ]
Chapter 9
Summary
In this chapter, you took a look at many of the modules that come bundled with ExpressionEngine. Some modules come pre-installed, some are included but not installed, and some have to be downloaded and installed separately. A typical module has a configuration screen (accessible via Add-Ons | Modules) and tags that can be used in templates to access the modules functionality. In the next chapter, you will be introduced to the other types of add-ons, including Accessories, Extensions, Fieldtypes, and Plugins. You will also learn about third party add-ons. Finally, you will learn key tips for running an ExpressionEngine website, including how to do database backups and version upgrades.
[ 261 ]
Extending ExpressionEngine So far, this book has taken a step-by-step approach to implementing the most popular modules in ExpressionEngine. In this chapter, you will not be building content for Ed & Eg's website, but rather looking at what else goes into maintaining an ExpressionEngine website. First, you will learn about essential maintenance tasks such as backups, restores, and upgrades. You will then be introduced to many of the most highly-rated addons that are available for ExpressionEngine before finally getting an overview of ExpressionEngine's spam controls, as well as ways to fine-tune ExpressionEngine. After completing this chapter (and the book), you will feel confident creating and maintaining an ExpressionEngine-powered website.
Backups and restores
ExpressionEngine is a database-driven application. So to back it up, you need to back up both the individual files on your web server and the database itself.
Backups
To back up ExpressionEngine, you need a tool such as phpMyAdmin. If your website is hosted by a website hosting provider, contact them and ask if phpMyAdmin or another tool is installed that will allow you to do MySQL database backups. If necessary, phpMyAdmin can be downloaded from http://www. phpmyadmin.net/. phpMyAdmin is included with local development environments, including WampServer, XAMPP, and MAMP, usually at an address such as http:// localhost/phpmyadmin (all in lower-case).
Extending ExpressionEngine
1. The first step to doing a backup is to clear all the unnecessary data from the database (such as cached templates). Log in to the control panel and select Tools | Data | Clear Caching. Select All caches and click Submit.
2. Access the phpMyAdmin control panel.
3. On the left-hand side, select the ExpressionEngine database (such as ee). After selecting the database, you are brought to a screen that shows all the ExpressionEngine tables on the left-hand side (beginning with exp). 4. In the main window, select Export from the top menu.
[ 264 ]
Chapter 10
5. On the Export page, at the top of the left column, verify that all the tables are selected.
6. All the options on the right-hand side can be left at their default settings. At the bottom, check the box Save as file. Select a Compression method of either zipped or gzipped and then select Go.
7. You are then prompted to save the file; save it to a safe place. Note that while phpMyAdmin is sufficient for smaller databases, the backup may time out when backing up very large databases. One option to work around this is to split out the database backup so that not all the tables are backed up into a single file. Another option is to look at the command line MySQL code or a utility such as My SQL Dumper (http://www.mysqldumper.de/en/).
In addition to backing up the MySQL database, it is also prudent to back up all the files on your web server, including any themes, language packs, and add-ons that may have been installed as well as any files that may have been uploaded to your File Upload Destinations (such as the /images directory).
[ 265 ]
Extending ExpressionEngine
Database restores
A backup is only useful if it is usable, and the only way to know if a backup is usable is to restore it. To test a database restore, it helps to have a second database created in phpMyAdmin (if your hosting package includes two databases). Alternatively, you can test a restore to a localhost environment. Testing a database restore using a different database or a localhost server is easy enough, but bringing up an entire ExpressionEngine website on a different database or server is more complicated. The guidelines on how you can accomplish this can be found in the ExpressionEngine wiki at http://www.expressionengine.com/wiki/.
1. If you are restoring a database to a test database, you can follow the instructions at the beginning of Chapter 1, Getting Installed to create a second database. 2. If you are restoring over the top of an existing ExpressionEngine database, you first have to delete the existing tables. In phpMyAdmin, select the database you are restoring to and select Structure from the menu at the top of the main window. Scroll all the way down and select Check All to check all the tables. In the drop-down box, select Drop. A confirmation window will appear—click Yes. Before doing this, be very sure that the database is well backed up or that losing all the data in all the tables will not be a problem.
3. Next, in the empty database, select Import from the menu in the top window. 4. Browse to the location where the database backup was saved. Leave all the other options at their defaults and click Go. [ 266 ]
Chapter 10
5. When the import is complete, there will be a message that says Import has been successfully finished.
6. If you are restoring to the same database/server that the backup was made from, make sure that the corresponding files have also been restored (including the /system directory).
Upgrading ExpressionEngine
EllisLab is always working on new versions of ExpressionEngine. These versions are often packed full of new features as well as security updates and bug fixes. Occasionally, EllisLab will put a price on a new feature (such as the discussion forum). However, the prices are very fair, and reflect the cost of development and support. Doing this keeps the cost of ExpressionEngine itself lower for those users who have no interest in the new feature.
There are two types of releases that ExpressionEngine goes through: •
A new build contains bug fixes or minor updates. It is generally not necessary to upgrade to a new build unless it contains a bug fix that you have been waiting for. Builds are numbered by date, and you can see what build you have in the footer of any page in the control panel.
•
A new version contains new features and improvements to existing functionality. A new version will include all the bug fixes and minor updates of any intermittent builds. Versions are numbered sequentially (such as 2.0.0, 2.0.1, 2.0.2, 2.1.0, and so on).
[ 267 ]
Extending ExpressionEngine
When a new version is released, ExpressionEngine will indicate this prominently on the control panel home page.
When upgrading, you can skip builds, but it is not recommended to skip too many versions. Not only will you miss out on security updates, bug fixes and new features, but if you seek support in the forums and there are significant changes between your version and the current version, you may be asked to upgrade. The instructions for updating to the latest build can be found at http://www. expressionengine.com/user_guide/installation/update_build.html and the instructions for updating to the latest version can be found at http:// www.expressionengine.com/user_guide/installation/update.html. The
instructions are basically the same, except that for a new build, you do not have to run the server update wizard. The basic instructions for upgrading to a new version are as follows: 1. Download the latest version of ExpressionEngine. Read the version update notes (step 5 at http://www.expressionengine.com/user_guide/ installation/update.html) to verify there are no changes that might have a big impact on the specific website that is being updated—for example, a compatibility issue with an add-on that is used. 2. Perform a backup of the database and ideally back up your entire website, including the system, themes, and images directories as well as the index. php file (located in the root directory of your website—though it may have been renamed as part of the ExpressionEngine installation in Chapter 1, Introduction to ExpressionEngine). 3. Take your website offline. ExpressionEngine includes an offline.html template in the /system/expressionengine/utilities/ directory that you can modify and copy to the root of your website. Rename your index. php to index_old.php and then rename offline.html to index.php. 4. If you chose to rename index.php as part of your ExpressionEngine installation, then replace the renamed file with the offline.html template instead.
[ 268 ]
Chapter 10
5. Clear your cached data. Log in to the control panel and select Tools | Data | Clear Caching. Select All caches, and click Submit. 6. On your website, rename your system and themes directories to system_old and themes_old. By keeping the directories on the server for now, it makes it easier to roll back the update if, for some reason, an issue is encountered. The official update instructions recommend renaming the new files being uploaded first, then renaming the existing files after the new files are uploaded, and finally renaming the new files to the names of the original files. This is equally effective and potentially minimizes downtime (if you wanted to keep the website up while the new files are being uploaded).
7. Upload the system and themes directories from the new ExpressionEngine version to your website. You will upload the index.php file right before the upgrade so that, for now, your website continues to reflect that it is offline. If you use additional control panel themes, such as Corporate, Fruit, or the Mobile theme, you will also need to download these themes from http://www.expressionengine.com/ and upload them to the /themes/cp_themes/ directory.
8. From the backup of your old system directory, upload the following directories to your new system directory: /system/expressionengine/third_party/ /system/expressionengine/config/ /system/expressionengine/templates/
9. Set the file permissions for /system/expressionengine/config/config. php and /system/expressionengine/config/database.php to 666 (writeable). Set /system/expressionengine/cache to 777 (writeable). 10. Now upload the index.php file, overwriting the offline template that you earlier saved as index.php. [ 269 ]
Extending ExpressionEngine
11. If this is a version update rather than a build update, point your browser to / system (for example, http://localhost/system or http://www.example. com/system) and follow the on-screen instructions to perform the update to the latest version.
12. After you see a message saying that you are running the most current version of ExpressionEngine, delete the /system/installer directory. 13. If you renamed your system directory, you will need to edit the newly uploaded index.php and update the $system_path = './system'; line towards the top of the file to reflect your renamed system directory. 14. If you mask the location of your control panel by accessing your control panel from a URL other than http://localhost/system/index.php (such as http://localhost/admin.php), you will also have to copy /system/ index.php and replace your masked-access file (such as /admin.php). Once you have done this, you will also have to update the $system_path = ''; line towards the top of the file to reflect the path to your system directory. 15. Follow the Version Specific Notes for any versions between the version you are updating to and the version you are updating from. The Version Specific Notes will contain details on any changes that need to be made above and beyond the normal upgrade changes just listed. For example, if additional files need to be uploaded, a theme or language pack has been updated, or if a new setting in the control panel needs to be defined, the Version Specific Notes is where you will find that out. If you have customized your own themes and the Version Specific Notes indicate that a theme was updated, you will have to manually update your theme with the same changes that were made to the built-in themes. Luckily, EllisLab is very good at identifying these changes in a version upgrade and at outlining what needs to be done.
16. Verify that your website is working as expected, and then delete the system_ old and themes_old directories, as well as the index_old.php file at the root of your website. [ 270 ]
Chapter 10
When you first log into the control panel, you will be warned that one or more core files have been changed—click to accept these changes. You may also receive an e-mail saying the same thing.
17. Finally, in addition to ExpressionEngine itself, modules you install (such as the Discussion Forum and Multiple Site Manager) can also be subject to new versions. For example, the discussion forum version update instructions can be found at http://expressionengine.com/user_guide/modules/forum/ forum_update.html.
ExpressionEngine add-ons
Although not open source software, ExpressionEngine has many ways in which both EllisLab and the members of the ExpressionEngine community can add to it. ExpressionEngine 2 is built on CodeIgnitor—an open source PHP web application framework also by EllisLab. CodeIgnitor is a popular framework for PHP developers, allowing rapid development of PHP web applications. For ExpressionEngine users, this means that add-on developers have the ability to build more complex add-ons (even entire applications) for ExpressionEngine by using CodeIgnitor. It also means that there is a much larger base of developers who can build ExpressionEngine add-ons. More developers building more and more complex add-ons for ExpressionEngine can only mean one thing. If there is something you need to do that is not supported natively, there is likely an add-on for it. The add-on market has grown hugely in the last few years and there are now several companies that have either started or been able to branch into developing and selling ExpressionEngine add-ons. Although this means that some add-ons come at a cost, it also means those same add-ons are likely to be high-quality, reliable tools to expand the functionality of ExpressionEngine. The best resource for ExpressionEngine add-ons is http://www.devot-ee.com/—an official EllisLab community partner.
Types of add-ons
ExpressionEngine add-ons come in five flavors, namely, modules, accessories, extensions, fieldtypes, and plugins. All add-ons are managed through the Add-Ons menu in the control panel—here you can install, uninstall, or access the configuration screens (if applicable). [ 271 ]
Extending ExpressionEngine
Modules
Throughout this book, you have been working with ExpressionEngine modules, including the Channel module, the Member module, the Comment module, and the jQuery module. A module can be simple and focused (that is, do one thing and do it well), or they can be close to applications in their own right, complete with their own control panel configuration screens and their own library of tags. Some modules are aimed at control panel users and do not add any visible functionality to the frontend of your website—an example is the Blacklist/Whitelist module, which allows you to block spammers from your website but does not change anything on your website. Other modules are designed specifically to add functionality to your website—they provide tags that can be used within templates so that you can control where this functionality appears and how it looks. The Search module works like this—it does not add any functionality to the control panel, but it allows you to add integrated searching capabilities to your website. Finally, there are modules that add functionality to both the control panel and your website. For example, the Mailing List module provides a control panel configuration screen where you can set up mailing lists and manage subscribers, and it also provides tags that you can use in templates to allow visitors to sign themselves up. Modules can read and write data to your database, making them a very powerful tool in an ExpressionEngine installation.
Accessories
Accessories are new in ExpressionEngine 2. They are the tabs that appear on the bottom of each control panel page.
ExpressionEngine comes bundled with the ExpressionEngine Info accessory installed and three other accessories that are included but not installed (Learning EE, News and Stats, and Quick Tips).
[ 272 ]
Chapter 10
To install a new accessory, you can go to Add-Ons | Accessories, and then click Install on the accessory (or accessories) of your choice (third-party accessories must be uploaded to the /system/expressionengine/third_party/ directory before they appear in this list to install). Once installed, clicking on an accessory name will open a preferences page where you can define which member groups can see the accessory and on what control panel pages the accessory appears. In this way, an accessory that is useful when creating templates (for example) can be set to appear only on Design pages of the control panel, and only to member groups that would be working with templates.
Building your own accessory is a great way to start getting into ExpressionEngine add-on development. One use for an accessory (if you build websites for clients) is that it can be used to provide easily accessible help and tips to your client, right inside the ExpressionEngine control panel.
Extensions
Extensions are a type of add-on that uses hooks within ExpressionEngine to modify how ExpressionEngine itself works. Unlike modules, extensions do not have tags that are used in templates. Instead, they modify aspects of how ExpressionEngine works. For example, there are extensions that allow you to change how CAPTCHA works, that allow you to change the page ExpressionEngine loads after a member logs in, and that allow you to change system messages so that they use a regular template instead of the template found under Design | Message Pages | User Messages. [ 273 ]
Extending ExpressionEngine
Like accessories, third-party extensions need to be uploaded to /system/ expressionengine/third_party/ before they can be enabled from the Add-Ons | Extensions control panel page. Most extensions will come with instructions on how to install them. ExpressionEngine does not come bundled with any extensions that are ready to go, but extensions are a very common type of add-on.
Field types
ExpressionEngine comes bundled with several different types of fields that can be used in entries. Throughout this book, you have used Text Input and Textarea extensively. You used File when building the photo gallery and you also used the Relationship field when building the calendar so that you could relate events in one channel to event sponsors in another. Fieldtype add-ons allow you to expand the range of fields that you can use for your channels.
Plugins
Plugins are the most basic form of add-on for ExpressionEngine. Unlike a module, plugins cannot store data in the database (though they may still query the database), and do not have their own control panels. Unlike an extension, plugins do not change the functionality of ExpressionEngine itself. A plugin works by making one or more tags available that can then be used in templates. Like other add-ons, third-party plugin directories need to be uploaded to /system/ expressionengine/third_party/ before they can be enabled from the Add-Ons |
Plugins control panel page. Clicking on the title of an installed plug-in will give you instructions on how to use it.
[ 274 ]
Chapter 10
Plugins exist for lots of nifty purposes—replacing text with other text, creating random text, converting kilograms to pounds, the list is endless. For EE2 compatible plugins and other add-ons, please visit http://www.devot-ee.com/.
Third-party add-ons and add-on developers
While there are far too many add-ons to list them all, what follows are some prominent add-on developers whose add-ons are worth knowing. This is not a comprehensive list, and it can be expected that different people would have different ideas regarding which add-ons are the most useful. Devot:ee is the best place on the web to find up-to-date information about add-ons, and EE Insider (http://www.eeinsider.com/) is another good site to follow for tips, information, and interviews on all things ExpressionEngine.
Pixel & Tonic http://www.pixelandtonic.com/
Although Pixel & Tonic is a relatively new company, Brandon Kelly has been building add-ons for many years, including the FieldFrame extension that became the basis of the Fieldtype add-on in ExpressionEngine 2. Several of Pixel & Tonic's add-ons are considered essential by ExpressionEngine developers, including: •
•
•
Matrix: This adds the ability to have tables in your channel entries. This is a huge improvement over using repeated textarea and text input fields for as many "rows" as you are likely to need. With Matrix, you can define the columns and in each entry, create as many rows as you need. Matrix can be used whenever tabular data is involved. One common use is to create photo galleries where each channel entry represents a gallery containing multiple photos (one per row) as opposed to having one photo per-entry (like you did when building the photo gallery in Chapter 8, Creating a Photo Gallery). Playa: This is a field type that works very similarly to the Relationship field that is built into ExpressionEngine, but instead of only allowing you to relate only one entry in another channel to your entry, Playa allows you to relate multiple entries in many other channels to your entry. Using the calendar example from Chapter 7, Creating a Calendar, you could have multiple sponsors for each calendar event, instead of being limited to picking just one (or having to create multiple Relationship fields). Wygwam: This adds WYSIWYG (What You See Is What You Get) functionality to ExpressionEngine's publish page. Instead of plain-text fields on the Publish page, Wygwam allows you to create content using wordprocessor-like functionality—you can add images, format, and layout the text just like you would in a word processor. [ 275 ]
Extending ExpressionEngine
Solspace http://www.solspace.com/
Solspace is a leading add-on developer for ExpressionEngine. Their work includes: •
Tag: A module that allows you to tag channel entries and organize your content by tag. You can also build a tag cloud.
•
FreeForm: A module that makes it easy to create and manage forms that collect information from your visitors.
•
User: A module that overhauls ExpressionEngine's native member functionality, bringing the default member templates into regular templates and making them much easier to customize and brand.
•
Facebook Connect: A module that adds Facebook SSO (Single Sign-On) capabilities to your website.
•
Super Search: This is a module that overhauls ExpressionEngine's native search functionality, improving the performance and allowing results to be sorted by relevance.
•
Friends: A module that updates the member functionality to be more like a social network. Members can invite each other to become friends, they can restrict their profile so that it is only visible to their friends and they can post status updates similar to Facebook or LinkedIn (at the time of writing, this module was not yet compatible with EE2).
•
Calendar: A full-featured calendar that goes far beyond what is possible with ExpressionEngine's built-in calendar functionality (the main improvement being the addition of recurring events—a key requirement of most calendar applications) (at the time of writing, this module was not yet compatible with EE2).
Newism (Leevi Graham) http://www.expressionengine-addons.com/
Newism is the author of many very popular ExpressionEngine 1 add-ons. Newism's add-ons include: •
NSM Addon Updater (previously LG Addon Updater): This accessory works with other compatible add-ons to let you know when a new version of the add-on is released. Each compatible add-on is listed in an accessory tab, along with the installed version and the latest available version.
[ 276 ]
Chapter 10
•
NSM Better Meta (previously LG Better Meta): This extension makes it easy for you to generate unique HTML meta tags for each entry without having to create custom fields in each of your channels for the meta tags (such as description, keywords, author, and so on). By having unique meta tags on your pages, your website is more search-engine friendly, potentially making it easier for people to find you through search engines. The extension can also generate search engine XML sitemaps.
•
NSM TinyMCE (previously LG TinyMCE): This is a free WYSIWYG custom field type, similar to Wygwam.
•
NSM Transplant (previously LG Replace): When creating new entries on the Publish page, this plugin allows you to insert the contents of one custom field inside the contents of another custom field. For example, if you have one or more image fields and a textarea field, you could insert a tag (called a needle) inside the text area so that the images appear within your text. (In your template, you can only place custom fields before or after each other, not inside each other).
•
NSM Live Look (previously LG Live Look): This extension allows you to view what your entry will look like on your website, directly from the Publish page.
Low (Lodewijk Schutte) http://www.loweblog.com/software/
Low has created many ExpressionEngine add-ons, including Low NoSpam, which will check comments, forum posts, and wiki articles submitted to your site against a service such as Akismet or TypePad AntiSpam to see if the submission is spam. Low Variables is another add-on that builds upon and improves ExpressionEngine's native variable management, allowing you to hide variables from other control panel users on a per-variable basis, as well as allowing you to group, sort, and label them.
nGen works http://www.ngenworks.com/software/ee/
nGen Works have built a number of ExpressionEngine add-ons, of which one of the most popular is Structure (http://www.buildwithstructure.com/). Structure bypasses the template structure of the standard ExpressionEngine website and instead allows you to define static and dynamic pages in an easy-to-use site-map view.
[ 277 ]
Extending ExpressionEngine
Other notable add-ons
The following add-ons can also be useful when building ExpressionEngine websites: •
Template Variables (by Matthew Krivanek) is a third-party accessory that displays the custom field names, snippets, and global variables that are on your site, so that you never again forget what you called a particular field, snippet or variable. The accessory includes quick links to add or edit custom fields, snippets, and global variables. Clicking a name copies the syntax onto the clipboard for easy pasting into a template (http://www.devot-ee.com/ add-ons/template-variables/).
•
Image Sizer (by David Rencher) is plugin that makes a template tag available which, when wrapped around an HTML tag, will resize the corresponding image to the size specified in the parameters and cache the resized image. This means that instead of having to require images to be of a certain size when they are uploaded to ExpressionEngine, they can be dynamically resized from within the template the first time the template is accessed. The plugin has won Devot:ee's AcademEE Plugin of the Year award multiple times (http://www.devot-ee.com/add-ons/imagesizer/).
•
First Timer (by Ryan Irelan) is an extension that allows you to alter where members are redirected to after they log in (http://www.devot-ee.com/ add-ons/first-timer/).
•
Backup (by Thomas Myer) is a module that makes it easy to do a database backup and download the file right from within the ExpressionEngine control panel—no logging into phpMyAdmin needed (http://www.devotee.com/add-ons/backup/).
•
Accessible Captcha (by Greg Salt) is an extension that changes the graphic CAPTCHA to a random question & answer system that plays well with screen-readers in a way that image-based CAPTCHAs do not. It works in much the same way as a regular CAPTCHA—making it easy for a person to complete the question, but making it difficult for an automated script to do so (http://www.devot-ee.com/add-ons/accessible-captcha/).
•
MD Detect Page Type (by Ryan Masuga) is a plugin that can be used in a template to detect what type of page is being rendered. This makes it easy to build conditional statements based on whether a page is a basic multipleentry page, a category page, a paginated page, an archive page or a singleentry page, and therefore makes it easier to use a single template for some or all of these scenarios (http://www.devot-ee.com/add-ons/md-detectpage-type/).
[ 278 ]
Chapter 10
•
Custom System Messages (by Brian Litzinger) is an extension that allows you to change the template that system messages are displayed with, allowing your system messages to share the same layout as the rest of your website and allowing you to use the full range of ExpressionEngine tags on the page (http://www.devot-ee.com/add-ons/custom-systemmessages/).
•
Channel Images (by DevDemon) is a module/extension that improves upon ExpressionEngine's native file manager functionality, including features such as multi-select image uploads from the control panel (http://www.devotee.com/add-ons/channel-images/).
•
Search Results (by Planet/EE) is a module that improves upon ExpressionEngine's default search capabilities, allowing you to group and sort search results, highlight search terms, use custom fields in search results, and more (http://www.devot-ee.com/add-ons/search-results/).
•
Cartthrob (by Chris Newton) and FoxEE (by HCC Development) are both full-featured shopping cart modules. (At the time of writing, they are not yet available for ExpressionEngine 2; http://www.devot-ee.com/add-ons/ cartthrob/ and http://www.devot-ee.com/add-ons/foxee/).
There are many more add-ons available for ExpressionEngine—more than can possibly be listed here. If there is something you wish ExpressionEngine could do (or could do differently), search the add-on library at http://www.devot-ee.com/ first.
Optimizing ExpressionEngine
Out-of-the-box, ExpressionEngine works very well, but on larger sites that attract more traffic, there are several options to fine-tune that can help you keep ExpressionEngine humming.
[ 279 ]
Extending ExpressionEngine
Spam
One downside of any website that allows members of the public to submit content is spam. Spam can take many forms, including comment spam, forum spam, and member registration spam (where spammers register as new members on your site and then place links in their profile pages), Luckily, ExpressionEngine has several tools you can use to combat spam, many of which are outlined in the ExpressionEngine documentation at http://www.expressionengine.com/user_ guide/general/spam_protection.html. Suggestions include: •
Use the blacklist/whitelist module to keep known spammers from your website and prevent content (in comments or member profile fields) that matches anything in the blacklist from being submitted. There is a oneclick option to download the latest blacklist from ExpressionEngine and you can also add items to the blacklist/whitelist that may be unique to you (downloading the list will not overwrite anything you add manually). The bottom line is that there is no reason not to use this module. (This module can be found in Addons | Modules in the control panel).
•
Require all comments to be moderated, require membership in order to post comments, or enable CAPTCHA for comment postings. If nothing else, you should ensure that you are set up to receive e-mails whenever comments are posted. All these settings can be found under Admin | Channel Administration | Channels for each channel.
•
Enable membership CAPTCHA (under Members | Preferences) or require all new member registrations to be activated manually by an administrator (though even administrators may not be able to spot spam registrations).
•
Disable New Member Registrations entirely (under Members | Preferences) if you do not plan to use the member features of ExpressionEngine. Remember that this feature is enabled by default, meaning that even if your website does not link to the member URLs, the member URLs are active. [ 280 ]
Chapter 10
•
Use Word Censoring (under Admin | Security and Privacy | Word Censoring), which allows you to replace any user-submitted word (or partial word) with the # symbol (or a word of your choice).
•
Apply Rank Denial (under Admin | Security and Privacy | Security and Sessions). This makes your website less attractive to spammers because user-submitted links point to a redirect page on your own site rather than pointing directly to the spammer's site. This means that any links posted to your website will not improve the spammers search engine page rank.
•
To prevent Denial of Service attacks, ExpressionEngine has Throttling Preferences (under Admin | Security and Privacy) that allow you to set how many pages can be downloaded in a given time period by a single person before that person is temporarily locked out.
•
Other recommendations in the documentation include setting a longer Comment Time Interval in the preferences for each channel (to prevent spammers from submitting hundreds of comments in a short space of time), using Secure Form Mode in the Security and Session preferences to prevent the same form being submitted multiple times without being refreshed and Deny Duplicate Data (also in the Security and Session preferences) to prevent the same comment being made more than once.
•
Finally, in addition to ExpressionEngine's built-in features, there are also several add-ons including Accessible CAPTCHA, Low NoSpam, and No Follow, all designed to make your website less attractive to spammers. Search for these and others at http://www.devot-ee.com/.
In summary, none of these options are a perfect solution, and there is certainly a trade-off between functionality and anti-spam controls. For example, requiring membership to post comments does not prevent a member from posting spam in comments but it at least provides an extra layer of protection.
Performance
ExpressionEngine is database-driven, and for most websites, the performance is excellent out of the box. With that said, if you are expecting high traffic volumes, it is worth being aware of (and following) good design practices as you build your website. The most fundamental technique that you can use to reduce template load times is reducing the number of ExpressionEngine tags in a template. A template that uses multiple embedded templates, nested conditionals, add-ons, and so forth involves more database queries and so will take longer for ExpressionEngine to render than a simple template with only a handful of standard ExpressionEngine tags. [ 281 ]
Extending ExpressionEngine
Other techniques to reduce page load times include the following: •
Use embedded templates, snippets, and global variables appropriately. An embedded template comes with all the overhead of rendering a template, whereas a snippet does not. So, if a snippet can be used instead of an embedded template, it should be.
•
Use the Disable Parameter liberally. By default, the {exp:channel:entries} tag fetches all the information about the channel entry that is stored in your database (including category information, member data, and the data in the custom fields). In many cases, you do not use all this data, so there is no point in retrieving it from the database. The disable parameter allows you to reduce the number of database queries by turning off queries for certain types of data. For example, you used this parameter when retrieving the entry title for the HTML in your single-entry templates. Since you only needed the title of the entry (which is not a custom field), disabling all the extra database queries made sense: disable="categories|category_fields|custom_fieldsmember_ data|pagination".
For more information on the disable parameter, visit http://www. expressionengine.com/user_guide/modules/channel/ parameters.html#par_disable.
•
Use Simple Conditionals instead of complex conditionals. A simple conditional is an if statement that evaluates one condition and does not have any if:else clauses. A simple conditional is parsed early, meaning that any ExpressionEngine tags within the simple conditional are ignored if the condition is false. More complex conditional statements (involving multiple conditions or multiple else clauses) are parsed later, meaning any ExpressionEngine tags within them are parsed, even if the condition turns out to be false.
•
Consider enabling GZIP output. This option (under Admin | System Adminstration | Output and Debugging Preferences) compresses website pages (which are then decompressed seamlessly by most modern browsers). This can result in faster download speeds.
•
Optimize ExpressionEngine's SQL tables. Under Admin | Utilities | SQL Manager, select Manage Database Tables, select all tables, and click Optimize. When run from time to time, this can help make database queries faster by eliminating database fragmentation.
[ 282 ]
Chapter 10
ExpressionEngine also includes a variety of different types of caching that can help improve performance by minimizing the number of queries needed to render a template. The benefits of enabling these options can vary depending on the server the website is hosted on (if the server already has caching enabled, then enabling caching within ExpressionEngine may cause double-caching and therefore an increase in load). More information can be found at http://www. expressionengine.com/user_guide/general/caching.html. ExpressionEngine caching is useful to reduce the number of database queries that a specific URL creates (such as your home page). However, caching is done by URL, meaning that for each new URL, a new cache is created, even if the elements on the pages at two different URLs come from the same template. Given that a single template can be the basis of hundreds or thousands of URLs (depending on the number of channel pages), websites with a lot of traffic spread over a large number of URLs may not see much benefit in page load times by caching, even if the traffic is concentrated on a small number of templates.
For sites with high traffic loads, the documentation also includes information on how to further optimize ExpressionEngine by turning off tracking and minimizing Disk I/O. Please see http://www.expressionengine.com/user_guide/general/ handling_extreme_traffic.html for more information. Solspace offers a Site Performance Evaluation for ExpressionEngine sites (http://www.solspace.com/development/ performance/) that may be worth considering for large, high-traffic websites.
Summary
In this chapter, you learned about the routine maintenance tasks that come with running a powerful database-driven website (such as database backups and software upgrades). You learned about the different types of add-ons that ExpressionEngine accommodates, and about specific add-ons and add-on developers that are worth being aware of. Finally, you learned about optimizing ExpressionEngine to fight spam and improve page-load times. The key points to remember after working through this chapter (and the book) are: •
Back up your website, including the database.
•
Upgrade ExpressionEngine when new versions are released (or at least every few versions). If you continue to use an older version, you will not have all the latest features and bug-fixes, and newer add-ons may not be compatible. [ 283 ]
Extending ExpressionEngine
•
ExpressionEngine is highly extensible, and many of the add-ons are highquality commercial grade pieces of software. If there is something you wish ExpressionEngine could do, research the add-on library first.
•
The ExpressionEngine documentation is an excellent resource—clear, concise, accurate, and with plenty of examples. It is a great way to learn about a new feature (or to learn more about a feature you are already familiar with).
•
Visit the ExpressionEngine support forums often (http://www. expressionengine.com/forums). If there is something you are trying to accomplish, the chances are good that someone else has tried the same thing. A quick search can often reveal lots of ideas. The how-to forum is a great place to get ideas, seek advice, or even get feedback.
[ 284 ]
Installing WampServer In this appendix, you will walk through downloading, installing, and setting up WampServer. This will allow you to run ExpressionEngine on your own computer. If you already have WampServer installed (or an alternative product such as XAMPP or MAMP for Mac OS X), then you can skip these instructions. WampServer is a free package that includes an easy-to-set up web server (Apache), database server (MySQL), and server-side scripting language (PHP), all of which are requirements of ExpressionEngine. Installing WampServer lets you experiment with ExpressionEngine on your own computer instead of a live website. Setting up each piece of an Apache, MySQL, and PHP (AMP) environment individually can be complicated, but with WampServer, the system comes pre-configured and ready to go, so you can concentrate on learning ExpressionEngine. You are installing WampServer as a development (or testing) environment only. You will not be using WampServer to build a live server that presents your website to the outside world. Setting up and securing a production web and database server is a topic beyond the scope of this text.
WampServer is a Windows only package. If you are using Mac OS X, MAMP is a good alternative (http://www.mamp.info). XAMPP is another alternative that is available for Windows, Linux, Mac OS X, and Solaris. If you choose to use an alternative package, the installation instructions for that package are going to be different and there may be some differences when you install and configure ExpressionEngine on your server in Chapter 2, Getting Installed. However, ExpressionEngine itself will work exactly the same.
Installing WampServer
WampServer is free to download, and the package contains the following: •
The AMP environment of Apache, MySQL, and PHP (needed to install ExpressionEngine)
•
phpMyAdmin, which is the leading web-based interface to MySQL (needed to manage the ExpressionEngine database)
Installing WAMPServer First, you must download WampServer:
1. Visit http://www.wampserver.com/en 2. On that page, there will be a link to the download page of WampServer. Select it and you should see a link to download WampServer. 3. Clicking the download link will take you to SourceForge.net where you can download the file. The file download should begin automatically, but if it does not start, there should be a direct link that you can use to start the download. If you have Internet Explorer 7 or higher, it may block the site from downloading files to your computer. A warning will appear in a small bar at the top of your browser screen. Click on it and select Download File.
4. Next you will be prompted to save the file. Save it to your Downloads, Desktop, or My Documents area. Depending on the speed of your Internet connection, the file may take some time to download. Now that you have downloaded the software, the next step is to install it. If you are running the Skype VOIP application, or IIS Server, you will need to exit them before proceeding. Apache cannot start as a service if Skype or IIS is also running as they all use port 80. If you have Skype, you can set it to no longer use port 80 by going into the Advanced page of the options screen in Skype.
1. Double-click on the file that you downloaded in order to run it. If you get a Windows security warning, click on Run. 2. A welcome screen will display. Click on Next.
[ 286 ]
Appendix A
3. A license agreement screen will display. WampServer is an open source software package released under the GNU General Public License. Accept the license agreement. 4. WAMPServer, by default, installs in C:\wamp, and that is where this book will assume it is installed.
5. Select whether you would like a Quick Launch or Desktop icon, then click on Next. 6. A summary screen will display, showing where WampServer will be installed. Click on Install.
[ 287 ]
Installing WampServer
7. The installation will take a few minutes to run, during which you will see all the files being extracted. After all the files have extracted, a dialog box will appear asking you to pick your default browser (this is used by WampServer to know what browser to use when you use WampServer shortcuts to open your website; it does not prevent you from using other browsers installed on your machine if you later wish to do so). If you have Firefox installed, it will ask if you wish to use Firefox. If you do not, browse to Internet Explorer (typically located in C:\Program Files\Internet Explorer\iexplore. exe). Click on Open.
8. The installation will run for a little longer, and then you will be prompted for your PHP mail parameters. Although ExpressionEngine does make use of e-mail (for example, when registering new members), it is not an essential part of this book. If you have an SMTP server you can use, feel free to enter the information, otherwise accept the default settings. Click on Next.
[ 288 ]
Appendix A
9. Finally, leave the checkbox to launch WampServer checked and click on Finish.
WampServer is now installed and running.
Using WampServer
When WampServer is running, you should see a new icon on your taskbar next to the clock. Clicking on this will produce a menu with useful links. (If you do not see the icon, try launching WampServer again by clicking on start WampServer under WampServer in your Start menu).
[ 289 ]
Installing WampServer
Localhost will launch your website (you can also access your website by visiting http://localhost/ in your browser). phpMyAdmin is used to manage your website databases, and we will use it in Chapter 2 to set up the database that ExpressionEngine will use. www directory will open C:\wamp\www in Windows Explorer. Any files placed in this directory will be visible on your website. This directory is therefore where you will place your ExpressionEngine installation files. The other options allow us to control the different services individually. You can stop and start services individually (or stop and start all services). You can also switch between versions and change settings specific to each service. By default, when you visit http://localhost/, you will see a WampServer home page. If you are using Internet Explorer and see a message at the top of your screen that says Intranet settings are now turned off by default, left-click on it and select Don't show this message again.
In order for us to develop our website, you should delete this welcome page.
[ 290 ]
Appendix A
This welcome page displays configuration information about your PHP installation. A comprehensive view of the same information can be accessed from within the ExpressionEngine control panel (under Tools | Utilities | PHP Info).
1. Navigate to C:\wamp\www and delete the file index.php. 2. In your browser, navigate to http://localhost/, and you should now see an empty directory listing.
Allowing .htaccess files to be used
To take advantage of some features in ExpressionEngine (such as removing the index. php from ExpressionEngine URLs), you need to use a .htaccess file, which requires the Apache module mod_rewrite to be enabled. 1. Left-click the WampServer task bar icon, click Apache | Apache Modules, and then scroll down the list of modules until you see the rewrite_module. Left-click on the rewrite_module option to enable it.
[ 291 ]
Installing WampServer
It will take a few seconds for it to enable, but then your .htaccess files will be recognized; you will be using them in Chapter 2, Getting Installed.
Summary
In this appendix, you walked through the installation of WampServer, one of several products available for simulating an Apache, MySQL, and PHP environment on your computer. Other alternatives include XAMPP and MAMP (for Mac OS X). The key points to remember after working through this appendix: •
Your website can be accessed in a browser at http://localhost/.
•
To upload files to your local website, you have to save them in C:\wamp\www.
[ 292 ]
Solutions to Exercises Most of the exercises throughout this book have more than one solution. The following are the example solutions to some of the exercises in this book. Where a solution has not been provided, the instructions in the chapter can be adapted to complete the exercise. Chapter 3, Exercise 1 To limit the entries that are displayed to 2, you need to edit the channel tag to read as follows: {exp:channel:entries channel="news" limit="2"}
Chapter 3, Exercise 2 To post a new entry to a channel, log into the control panel at http://localhost/ admin.php (or http://localhost/system/index.php), and select Content from
the menu at the top of the screen. Highlight Publish and then select the channel you wish to post to (in this case, News), and type in the new entry. Select an image and then click Submit when you are done. Chapter 3, Exercise 3 To edit an entry, you can either select Content from the main menu, then select Edit, or you can select Entry under Modify or delete. Click on the entry you wish to edit and then edit away.
Solutions to Exercises
Chapter 3, Exercise 4 Try searching for html css tutorials in your favorite search engine. A couple of good resources include: • •
http://www.htmldog.com/guides/ http://www.w3.org/Style/Examples/011/firstcss
If you prefer learning from a book, pop down to your local bookstore's Computing & Technology section, and you will find plenty of books. Look for ones that focus on HTML and CSS, rather than other software applications (such as Dreamweaver). Chapter 4, Exercise 1 To create new pages, select Content | Publish | Website and copy in the text from the corresponding static HTML file. Add in HTML tags for the headings (), links (using {site_url}), and italic (<em>) where appropriate, and remember that you can choose the previously uploaded picture, rather than uploading the picture again. Make sure that the URL title for each entry matches the URL title in the table below. Next, create the following template groups and select to duplicate the site template group. Then edit the index template of each group and adjust the url_title parameter to be as follows: Template Group Name
URL Title
business
small_business
contact
get_in_touch
promotion
promotion
Notice how when you enter e-mail addresses into the Contact Us entry, they are automatically converted to links on your page. The links are automatically encrypted using JavaScript to make it harder to harvest by spambots.
Chapter 5, Exercise 1 To set the amount of time to show a comment, go to Admin | Channel Administration | Channels. Select the FAQs weblog and click Edit Preferences. Select Comment Posting Preferences and change the Comment Expiration field to 60. Optionally, check the box to update existing comments with this setting and then click Update.
[ 294 ]
Appendix B
Chapter 5, Exercise 2 To include the author and the date of a post, update the line of code that reads
<strong>Q: <em>{faqs_question}
in both the faqs/ index and faqs/browse templates to read as follows: <strong>Q: <em>{faqs_question}
<strong>Posted by {author} on {entry_date format="%m/%d"} p>
More information about the different types of dates that you can display in your entries can be found at http://www.expressionengine. com/user_guide/modules/channel/variables.html#date_ variables. More information about date formatting code can be found at http://www.expressionengine.com/user_guide/ templates/date_variable_formatting.html.
Chapter 5, Exercise 3 If your installation included Agile Records, then you will already have a custom status called Featured. If you are using the blank installation, then you will need to create such a custom status. To create it, go to Admin | Channel Administration | Custom Status Groups, click Add/Edit Statuses, and then click Create a New Status on the top right. Call the new status Featured and click Submit. Before you update your snippet, you should first make at least three of the entries in your channel Featured entries. To do this, edit an entry and select the Options tab. Under Status, change the status to Featured. Next, update the snippet code to include a new parameter which says that the status must be featured in order to display. {exp:channel:entries channel="faqs" limit="3" orderby="random" dy namic="off" status="featured"}
[ 295 ]
Solutions to Exercises
Finally, you have to update the faqs/index, faqs/browse (both in the title and in the body of the page), faqs/rss and faqs/atom to display featured entries in these templates. By default, ExpressionEngine will only display entries with an open status—if you want to display entries with a different status, you have to explicitly tell ExpressionEngine to do so. Modify any {exp:channel:entries} tags in these templates to have the status="Open|Featured" parameter as in this example: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Featured"}
Chapter 6, Exercise 1 To create a new member group that can only modify templates, go to Members | Member Groups and select Create a New Member Group. Call the new member group Designers. Click on Control Panel Access and say Yes to accessing the control panel, and Yes to the design section. Under Template Editing Privileges, select which templates can be edited (business, contact, faqs, includes, individual, promotion, and site). Click Submit. Next, select Members | Register Member and create a new member in the Designers member group. Log in as the new member and verify that it works as expected. Chapter 6, Exercise 2 To create a custom member field, you go to Members | Custom Member Fields. Select Create a New Member Field. Choose a field name of existing_customer and a field label of Are you an existing customer of Ed & Eg?. Change the field type to Select List and enter two options (one on each line)—Yes and No. Leave Text Formatting set to None. Say Yes to this being a required field, No to the field being visible in public profiles, and Yes to being visible in registration pages. Click Submit. Log out of the control panel, then visit your website and click Register. You should see the new field on the registration screen.
[ 296 ]
Appendix B
Chapter 6, Exercise 3 Copy the includes/404 template code and then edit the promotion/index template (created as part of the exercises in Chapter 4, Moving a Website to ExpressionEngine). At the top of the template, add a line of code that says {if logged_in}. Underneath the {embed} line, add in another line of code that says {if:else}. Underneath this, paste in the code from includes/404. Then modify the
and the to reflect that you are on the Promotions page rather than the 404 page and modify the paragraph of text to indicate that promotions are available to members who are logged in only. Finally, at the very end of the template, add a closing {/if} tag. The overall template structure will be as follows: {if logged_in} {embed="includes/.website_page" url_title="promotion"} {if:else} [Modified template code from includes/404] {/if}
Chapter 7, Exercise 1 To modify how the days of the week in the calendar are displayed, you need to edit the code in between the calendar_heading tags in the calendar/index template to read as follows: {calendar_heading}
{lang:weekday_short} {/calendar_heading}
Another alternative is to use {lang:weekday_long}, which will output the full name
of the day (such as Friday). Chapter 7, Exercise 2
To display the next event that is coming up underneath your calendar, you need to use the {exp:channel:entries} tag with two parameters, namely, dynamic="off" and start_on="{current_time format='%Y-%m-%d %H:%i'}".
[ 297 ]
Solutions to Exercises
The dynamic="off" parameter decouples the channel entries being displayed at the URL. By default, the channel tag will look at the URL of the page you are on to determine the entries to display. So, if you were viewing May 2012 (and the URL was http://localhost/calendar/2012/05), your {exp:channel:entries} tag would also only display entries from May 2012. dynamic="off" means that the channel will display any entry from your channel, regardless of the URL. The second parameter is start_on="{current_time format='%Y-%m-%d %H:%i'}". The current_time is a system global variable for the current time on the server. The start_on parameter says that you only want to display channel entries with an entry date on or after the date you provide—in this case, the current date. This means that events in the past will not be displayed—you will only display events that are yet to happen. Read more about global variables at http://www. expressionengine.com/user_guide/templates/globals/ single_variables.html and read more about the start_on parameter at http://www.expressionengine.com/user_ guide/modules/channel/parameters.html#par_start_on
Insert the following code after the {/exp:channel:calendar} tag and immediately before the tag in the calendar/index template: Upcoming Event
{exp:channel:entries channel="{my_channel}" limit="1" re quire_entry="yes" show_future_entries="yes" sort="asc" dynamic="off" start_on="{current_time format='%Y-%m-%d %H:%i'}"} {if no_results}
No Upcoming Events
{/if} <strong>{title}
<em>{entry_date for mat="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{if events_description} {events_description}
{/if} {if events_sponsor} {related_entries id="events_sponsor"} More About Our Sponsor: {title}
{if event_sponsors_about} {event_sponsors_about}
{/if} {/related_entries} {/if} {/exp:channel:entries} [ 298 ]
Appendix B
Chapter 8, Exercise 1 Limiting the number of photos and randomizing them simply requires adding parameters to the {exp:channel:entries} tag in the photos/index template. This also limits the number of photos that will display in each category, so you want to be sure not to add more photos in a given category than the limit you set here. Alternatively, you can use pagination so that if there are more photos than the limit, they display on separate pages. {exp:channel:entries channel="{my_channel}" or derby="random" limit="10"}
Chapter 8, Exercise 2 To track the number of single-entry page views, you must first add a parameter to the {exp:channel:entries} tag in your single-entry page template (photos/ comment). ExpressionEngine offers four view counters that can be added to different single-entry pages, helpfully numbered one through four. Since you only have one single-entry page, you can use view counter one. {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes" status="Open|Premium" track_views="one"}
Next, add a conditional statement to your multiple-entry page (photos/index), immediately after the code that displays how many comments there are and before the :
{if view_count_one>="10"}***Popular***{/if}
The second
helps keep the photo thumbnails aligned, when some are considered popular and some are not.
Note that the view counter is not incremented when a photo is viewed in the lightbox because the lightbox is displaying the actual image file and not the single-entry template.
[ 299 ]
Solutions to Exercises
For channel entry view tracking to work, it must be enabled in Admin | Security and Privacy | Tracking Preferences (by default, it is enabled). The single-entry template in question must also not have caching enabled (by default, caching is disabled). To change the caching preferences of a template, select Preferences from either the Template Manager or the Edit Template screens. For more information on entry view tracking, please see http://www.expressionengine.com/ user_guide/modules/channel/entry_tracking.html.
Chapter 8, Exercise 3 When extracting code that is repeated, you must decide on the best tool to use. In this case, since you use this repeated code in more than one template, Preload Text Replacements are automatically ruled out (since they can only be used in the template in which they are defined). Global variables are also not an option here because the code contains ExpressionEngine tags such as {exp:comment:form}. The choice, therefore, comes down to Snippets or Embedded Templates. Snippets are preferable if the code is identical, regardless of which template might be using it. Embedded Templates are useful if you need to pass in variables to account for small variances in the code. In this case, the {exp:comment:form} requires you to define the preview template. Since this is different for the FAQs channel versus the Photos channel, you will need to use an Embedded Template and pass in the preview template information as a variable. First, create a template called .comment in the includes template group. The preceding dot means that the template is hidden and cannot be accessed directly. The template type should be Web Page. In the .comment template, copy in all the code from photos/comment from Comments
all the way down to {/exp:comment:form}. Change the {exp:comment:form} line to read {my_template_group} and {my_single_entry_ template} as embedded variables rather than Preload Text Replacements: {exp:comment:form pre view="{embed:my_template_group}/{embed:my_single_entry_template}"}
Click Submit to save the new template. Now edit faqs/browse and photos/ comment and replace all the code from Comments
all the way down to {/ exp:comment:form} with the following: {embed="includes/.comment" my_template_group="{my_template_group}" my_single_entry_template="{my_single_entry_template}"}
[ 300 ]
Appendix B
Both the faq/browse and photos/comment templates have Preload Text Replacements for {my_template_group} and {my_single_entry_template}. This line simply passes these text replacements to the embedded template. In this way, even though both the Photos and FAQs channel are using the same chunk of code to display comments, if a member chooses to preview their comment, they are redirected to the appropriate template based on the channel. Visit both the FAQs and Photo sections of your website, and you should see no difference in the functionality of viewing, previewing, and posting comments. The only difference is that now your single entry templates contain a lot less code and if you ever want to change the comment form, you can do so in one template, instead of having to go through multiple templates. Reducing repetition in this way is a powerful feature of ExpressionEngine, and it makes websites easier to maintain.
[ 301 ]
Index Symbols 404 Page improving 140 404 Page not found 98 {exp:search:advanced_form} tag 235 .htaccess files allowing, to be used 291, 292 {site_url} variable 87
A Accessible Captcha extension 278 accessories 272, 273 add-ons, ExpressionEngine about 271 accessible Captcha extension 278 accessories 272, 273 add-on developers 275 backup module 278 Cartthrob module 279 channel images add-ons 279 channel images module/extension 279 custom system messages extension 279 extensions 273 field types 274 first timer extension 278 FoxEE module 279 image sizer plug-in 278 Low (Lodewijk Schutte) 277 MD detect page type plugin 278 modules 272 Newism (Leevi Graham) 276 nGen works 277 notable add-ons 278, 279 Pixel & Tonic 275
plugins 274, 275 resources, URL 271 search results module 279 Solspace 276 template variables accessory 278 third-party add-ons 275 types 271 advanced search form, Search module 235, 236 Agile Records website 37 Atom feed about 136 and RSS feed, differences 139 creating 139 setting up 136-139
B backup module 278 backups, ExpressionEngine 263-265 banned member group 155 Blacklist/Whitelist module 259 blank calendar template creating 179 Body field 46 build release 267
C caching 283 calendar blank calendar template, creating 179 calendar CSS template, creating 183, 184 creating 179-182 designing 173, 174 events, displaying 191-195 exercise 196
formatting, with CSS 183 solution 297 styles, adding to calendar CSS 184-187 weblog, creating 207 calendar CSS styles, adding to 184-186 calendar CSS template creating 183, 184 Calendar module, Solspace 276 calendar template blank calendar template, creating 210 blank calendar, creating 182 CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) 123 Cartthrob module 279 categories about 64 browsing page, distinguishing 132, 133 creating 108-111 data, organizing 129, 130 displaying, with entries 130, 131 related entries, displaying by 133, 134 categories, photo gallery channel creating 205, 206 category browsing page distinguishing 132, 133 channel categories 64 categories, creating 108-111 content, creating 75-77 creating 63 custom channel fields, creating 105-107 custom field group, creating 65 custom fields 64, 65 custom fields for event sponsors, creating 174, 175 custom statuses 64 designing 104, 105 events custom fields, creating 176, 177 event sponsors channel, creating 175, 176 example events, creating 177-179 first custom field, creating 66 Information Pages channel 45 new channel, creating 73, 74 new channel. creating 111, 112 News channel 45
setting up 174 templates, pointing to 82, 83 channel images module/extension 279 channel images, photo gallery add-ons 224 comments allowing, on entries 120 form, creating 125-128 previewing, by visitors 128, 129 spam, preventing 120-125 Constrain Proportions checkbox 49 contact form, Email module 241-243 content about 44 Body field 46 Constrain Proportions checkbox 49 Extended text field 48 Information Pages channel 45 new content, creating 45 News channel 45 selecting, from top menu 45 URL title 46 View Entry page 50 Write Mode 47 content management system (CMS) 7, 9 control panel, ExpressionEngine about 38 administrative control panel access 39 Corporate theme 44 Default Control Panel Theme 43 ExpressionEngine Info tab 39 Fruit theme 44 hide sidebar link 39 home icon 39 home page 39 logging into 29, 30 navigation 39 notepad 41 profile 39 Quick Links Manager link 42 Quick Links section 39 reveal sidebar 39 tab manager 40, 41 themes 42 website 39 CSS calendar, formatting with 183 custom field group
[ 304 ]
creating 65 custom fields about 64, 65 creating 66, 70, 71, 105-107 creating, for event sponsors 174, 175 options 72 custom fields, photo gallery channel creating 203-205 custom statuses 64 custom system messages extension 279
D data organizing, with categories 129, 130 Default Control Panel Theme 43 design, photo gallery changing 209, 210 single-entry page layout, creating 210 Devot-ee 275 Discussion Forum module 259 Duplicate an Existing Template Group option 53
E Ed & Eg 61, 62 Editors 155 Email module about 241 contact form, creating 241-243 tell-a-friend form, creating 244 tell-a-friend template, creating 244-247 embedded template 96-98 entries categories, displaying with 130, 131 editing, solution 293 limiting, solution 293 posting to channel, solution 293 events displaying, on calendar 191-194 solution 297, 298 events channel creating 177 events custom fields creating 176, 177 event sponsors custom fields, creating for 174, 175
event sponsors channel creating 175, 176 example events creating 177, 179 exercises solutions 293-301 ExpressionEngine 404 Page, improving 140 .htaccess files, allowing to be used 291, 292 about 9, 11 accessories 272, 273 add-ons 271 Agile Records website 37 assumptions 20 backups 263, 264, 265 business case 12 calendar 173 CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) 123 channel, designing 104, 105 control panel 38, 39 control panel, logging into 29, 30 database restores 266, 267 database, setting up 21, 22 documentation, URL 15 Email module 241 extensions 273 field types 274 file manager 200-203 files, downloading 22, 23 files, uploading 23, 24 image editing, features 221-223 installing, steps 24-28 Mailing List module 236 members, types 39 Moblog module 248 modules 272 official installation guide, URL 19 photo gallery channel, creating 203 photo gallery, designing 199, 200 phpMyAdmin 21 repetition, reducing 90, 91 requisites 20 resources, URL 16, 17 search box, adding to site 229, 230 Search module 228 [ 305 ]
technical case 12 templates, creating 209 templates 50 updating 19 upgrading 267 upgrading, steps 268-271 user-friendly URLs, creating 31 WampServer 21, 285 WampServer, downloading 286, 287 WampServer, installing 288, 289 wiki module 255 ExpressionEngine 2 15 ExpressionEngine database setting up 21, 22 ExpressionEngine documentation, URL 15 ExpressionEngine modules Blacklist/Whitelist 259 Discussion Forum 259 IP to Nation 260 Query 260 Referrer 260 ExpressionEngine modulesSimple Commerce 259 Statistics 260 ExpressionEngine, optimizing performance 281-283 spam 280, 281 ExpressionEngine page index.php 31 ExpressionEngine URLs index.php, hiding 32, 33 index.php, renaming 34, 35 Extended text field 48 extensions 273
F Facebook Connect module, Solspace 276 FancyBox setting up 187, 188 FAQ snippet 134-136 FAQ template creating 114-118 single-entry page, creating 118-120 field types, ExpressionEngine about 274 checkboxes 67
date 67 file 67 multi select 67 radio buttons 67 relationship 67 select dropdown 67 textarea 67 text input 67 file manager 200-203 first timer extension 278 FoxEE module 279 FreeForm module, Solspace 276 Friends module, Solspace 276
G guests member group 155
H hide sidebar link, ExpressionEngine control panel 39
I image editing features 221- 223 image sizer, photo gallery add-ons 223 image sizer plugin 278 includes, template group 78 index.php hiding, in ExpressionEngine URLs 32, 33 renaming, in ExpressionEngine URLs 34, 35 Information Pages channel 45 installing photo gallery 203 installing, ExpressionEngine files, downloading 22, 23 files, uploading 23, 24 steps 24-28 IP to Nation module 260
J jQuery module 173
[ 306 ]
L Low (Lodewijk Schutte) 277 Low NoSpam 277 Low Variables 277
M Mailing List module about 236 e-mails, sending 239, 240 mailing list, setting up 236, 237 member registration, allowing 238, 239 Make the index template in this group your site's home page? box 53 MAMP 285 Matrix 275 MD Detect Page Type URL 141 MD Detect Page Type plugin 278 member groups about 154 banned member group 155 Channel Assignment 159 Channel Posting Privileges 159 Comment Administration 159 configuring, options 155, 156 control panel access 158 Control Panel Email Privileges 159 creating, solution 296 custom member field, solution 296 editor member group, creating 155 guests member group 155 members member group 154 Module Access Privileges 159 new member group, creating 159 pending member group 154 site access 156 Template Editing Privileges 159 member-only content content, making visible to members 167-170 creating 166, 167 members creating 160 Editor Ed, logging in as 160-162 list 151, 152 member groups 154 member-only content, creating 166
new member, registering as 147-149 profile 149-151 templates, linking to 152-154 types 143, 144 with administrative control panel access 144 without administrative control panel access 144 membership designing 143 member groups 144, 154 member, list 151, 152 member, profile 149,-151 member templates, linking to 152-154 new member, registering as 147-149 preferences 144-147 members member group 154 menu, snippets creating 95, 96 Moblog e-mail, Moblog module sending 253, 254 Moblog module about 248 Moblog e-mail, sending 253, 254 setting up 248-252 template, setting up 252, 253 modules about 272 multiple-entry page content, adding 215-221 creating 213, 214 Multiple Site Manager 260
N Newism (Leevi Graham) NSM Addon Updater 276 NSM Better Meta 277 NSM TinyMCE 277 NSM Transplant 277 News channel 45 nGen works 277 no-results template 235 no-results template, Search module 234 notepad, control panel 41 NSM Addon Updater, Newism (Leevi Graham) 276
[ 307 ]
NSM Live Look, Newism (Leevi Graham 277 NSM TinyMCE, Newism (Leevi Graham) 277 NSM Transplant, Newism (Leevi Graham) 277
O official installation guide URL 19
P page load times reducing, techniques 282 pages adding 84, 85 creating, solution 294 second page, publishing 86, 87 second template, creating 88-90 Pages module URL 85 pending member group 154 photo gallery add-ons 223 advanced features 221 channel, creating 203 design, changing 209, 210 designing 199, 200 installing 203 photo gallerysolution 299 setting up 205 photo gallery, add-ons channel images 224 image sizer 223 photo gallery channel categories, creating 205, 206 creating 203, 207 custom fields, creating 203-205 photos, uploading 207-209 photos direct upload 208 uploading, to website 207 phpMyAdmin 21, 290 Pixel & Tonic about 275 Matrix 275 Playa field type 275
Wygwam 275 URL 200 Playa field type 275 plugins 274, 275 Pluralism 62 preload text replacements 91, 92 Publish page layout modifying 162-164 options, configuring 165
Q Query module 260 question set publishing 112, 113 Quick Links Manager, control panel 42
R Referrer module 260 repetition preload text replacements 91, 92 reducing, ways 90, 91 user-defined global variables 92, 93 resources ExpressionEngine documentation, URL 15 URL 17 restores, ExpressionEngine build release 267 database restores 266 releases, types 267 version release 267 RSS feed about 136 and Atom feed, differences 139 setting up 136-139
S search box Search module adding, to site 230 search box, Search module adding, to site 229 Search module advanced search 235 no-results template 234, 235 search results template, creating 231-233 search results module 279 [ 308 ]
setting up 252, 253 templates, ExpressionEngine about 10, 50 Access section 54 as files 99-101 content displaying, tags used 55-58 content, adding to multiple-entry page 215-221 creating 78-82, 290 Duplicate an Existing Template Group option 53 editing 54 group, creating 53, 54 index template 52, 55 Make the index template in this group your site's home page? box 53 multiple-entry page, creating 213, 214 pointing, to channel 82, 83 Preferences section 54 second template, creating 88 single-entry page, creating 210-213 tag 56 tag pair 57 Template Notes section 54 URL, relationship 52 URLs, relating to 51, 52 template variables accessory 278 themes, control panel corporate theme 44 Default Control Panel Theme 43 downloading 42 fruit theme 44 mobile theme 43 switching 43
search results template, Search module creating 231-233 Simple Commerce module 259 single-entry page creating 210-213 single-entry page, FAQ template creating 118-120 solution 299 single-entry page layout, photo gallery creating 210 photo comments, displaying 213 single-entry template creating 188-191 snippets about 93-95 menu, creating 95, 96 Solspace about 276 Calendar module 276 Facebook Connect module 276 FreeForm module 276 Friends module 276 Super Search module 276 Tag module 276 User module 276 solutions to exercises 293-301 spam 280, 281 Statistics module 260 styles adding, to calendar CSS 184-186 Super Search module, Solspace 276
T tab manager, control panel Template Manager screen 40, 41 Tag module, Solspace 276 tag pair 57 tags about 10, 56 used, to display content in templates 55-58 tell-a-friend form, Email module creating 244 tell-a-friend template, Email module creating 244-247 template, Moblog module
U upgrading, ExpressionEngine steps 268-71 URL title 46 user-defined global variables 92, 93 user-friendly URLs, ExpressionEngine creating 31 index.php, hiding 32, 33 index.php, renaming 34, 35 User module, Solspace 276
[ 309 ]
V version release 267 View Entry page 50 visitors allowing, to preview comments 128, 129
W WampServer about 285 downloading 286, 287 home page, URL 290 installing 288, 289 Localhost 290 package 286 using 289 welcome page, deleting 290 www directory 290 WampServer, package AMP environment 286 phpMyAdmin 286 website converting into ExpressionEngine, approaches 62, 63 wiki module about 255 wiki, setting up 255, 256 wiki, working 257-259 Write Mode 47 Wygwam 275
X XAMPP 285
[ 310 ]
Thank you for buying Building Websites with ExpressionEngine 2
About Packt Publishing
Packt, pronounced 'packed', published its first book "Mastering phpMyAdmin for Effective MySQL Management" in April 2004 and subsequently continued to specialize in publishing highly focused books on specific technologies and solutions. Our books and publications share the experiences of your fellow IT professionals in adapting and customizing today's systems, applications, and frameworks. Our solution based books give you the knowledge and power to customize the software and technologies you're using to get the job done. Packt books are more specific and less general than the IT books you have seen in the past. Our unique business model allows us to bring you more focused information, giving you more of what you need to know, and less of what you don't. Packt is a modern, yet unique publishing company, which focuses on producing quality, cutting-edge books for communities of developers, administrators, and newbies alike. For more information, please visit our website: www.packtpub.com.
Writing for Packt
We welcome all inquiries from people who are interested in authoring. Book proposals should be sent to author@packtpub.com. If your book idea is still at an early stage and you would like to discuss it first before writing a formal book proposal, contact us; one of our commissioning editors will get in touch with you. We're not just looking for published authors; if you have strong technical skills but no writing experience, our experienced editors can help you develop a writing career, or simply get some additional reward for your expertise.
CodeIgniter 1.7 Professional Development ISBN: 978-1-849510-90-5
Paperback: 300 pages
Become a CodeIgniter expert with professional tools, techniques and extended libraries 1.
Learn expert CodeIgniter techniques and move beyond the realms of the User Guide
2.
Create mini-applications that teach you a technique and allow you to easily build extras on top of them
3.
Create CodeIgniter Libraries to minimize code bloat and allow for easy transitions across multiple projects
CodeIgniter 1.7 ISBN: 978-1-847199-48-5
Paperback: 300 pages
Improve your PHP coding productivity with the free compact open-source MVC CodeIgniter framework! 1.
Clear, structured tutorial on working with CodeIgniter for rapid PHP application development
2.
Careful explanation of the basic concepts of CodeIgniter and its MVC architecture
3.
Use CodeIgniter with databases, HTML forms, files, images, sessions, and email
4.
Full of ideas and examples with instructions making it ideal for beginners to CodeIgniter
Please check www.PacktPub.com for information on our titles
jQuery 1.4 Reference Guide ISBN: 978-1-849510-04-2
Paperback: 336 pages
A comprehensive exploration of the popular JavaScript library 1.
Quickly look up features of the jQuery library
2.
Step through each function, method, and selector expression in the jQuery library with an easy-to-follow approach
3.
Understand the anatomy of a jQuery script
4.
Write your own plug-ins using jQuery's powerful plug-in architecture
Drupal 6 Content Administration ISBN: 978-1-847198-56-3
Paperback: 196 pages
Maintain, add to, and edit content of your Drupal site with ease 1.
Keep your Drupal site up to date: easily edit, add to, and maintain your site's content, even if you've never used Drupal before!
2.
Covers the full range of content that you might want on your site: richly formatted text, images, videos, as well as blog posts, calendar events, and more
3.
Get to grips with managing users, slaying spam, and other activities that will help you maintain a content-rich site
4.
Concise, targeted information with easy-tofollow hands-on examples
Please check www.PacktPub.com for information on our titles
Recommend Documents
Building Websites with ExpressionEngine 2
A step-by-step guide to ExpressionEngine: the web-publishing system used by ...
Building Websites with ExpressionEngine 2
A step-by-step guide to ExpressionEngine: the web-publishing system used by ...
Building Websites with XOOPS A step-by-step Tutorial
Get your XOOPS website up fast using this easy-to-follow guide
S...
Building Websites with Joomla! A step by step tutorial to getting your Joomla! CMS website up fast
Hagen Graf
BIRMING...
Building Websites with Joomla! A step by step tutorial to getting your Joomla! CMS website up fast
Hagen Graf
BIRMING...
Building Websites with XOOPS A step-by-step Tutorial
Get your XOOPS website up fast using this easy-to-follow guide
S...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Sign In
Our partners will collect data and use cookies for ad personalization and measurement. Learn how we and our ad partner Google, collect and use data. Agree & close
5. Next, write the code to display the Frequently Asked Questions' introduction. After the
Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
6. Now you are going to write the code to display up to ten questions on a page using pagination. This first piece of code displays the title of each entry. The limit parameter is what determines how many entries to display on each page, and the paginate parameter indicates where you would like the pagination links to appear (the choices are top, bottom, or both). Within the paginate variable pair, a conditional statement makes sure that there is more than one page of entries before displaying in order to display the pagination links. (This means that, initially, since you do not have more than ten entries, you will not see these pagination links). Insert the following code just before the
Chapter 5 {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom"}
{title}
{paginate} {if "{total_pages}" != 1}Page {current_page} of {total_pages} pages {pagination_links}
{/if} {/paginate} {/exp:channel:entries}7. If you click Update and then visit http://localhost/faqs, you will see the titles for the channel entries you have already submitted.
8. Now you can add the questions for each entry, along with a link to read the answers. Insert the following code after the
header:
<strong>Q: <em>{faqs_question}
<strong>A: Read the answer here!
[ 117 ]
Creating a Fully-Equipped Channel
The permalink tag generates an HTML link to the URL for the single-entry page for each entry. A permalink is so called because it is a permanent link to that entry. For example, the multiple-entry page http://localhost/faqs may display different FAQs in different orders at different times, but the permalink http://localhost/ faqs/browse/living_paycheck_to_paycheck will always be a link to the Living Paycheck to Paycheck entry. (Note that you have not yet created the browse single-entry template). The permalink tag includes one parameter, which is the template group and the template to use to display the entry. It then dynamically adds the URL title for you. In this case, you are linking to the browse template of the faqs template group (although you are using Preload Text Replacements instead of referencing faqs/browse directly).
Now visit http://localhost/faqs and you can see the questions along with links to read the answers. The links do not work yet since you have not yet created your single-entry template. You will do this next.
You are done with your multiple-entry page template! Next, you have to create the single-entry page.
Creating your single-entry page
As previously explained, you are going to use the faqs/browse template for your single-entry pages. 1. In the control panel, go to Design, Templates, and then click on Template Manager. Highlight the faqs template group and select New Template. [ 118 ]
Chapter 5
2. Name the new template browse. Leave the template type as Web Page. Under Default Template Data, highlight Duplicate an Existing Template and select faqs/index as the template to duplicate. Click Create and Edit.
3. The first change you are going to make is the HTML
4. Underneath the line
down to (and including) the {/exp:channel:entries} tag. 5. Now add the following code in the section instead. This code is very similar to the code for your browsing page, except that you are displaying the answer and instead of links to the single-entry page, you have a link back to the main browsing page. {exp:channel:entries channel="{my_channel}"} {title}
<strong>Q: <em>{faqs_question}
<strong>A: {faqs_answer}
[ 119 ]
Creating a Fully-Equipped Channel {/exp:channel:entries}
Note the use of the path variable to provide a link back to the index template of the faqs template group. If you wanted a link to a template that was not index, you would have to write it as: {path=template_ group/template}. The difference between the permalink variable used to link to the single-entry page and the path variable used to link back is that the permalink variable automatically adds the URL Title of the entry to the template specified (so you are taken to the URL specific to the entry), whereas the path variable does no such thing (it simply takes you to the template group and template specified).
You now have a FAQs page that displays all your faqs (with built-in pagination once you post enough entries). You can also click on individual questions to see the answer. The next step is to add some user interactivity to the single-entry page by allowing visitors to leave comments or add their own suggestions to each question.
Allowing comments on your entries
Comments are one of the easiest ways for visitors to interact with your site. They are also an easy way to attract spammers, who will be glad to leave hundreds of comments linking to websites of dubious quality. Luckily, ExpressionEngine includes features designed to prevent abuse.
Preventing comment spam
1. Comment preferences are set on a per-channel basis, allowing you to have different preferences for different channels (although when you create a new channel, you can copy the preferences from an existing channel to make things simpler). Go to Admin | Channel Administration | Channels and select Edit Preferences for the FAQs channel. [ 120 ]
Chapter 5
2. Here are all the aspects of the channel that you can fine-tune, organized into expandable groups. The General Channel Preferences were set when you created the channel, and include the channel name and short name.
3. Click on Path Settings. The path settings are the URLs that are unique to this channel. When creating links in your templates, ExpressionEngine will use these settings to know what URL to link to. Set your Channel URL to http://localhost/faqs and set your Comment Page URL and Search Results URL both to http://localhost/faqs/browse. You have not yet created an RSS template, but you can set your RSS Feed URL to be http:// localhost/faqs/rss in anticipation. The Ping Return URL does not apply to this channel.
When the Live Look Template is set, you will see a new Live Look link after publishing a new entry, as well as a new View link on the Content | Edit page. When you click one of these links, you will be taken to the livelook template to see the entry. A live-look template is coded exactly like an ordinary single-entry page template, and although you can define your single-entry template to be your live-look template, the true power comes into play when you define a live-look template that displays entries that would not be visible in your single-entry page template (either because they are future-dated or because they do not have an open status). This allows you to draft an entry with a closed status, for example, and view what it will look like on your website before you publish it with an open status.
[ 121 ]
Creating a Fully-Equipped Channel
4. The Administrative Preferences sets up defaults for each entry. For example, if you know the channel does not have comments, instead of having to click No to Allow Comments on each entry, you can set the default for every new entry to be no here (leave it set to Yes right now). The field for the search excerpt allows you to define which custom field is displayed when a member searches your site—the excerpt will automatically strip out any HTML formatting. For now, leave this set to Question. 5. The Channel Posting Preferences determines what to do with URLs inside a channel entry—you can either automatically link to them or leave them as plain text. Since only trusted people (such as yourself, Ed & Eg) will be able to post to this channel, you can Allow ALL HTML and say Yes to allowing images as well as to converting URLs into links. If your channel will involve lots of example HTML code, you could Convert HTML into character entities, meaning that any HTML entered as part of an entry will display on screen as-is and not be interpreted by the browser. At this time, no changes are needed. 6. Next, click on Versioning Preferences and set Enable Entry Versioning to Yes. By doing this, you can keep old versions of a channel entry saved. This is useful as it provides a quick undo feature for edits which were made erroneously. Enabling this option creates a new Revisions tab on your channel Publish page where you can load previous revisions. This option is not a substitute for doing a full database backup at regular intervals. [ 122 ]
Chapter 5
7. Select Notification Preferences. These preferences allow you to set up individuals to receive e-mails whenever a new entry or comment is posted. Setting this is essential if you require a moderator to approve all comments but can also be useful if you do not moderate your comments, as a means to monitor comments for comment spam. If you are using a localhost environment, outgoing e-mails may not work. So for now, leave all the notification options set to No. 8. Select Comment Posting Preferences. This is where you can either lock down or open up who can post comments and how many hoops they have to jump through in order to do so. Right now, say Yes to allow comments and No to requiring membership in order to post comments. As you are not requiring membership, say Yes to enabling a CAPTCHA for comment posting and say Yes to requiring an e-mail address to be entered when a reader tries to post a comment, but say No to moderating comments. Comment moderation means that an administrator, such as you, must approve every comment before it actually appears on your website. CAPTCHA stands for a Completely Automated Public Turing test to tell Computers and Humans Apart and is a puzzle that is easy for a human to solve, but not easy for a computer to solve. It is designed to filter out real people posting comments from automated scripts that are posting comment spam. ExpressionEngine's CAPTCHA technology relies on an image of letters with a background that makes it difficult for a computer to identify the letters. The person submitting the comment must type in the letters from the image correctly in order to post their comment. The downside to using an image in CAPTCHA technology is that it is not very accessible for visually-impaired visitors who might be relying on screen-readers to navigate your website. There are add-ons that provide a solution to this, such as Accessible Captcha (available at http://devotee.com/add-ons/extensions/accessible-captcha/). This addon changes the graphic to a user-defined question and answer, such as 2+2. A human could easily answer 4, but an automated spam program would not be able to do so. Search for CAPTCHA at http://devotee.com/ for other add-ons [ 123 ]
Creating a Fully-Equipped Channel
9. Leave the Maximum number of characters allowed in comments at 5,000, but set a comment re-submission time interval of 30 seconds. This option prevents an automated script from submitting more than one comment every 30 seconds. It can be useful as a deterrent against comment spam (especially if you are not moderating your comments or using CAPTCHA technology). Leave the comment expiration setting at 0 (meaning comments do not expire). If desired, you can use this setting to stop accepting comments on entries after a certain number of days. This can be useful to reduce the number of places on your website where comment spam can be posted. For the Comment Text Formatting, select XHTML but Allow only safe HTML. This means that formatting HTML, such as <strong> and <em>, will work, but more complex HTML will be rendered in plain text rather than being interpreted by a browser (thereby preventing malicious code being executed on your website). Do not allow image URLs in comments and do not automatically turn URLs and e-mail addresses into links (these options discourage spammers because their comments do not become links that could drive traffic to their website).
[ 124 ]
Chapter 5
10. Finally, the Publish Page Customization allows you to set a default entry title or URL title prefix that will apply to all new entries. This can be useful if you want all your entries to have the same prefix. Right now, leave these blank. Also, leave the Display Rich Formatting Buttons option set to Yes. Setting this to No would turn off the HTML formatting buttons (such as bold and italics) on all your custom fields, regardless of each individual custom field setting. 11. Click on Update and Finished to save all your settings. The settings you have just seen are useful in combating comment spam, especially from automated scripts, and it's recommended to consider them carefully before enabling comments. Using some combination of either requiring membership to post comments, enabling CAPTCHA technology, and/or enabling comment moderation along with setting an administrator up to receive notifications of new comments allows you to minimize comment spam as much as possible and quickly identify it when it does occur. You are now ready to create a form to accept comments. More information on all of these preferences can be found in the ExpressionEngine documentation at http://expressionengine. com/user_guide/cp/admin/content_admin/channel_edit_ preferences.html.
Creating a comment form
The first step in accepting comments is to create a form where visitors can write and submit their comments. Comments have to be tied to a specific channel entry, and therefore, the comment form can only appear on single-entry pages. Therefore, you will add your comment form to the faqs/browse template. 1. Open the browse template in the faqs template group for editing and type in the following code after {/exp:channel:entries}. This code displays the comments that other people have submitted. The title of the section is Comments. Comments
{exp:comment:entries} {if comments} {comment}
Posted by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/if} [ 125 ]
Creating a Fully-Equipped Channel {if no_results} There are no comments at this time - be the first to share your thoughts!
{/if} {/exp:comment:entries}
2. Next, add the code to create a comment form. Add this after the {/ exp:comment:entries} tag. First, this creates the fields for the visitors name and e-mail address. Since you would already have the name and e-mail address of any member who is logged in, you only need to ask for this information if the visitor is logged out. {exp:comment:form} Post Your Own Comment
{if logged_out}
{/if}
{if logged_out}
{/if}
{if captcha} {captcha}
[ 126 ]
Chapter 5
{/if}
{/exp:comment:form}
You can also add fields for a visitor's location or website. Use the same format as the email field in the previous code, but replace the word email with either location or url.
3. Now try posting your first comment. In order to see the website as a visitor will see it, log out of the control panel by clicking on Logout at the top-right and confirming you want to log out. (Closing the control panel without logging out will leave you logged in). Now visit http://localhost/faqs and click on a question. 4. Fill in your name, e-mail, type in a comment, and leave the box to remember your personal information, and the box to notify you of follow-up comments unchecked. If you check Remember my Personal Information, then the next time you see a comment form, your name and e-mail address will be pre-filled. Note that if you are logged in when you visit this page (for example, if you were previously logged into the control panel), then you will not see the fields for the name or e-mail and you will not see the CAPTCHA.
5. Enter the CAPTCHA word. Notice that each time you refresh the page, a different image with a different word is shown for your CAPTCHA. When you have completely filled in the comment form, click Submit.
[ 127 ]
Creating a Fully-Equipped Channel
Note that currently the Preview button will not work as you have not yet set up a preview template. If you are using a localhost environment, posting comments can be more difficult than when using an installation on a real website. If you are unable to post comments in the localhost environment, try changing the setting Require IP Address and User Agent for Login to No. This setting can be found in the control panel under Admin | Security and Privacy | Security and Sessions.
6. The page will auto-refresh, and you should now see the comment that you submitted.
Allowing visitors to preview comments
One final aspect of comments that hasn't yet been covered is the ability to preview the comment before publishing. You may have noticed the Preview button on the comment form that does not work yet. 1. First, modify the faqs/browse template to include the following code after the {/exp:comment:entries} and before the {exp:comment:form} line. Notice how the code is almost exactly the same as the code to display an actual comment, except that you are using the {exp:comment:preview} tag instead of the {exp:comment:entries} tag. This means that the look and feel of the previewed comment is identical to how it would look if it were an actual comment. {exp:comment:preview} {comment}
Being previewed by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/exp:comment:preview}
[ 128 ]
Chapter 5
2. Next, change the line {exp:comment:form} to include the preview parameter as follows. This parameter tells the form which template to load if the preview button is clicked. {exp:comment:form preview="{my_template_group}/{my_single_entry_template}"}
3. Now go to the FAQs page, type in a comment, and click Preview instead of Submit. You can see that the comment appears and looks exactly as if you had submitted it, except that instead of Posted by in the footnote, it says Being previewed by. You can keep editing the text and clicking on Preview as often as you like.
Organizing your data with categories
Although you have created custom categories and assigned your entries to some of your categories, you haven't yet used categories to help visitors browse the FAQs. You will now do this, but first set ExpressionEngine to use category names rather than ID numbers in the URL. This means that instead of category browsing pages having a URL such as http://localhost/faqs/C8, the category URL will be more like http://localhost/faqs/category/getting_married 1. In the control panel, go to Admin, Channel Administration, and then Global Preferences.
[ 129 ]
Creating a Fully-Equipped Channel
2. Say Yes to using category URL titles in links. Leave the Category URL Indicator as category. (If you do change this, bear in mind that whatever word you use here becomes a reserved word and cannot be used as a template name).
3. While you are on this page, also select No to auto-assigning category parents and click on Submit. Later in the chapter, you will use categories to show visitors who are viewing one question other related questions from the same categories. If all questions have the same two parent categories autoassigned, the related questions that are displayed are going to be less tightly coupled to the question being viewed.
Displaying categories with your entries
To encourage visitors to browse by category, it makes sense to display the categories that each entry belongs to underneath the questions on the faqs/index page. For this, you will use the channel {categories} tag, which allows you to list the categories, along with the {comment_total} tag to show how many comments each entry has and the {comment_url_title_auto_path} tag to link to your single-entry page for comments. Note that the {comment_url_title_auto_path} tag autogenerates the URL to your category template, as defined in Admin | Channel Administration | Channels, under Edit Preferences for the FAQs channel, then under Path Settings. The option Comment Page URL should be set to http://localhost/faqs/browse.
1. Edit the faqs/index page and add the following code underneath the Read the answer here! permalink and above the {paginate} line. <strong>Categories: [ 130 ]
Chapter 5 {categories backspace="3"}{category_name} | {/categories}Comments ({comment_total})
Everything between the {categories} opening tag and the {/ categories} closing tag is repeated for each category that the channel entry is assigned to. In this code, there is a vertical bar (|) after the category name and before the next category name to separate the categories. To prevent this vertical bar appearing after the last category, we use the backspace parameter. This parameter removes the specified number of characters from the end of our code after the last category name only (in this case, the | and the surrounding two spaces). This parameter is specifically designed to remove separators or other code that it makes sense to have between categories, but not after the last category.
2. Click on Update and Finished and then visit the FAQs page. You should now see underneath each answer—a piped list of categories that the entry belongs to. Clicking on one of the categories takes you to a category browsing page where you can see other entries that have the same category. At the moment, given that you only have two entries right now, namely, your category browsing pages and your main multiple-entry page, it will not be substantially different unless you pick a category that is unique to just one entry. Once the number of entries starts getting higher, browsing by category will be a much faster way of finding related questions than simply browsing through all the questions.
[ 131 ]
Creating a Fully-Equipped Channel
Distinguishing your category browsing page
Currently your category browsing page and your main multiple-entry page look identical—they have the same page title and the same introduction. Within the faqs/ index template, you can tell if you are on the main multiple-entry page or a category browsing page by looking at the URL. If segment_2 (the part of the URL after faqs) is category, you are on a category browsing page. You can, therefore, use this condition to display slightly different content accordingly. 1. First update the HTML title (which appears on the title bar of the window). To do this, edit the faqs/index template and replace the
Frequently Asked Questions - Ed & Eg Financial Advisors with the following: {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} Questions About {category_name} - Ed & Eg Financial Advisors {/exp:channel:category_heading} {if:else} Frequently Asked Questions - Ed & Eg Financial Advisors {/if}
2. Next, you can replace the code appearing after down to, but not including, the exp:channel:entries tag with the following: {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} Questions About {category_name}
{category_description}
{/exp:channel:category_heading} {if:else} Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
{/if}
[ 132 ]
Chapter 5
This code says that if you are on a category-browsing page, then the page heading should be Questions About {category_name} and the introductory text should be the category description. To edit the category descriptions, you have to edit the individual category in question. Go to Admin | Channel Administration | Categories, then click on Add/Edit Categories for the FAQ Categories group, and edit the category you want.
Now your category browsing pages look markedly different to your main multipleentry browsing page. However, this setup still requires your visitors to deliberately click on a category that interests them in order to find other FAQs that might be of interest. A different approach would be to display, at the end of the single-entry page, a list of other FAQs that have the same category (and therefore, are likely to be of interest to the visitor). In this way, the visitor is encouraged to keep browsing without ever realizing they are using categories.
Displaying related entries by category
To display other entries in the same category on your single-entry page, you need to make use of the ExpressionEngine parameter related_categories_mode. This looks at the URL of your single-entry page and then brings back the data of other entries that are in the same category as the page you are on. 1. Edit the faqs/browse template. Insert the following code after the line {/ exp:comment:form}: Other Questions Like This
{exp:channel:entries channel="{my_channel}" limit="5" related_categories_mode="yes" custom_fields="yes" orderby="random"} {if no_results} There are no questions like this currently – check back soon though...we're always adding more!
{/if} <strong>Q: <em>{faqs_question}
[ 133 ]
Creating a Fully-Equipped Channel <strong>A: Read the answer here!
{/exp:channel:entries}
Here you are bringing back up to five entries that are in the same categories as the question being viewed. To ensure variety, the entries are displayed in a random order, meaning that if you have more than five entries, no two sets of related questions will be the same.
2. If you now visit http://localhost/faqs and click on an entry, you should see a link to the entry you did not click on at the bottom of the single-entry page. If you do not see a link to your entry, it means the entry you are viewing is the only one in that category.
Now, as Ed & Eg go through and start adding hundreds of questions and answers, ExpressionEngine will dynamically organize the content. In this way, you may catch a visitor's eye with a question they want to know the answer to, and then keep them hooked by dynamically showing them other questions that are similar to the question they initially clicked on.
The FAQ snippet
The final step in getting visitors into the Frequently Asked Questions section of the website is to display Frequently Asked Questions in the widebar at the bottom of each page. Currently, there are two, static FAQs that are displayed in the widebar. In this section, you will update the widebar to display three random entries from the FAQs channel. To do this, it makes sense to use a snippet. Why a snippet? If you recall from Chapter 4, a snippet is used when you want to reduce repetition. In this case, since the widebar will be used on lots of templates, it is a great candidate for becoming a snippet. Why not a global variable? Remember that global variables do not support ExpressionEngine tags. Since you are planning to show data from an ExpressionEngine channel, a snippet is required. [ 134 ]
Chapter 5
In this section, you are choosing to display three random entries in your widebar. If you wanted more control over which FAQs were displayed at the bottom of every page, you could manually set the status of three entries to a custom status such as Featured (instead of open). Then, in your snippet, you could specify in the {exp:channel:entries} tag that you only want to include entries where status="Featured". You would also have to add a parameter status="open|featured" to the {exp:channel:entries} tags in all your other templates that use the FAQs channel. ExpressionEngine does not display entries that do not have a status of open, by default.
1. In the control panel, click on Design, then Templates, and finally Snippets. Then click on Create a New Snippet. 2. Call the snippet website_faqs and type in the following code to display your random entries. Note the use of the switch parameter—this essentially says that for the first entry, use colA as the div id. The second entry should use colB and the third entry should use colC. If you were displaying more than three entries, the fourth entry would use colA again, which, in this case, does not make sense to do. {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off"} Frequently Asked Question
{faqs_question} Find out…
{/exp:channel:entries}
Remember that ExpressionEngine uses the URL to dynamically determine whether you are on a single-entry page or a multiple-entry page. (If the URL has the url_title of a specific entry after the template name, then ExpressionEngine recognizes that you are on single-entry page and will only display content from that entry). This means that you cannot display content from another entry (or another channel) on a single-entry page unless you tell ExpressionEngine to ignore the fact that you are on a single-entry page. This is what the dynamic="off" parameter does.
[ 135 ]
Creating a Fully-Equipped Channel
3. Next, edit all your existing templates that show the widebar (includes/. website_page, includes/404, faqs/index, and faqs/browse) and replace the widebar code with a reference to this snippet instead. For each template, delete all the code including and between to and replace it with {website_faqs}.
Your work with the FAQ page is almost complete. The next step is to provide a way for visitors to be notified about new FAQs, without having to constantly re-visit your website. For this, you will use a feed.
Setting up an RSS or Atom feed
RSS or Atom feeds are an alternative way of allowing visitors to keep up-to-date on your website. Essentially, the visitor subscribes to your feed through their e-mail software, browser, or other news readers, and then they get notified when you post new entries. This saves them from having to periodically revisit your website to see if there is new content or not. Having a feed available can make the difference between a visitor being someone who visited your website and liked it (but does not come back) and someone who visited your website and now reads every new post. When building a feed, the easiest approach is to start with a pre-built ExpressionEngine feed template. This will take care of the top portion of the feed (containing meta-information such as the date, the URL of the entry, and so forth), meaning you only have to make a few customizations so that the feed displays the content from your custom fields. An RSS 2.0 template can be found at http://expressionengine.com/wiki/RSS_ Template_for_EE2/. However, since Agile Records comes with both an RSS 2.0
and an Atom 1.0 template, you can also base your template on theirs. If you did not install Agile Records, using the template from the wiki will have the same results. 1. From the Template Manager, select the FAQs template group and create a new template called rss. The template type should be RSS Page and you should duplicate a template, namely, the news/rss template. Click on Create and Edit. [ 136 ]
Chapter 5
2. On the first line, change {exp:rss:feed channel="news"} to {exp:rss:feed channel="faqs"}. (If you are starting from the wiki template, then the channel on the first line is howto, but should still be changed to faqs). 3. About half-way down, you will see a familiar {exp:channel:entries} tag. In this tag, change news to faqs. The limit parameter limits the number of results to 10 and the disable parameter tells ExpressionEngine not to query the database for member data (reducing the amount of data that is queried). Finally, every time a news-reader polls your website for new entries, it provides the last date/time that it checked. The dynamic_start parameter tells ExpressionEngine to only return entries (if any) that have been posted since that particular last date/time. {exp:channel:entries channel="faqs" limit="10" dynamic_start="on" disable="member_data"}
4. Even further down, look for the XML tag <description>. On that line, you will see an ExpressionEngine tag {news_body} (or {body} if you are starting from the wiki template). This is a custom field, so you should change this line to use your own custom field—{faqs_question}. You could display both the question and the answer in the feed. However, in this example, you are going to display only the question, followed by a link to the answer page (using code you have already used on your multiple-entry page). <description>{faqs_question}]]>
[ 137 ]
Creating a Fully-Equipped Channel
5. Click on Update and Finished. If you now browse to the RSS template (http://localhost/faqs/rss), your browser will likely recognize it as an RSS feed.
If you get an error, you may not have set the template to be an RSS Page. Check the template preferences for your RSS template.
6. Now all you have to do is link to the feed from your FAQs page so that people know it is there. Edit the faqs/index template and add the following after the introductory paragraph and before the {/if}: Don't forget to subscribe to our RSS feed to stay up-to-date with new FAQs as they are posted.
[ 138 ]
Chapter 5
You can now use your favorite RSS reader to view the content. If you do not have a favorite RSS reader, your e-mail client will likely already support it. For example, Mozilla Thunderbird 1.0 and greater and Outlook 2007 and greater, both have builtin support for feeds. Alternatively, Google Reader is a popular and free web-based alternative (http://www.google.com/reader). If you are following along in a localhost environment, then web-based feed readers will not be able to access your feed.
The instructions for creating an Atom feed are almost identical to those for creating an RSS feed: 1. Create a template faqs/atom and duplicate the news/atom template from the Agile Records example site into your new template. (The template type should still be RSS Page). 2. Change the feed channel on the first line to faqs. {exp:rss:feed channel="faqs"}
3. Change the channel in the exp:channel:entries tag to faqs. {exp:channel:entries channel="faqs" limit="15" dynamic_start="on" disable="member_data"}
4. Unique to Atom feeds, change the scheme to point to the single-entry template where the entry is: scheme="{path=faqs/browse}"
5. Change the custom fields inside the CDATA[] tag to reflect the content that you want to display inside your feed: {faqs_question} ]]>
6. Save your template and verify that you can subscribe to your new feed (http://localhost/faqs/atom). What is the difference between an RSS and an Atom feed? RSS 2.0 is the older and more established feed. Atom 1.0 was designed as a modern alternative to RSS. For practical purposes, news readers can read either feed, so which one you choose is up to you or you can use both types of feed and let your visitors pick whichever they prefer.
[ 139 ]
Creating a Fully-Equipped Channel
Improving your 404 Page
In the last chapter, you created a 404 Page for your site. ExpressionEngine allows for great flexibility with URLs and the downside of that is that invalid URLs can often return valid content. As an example, if you type in an entry URL that does not exist (such as http:// localhost/faqs/browse/ihatetoast, you see an actual page with content instead of your 404 template. This can be confusing to visitors if they mistype the URL. Luckily, there are options available to fix this. ExpressionEngine comes with a redirect tag that you can use to redirect visitors to another template, based on a conditional. Typically, the syntax of this tag would be {redirect="template_group/template"}. However, when redirecting to a 404 Page, rather than redirecting to "includes/404", you can redirect to "404". This will return the template that you defined in chapter 4 as your 404 template (if you have not yet defined this template, you can do so in Design | Templates | Global Preferences). The difference between a redirect to the template directly and a redirect to 404 is that, if you redirect to just 404, the redirect also includes 404 Page headers, meaning that search engines visiting that URL will recognize it as invalid and will not index it. 1. First edit the browse template of the faqs template group. Change the HTML to read {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes"}. This change means that if the URL does not match up to the URL of an entry, it will not display any content from the channel. 2. Next, between the opening {exp:channel:entries} tag and the closing {/ exp:channel:entries} tag, add the following code. This change says that if there is not an entry to display, then show your 404 Page instead. {if no_results} {redirect="404"} {/if}
3. Now visit http://localhost/faqs/browse/ihatetoast and you can see that your 404 template is now returned. 4. You can go one step further with your redirect. For example, you know that there should not be a segment in the URL after the URL of the entry (that is, http://localhost/faqs/browse/living_paycheck_to_paycheck is a valid URL, but http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus is not). Right now, the hippopotamus URL will still display your entry. If you add the following code to your faqs/browse template, immediately after the code you added above, it will cause a 404 redirect to take place instead: [ 140 ]
Chapter 5 {if segment_4!=""} {redirect="404"} {/if}
5. Now visit isit http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus and you will see a 404 Page instead. What about your multiple-entry page? For example, a URL of http://localhost/ faqs/rubbish should return a 404 Page, but it currently displays your multiple-
entry page. If you were not using categories or pagination, you could safely say that there should not be a segment 2, and if there is, redirect to 404. However, category URLs (such as http://localhost/faqs/category/debt) also use the faqs/index template, so you would need to build in logic to say that if segment 2 is category, then do not redirect to a 404. However, this logic gets more complicated. Once you have more than 10 entries, your entries will paginate over different pages, and the URLs for the pages will also be category 2 segments (for example, http://localhost/faqs/P0). Entries can also be archived by date. For example, a URL of http://localhost/ faqs/2011/11 will only display entries from November 2011. If you are organizing your entries by date in this way, then any year could appear in segment 2. One solution is to use an add-on such as MD Detect Page Type (http://devot-ee. com/add-ons/plugins/md-detect-page-type/), which makes it easy to tell if
you are on a category page, paginated page, or archive page, and therefore makes it much easier to build a conditional statement to display a 404 Page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. You have suddenly started getting spam comments on old FAQs. Set the comments on the FAQ channel so that after 60 days, no more comments are accepted. 2. Your FAQs currently have no indication of when they were posted or who posted them. On both the single-entry and multiple-entry pages, modify the question to include who posted the question and the date of the post (although this is something that might not make sense on the FAQs channel, in most situations where articles are being posted regularly, displaying the date of the post is a common requirement). to include the date of the post. [ 141 ]
Creating a Fully-Equipped Channel
3. Update the snippet that displays the three FAQs on every page of your website so that instead of displaying three random entries, it displays three featured entries (based on a custom status of "Featured").
Summary
In this chapter, you got more practice in using custom fields, channels, and templates. You also got introduced to categories, comments, and feeds. In the next chapter, you will get an in-depth look at the built-in membership module, including registering members, managing members, setting member privileges and permissions, and creating parts of your website that only members can see. The key points to remember after working through this chapter: •
You used a FAQ example in this chapter. However, all the functionality covered in this chapter would equally apply to any dynamic content that your site might have—whether it's a blog, news articles, recipes, or the products you sell.
•
ExpressionEngine contains many options to help you control and filter comments. You can use CAPTCHAs, you can moderate all comments, and you can require membership for comments. You can also set it up so that you get e-mailed when new comments are posted.
•
Feeds are a great option to encourage repeat visitors—they are easy to set up and give people an alternative way to keep up with your website.
•
Preload Text Replacements, Global Variables, Snippets, and Embedded Templates are incredibly useful—it is definitely worth becoming comfortable using them.
•
Conditional {if} statements are also a powerful tool, allowing you to account for different situations in a single template such as redirecting to a 404 Page if there are no entries or displaying category-specific information if the URL segment is a category.
[ 142 ]
Members You have now used ExpressionEngine to build a fully-functional website for Ed & Eg. So far, however, you are the only one who has logged into ExpressionEngine on your website and the only one who has been making any changes. Now is a good time to explore the member functionality of ExpressionEngine. The Freelancer license does not include member management, so this chapter will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing. In this chapter, you will: •
Allow visitors to register on your website and see what they see
•
Create a member group for Ed & Eg, so they can log into the control panel and publish and edit entries (but not edit template code or change administrative options like you can)
•
Use conditional statements to create content that only members can see
First, however, it makes sense to review how membership management works in ExpressionEngine and what all your options are.
Designing your membership ExpressionEngine allows two types of members:
1. Members who can log in to your website, but not into the administrative control panel. These members can see any content that you have coded in your templates as member-only as well as perform any actions that you have set to require membership (such as post comments).
Members
2. Members who can log into your website and also the administrative control panel. Depending on the permissions you give these members, they may be able to complete tasks such as creating or modifying channel content, creating or modifying templates, or changing global settings. If you have an ExpressionEngine-powered website, allowing members is not a requirement. If you do not intend to support members on your website, it is recommended to turn off new member registrations completely (the first option under Members | Preferences in the main menu). Membership in ExpressionEngine is based on member groups, which are what determine the permissions a member has. Each member can only be in a single member group. For members with administrative control panel access, ExpressionEngine offers a huge amount of granularity over what the members can see and do inside the control panel. You can define which channels they can post to (if any), which template groups they can modify (if any), and much more. For members without administrative control panel access, ExpressionEngine offers a member control panel, where members can post a profile, see other members' profiles, as well as send an e-mail or a private message to another member. As with the administrative control panel, you have control over what different member groups can actually do. To make joining your website attractive, you can make some or all of your content member-only by using conditional statements in your templates. You can look to see if a member is logged in and then display different content based on that, or you can display different content to different member groups. In this chapter, you will create a new member group for Ed & Eg that allows them to edit and post channel entries, but that does not allow them to edit templates. Then, to encourage members to join your website, you will update the FAQs channel so that some FAQs are viewable only to members. First, though, you will explore the membership preferences, and then explore the member profile screens as if you were a new member.
Membership preferences
There are many options you can set for your members on a global level that will impact their experience on your site. 1. First, log in to the control panel (http://localhost/admin.php) with your administrator login. [ 144 ]
Chapter 6
Note that you are also assigned to a member group—the Super Admins group. This group gives you access to everything. ExpressionEngine also comes with a Members member group, which does not have administrative control panel access, but can do everything in the member control panel. The permissions of the Members member group can be modified in Members | Member Groups, but the Super Admins group cannot be altered.
2. From the top menu, select Members and then select Preferences. 3. The first section is called General Configuration. Here, you can set whether you want members to be able to register themselves or not and the hoops they have to jump through in order to register. For example, you can require member account activation. If you do not require this, then any new members automatically become assigned to the Default Member Group (which is Members, but can be changed further down). If you require activation (either by an administrator or by requiring the new member to click on a link in their e-mail), then members will be placed into a Pending member group until they are actually activated (by selecting Members | Activate Pending from the main menu). For now, if you are using a localhost environment, say Yes to allow new members and select No activation required (since a localhost environment does not include an e-mail server and so cannot send activation e-mails). If you are following along on an actual website, it is recommended that you require activation of some kind.
4. Further down, you can require new members to accept a terms of service (if you say No, the terms of service will still display) or to complete a CAPTCHA form when they register. You can also allow members to set their own localization preferences (that is, members can set what time zone they are in and then see all times in their local time zone). Ensure that all these are set to Yes.
[ 145 ]
Members
5. Further down, you can set the member group that new members are assigned to (for now, leave this set to Members). You can also change the Default Member Profile Theme. You have two choices: Agile Records or Default. Since the Agile Records theme is designed specifically for the Agile Records website, select Default here. Finally, you can change the Profile Triggering Word, which changes the URL for the member control panel. (For example, if you changed this to guest, then all member control panel URLs would include the word guest instead of member). Leave this set to member for now and click Update. If you do not see any options for the default member profile theme (not even default), then you may be using the Freelancer license, which does not include member management.
6. The Member List Preferences allows you to change the default sort and order of your public member list page (which lists all the members on your site). Do not make any changes right now. 7. The Notification Preferences allows you to receive an e-mail whenever a new member registers at your site. This can be useful if you require an administrator to activate all new member registrations, or if you simply want to monitor new member registrations. If you are using a localhost testing environment, do not make any changes to this screen right now (as the localhost environment does not include an e-mail server, meaning such e-mails cannot be sent). If you are following along on a live website, type in your e-mail address here.
[ 146 ]
Chapter 6
8. ExpressionEngine includes functionality to allow members to contact each other via your website through Private Messages. The Private Messaging Preferences allows you to restrict the number of characters or the size of the attachments that can be attached to private messages. 9. ExpressionEngine includes the ability for members to associate an avatar (image) with themselves, which you can then display next to comments or forum posts that the member makes. The Avatar Preferences allows you to control whether avatars are enabled and whether members can upload their own images. 10. You can also choose whether you want to allow members to upload photos of themselves (which are then displayed on their profile). 11. Finally, you can choose whether or not you want to allow signatures, which appear after every forum post. Signatures are enabled by default, though signature images are turned off. 12. If you have not already done so, click Update to save any changes you have made. Now that you have made these modifications, the next step is to walk through registering as a member and explore the member control panel.
Registering as a new member
The membership functionality in ExpressionEngine is very rich, so rather than having to design your own membership templates from scratch, ExpressionEngine comes with pre-built member templates that you can use for members to login, register, share profiles, change settings, and send e-mails/private messages to other members. When following along in this section, remember that you are a member of your own website. This means that in order to register as a new member, you must first log out of the control panel by clicking Logout at the top right. 1. After logging out of the control panel, visit http://localhost/member/ register. (Remember, if you have the Freelancer license, this URL will not work). 2. You will be presented with a standard Member Registration screen, complete with a generic terms of service. Fill in the form with settings different than the administrator login that you have been using up to this point.
[ 147 ]
Members
Note that, by default, there can only be one username per e-mail address, so you cannot use the same e-mail address for this member as you did for your administrator login. This setting can be changed in Admin | Security and Privacy | Security and Sessions, although it is recommended not to change this setting as it can cause issues if a member with two accounts associated with their e-mail address forgets their password.
3. Select the check box to agree to the terms of service, fill in the CAPTCHA, and click Submit.
[ 148 ]
Chapter 6
4. As long as there were no errors with the information provided, you should be presented with a registration complete message and a link to go back to the main website. You are now registered as a new member!
The member profile
Now that you have walked through registering as a new member, you can see what the member control panel looks like. For this section, you can either be logged in as the member you just created or logged in using your Super Admin username. 1. Go to http://localhost/member/profile. If you are prompted to log in, log in first. 2. You should see a screen with your account statistics: your e-mail address, when you became a member, when you last visited the website, how many channel entries you have posted, and how many comments you have made. Along the top are links to log out or to see the member list. Along the left are links that allow the member to modify and personalize their account.
3. Click Edit Profile on the left-hand side and you can change what other members see about you. Go ahead and fill it in so that when you later visit your profile screen, you can see how it looks. 4. As mentioned earlier, Edit Signature and Edit Avatar are more relevant if you have purchased the forum module. If enabled, members can set their signature and avatar here. ExpressionEngine comes with a default set of avatars that members can select from. [ 149 ]
Members
5. With Edit Photo, you can also associate a member photo that other members can see when they visit your profile (although this option is not enabled by default).
6. Select Email Settings from the left-hand side. This allows members to finetune what notification e-mails they receive. By default, ExpressionEngine allows members to e-mail other members—a member can turn this off here. You can also change your e-mail address on this page. 7. Username and Password allows you to change your username, your screen name, or your password. 8. Edit Preferences allows members to determine whether avatars, signatures, or smiley images are displayed. Members can also prevent Private Messages from being sent to them on this screen.
[ 150 ]
Chapter 6
9. The Localization Settings allow a member to specify their Time Zone, their Time Formatting (US or European), and their Language (if you have multiple language packs installed). By selecting a different time zone, the member can see times in their local time zone. If the times on your website do not appear correct, it may be that either the server timezone or the daylight savings (summer) time setting has been set wrongly. These can be set in Admin | Localization Settings.
10. If a member has posted comments and selected to be notified of follow-up comments, then they are considered subscribed to that channel post. The Subscription Manager shows which posts a member is subscribed to and allows them to unsubscribe if desired. 11. The Ignore List allows members to ignore other members. As a result, any forum posts made by them will not display. 12. The Private Messages section is where members can send private messages to each other and view the ones they have received. 13. Finally, the Notepad is a scratch pad—any text typed into the notepad will be there next time the member logs in. This is most useful for members with administrative control panel access, as the notepad contents also appears on the right-hand side of the administrative control panel. The member control panel is very feature rich, allowing for a lot of functionality and configurability right out of the box. Members can send messages to other members, control what other members can see about them, and personalize settings such as their signature, avatar, or photo to suit their preferences.
The member list
Another option your members have access to is the member list. This can be used for members to browse other members and find their profiles or to send messages. 1. Click on Member List at the top-right of the member control panel or go to http://localhost/member/memberlist. Here, you are provided with a list of all active members. If there are lots of members, you can use filters or searches to find the person you are looking for.
[ 151 ]
Members
2. Click on a specific member and you can see the member profile, including any information the member may have personalized on their profile page.
3. Notice how the member's e-mail address is not publicly displayed. Click on the EMAIL button and you are brought to a form that you must fill in to send an e-mail. It is up to the recipient to decide whether they want to reply (and thereby reveal their e-mail address). With all this functionality, it is easy to build a website that members can use as a springboard to interact with other like-minded people. If you want to customize the member screens so that they share the same look and feel as the rest of your website, the templates can be edited in Design | Themes | Member Profile Templates and the corresponding files can be found in the /themes/profile_themes directory. (Note that it is best to make a backup of the templates before modifying them, in case you need to undo a change). Since each member page is made up of multiple templates, one technique (that you can see in the Agile Records templates) is to put an HTML comment in each template with the template name. In this way, you can view the source of the member pages and more clearly see which templates make up the page.
Linking to the member templates
As you have just seen, all the member functionality is pre-built. All you have to do is link to the pre-existing member URLs on your website and members can start registering and using your website.
[ 152 ]
Chapter 6
Next, you will set up the links in the sidebar on the right-hand side. If the visitor is logged out, there will be links to log in, register, or reset their password. If they are logged in, there will be links to log out, go to the member profile pages, or see the member list. 1. Log in to the control panel as a Super Admin. From the top-menu, select Design | Templates | Snippets. Select the website_sidebar snippet that you created in Chapter 5, Creating a Fully-Equipped Channel. 2. Add the following code to create the links immediately before the last in the snippet. Notice the use of the ExpressionEngine path variable (that you first saw in chapter 5)—this auto-generates a URL to the specific template group and template you specify. In this case, member is not a traditional template group, but rather the keyword you have defined in member preferences. If you do not feel like typing this in, remember that the finished code for each chapter can be downloaded at either http://www.packtpub. com/support or http://www.leonardmurphy.com/book2. Member Links
{if logged_out} - Login
- Forgot Password?
- Register
{/if} {if logged_in} - Profile
[ 153 ]
Members - Member list
- Logout
{/if}
3. Click Update and Finished and now visit the main website home page. Underneath Key Services, you should now see Member Links (depending on whether you are logged in or out will determine which links you see). Try the links to make sure they work.
You have now enabled the ability for visitors to register themselves on your website.
Introduction to member groups
By default, there are five member groups. You are already familiar with the Super Admins member group (which you are a member of). The Members member group is the group that approved members are put into (unless you have changed the default member group in the member preferences). By default, members in this group can do everything available on the member screens (such as sending private messages) as long as you have not disabled the option in the global Member Preferences. However, members cannot log into the control panel. The Pending members group is for members who have registered but have either not activated their membership via e-mail (if you allow self-activation by e-mail) or have not yet been manually approved (if you require members to be approved by an administrator). If you do allow self-activation by e-mail, it is a good idea to review the members of this group periodically and delete stale applicants (do this via Member | Activate Pending). [ 154 ]
Chapter 6
Members in the Banned member group cannot see your ExpressionEngine website, and the Guests member group is used for members who are not logged in. Since Super Admins can do anything and everything in ExpressionEngine and cannot be restricted, you should be very cautious about which members you assign to the Super Admin group. For example, while Ed & Eg need to be able to post and modify channel entries, it would be better not to give them access to templates, where they might accidentally change something. To accomplish this, you can create a new member group for Ed & Eg.
Creating a member group
In this section, you will create a new new member group called Editors for Ed & Eg. This will allow them to be able to log into the main control panel and publish or edit entries but will not allow them to view templates or change administrative preferences. After you create the member group, there will be two sets of options to configure. The first set of options applies to the member profile screens (and controls such things as whether they can send private messages). The second set of options control what the members can do within the control panel. For most members, you would not even allow them access to your control panel, so this second set would not apply. Throughout the configuration process, any options that you would not want to assign to someone you do not know and trust is bolded and colored red. 1. The first step is to create the member group. Log into the control panel as a Super Admin and go to Members | Member Groups. 2. Rather than creating a member group from scratch, you will base the new member group on the Super Admins member group. Underneath the member group listing is the option Create a new group based on an existing one. Select the Super Admins group from the drop-down box and click Submit.
[ 155 ]
Members
3. You will be brought to a new screen where you can give the new group the name Editors. Optionally, you can type in a description.
4. Continuing down the screen, the next option is Security Lock. If you allow groups, other than Super Admins, to administer members, you can control which member groups they can assign users to. As editors and owners of the website, you would want Ed & Eg to be able to approve and manage their members, but you would not want them to be able to assign members to the Super Admin or Editors group (for example). To accomplish this, leave this group Locked (meaning only Super Admins can assign members to the Editors group). To allow Ed & Eg to be able to assign members to the Members group, you would have to edit the Members group and adjust the group security lock to be Unlocked (by default, the Members group is locked, meaning only Super Admins can assign members to it).
5. The next option is Site Access. Since you would want Ed & Eg to have access to the website when it is offline, leave both options as Yes. (If you were creating a member group for members of the public, you would typically set this to No). [ 156 ]
Chapter 6
Within Admin | General Configuration, you can choose whether your system is on or not. You might choose to turn it off if you are doing updates and do not want members of the public to stumble across an incomplete site while the changes are in progress.
6. In the next option, Member Account Privileges, say No to allowing Ed & Eg to be able to delete their own account—if they accidentally did this, it would cause any content they had created to be deleted as well.
7. Comment Posting Privileges, Search Privileges, and Private Messaging Privileges allow you to control whether this member group can use these functions (and allows you to set member group-specific restrictions on their use). Since Ed & Eg own this website, do not make any changes to these screens.
[ 157 ]
Members
8. Control Panel Access is where you can allow (or prevent) the member group from accessing either the entire control panel or specific sections within the control panel. Since you want Ed & Eg to only have access to options they can safely use, say No to the following sections: DESIGN, add-ons (all five sections), ADMIN (all three sections), and say No to TOOLS (Utilities, Data, and Logs only). Leave the TOOLS section and the TOOLS: Communication set to Yes. Ed & Eg will only have access to the options set to yes here.
9. Under Control Panel Administration, say No to all the options except administrating member accounts, changing member groups, and banning users.
[ 158 ]
Chapter 6
10. Control Panel Email Privileges allows you to prevent Ed & Eg from sending e-mails through ExpressionEngine. Since there is no reason to do this, leave all the options as Yes. If you have a website where a large number of people will have control panel access (such as in a larger business), you might want to set this setting to No. 11. The Channel Posting Privileges allows you to decide what Ed & Eg can do with channel content (for example, if they can delete entries or edit other peoples' entries). Since Ed & Eg are the owners of the website, do not make any changes. 12. The Channel Assignment allows you to choose which channels Ed & Eg can publish to and edit. If you have Agile Records installed, you would want to ensure that Ed & Eg cannot see the Agile Record channels. Therefore, only say Yes to FAQs and Website—say No to Information Pages and News if they are there.
13. Comment Administration allows you to configure what comments Ed & Eg can view, moderate, edit, or delete. Leave all these options set to Yes. 14. Template Editing Privileges allows you to control which template groups Ed & Eg can edit. Since you do not want Ed & Eg editing any templates, say No to all of them. 15. Module Access Privileges allows you to control which modules Ed & Eg can access. Since you are not giving Ed & Eg access to the Add-On screens, you can say No to all modules (if there are any listed). 16. Click Submit to create the member group. You will be returned to the Member Groups page, where you will see your new member group in red and bold (because it has access to the control panel). You have now created an Editors member group, and all your changes have been saved. Next, you can log into the control panel as Ed or Eg and see what it looks like.
[ 159 ]
Members
Creating a member
Earlier in this chapter, you saw how to register yourself as a new member. Thankfully, as Super Admins, you can bypass this process and create new members directly in the control panel. In this section, you will create your first editor group member, Ed the Editor. 1. From the top menu, select Members | Register Member. 2. Fill in the username (edward), password, screen name (Ed), and e-mail address for your new member. (Remember that, by default, only one e-mail address can be used per member). Be sure to select the Editors member group as the member group assignment and then click Register a New Member.
3. You will be returned to a list of members in the Editors member group (right now, Ed is your first and only editor). Do not close this listing.
Logging in as Editor Ed
Another advantage of being a Super Admin is that you can log in as any other member without having to know that member's password. This allows you to see your website as they see it—which is helpful when you are developing new features or troubleshooting reported issues. 1. From the View / Search Members screen that you are on, click on the edward hyperlink.
[ 160 ]
Chapter 6
2. You will be taken to the member control panel for this member. From the left-hand side, select Login as Member (the second option from the bottom).
3. You can now choose which page of your website you want to see as Editor Ed. Select the Control Panel radio button and click Submit.
[ 161 ]
Members
4. You will then be logged in as Editor Ed. Although it looks like the control panel you have been working in so far, notice that there are far fewer options, both in the menu and on the main screen. Essentially, all Ed can do is publish new entries, edit existing entries, and administer members. ExpressionEngine has many options that allow you to decide how much access other people have to the control panel—you could set up a member group that can only post entries to a single channel or you could set up a member group that can do everything but post entries to a given channel. You can also set up member groups that do not have control panel access such as a trusted members group, which is exempt from comment moderation or that can search more frequently than regular members. You have now created a member group specifically for Ed & Eg to be able to create content without risk. However, there is one more area that can be customized by the member group: the Publish Page.
Modifying the Publish page layout
By default, the Publish page contains lots of options, spread across several tabs, some of which you will be unlikely to use for a given channel (such as the expiration date for an entry) and some of which you will intend to use, but will be liable to forget about (such as selecting the categories for an entry). Luckily, as a Super Admin, you can customize the Publish page so that the workflow better suits your needs. In the FAQs channel, you know you must select the category for a new entry, so instead of having the categories on a separate tab, you will move it to the bottom of the main tab so that you must scroll past it in order to submit your entry. In this way, you are less likely to forget to fill it in. 1. Log into the control panel as a Super Admin, and go to the Publish screen for the FAQs channel (Content | Publish | FAQs). 2. Towards the top-right (just to the left of the Notepad on the right-hand side), you should see an option that says show toolbar. Click this. (If you are not logged in as a Super Admin, you will not see this).
[ 162 ]
Chapter 6
3. A toolbar will appear with a list of fields, tabs, and authors. First, notice the eye on the right-hand side of each field name. If the eye is open, it means the field is visible. If the eye is closed, it means the field is not visible. (If there is no eye, it means the field is mandatory and cannot be made invisible). Click on the eye to toggle between open and closed. Close the following fields that Ed or Eg will be unlikely to modify on a per-entry basis in the FAQs channel: Expiration Date, Comment Expiration Date, Pings, Channel, and Options.
[ 163 ]
Members
4. The Tabs section allows you to delete tabs or create your own. For example, there are several tabs that have only one or two options on them. Rather than having all these tabs, you could delete all of them, and create a new tab for all your lesser-used options (such as the URL title and entry date, which you may want to alter for an entry, but not every entry). First, click Add a New Tab and call it Rarely-Used Options. Then click Add a Tab.
5. Next, click on the newly created tab and drag fields from the list of fields in the toolbar onto the main window in the position you would like them. Move the following fields: Entry Date, URL Title, Author, Status, and Revisions. If you do not see the revisions tab, you may not have enabled entry versioning while following chapter 5—to do so, go to Admin | Channel Preferences | Channels and then Edit Preferences for the FAQs channel. 6. Since Categories is something you always want Ed or Eg to select when they publish an FAQ (because the content is organized by category), click on the Publish tab and drag the Categories field from the toolbar onto the Publish tab. 7. Next, you can delete all the other tabs that you no longer need. Click on the trash can to the right of each tab name (other than Publish and Rarely-Used Options).
[ 164 ]
Chapter 6
Finally, each field on the main screen also has a little triangle at the bottom right and a little rectangular tab on the left. The triangle allows you to modify the size of the field (for example, so that it does not take up the entire width of the screen) and the rectangle allows you to modify the position of the field in relation to other fields. In this way, for example, you can put two smaller fields beside each other or you can reorder the fields as you see fit. 1. Now you can save your updated layout. At the bottom of the toolbar, check the boxes to apply the layout to both the Super Admins and the Editors member groups and then click Save Layout.
2. Now click hide toolbar to hide the toolbar, and you can see that the Publish page is substantially simplified. Instead of six tabs and lots of options you never use, there are two tabs—the first tab with options that you always want to set for a new entry, and the second tab with options that you rarely need to set, but might want to on occasion. To summarize, there are three ways to configure options on the Publish page: 1. The Member Group options allows you to configure which member groups can publish to which channels (or even whether a given member group with control panel access can publish to any channels). 2. The Custom Field options (reviewed in previous chapters) allows you to configure which options appear for each field—such as the HTML formatting buttons, write-mode, the spell-check, and so forth (and also whether the fields are mandatory or not). 3. The toolbar on the Publish page allows you to configure which options are visible on a per-channel, per-member group basis. This level of flexibility allows you to build a website for someone else to maintain, and to keep the interface uncluttered for that person, so that they only see the options they need to use. [ 165 ]
Members
Creating member-only content
So far you have seen the options available to you in the control panel for different member groups. For members with control panel access, the options are very comprehensive—you can disable entire sections (such as template editing) or disable individual items within a section (such as which template groups can be edited or which fields on the Publish page are visible). For members without control panel access, it is up to you how attractive you make the membership of your site, because any member-only feature has to be specifically coded that way in your templates. There are two ways you can restrict what nonmembers can see: 1. You can configure templates to not be viewable by certain member groups. If a person in an unauthorized member group attempts to access one of these templates, you can redirect them to a different template that says the content is for members only. From the Template Manager, where you would normally click to edit the template, click Access to change who can view the template and what template they should see instead. This can be useful if you are creating a new section to your website and want to allow certain member groups to try it out before going live to everyone.
[ 166 ]
Chapter 6
2. Alternatively, you can use conditional tags within templates to display different content. This allows you much more control and flexibility over what your visitors see—you can display different content depending on whether the member is logged in, depending on the member group of the member or based on any number of variables (for example, the username of the member or how many comments a member has posted). Read more about conditional tags at http://expressionengine.com/user_guide/ templates/globals/conditionals.html. Next, you are going to create a new custom status called Premium. If an FAQ is marked with a premium status, only registered members will be able to see the answer. Non-members will be able to browse all the FAQs, but if they select a premium FAQ, they will only see the question, along with a message encouraging them to register to see the answer.
Making content visible to members only
You have already seen the {if logged_in} and {if logged_out} tags to display different links, depending on whether a member is logged in or not. You will now use these same tags to determine whether or not to show them member-only content. WARNING: If you use conditional statements {if logged_in} and {if logged_out} inside the {exp:channel:entries} tag on a template, do not enable caching on that template or the conditionals will not work. The first person to visit the template will have their logged in state cached, meaning every subsequent visitor will be treated as if they have the same logged in state as that first visitor. Caching can be set for each template on the Template Manager screen by clicking on Edit Preferences for the template in question—by default, template caching is not enabled.
1. Before you can assign any channel entries to a premium status, you must first create the premium status by going to Admin | Channel Administration | Custom Status Groups. You currently only have one status group (statuses), so click Add/Edit Statuses.
[ 167 ]
Members
2. Next, click Create a New Status at the top right. (The Featured status you see in the screenshot will only exist if you installed Agile Records).
3. Call the new status Premium. Leave the Highlight Color blank. This controls the color of the status in the control panel—for example, if you typed red, the status would be in red text. Leave the specific groups who can access the status set to Yes. Click Submit.
The ability to restrict status to members of specific groups allows you to use statuses as a workflow on your website. For example, if you have a member group called authors, you could allow them to publish to a channel, but restrict what status they can assign the new entry so that their work is not open (for example they might only be able to publish to a 'needs review' status). You can then have another member group (such as editors) that do have the right to change the status from 'needs review' to 'open'—thereby ensuring that anything published on your website has been reviewed by a member of the editors group.
[ 168 ]
Chapter 6
4. Now post a new entry to the FAQs channel, and before clicking Submit, ensure that you set the status to Premium (on the Rarely-Used Options tab if you customized your Publish Page layout in the previous section, otherwise on the Options tab).
5. If you now visit http://localhost/faqs you will notice that your new entry does not appear. This is because you must specify in the {exp:channel:entries} tag in each template if you want entries to appear that have a status other than open. Modify the four templates (faqs/index, faqs/browse, faqs/rss, and faqs/atom) and the website_ faqs snippet to include the status="Open|Premium" parameter in the {exp:channel:entries} tag. The | means OR—as in, you want to entries that have either the Open or the Premium status. If you just specified status="Premium", then any entries with a status of open would not display. •
faqs/index: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Premium"}
•
faqs/browse (in HTML ): {exp:channel:entries channel="{my_channel}" disable="categories|category_fields|custom_fields|member_ data|pagination" status="Open|Premium"}{title}{/ exp:channel:entries} - Ed & Eg Financial Advisors title>
•
faqs/browse (after ): {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes" status="Open|Premium"}
•
faqs/rss: {exp:channel:entries channel="faqs" limit="10" dynamic_ start="on" disable="member_data" status="Open|Premium"}
•
faqs/atom: {exp:channel:entries channel="faqs" limit="15" dynamic_ start="on"disable="member_data" status="Open|Premium"} [ 169 ]
Members
•
website_faqs: {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off" status="Open|Premium"}
6. Now, modify the faqs/browse template and replace the line <strong>A: {faqs_answer}
with the following conditional statement. This says to display the answer if either the status is not Premium or if the visitor is logged in. If neither of these conditions are true (that is, the status is Premium and the visitor is not logged in), then do not display the answer. {if status!='Premium' OR logged_in} <strong>A: {faqs_answer}
{if:else} <strong>A: This answer is available to registered members only. If you are already a member, please login. Otherwise, consider registering for free & unlimited access to all our advice.
{/if}
7. Click Update and Finished, and now log out of the control panel (link in the upper-right-hand corner of the screen). 8. Now that you are not logged in, visit your premium content FAQ. Instead of seeing the answer, you should see a message telling you to log-in (as shown below). Verify that you can log in and see the answer.
[ 170 ]
Chapter 6
You have now given Ed & Eg the ability to make content Premium, encouraging visitors to register on the website. Although this is a simple example, ExpressionEngine's conditional statements are very flexible and very powerful. For example, you could show a promotion (5 percent off!) on your homepage, but only to registered members, or even only to registered members who have commented a set number of times. You could also show different content to different member groups. Each member group has a Group ID number, viewable under Members | Member Groups. Using this Group ID, you can use a condition such as {if member_group='6'} (where 6 is the Group ID of the Editors member group) and then create a draft status and allow Editors to see entries with a draft status, but keep them invisible to all other members and non-members. The choices are limitless.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. Try creating a new member group called Designers that can only be used to modify templates. Members of this group should not be able to post or modify any channel entries. 2. When a member registers for the first time, you have the option to collect additional information (beyond the username, name, and e-mail address) in Custom Member Fields. For example, if you have a motorcycle website, you could have a custom field to ask new members what make/model of motorcycle they have. Alternatively, if you give a free t-shirt to new members, you could ask for their t-shirt size. For this exercise, create a custom member field that asks "Are you an existing customer of Ed & Eg?" with possible answers being Yes or No. 3. On the right-hand side of your website is a box with a title of Promotion! that links to a Promotions page. Ed & Eg have decided that they want promotions to be visible only to registered members of the website. Modify the promotions/index template to display the promotion if a visitor is logged in, but otherwise display a message asking the visitor to register. (The promotions/index template is created as part of the challenges in Chapter 4, Moving a Website to ExpressionEngine).
[ 171 ]
Members
Summary
In this chapter, you learned all about member functionality in ExpressionEngine, including the built-in member control panel. You also looked at setting up new member groups and customizing the administrative control panel for different member groups (that have control panel access). Finally, you looked at how to use conditional statements in your templates in order to make membership attractive to visitors. The key points to remember after working through this chapter are as follows: •
You can control what all members can or cannot do in the Member | Preferences screens. You can also make exceptions on a member group basis in Members | Member Groups. So, for example, you can require that all comments are moderated, but make an exception for members in a specific group.
•
Be cautious about who you assign to the Super Admins member group. If someone needs control panel access, but does not need access to everything in the control panel, it is a better practice to set up a new member group with only the permissions that the member group needs.
•
If you are building a website for a client, remember that you can modify the Publish page to make it more intuitive. You can hide fields that are not relevant and at the same time make other fields more prominent.
•
How attractive membership is on your site is up to you. Using conditional statements, you can control what content members can see, displaying different content for different member groups or based on different conditions.
•
If you have a template that uses the conditional statements {if logged_in} or {if logged_out} inside the {exp:channel:entries} tag to display different content to different members, do not enable caching for that template.
[ 172 ]
Creating a Calendar Many organizations have events, and a calendar is a very visual way of indicating what is going on and when. The built-in ExpressionEngine calendar functionality is limited (for example, it does not allow recurring appointments). However, you can use it to display event titles with clickable links for more information. If a calendar is a key part of your website, you may be interested in checking out Solspace's calendar module (at the time of publication, it is not yet available for ExpressionEngine 2). http://www. solspace.com/software/detail/calendar/. The module contains support for more sophisticated calendar functionality such as recurring appointments.
In this chapter, you are going to use the built-in functionality of ExpressionEngine to build a simple events calendar that is easy to post to using the Publish page in the control panel. You will use the jQuery module to display more information when an event is clicked. Finally, you will also be introduced to the concept of Related Entries (relating the post from one channel to a post in another channel)—a useful tool to reduce repetition in channel entries.
Designing the calendar
Ed & Eg frequently host free seminars for customers and members of the community in their conference room. These seminars are usually sponsored by another organization. Ed & Eg would like a calendar on their website that shows each seminar on the date that it is to take place, along with a link so that visitors can read more about the topic of a given seminar as well as who the sponsor company is.
Creating a Calendar
One way you can design such a calendar is to create an events channel, which contains all the information regarding both the event and the event sponsor. This would work, but because a single event sponsor is often associated with more than one seminar, this design would result in you having to include the same information about the same sponsors in more than one channel entry. For example, if Anytown Bank sponsors five seminars, there would be five entries where you would have to provide information about Anytown Bank. Related Entries is a way to reduce repetition in channel entries. (Not to be confused with relating entries by category—which you did when you built the FAQs channel). Essentially, if you have two kinds of data (events and event sponsors), you can create two channels and then include the data from one channel in the other. In this way, you can have an event_sponsors channel, which contains all the pertinent information on the event sponsors (such as their name, location, opening hours, and services offered). The event channel itself will then only contain information about the event (such as the date, time, and topic). When Ed or Eg creates a new event, they can simply select the sponsor (such as Anytown Bank) from a drop-down list of sponsors in the event_sponsors channel, and all the information about the event sponsor will automatically populate for them—no retyping necessary.
Setting up your channels
To set up an event and an event sponsors channel, you will first create the custom fields, then create the channels, then populate the channels with example data, before finally creating the templates that you will use to display the channel data. When creating two channels that are to be related, it's best to start with the channel whose data will be included in the other channel—therefore, start with the event sponsors channel.
Creating custom fields for event sponsors 1. Select Admin | Channel Administration | Custom Fields.
2. Select Create a New Channel Field Group and call the field group event_ sponsors. Click Submit. 3. Now select Add/Edit Custom Fields for the event_sponsors field group. 4. For now, keep things simple and create only one field—a generic about field. (You could, of course, create as many fields as you want). Select Create a New Custom Field. [ 174 ]
Chapter 7
5. The field type will be Textarea. The field label will be About and the field name will be event_sponsors_about. The field will be required, will not be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. The event_sponsors field group is now ready to go. The next step is to create the event_sponsors channel.
Creating the event sponsors channel
By now, you should be familiar with the process of creating a channel. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Event Sponsors with a short name of event_sponsors. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and event_sponsors for the field group (the category group can be left as none, as you will not be using categories with this channel). Remember, if you do not select a Status Group when creating a new channel, then only Super Admins can post open entries. If any other member group posts an entry, it will be closed by default (and therefore not visible on your website).
3. Finally, select No to creating new templates and then click Submit. 4. Now, go to the Content | Publish | Event Sponsors and create a couple of example sponsors (for example, Anytown Houses, Anytown Bank, and Anytown Law Firm).
[ 175 ]
Creating a Calendar
Now that you have your sponsors channel set up with some sponsors, you can go ahead and create the events channel.
Creating the events custom fields
As before, you will first create your channel custom fields, before creating the channel, and then some example content. 1. Select Admin | Channel Administration | Custom Fields. 2. Select Create a New Channel Field Group and call the new field group events. Click Submit. 3. Now select Add/Edit Custom Fields for the events field group. 4. You will create two fields for your events—Description and Sponsor. Select Create a New Custom Field. Note that you will not create a custom field for the date or the time of the event. This is because you can change the date/time of the entry to reflect the date/time of the event.
5. The field type will be Textarea, the field label will be Description, and the field name will be events_description. The field will be required, will be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. 6. Next you can create the relationship field. Click Create a New Custom Field. 7. From the drop-down of Field Types, select Relationship. The Field Label will be Sponsor, and the Field Name will be events_sponsor.
8. The field will not be required (some events might not be sponsored) and the field will not be searchable. Say Yes to show the field by default. [ 176 ]
Chapter 7
9. In the Custom Field Options, select the Event Sponsors channel and leave the display criteria at the default setting (Sort by Title in Descending Order). Click Submit.
Now all you have to do before you can start creating events is create the events channel.
Creating the events channel
Creating the events channel is a fairly straightforward process. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Events with a channel name of events. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and events for the field group (the category group can be left as none, as you will not be using categories with this channel). 3. Finally, select No to creating new templates and then click Submit. 4. Your channel is created! Now, you can bring together your Events and Event Sponsors by creating some events.
Creating example events
The final step in setting up these channels is to post some example events, so that when you create the calendar on your website, you have some events to see how it is working. Your first event is going to be a seminar called Common Pitfalls of Home Buying, sponsored by Anytown Houses. 1. Select Content, Publish, and select the Events channel. 2. Type in the title, Common Pitfalls of Home Buying. In the description field, type in some example topics that will be covered.
[ 177 ]
Creating a Calendar
3. Select Anytown Houses as the sponsor. That is all you need to do to associate the sponsor with the event.
4. Before clicking submit, select the Date tab at the top of the screen and select a date for your entry and a time of 6 p.m.
[ 178 ]
Chapter 7
5. Click Submit. 6. Go ahead and create a few more events with different sponsors, dates, and times, so that when you create the calendar, you have a few entries to play with. Now that you have the channels built and have some example events too, you can go ahead and create the calendar!
Creating the calendar
For the rest of this chapter, it will be useful to refer to the official ExpressionEngine documentation on the calendar tag at http://www.expressionengine.com/user_ guide/modules/channel/calendar.html, where much of the code in this section is adapted from. The first steps in creating a calendar are to create a calendar template group, add the basic HTML to construct the page, build the outline of the calendar, and add CSS to make the calendar look good.
Creating a blank calendar template
1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group calendar. Do not duplicate a group and do not make the index template in this group your home page. Click Submit. 2. Copy and paste the code from the includes/404 template (or any template that has all the normal page components such as the header, sidebar, widebar, and footer). Paste the code into the new calendar/index template. At the top of the template, add a my_channel preload replace as follows: {preload_replace:my_channel="events"}
3. Change the page title from Page Not Found to Calendar. Calendar - Ed & Eg Financial Advisors
4. Change the h1 title to Seminar Calendar and delete the paragraph underneath that says the page does not exist (including the and
tags). The content section should look as follows: Seminar Calendar
[ 179 ]
Creating a Calendar
Now you have a blank Ed & Eg themed template (viewable at http://localhost/ calendar) that you can use for your calendar.
Creating the calendar
The next step is to create a blank calendar—it will not display any events just yet. This code is adapted from the ExpressionEngine documentation. 1. In the calendar/index template, add the following code after the Seminar Calendar
line. The first piece of code is the exp:channel:calendar tag. This is a pair of tags with a number of parameters. {exp:channel:calendar switch="calendarToday|calendarCell" channel="{my_channel}" show_future_entries="yes"} {/exp:channel:calendar}
The channel parameter specifies that the entries on the calendar are coming from {my_channel}, where {my_channel} is a Preload Text Replacement corresponding to the events channel. The parameter show_future_entries="yes" means that the calendar will show future entries. In most channel applications, if you set an entry date in the future, ExpressionEngine does not make that entry visible until that date. This is useful if (say), you are going away but want to schedule new content to appear at a certain time while you are gone. In this case, if a calendar only showed entries that have already happened, it would not be a very useful calendar. The switch parameter is used to switch between two different stylesheet styles (you will create the calendar stylesheet next). If the day being displayed is not today, then the stylesheet's style will be calendarCell. If the day being displayed is today, then the stylesheet's style will be calendarToday. This allows today's date to be styled differently.
2. The next step is to start displaying the calendar itself. A calendar is a table with seven columns (one for each day of the week) so you will use the HTML table tag to display it. In the following code, you define the first row. In the top left cell, you will display << that can be clicked to move to the previous month. Likewise, in the top-right cell, you will display >> to navigate to the next month. The middle five cells will contain the name of the current month being displayed. The style calendarBG will be defined in the stylesheet that you will create in the next section. Add the following code after the {exp:channel:calendar} tag and before the closing {/ exp:channel:calendar} tag. [ 180 ]
Chapter 7 << {date format="%F %Y"} >>
The previous and next path links both point to the current template (calendar/index). < is HTML for the < symbol and > is HTML for the > symbol. The format code to display the current month and year, %F %Y, is taken from ExpressionEngine's date formatting code, available at http:// expressionengine.com/user_guide/templates/date_ variable_formatting.html
3. Go to http://localhost/calendar and you can see the calendar beginning to take shape. Click on the arrows and you can see that the name of the month changes, as does the URL of the page. 4. The next row will display the weekdays. The code {lang:weekday_abrev} refers to the one letter weekdays. You could also use weekday_long or weekday_short to either spell out the entire weekday or the first few letters of the weekday respectively. This must be wrapped in a {calendar_ heading} variable pair. Insert the following code after the closing tag and before the closing tag. {calendar_heading} {lang:weekday_abrev} {/calendar_heading}
[ 181 ]
Creating a Calendar
5. The next row will display the actual dates. There is no way to know how many rows might be needed for a given month (February might only require four rows; October might require six). ExpressionEngine dynamically determines how many rows to display using the {calendar_rows} variable pair, which repeats for as many rows as are necessary. Each row starts with the command and ends with the closing command. For each calendar cell, there are three possibilities—there may be events for that date; there may not be events for that date; or it may be an empty cell before the first day of the month or after the last day of the month. You want to handle each of these situations differently, so you will use conditional statements to distinguish between these three possibilities, although, right now, you will simply be displaying the date in each. Notice that, for your empty cells, you use a different class so that you can style it differently in your stylesheet. Insert this code after the closing tag and before the closing tag. {calendar_rows} {row_start}{/row_start} {if entries} {day_number} {/if} {if not_entries} {day_number} {/if} {if blank} {day_number} {/if} {row_end} {/row_end} {/calendar_rows}
You now have the beginnings of a calendar, although it looks a little basic.
[ 182 ]
Chapter 7
Before you start displaying your events on this calendar, first create some CSS to make the calendar look a little more calendar-like.
Formatting the calendar with CSS
Rather than adding the calendar styles to your main site/site_css stylesheet, it makes sense to create a separate stylesheet just for the calendar styles. This is because the calendar styles are only needed on the calendar page and do not need to be included on any other page.
Creating the calendar CSS template
First, you will create the template for the calendar CSS. Then you will point the calendar/index template to this new template. 1. From Design | Templates | Template Manager, click the calendar template group and select New Template. Call the new template calendar_css and choose a Template Type of CSS. Click Create and Edit.
2. The first line in your new template will import the main site/site_css template (so that the page outside the calendar continues to be formatted correctly). After typing this, click Update and Finished. @import url({site_url}includes/site_css);
[ 183 ]
Creating a Calendar
The {site_url} variable, which you have seen before, is converted to the actual URL to the root directory of your site, as stored in Admin | General Configuration. Note that the URL in this setting should have a trailing / (for example, http://localhost/ as opposed to http:// localhost) or the link above will not work (for example, it will resolve to http://localhostincludes/site_css instead of htttp:// localhost/includes/site_css).
3. The next step is to point the existing calendar/index template to use this new CSS template in place of site/site_css. To do this, edit the calendar/ index template and modify the stylesheet line to read as follows:
Now you can add some styles to your CSS.
Adding styles to your calendar CSS
In the calendar/index code so far, you have defined several styles: • • • • • •
calendarBG is used to format the overall table calendarHeader is used to format the month heading calendarDayHeading is used to format the weekday headings calendarCell is used for the calendar cells, except for today's date calendarToday is used for the calendar cell that represents today's date calendarBlank is used for calendar cells that are not for the dates this month
Helpfully, EllisLab provides a suggested stylesheet in the ExpressionEngine documentation (http://expressionengine.com/user_guide/modules/channel/ calendar_css.txt), which you can start with and then adapt to your own needs. 1. Open the template calendar/calendar_css for editing. Copy and paste the example code from the URL above into the CSS stylesheet (below the @ import line) and click Update.
[ 184 ]
Chapter 7
2. Next, modify the three cell styles (calendarCell, calendarToday, and calendarBlank) to position the date in the top-left of the cell (so that there is room for your event text). To do this, modify the following two styles for .calendarCell and .calendarToday and add them to .calendarBlank: text-align: left; vertical-align: top;
3. Now modify the same three cell styles to have a fixed width. Otherwise, as events are added to your calendar, some columns will expand and other columns will shrink. Add the following styles to .calendarCell, .calendarToday, and .calendarBlank: width: 60px; height: 60px;
4. Finally, you can create some styles for displaying your events. You want to keep the font clear to read but small. The following code will give each event a border, so that if there are two events on the same day, the text will not run together. Since all the events will be links (for more information), this code will also change the background color of the event when the mouse moves over it to make it clear that it is clickable. Add the following to the end of the calendar_css stylesheet: .calendarEvent a{ font-family: Arial, Trebuchet MS, Tahoma, Verdana, Sansserif; [ 185 ]
Creating a Calendar font-size: 10px; font-weight: normal; letter-spacing: 0em; text-decoration: none; border: 1px solid #666; vertical-align: top; text-align: left; margin: 5px; padding: 5px; display: block; } .calendarEvent a:hover{ background-color: #ccc; }
You now have a pretty, but blank, calendar. You can, of course, go further and change the styles so that it suits your site. It is all easily configurable within the CSS. The next step is to start displaying events on your calendar. Since space on the calendar is limited, you will only display the title of the event on the calendar itself, with a clickable link for more information. (In fact, only the title field from the channel is available in the {exp:channel:calendar} tag—none of the custom field tags will work). The basic way to build the clickable link is to simply create a new, single-entry page template that you link to (just as you did with the FAQs channel). However, to keep things interesting, a new approach is called for. You will still create a single-entry page template, but rather than just linking to it directly, you will use the jQuery module combined with the FancyBox plug-in (http://fancybox.net/) to display the single-entry page in an iFrame lightbox that floats over the calendar. To accomplish this, you must first download the FancyBox tool and upload the files to your website. (FancyBox is also used in the next chapter on photo galleries). If you are removing the index.php from your URLs, then you will likely have to modify your .htaccess file so that you can access the FancyBox files. You can then create your single-entry template (and a corresponding, simplified CSS file). Finally, using the jQuery module and FancyBox, you can create a link to your single-entry template from your calendar.
[ 186 ]
Chapter 7
Note that although this chapter is using a third party jQuery plugin, the focus of this book is on using ExpressionEngine—not on learning jQuery (or FancyBox). For more information about jQuery, please visit http://jquery.com/.
Setting up FancyBox
You can download the latest version of FancyBox directly from http://fancybox. net/, or a copy of the latest version is included in the code for this chapter at either http://packtpub.com/support or http://www.leonardmurphy.com/book2/ chapter7. 1. First, download FancyBox and extract all the files from the compressed directory into a directory on your computer. 2. Once extracted, you should see a directory called fancybox, complete with a number of images, JavaScript files (.js), and a CSS file. Upload this entire directory to the root of your website. Note that for the purposes of this chapter, you do not need any of the example files that ship with FancyBox. 3. Next, if you are removing the index.php from your ExpressionEngine URLs using the exclude method, you will have to add this new directory to your .htaccess file (otherwise it will be treated as an ExpressionEngine template group, rendering it inaccessible). Open .htaccess and add FancyBox to the end of the list of real directories and files as follows (but do not create a second RewriteCond line—modify the line you already have). RewriteCond $1 !^(images|system|themes|index\.php|admin\.php|fancybox) [NC]
For an example of a complete .htaccess file using the exclude method, please see either http://packtpub.com/support or http://www. leonardmurphy.com/book2/chapter2. Your .htaccess file may include other files or directories that you have in the root directory of your website (such as robots.txt or favicon.ico) that you should leave in place. 4. To verify that your .htaccess file is not blocking access to the fancy box directory, open http://localhost/fancybox in your browser. If you see your ExpressionEngine 404 page, then your .htaccess file is treating the fancybox portion of your URL as an ExpressionEngine template group. Review your .htaccess file.
[ 187 ]
Creating a Calendar
Troubleshooting problems that are due to the .htaccess file can be challenging. Many times you set up a .htaccess file when you install ExpressionEngine and then forget that it exists, so you do not even think of the .htaccess file. Remember that EllisLab does not provide support for removing the index.php using a .htaccess file (because there are so many ways to do it and every server works a little bit differently). If you suspect your .htaccess file is causing problems, you can temporarily remove it and add the index.php back into your website URLs (in Admin | Configuration, under Name of your site's index page). If you do this, it will at least confirm whether the issue you are seeing is due to your .htaccess file or something else entirely.
5. Finally, if you are using Internet Explorer, you may want to modify fancybox/jquery.fancybox-1.3.1.css to include a / at the start of the AlphaImageLoader sources. (This tells Internet Explorer that FancyBox is a directory at the root of your website and therefore enables it to find the images it needs). The easiest way to do this is to do a find and replace and replace AlphaImageLoader(src='fancybox/ with AlphaImageLoader(src='/fancybox/
FancyBox is now in place and ready to go. Next, you will create your single-entry template, along with a pared-down CSS file.
Creating your single-entry template
First, you will create a pared down CSS file, before creating your single-entry template. Both will be much smaller versions of your regular templates/CSS (since you would not view this template on its own, but rather as an overlay on an existing page, you do not need the usual Ed & Eg header, sidebar, or footer. As a result, the template and the CSS are smaller). 1. Create a new template in the calendar template group called event_css. The template type will be CSS. Duplicate an existing template, namely, includes/site_css. Click Create and Edit. 2. Delete the input, textarea style. Further down, delete everything that appears after the /* Wrapper */ comment (including /* Wrapper */ itself). 3. Now update the body style to read as follows (essentially removing the background and adding in a four percent padding so that the text in the popup overlay will not touch the sides of the pop-up overlay box): body { font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; [ 188 ]
Chapter 7 font-size: 12px; color: #6B6B6B; padding: 4%; }
4. Finally, remove the h2 from the h1,h2 style (not the h1, h2, h3, h4 style) and instead, add it to the h3 style. The styles should end up looking as follows: h1 { font-size: 28px; } h2, h3 { font-size: 16px; font-weight: bold; }
5. Click Update and Finished to save this CSS template. 6. Next, you will create your event template. In the calendar template group, click New Template and name the template event. The template type will be Web Page. Select to duplicate the calendar/index template and click Create and Edit. This template will be visible at http://localhost/calendar/ event. 7. Delete everything between the and tags. Also, change the to be Calendar Event as follows: Calendar Event - Ed & Eg Financial Advisors
8. Next, change the stylesheet so that instead of pointing to calendar_css, it is pointing to the CSS stylesheet you just created (event_css).
9. Next, after the tag, add the following code to display the event information. {exp:channel:entries channel="{my_channel}" show_future_entries="yes" limit="1" require_entry="yes"} {if no_results} {redirect="404"} {/if} {title}
<strong>Join us on {entry_date format="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{events_description}
{/exp:channel:entries} [ 189 ]
Creating a Calendar
Notice that the show_future_entries parameter has to be included here, since this template is going to be displaying event entries that have an entry date after today's date. Also note the use of require_ entry and if no_results to ensure that only valid events can be displayed—all others will be redirected to your 404 page.
10. Next, you will display the sponsor information from the event_sponsors channel. Since you are displaying the content of the event_sponsors channel inside the events channel, ExpressionEngine needs a way to know which channel it is supposed to be displaying the data from (fields such as {title} could refer to either channel). To accomplish this, you wrap all your event_sponsors information in the tag {related_entries} using an ID that corresponds to the relationship field in the events channel (in this case, the events_sponsor custom field). You can then use the custom field names from the event_sponsors channel. The ID is a way for ExpressionEngine to support more than one relationship field in the same channel. Insert the following code after the {events_description}
line: {if events_sponsor} {related_entries id="events_sponsor"} More About {title}
{event_sponsors_about}
{/related_entries} {/if}
You have now completed this separate, pared-down single-entry template to show more information on your calendar entries. Although the plan is to only display this template in a pop-up overlay on your calendar page, you can see what the template looks like by itself by going to a URL like http://localhost/calendar/event/
common_pitfalls_of_home_buying.
[ 190 ]
Chapter 7
Notice how the information from the Event Sponsors channel is populated into the event information. Although you only have a few events right now, so the effort of creating two channels might not seem to outweigh the benefits, if you had tens or hundreds of events, all of which shared the same handful of sponsors, being able to simply select the sponsor information from the drop-down menu represents a significant time-savings over having to type in information about the sponsor in every event. The next step is to display these entries on your calendar.
Displaying events on your calendar
To display the event on your calendar, you will use an ordinary hyperlink to your single-entry template with a special class (pop-up). The pop-up class will correspond to JavaScript in your HTML header that will call upon the FancyBox jQuery plugin to display the single-entry template in an overlay dialog box. First, you need to enable the jQuery module in your template. 1. First, verify that the jQuery module is enabled. It is enabled by default if you have installed Agile Records. Select Add-Ons | Modules from the main menu and verify that jQuery is marked as installed. If not, click Install in the Status column to install it. 2. Edit the template calendar/index.
[ 191 ]
Creating a Calendar
3. The first change you are going to make is to activate the jQuery module. In the section of the template, add the following tag: {exp:jquery:script_tag}
When saving your template, if you see a warning that no closing tag was found, do not worry. The jQuery tag is a tag that does not require a closing tag.
4. Next, you are going to include the FancyBox jQuery files that are in the fancybox directory that you uploaded to the root of your website. You will link to the main FancyBox JavaScript files, plus the CSS file. Type this code in directly underneath the above tag. <script type="text/javascript" src="{site_url}fancybox/jquery.fancybox-1.3.1.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.mousewheel-3.0.2.pack.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.easing-1.3.pack.js">
Note that if you downloaded the newest version of FancyBox, then the filenames and the version numbers in each of the filenames are subject to change.
5. Now you are going to include the FancyBox code for the pop-up class. This tells FancyBox how you want the lightbox to work. You want the box to be 75 percent of the width and height of the page, with no margin or padding. OverlayOpacity means that you want the calendar page underneath to still be visible, but dimmed. The hideOnContentClick means that if you click anywhere off the lightbox, the lightbox will close. The iframe type means that the lightbox will display the contents of another URL (in this case, your single-entry template URL). For more information on all the FancyBox parameters, please visit http://www.fancybox.net/api. Type this code in directly underneath the above tags (still in the section). <script type="text/javascript"> $(document).ready(function() { $(".popup").fancybox({ 'width': '75%', 'height': '75%', [ 192 ]
Chapter 7 'titlePosition': 'outside', 'autoScale': true, 'margin': 0, 'padding': 0, 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none', 'type': 'iframe' }); });
6. Finally, add your link with the class of popup (that corresponds to the .popup used in the above JavaScript so that FancyBox knows that you want to use FancyBox, and not actually open the link like you normally would). Add the following code after {if entries}, deleting the existing {day_number} line. {day_number} {entries} {/entries}
7. As one date can contain multiple events, this variable pair {entries} applies to each entry. Since this hyperlink applies to each entry, you include it within the {entries} variable pair.
[ 193 ]
Creating a Calendar
8. Go to your calendar and navigate to a month that has events to verify that you can see the hyperlinks.
9. Finally, click on one of the events to verify that your single-entry template appears with the correct information in a FancyBox overlay. If your event does not appear in a pop-up window, but rather opens in a separate window or tab, there are a number of things you can check. First, verify that the fancybox directory is at the root of your website and that you can access the files in your browser (if not, check your .htaccess file). Next, verify that the paths in the calendar/ index template point to the script/CSS files in the fancybox directory and check the filenames for misspellings.
[ 194 ]
Chapter 7
Your calendar is now complete. As you can see, the calendar functionality in ExpressionEngine is limited in what it can do and is certainly not as flexible as specialized calendar applications. However, for simpler designs, it is quite functional.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. [ 195 ]
Creating a Calendar
1. Currently, your calendar displays the days of the week using single letters (for example, M, T, W). Modify this so that the first three letters of each weekday are displayed (for example, Mon, Tue, Wed). 2. Underneath your calendar, display the next event that is coming up (no matter what month is being displayed on the calendar).
Summary
In this chapter, you took a look at the calendar functionality in ExpressionEngine. You also got to see a working example of related entries and how it can help you reduce repetition in your channels. The calendar functionality can be daunting for beginners, as there is a lot of code involved. However, once mastered, the calendar is very flexible in terms of what you can display on it, how it is displayed, and how it all works together. The key points to remember after working through this chapter: •
The calendar functionality uses all the usual channel features that you know and love—custom fields, categories, status groups, and the Publish page. You can create channels with as many custom fields as you want, although you can only display the title field on the calendar itself.
•
Related Entries is when the contents of one channel are included in another channel. Although the events calendar was a natural choice, it could be used for any kind of channel. For example, if you have a recipes channel, you may have a second channel for common sub-recipes (such as making a pie-crust). In this way, you can have 14 different recipes that call for a pie-crust and you do not need to type out the instructions to make the pie-crust 14 times. Reducing repetition by using related entries also makes your website easier to maintain and update (for example, if you wanted to adjust your standard pie recipe, you only have to do it in one spot instead of in 14 places).
•
Related Categories has nothing to do with Related Entries. Related Categories is when two entries in a channel share a category and can therefore be considered to be related.
[ 196 ]
Chapter 7
•
The jQuery module allows you to use jQuery on your website without having to download it yourself (it comes included with ExpressionEngine). ExpressionEngine also masks where the jQuery file is, so it does not reveal the location of your system directory. Teaching jQuery is beyond the scope of this book, but when used thoughtfully, it can enhance the usability of a website.
In the next chapter, you will be building a photo gallery in ExpressionEngine.
[ 197 ]
Creating a Photo Gallery Although ExpressionEngine 2 does not come with a built-in photo gallery module, it does have many features designed to make working with photos easier. In this chapter, you will create a photo gallery channel, use file manager to manage your photos, and use jQuery to display the photos on your website. This chapter uses the FancyBox jQuery plugin that you set up in the previous chapter. If you did not follow the previous chapter, please follow the instructions in Chapter 7, Creating a Calendar under Setting up FancyBox
Although this chapter focuses on building a tool for Ed & Eg to share their personal photos, the techniques in this chapter will be useful in any situation where you want to display images—whether personal photos, a portfolio of your work or items for sale.
Designing your photo gallery
There are many different ways you can approach creating a photo gallery in ExpressionEngine. At the most basic level, you have a choice between each channel entry containing only one photo (and a description) or each channel entry containing a set of photos. If you allow only one photo per entry, you can use categories to organize the photos into galleries (and you can even include the same photo in more than one gallery). If you allow multiple photos per channel entry, each entry represents a photo gallery by itself. One way to accommodate multiple photos per entry is to create as many custom fields as the photos you think you will have in a gallery. For example, if you know each gallery will have a maximum of 20 photos, then you could create 20 custom fields for the photos and 20 custom fields for the descriptions. This solution works, but is not the most flexible (that is, to add 21 photos to a gallery, you would have to modify your custom fields and your templates).
Creating a Photo Gallery
An alternative approach to accommodate multiple photos per entry without creating an abundance of custom fields is to use a third party add-on such as Matrix by Pixel & Tonic (http://pixelandtonic. com/matrix). This add-on allows for tabular data in channel entries— you define the column headings (such as the photo and the description) and then add a row in the table for each photo. In each channel entry, you can create as many rows as you need. For example, you can create one entry with 12 photos and another entry with 25 photos.
Rather than creating lots of custom fields, or using a third party add-on, this chapter will show you a simple and elegant way to create a photo gallery using the one photo per entry design and then will use categories to organize the photos into galleries. Before you create your photo gallery channel, you first need to define where your photos will be stored.
File manager
The file manager is where you can upload new photos or crop, resize, rotate, or delete the images you have already uploaded; all from within the ExpressionEngine control panel. For this photo gallery, you will create a new upload destination—this is the directory on your server where ExpressionEngine will store your photos. 1. The first step in creating a new upload destination is to create the new directory on your server. Create a new directory called photos in /images. If you are following along on an actual web server, ensure that the new directory has 777 permissions (usually right-clicking on the directory in your FTP client will allow you to set permissions). If, instead of creating a new sub-directory inside the /images directory, you prefer to create a new top-level directory and you are using the .htaccess exclude method to remove the index.php from ExpressionEngine URLs, then be sure to add the new directory to your .htaccess file.
2. Next, you need to tell ExpressionEngine where this directory is. Inside the control panel, select Content and then File Manager.
[ 200 ]
Chapter 8
3. On the left-hand side of the screen, you will see the directory or directories where you can currently upload files to (if any), along with the files currently in each directory. In the toolbar on the right-hand side, underneath File Tools, select Create New Upload Destination.
4. Enter a descriptive name of Photo Gallery. The Server Path and URL may be pre-filled, however, you should make sure they point to the actual directory you just created (/images/photos). If you are following along in a localhost environment, the URL would be http://localhost/images/ photos. Leave Allowed File Types as Images only.
[ 201 ]
Creating a Photo Gallery
5. All the fields that begin with maximum can be left blank. These fields allow you to restrict the size, height, and width of photos. If you do enter values in here, and then later try to upload a file that exceeds these limits, you will see an error message such as The file you are attempting to upload is larger than the permitted size. 6. Set the Image Properties, Image Pre Formatting, and Image Post Formatting to be blank. These fields allow you to enter code that appears inside, before, and after the img tag. However, you can format your img tag as needed inside your template.
7. The File Properties, File Pre, and Post Formatting can be ignored for now as they only apply to non-image files that you upload (and you have specified that you are only allowing images in your photo gallery). 8. If desired, you can allow certain member groups to upload files. The member groups you see listed (if any) will depend on the member groups you have. Set all the member groups to Yes except for Members, which should be set No.
[ 202 ]
Chapter 8
9. Click Submit and your new upload destination will be ready to go. Go back to the file manager and you can see the new photo gallery upload destination with no files.
Creating your photo gallery channel
Now that you have created a place to store your photos, you can create your photo gallery channel. As with every other channel you have created in this book, you will follow the same basic steps—creating custom fields and categories, creating your channel, publishing some entries, and then building your templates.
Creating your custom fields
Since you are going to have one photo per channel entry, you have a lot of flexibility to create as many custom fields for each photo as you see fit—for example, you could have fields to capture the location of the photograph, the subject of the photo, the type of camera that was used, the name of the photographer, and so forth. However, to keep things simple, you will only create two custom fields right now—one for the photo itself and one for the description. 1. From the main menu of the control panel, select Admin, Channel Administration, and then Custom Fields. 2. Select Create a New Channel Field Group and call the new group photos. Click Submit. 3. Next to the new group, select Add/Edit Custom Fields and then select Create a New Custom Field.
[ 203 ]
Creating a Photo Gallery
4. The field type will be File. The field label will be Photo and the field name will be photos_photo (the first part representing the field group name). In the instructions for the field, indicate that photos in the photo gallery should be no more than 600x800 pixels (so that they fit on a typical computer screen without scrolling). You could also prevent photos that are bigger than 600x800 pixels from being uploaded by specifying the maximum width and height in the File Upload Preferences for the photo gallery upload destination. You have not done this here because it would prevent you from being able to upload a larger photo and then re-size it using file manager.
5. The field should be required, but not searchable, and should be shown by default. The field display order should be 1 and the file type should be Image. Click Submit. 6. Click Create a New Custom Field again. This time, the field type should be Textarea, the field label Caption, and the field name photos_caption. The field instructions can be left blank. Answer Yes to it being a required field, being searchable and being shown by default. The Field Display Order should be 2. 7. The number of rows can be left as 6 and the default text formatting should be set to Auto
(this will prevent unwanted whitespace in your captions due to extra paragraph tags being added, but will also allow multi-line captions). Say No to allowing an override on the Publish page. The text direction can be left as left-to-right. [ 204 ]
Chapter 8
8. Finally, say Yes to Formatting Buttons, Spellcheck, and Write mode. Say No to Smileys, Glossary, and the File Chooser. Click Submit to create the new field. Now that you have your custom fields, you can define your categories.
Creating your categories
As discussed at the beginning of this chapter, you are going to use categories to distinguish between photo galleries. To start with, you are going to create two photo galleries—one for vacation photos and one for local photos. You can always come back and add more galleries later. 1. Still in the control panel, select Admin, Channel Administration, and then Categories. 2. Select Create a New Category Group and name it Photo Categories. Select Allow All HTML in the category field formatting and check the boxes to allow other member groups to edit (or delete) categories as appropriate. (If you see a message saying that there are no member groups allowed to edit/ delete categories, this is fine too). Click Submit.
3. Back on the Category Management screen, select Add/Edit Categories for the Photo Categories category group.
[ 205 ]
Creating a Photo Gallery
4. Click Create a New Category. The first category will be called Local Photos. The Category URL will default to local_photos. Type in a category description (you will later display this on your website), leave the Category Image URL blank, leave the Category Parent set to None, and click Submit.
5. Select Create a New Category again. This time call the new category Vacation Photos, with a URL of vacation_photos. Type in a category description such as A selection of vacation photos taken by Ed & Eg. Leave the category image URL blank and the category parent as None. Click Submit.
Now that you have your category group and custom field group defined, you can go ahead and create your channel. [ 206 ]
Chapter 8
Creating your channel
The process of creating your channel is straightforward. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Photos with a short name of photos. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Photo Categories for the category group, Statuses for the status group, and photos for the field group.
3. Answer No to creating new templates and then click Submit. Your channel is created! Now you can start creating some content and displaying the photos on your website.
Uploading your first photos
There are three ways to upload photos to your website. Your first option is to go to File Manager (under the Content menu) and select File Upload on the right-hand toolbar. Alternatively, you can go to publish an entry in the Photos channel, click on Add File, and upload a file. Both of these options are convenient since they use the built-in ExpressionEngine file manager to upload your file—you never have to leave the control panel. However, you can upload only one photo at a time and you may run into issues if you try and upload very large photos (greater than 2 MB).
[ 207 ]
Creating a Photo Gallery
The third option for uploading photos is to do so directly, using FTP, just as you would upload any files to your website. Since this requires another tool, it is less convenient than uploading a single photo from within ExpressionEngine, but if you are uploading lots of photos, then using FTP is a lot faster to do. That is the method we will use here. The built-in file manager also allows you to crop, resize, and rotate images (although you can take advantage of these tools even if you do not use file manager to upload the files).
1. Download the example photos (local1.jpg through local8.jpg and vacation1.jpg through vacation8.jpg) from either the Packtpub support page at http://www.packtpub.com/support or from http://www. leonardmurphy.com/book2/chapter8. (Or you can substitute your own photos). 2. Copy or FTP the photos into the /images/photos directory that you created earlier in the chapter. 3. Back in the ExpressionEngine control panel, select Content | Publish and then select the Photos channel. 4. Type in a title of Fireworks and a caption Fireworks exploding with a bang. Then select Add File. 5. The first screen to appear in the Upload File screen. Since you have already uploaded the files, you can simply select the photo gallery option in the lefthand menu. If no photos appear under the photo gallery, or the files appear but no thumbnails appear, try logging out of the control panel and logging back in. (This helps to refresh ExpressionEngine so it recognizes the new files—the first time you access the files after uploading via FTP, ExpressionEngine has to create the thumbnails).
[ 208 ]
Chapter 8
6. Select local1.jpg.
7. On the Categories tab, select Local Photos. Then click Submit. 8. Now, repeat the same steps to create entries for the rest of the photos, using appropriate captions that describe the photos. Be sure to select a category for each photo. There are 16 example photos (eight local and eight vacation photos). Having several example photos in each category will demonstrate how the photo gallery works better.
Creating your templates
As with everything in ExpressionEngine, everything that appears on your website must be coded in a template. Your photo gallery is no exception. You will now create new templates in a design very similar to the one used by the FAQs channel—a single-entry template called comment so that visitors can leave comments on individual images, and a multiple-entry page where visitors can browse and view images by category. You will start with the single-entry page.
[ 209 ]
Creating a Photo Gallery
Creating the single-entry page
The single-entry page is where an individual photograph is displayed, along with the caption and any comments. In this section, you will create a new template group called photos and then create a new template called comment (since the primary reason to visit the single-entry template will be to view and post comments). 1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group photos. Do not duplicate a group and do not make the index template in this group your homepage. Click Submit. 2. Next, with the photos group highlighted on the left-hand side, select New Template. Call the template comment and leave the template type as Web Page. Since your single-entry page here will be very similar to the singleentry page you created for the FAQs channel, select Duplicate an existing template and then choose the faqs/browse template to duplicate. Click Create and Edit.
[ 210 ]
Chapter 8
If you did not follow Chapter 5, Creating a Fully-Equipped Channel completely and do not have an faqs/browse
template to duplicate, it can be downloaded from http:// www.packtpub.com/support or from the chapter 5 page at http://www.leonardmurphy.com/book2/chapter5.
3. Whenever you copy a template, the first thing to update is the Preload Text Replacements at the top. Update them to the following: {preload_replace:my_channel="photos"} {preload_replace:my_template_group="photos"} {preload_replace:my_single_entry_template="comment"}
4. Further down in the template, delete all the code between (but not including) the {title}
and the {/exp:channel:entries}. 5. Replace the deleted code with the following code to display your image and your image caption (centered), along with a link to your multiple-entry photos/index template (which is still blank):
<em>{photos_caption}
The limited class is defined in your site/site_css stylesheet as having the property max-width: 555px;. This value matches the width of the #content ID container. Although the channel field instructions ask that photos be no bigger than 600x800, they may still be too big to fit nicely into the #content area without overlapping the sidebar. The max-width property proportionally shrinks images if they are too big, but otherwise leaves the image alone.
6. A lot further down, underneath the line {/exp:comment:form}, remove the Other Questions Like This section: everything from the
to the {/exp:channel:entries} inclusive.
[ 211 ]
Creating a Photo Gallery
7. Click Update and visit an example photo (such as http://localhost/ photos/comment/fireworks). If you uploaded photos with different titles, then remember that because this is a single-entry page, the last part of the URL (in this case, fireworks) is actually the URL Title from the entry to be displayed. You can replace this with the URL Title of another entry in your channel, and that entry will appear instead. Refer to Chapter 5, Creating a FullyEquipped Channel for more information on single and multiple-entry pages and how they work. If something does not look right in your single-entry page page, compare your code with the final code for the template, downloadable at either http://www.packtpub.com/support or http://www. leonardmurphy.com/book2/chapter8.
[ 212 ]
Chapter 8
Your single-entry page is complete! Go ahead and try adding comments if you like— both as a member and a visitor. Next up, you will create your multiple-entry page where visitors will be able to browse photos by category.
Creating the multiple-entry page
The multiple-entry page needs to attractively display a series of photos so that your visitors can quickly browse to the photos they are most interested in. A visitor browsing your photo gallery will likely spend a lot of time on this page. Although you will use thumbnails to display the photos on your multiple-entry page, you do not have to force visitors to go to your single-entry page in order to view a larger image. Instead, you can use jQuery and the FancyBox plugin that you used in the previous chapter. When a visitor clicks on a photo, a full-size version will appear in a FancyBox overlay, complete with caption. Visitors will be able to quickly scroll through the larger images directly from the FancyBox plug-in. Underneath each thumbnail, a link can take visitors who wish to leave comments to the singleentry page where they can do so. If you did not follow the previous chapter, please, at least, follow the instructions under the heading Chapter 7, Creating a Calendar under the Setting up FancyBox section.
Rather than re-inventing the wheel, you can base the multiple-entry page template on the calendar/index template that you created in the last chapter. (If you did not follow the previous chapter, you can download the template from http:// www.packtpub.com/support or from http://www.leonardmurphy.com/book2/ chapter7). 1. In the ExpressionEngine control panel, copy the calendar/index template code and paste it into the photos/index template. You will see a message indicating that no closing tag was found for {exp:jquery. Ignore this message as this tag is one of those that do not require a closing tag. 2. Update the Preload text replacement at the top to the following: {preload_replace:my_channel="photos"}
3. Update the to be Photo Galleries as follows: Photo Galleries - Ed & Eg Financial Advisors
[ 213 ]
Creating a Photo Gallery
4. The calendar/index template used its own stylesheet with extra calendar formatting—since you do not need to do this, change the stylesheet back to includes/site_css:
5. Your calendar uses a pop-up class attribute to display links in a pop-up iFrame FancyBox. Since you will be displaying images rather than an entire page in this FancyBox, you can set different options. Specifically, you should remove the type of iFrame, display the caption inside the pop-up box (on the calendar you had it display outside so that it did not blend in with the iFrame content), and set cyclic to true—meaning that as someone cycles through the images, once they reach the end of the set, the images will loop back to the start. Finally, do not set any limitations on the width or height of the FancyBox—you can allow the pop-up to auto-size itself to the size of the image being displayed. To accomplish all this, replace everything currently between <script type="text/javascript"> and with the following (leave the <script> tags as-is): $(document).ready(function() { $("a.gallery").fancybox({ 'cyclic': true, 'titlePosition': 'inside', 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none' }); });
For more information on FancyBox, including what the different options mean, you can visit http://fancybox.net/.
6. Finally, remove all the code that appears between (and including) Seminar Calendar
and {/exp:channel:calendar}. This is where your photo gallery thumbnails will eventually go. Click Update to save your work so far. At this point, you have a blank page (with a relevant page title and a FancyBox script that is ready for you to start using). Now you can start adding content.
[ 214 ]
Chapter 8
Adding content to your multiple-entry page
There are going to be two ways to browse your photos—visitors may go to the main photos/index page, where they will see all your photos. Alternatively, they can go to a category-specific page, where they will only see photos that fall into that category. Just like you did with your faqs/index template, you are going to use conditional statements to distinguish between when a visitor is on a category browsing page versus when they are not. Remember that a category browsing page will have the word category in segment 2 of the URL. 1. Still in the photos/index template, add the following code after . If you are on a category browsing page, this code displays the category name, category description, and a link back to the non-category version of your multiple-entry template. If you are on the non-category browsing page, then it will display the generic title of photo galleries and some instructions on how to browse the photos. {if segment_2=="category"} {exp:channel:category_heading channel="{my_channel}"} {category_name}
{category_description}
Browse all photos
{/exp:channel:category_heading} {if:else} Photo Galleries
<strong>Instructions: Select a gallery to view or click on a photo to see enlarged. When viewing in enlarged mode, use your left & right arrow keys to scroll between photos and the escape key to exit enlarged mode.
{/if}
[ 215 ]
Creating a Photo Gallery
2. Next, you can create a drop-down category selector to allow visitors to jump quickly to a given category. This code is adapted from the Channel Categories Tag documentation viewable at http://expressionengine. com/user_guide/modules/channel/categories.html#dropdown. It essentially uses a standard HTML drop-down form, populated with options from the channel categories tag that link to the photos/index template (though you specify only the template group photos, ExpressionEngine knows you mean photos/index because the index template is the default template). Add the following immediately after the previous code:
3. Click Update and then visit your photo gallery (at http://localhost/ photos). Verify that you can browse between categories and that when you are on a category page, you see the category information, and when you are not, you see the generic instructions. JavaScript must be enabled in your browser for the drop-down menu to work.
[ 216 ]
Chapter 8
4. It makes sense to display the thumbnails in a table. Since every gallery could have a different number of thumbnails, it is impossible for you to know in advance how many rows your table might need. You will therefore use a suggestion from Mark Bowen in the ExpressionEngine wiki (http:// expressionengine.com/wiki/Entries_In_Table/) to use the {switch} variable to insert a row break () after every five photos. You will combine this with a conditional statement that checks to see if the current entry is the last entry, in order to prevent a superfluous row being added at the end of your table. Remember that the switch variable allows you to insert different code for different entries. Typically, it might be used to alternate the background color of entries (for example, {switch="blue|red"} would mean your first entry is blue, your second entry is red, and your third entry is blue again. The different pieces of code that are alternated are separated by a pipe (|). When there are more entries than pipes, ExpressionEngine starts again from the beginning. {switch="|||| "} means that on every fifth thumbnail the row will be ended and a new one started—there is no code between any of the other pipes. For more information on the switch parameter, please visit http:// expressionengine.com/user_guide/modules/channel/ variables.html#var_switch.
5. Add the following code immediately after the : {exp:channel:entries channel="{my_channel}"} ***Image will go here*** {if count!=total_results}{switch="|||| "}{/if} {/exp:channel:entries}
[ 217 ]
Creating a Photo Gallery
6. If you visit your website now, you will see a table where your images will go as well as some placeholder text. If you browse between the different galleries, you will see a different number of table rows depending on the number of images that are in that category.
7. The next step is to replace the placeholder text with actual thumbnails. When designing your custom fields, you did not include a field for a thumbnail. Whilst you could include the full-size image with a small width/height, your visitors would then have to download all the full-size images in order to see this page—significantly impacting page load times. Instead, you can use thumbnails that are automatically generated by ExpressionEngine. 8. Whether you upload photos via FTP or via file manager, ExpressionEngine automatically creates thumbnails of any photos in a _thumbs subdirectory (/ images/photos/_thumbs) when you first view them in file manager. These thumbnails are used internally by ExpressionEngine, but you can also use them on your visitor-facing pages. To do this, you will use the custom File field (photos_photo) as a tag pair instead of as a single tag. This allows you to access the different components of each file (the path, the filename, and the extension) in each entry separately. By doing this, you can then insert the _thumbs subdirectory to the end of the path, and prefix the filename with the thumbs_ prefix that is automatically added to the thumbnails.
[ 218 ]
Chapter 8
For more information about using the File custom field as a tag pair instead of as a single tag, please visit http:// expressionengine.com/user_guide/modules/ channel/custom_fields.html#file_fields
9. Replace the ***Image will go here*** placeholder text with the following code:
If, after doing this, you have some thumbnails that are not showing up, you may need to log into ExpressionEngine, edit the entry in question, and re-add the photo using file manager. Make sure you can see the thumbnail in your entry before you submit it.
10. Visit your website again, and you will see thumbnails instead of the placeholder text you had before. Additionally, if you click an image, it will pop up in a FancyBox lightbox, with the caption underneath. This is because you gave the link a class attribute of gallery (which matches the class attribute you used in your FancyBox script). You can scroll through the photos in the FancyBox by clicking the left and right arrows or by using your mouse scroll wheel—this is because all the photos on the page have the same rel attribute, letting FancyBox know this is an image gallery. FancyBox treats whatever is in the title attribute as a caption—in this case, you included the {photos_caption} caption.
[ 219 ]
Creating a Photo Gallery
If your image does not appear in a pop-up overlay, but rather opens in a separate window or tab, you can check for a number of things. First, verify that the FancyBox directory is at the root of your website and that you can access the FancyBox files in your browser (if not, check your .htaccess file). Next, verify that the paths in the photos/index template point to the script/CSS files in the FancyBox directory and check the filenames for misspellings. Then, compare the photo/index template you have created with the photo/index template that is available for download from http://www.packtpub.com/support or http://www.leonardmurphy.com/book2/chapter8. Look carefully for any spelling mistakes or typos, especially in the code and <script> sections, as well as in the link code for the thumbnails. Finally, ensure that JavaScript is enabled in your browser.
11. The final step is to include a link to your single-entry page for visitors who want to leave comments. This can be accomplished by using a hyperlink underneath each photo that will mention how many comments have already been made. Add the following code immediately before the in your template:
{if comment_total=="1"}1 comment{if:else}{comment_total} comments{/if}
12. Now visit your photo gallery page and you will find the new hyperlinks. Click on one to confirm that you are taken to the single-entry page. Add a comment and verify the total increments correctly. If you have comment moderation turned on, you will have to mark the comments as open before they will be included in these counts (although if you are logged in as a Super Admin, you will be able to see the comments on the single-entry page). To mark a comment as open, select Recent Comments from the View section of the control panel home page, click on the comment you wish to open and then click View Comments. Here you can check all the comments you wish to open, and from the drop-down box, select Open Selected and click Submit.
[ 220 ]
Chapter 8
Your photo gallery is complete. You now have an easy way for visitors to browse your photos quickly, either from the main photos/index page or by gallery. It is also easy to see which photos already have comments and for visitors to add their own.
Image editing features
Now that you have gone through the process of creating a photo gallery, uploading images, and creating the corresponding templates, it is a good time to discuss how photos can be cropped, resized, and rotated all from within ExpressionEngine. 1. From the Content menu in the control panel, select File Manager. 2. If you have multiple upload destinations, it is good to know that if you click on the title of one (such as About), it will collapse the list of files. If you click again, the file list will expand. This can help reduce screen clutter. 3. If you select a filename (such as local6.jpg), a FancyBox pop-up will appear with the full size image. (Press escape or click the x in the top-right to close). 4. For the photo local6.jpg, select Edit (in the fifth column from the left).
[ 221 ]
Creating a Photo Gallery
5. At the top-right, there are three modes (Crop, Resize, and Rotate). Select Crop Mode.
6. The picture on the left will darken. To crop the photo, you can drag the rectangle over the picture until the part of the picture you want is framed. The rectangle can be resized or repositioned as needed. On the right-hand side, you can see information about the width, height, and X/Y coordinates of your crop.
[ 222 ]
Chapter 8
7. Once the rectangle is placed, click Save Image on the right-hand side to save your changes. 8. You can also resize the photo by clicking on the Resize option. In this case, setting a width will automatically adjust the height so the photo stays in proportion (and setting the height will automatically change the width). This feature is extremely useful if you want to upload a full-sized image, but then manually adjust it so the width is no more than a certain size (for example). When you upload a photo for the first time from the Publish page, you also have the option to resize an image. In this way, you can upload full-size images directly, and resize them on the fly in ExpressionEngine, rather than shrinking them in advance or uploading them and using the file manager to resize them.
Rotate mode is also fairly self-explanatory. However, be aware that selecting a different rotation (or flipping the image horizontally or vertically) automatically saves the image.
Photo gallery add-ons
In this chapter, you have walked through how to build a photo gallery in ExpressionEngine without using any third party add-ons. As you can see, the functionality in ExpressionEngine is very robust and flexible out of the box. That said, there are times when an add-on can be useful—especially if images are a large part of the content of your website. Pixel & Tonic's Matrix was already mentioned at the beginning of the chapter as a useful add-on for designing a photo gallery with multiple photos per channel entry. In addition, the following add-ons are specific to editing photos (though they are by no means representative of all the add-ons that are available. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available.).
Image sizer
http://devot-ee.com/add-ons/image-sizer/
Written by David Rencher, this plugin takes a large image, dynamically resizes it, and caches the resized image (to reduce page load times). Using this add-on in your template saves you from having to manually resize every image you upload (and eliminates the risk of breaking your page layout if you forget). Instead, images are resized on the fly. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available. [ 223 ]
Creating a Photo Gallery
Channel Images
http://devot-ee.com/add-ons/channel-images/
For a small fee, Channel Images by DevDemon allows you to batch-upload multiple files from within the ExpressionEngine control panel and simplifies image management on the Publish page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. Since the photo gallery uses the same tools as all the other sections of your website, these exercises are not so much specific to photo galleries, but are a good reminder of the techniques learnt in previous chapters. 1. The main page of the photo gallery works great when there are only a handful of photos. However, over time, you could end up with hundreds and hundreds of photos in your channel, all of which would get displayed on your main page. Change the main page so that it limits the number of photos that are displayed and randomizes which photos are shown. 2. ExpressionEngine has the ability to track how many times a channel entry has been viewed on a single-entry page (Entry Views). Using a conditional statement, indicate on your multiple-entry template which photos are ***popular*** photos, based on the number of single-entry page views. For now, consider more than ten single-entry page views to be a sign of a popular photo. 3. The form for submitting comments and the code for displaying comments on your single-entry page are almost identical to the form for submitting comments and the code for displaying comments on your FAQs channel. In the spirit of reducing repetition, choose between a Preload Text Replacement, a Global Variable, a Snippet, or an Embedded Template and extract the code from both photos/comment and faqs/browse, so that both templates use the same code for submitting and displaying comments.
[ 224 ]
Chapter 8
Summary
In this chapter, you took a look at how to adapt the channel functionality of ExpressionEngine to a photo gallery. The lack of a formal photo-gallery module can make ExpressionEngine seem less functional. However, as you can quite clearly see, the standard channel functionality is more than adequate for the task, and indeed allows for a lot more flexibility than a separate photo gallery module might offer— with unlimited custom fields, a multitude of ways that you can organize photos within your channel (using categories and/or status groups), and with no restriction on how you can build your templates, the sky is the limit. This chapter wraps up the step-by-step introduction to ExpressionEngine. By now, you should be fairly comfortable with the basics of ExpressionEngine—channels, templates, tags, custom fields, categories, status groups, and so on. In the next chapter, you will be introduced to some more specialized first party modules that you may find useful.
[ 225 ]
Beyond the Basics So far, this book has introduced the basic concepts and the most commonly used features of ExpressionEngine. Many of the same basic skills have been used time and again such as setting up custom fields and categories, creating a new channel, posting entries to the channel, and building templates with HTML/CSS and ExpressionEngine tags. ExpressionEngine comes bundled with many other modules that may or may not be useful, given your website. The modules range from the simple to the complex—the simplest create additional tags that you can use in your templates, while the most complex include their own configuration pages and library of tags. This chapter looks at some of the offerings, including: •
The Search module
•
The Mailing List module
•
The Email module (create a contact form or a tell-a-friend form)
•
The Moblog module (submit new channel entries via e-mail)
•
The Wiki module The Mailing List and the Email modules rely on ExpressionEngine being able to send e-mails. If you are following along in a localhost environment such as WampServer, XAMPP, or MAMP, you will find that ExpressionEngine cannot send e-mails. This is because a localhost environment does not include an e-mail server. You can either follow along on an actual website server, or if you choose to follow along in your localhost environment, be aware that in places where you would expect ExpressionEngine to send an e-mail, you will not see such an e-mail.
Beyond the Basics
The Search module
ExpressionEngine comes with a pre-built search tool to allow visitors to search your site. Although technically a module, the search functionality comes pre-installed and does not have any special setup. This means that you can start using the search tags right away. There are two parts to enabling search on your website, namely: •
Creating a form that allows visitors to type in and submit search terms (this could be as simple as a search box that appears in your sidebar or it could be an entire template dedicated to an advanced search).
•
Creating templates to display the search results (or that there are no results). The Search functionality only searches channels. The Discussion Forum module and the Wiki module both have separate search functions.
When you design your search forms, you can use parameters to control what is searched. By doing this, you can limit searches to particular channels, status groups, or categories. You can also determine whether you want the search to include expired or future entries (this is important if you are searching a channel, like an events calendar, where all the entries might be in the future). Finally, you can set whether you want to search for words only in channel titles, in all the custom fields of a channel, or in the channel title, custom fields, and comments. Be very cautious if you enable your search to include future entries and the search form searches more than one channel. While one channel might routinely have entries in the future that you want to be searchable, another channel might have future-dated entries that you want to keep hidden until that date/time. The parameters you set for your search form (such as whether to include future-dated entries) apply to all channels that you allow to be searched from that form.
In addition to the search tags, there are three settings in the control panel that control how the search behaves:
[ 228 ]
Chapter 9
1. Is the field searchable? Each custom field in ExpressionEngine can be set to either be searchable or not searchable. Having this field set incorrectly on your custom fields can mean entries not being found that otherwise would be. As a general rule, fields that contain content such as sentences and paragraphs should be set to searchable, but fields such as drop-down boxes or files should not be searchable. To change the searchable setting for any individual field, go to Admin | Channel Administration | Custom Fields, and then select the field group and the field you wish to edit. You could create a custom field on a channel that is searchable, but that is not displayed on your website. This field could then be used to store likely search-terms for each individual entry that might not otherwise appear in the article (such as variations in spelling), thus improving the possibility that meaningful results are returned for people searching your website.
2. Search Page URL. Each channel has a path that is used to link the search results to the actual entries that were found. If this path is set incorrectly, clicking on a given search result will send the visitor to a wrong page. The field should be set to the single-entry template for the channel. (For example, the Photos channel should be set to http://localhost/photos/ comment). To change this setting for a given channel, go to Admin | Channel Administration | Channels, then click Edit Preferences for a specific channel, and look under Path Settings. 3. Which field should be used for search excerpt? This is also found under Channel Preferences, under Administrative Preferences. This defines the custom field from which the excerpt displayed on the results page comes from. To demonstrate the search functionality, you will create a search box in the sidebar that searches both the FAQs and the Photos channels. Before you begin, ensure that the Search Page URLs for these two channels are set to http://localhost/faqs/ browse and http://localhost/photos/comment respectively.
Adding a search box to your site
In this section, you will create a search box in the sidebar for Ed & Eg's website, thus allowing visitors to start a search from any page they like. 1. Go to Design | Templates | Snippets and edit the website_sidebar snippet.
[ 229 ]
Beyond the Basics
2. In the snippet, add the following code immediately after the final and before the final . Notice the parameters—the channel parameter restricts the search to the FAQs and Photos channels. The search_ in="everywhere" parameter means that you want the search to include titles, custom fields, and comments. The where="any" parameter means that entries containing any of the searched-for words will be returned (as opposed to requiring an exact match). The status parameter means that you will include entries with a status of open or premium (the premium status was one that you created in Chapter 6, Members, and if you did not include it explicitly, only entries with an open status would be searched). Finally, the result_page and no_result_page define which templates should be used when there are results or when there are no results (in this case, the search/ index and search/noresults templates, which you are yet to create). The rest of the code is a standard HTML form (although the input box must have the name="keywords" attribute for the search form to work). For more information on each of these parameters, including alternative settings for them and additional parameters not included here, please visit http://expressionengine.com/user_guide/modules/ search/simple.html. {exp:search:simple_form channel="faqs|photos" search_in="everywhere" status="open|premium" where="all" result_page="search" no_result_page="search/noresults"}
{/exp:search:simple_form}
3. If you visit the home page of your website, you should now see the search box on the right-hand side. If you have the Agile Records example website template groups still installed, searching will result in the Agile Records themed advanced search template being returned—otherwise, you would get a 404 page. You will create the search result templates next.
[ 230 ]
Chapter 9
Creating a search results template
The search results template is specified in the parameters of the search form as search, which translates to the search/index template. Had you not defined a specific template, the search results template would be set to search/results. If Agile Records is installed, then you are likely to already have a search template group which you can adapt to display your results. Otherwise, go ahead and create a search template group now. 1. The first step is to start with your basic site outline (header, sidebar, and so on). You can accomplish this by copying the includes/404 template into the search/index template. Edit the search/index template and paste in a copy of the code from includes/404. 2. Change the title of the page to be: Search Results - Ed & Eg Financial Advisors
3. Change the heading to be Search Results: Search Results
4. Replace the next paragraph (that talks about the page not existing) with the following. The {exp:search:keywords} tag displays the keywords used for the search.
You searched for <em>{exp:search:keywords}.
If you see a warning about there not being a closing tag when you save your template, ignore it. The {exp:search:keywords} tag is one of those that does not have a corresponding closing tag.
[ 231 ]
Beyond the Basics
5. Underneath the preceding paragraph, insert the following code (adapted from the code found at http://expressionengine.com/user_guide/ modules/search/results.html). This displays your search results in a two-column table. The first column will have the entry title and the second column will have an excerpt from the entry (the first 50 words from the field designated as the search excerpt field in your channel preferences). First create the table and the header row.
Title Excerpt
{if paginate} <span>{page_count} {paginate} {/if}
The pagination code at the end works similarly to channel pagination—allowing a long list of results to span multiple pages.
6. The following code uses the {exp:search:search_results} tag to display the actual results. This tag loops through once for each result you have. In this case, a new table row is created for each result. The switch tag makes the first row light-gray, the next white, the third light-gray, and so on. (Remember from the photo gallery chapter that the switch tag uses the first switch for the first result, the second switch for the second result, and so on, until it runs out of switches, when it starts over). Prior to the entry title, the channel name (such as Photos: or FAQs:) is added to make it clearer what kind of entry is being linked. Underneath the entry title, the number of comments that the entry has received is displayed. Add this code after the closing of the header row, within the table you created earlier: [ 232 ]
Chapter 9 {exp:search:search_results} <strong>{channel}: {title}
{if comment_total=="1"} 1 Comment {if:else} {comment_total} Comments {/if} {excerpt} {/exp:search:search_results}
Within the {exp:search:search_results} tag, there are some special variable tags you can use, including {auto_path} and {excerpt}. {auto_path} creates a path to the entry using the Search Page URL, defined in the channel preferences, and {excerpt} displays the first 50 characters of the excerpt field defined in the channel preferences. You can also use tags (such as {comment_total}, {author}, or {entry_date}), which are normally available in the {exp:channel:entries} tag. More information on search resultspecific tags can be found at http://expressionengine.com/user_ guide/modules/search/results.html and information on channel entry tag variables can be found at http://expressionengine.com/ user_guide/modules/channel/variables.html.
[ 233 ]
Beyond the Basics
7. Now click Update and Finished, go to your website, and search for something (for example, money). Your results will be displayed.
The no-results template
One other template you defined in your website_sidebar snippet was a no_ result_page of search/noresults. This can be a simple template that uses {exp:search:keywords} to display the search term and indicates that no results were found.
1. In the Search template group, create a new web page template called noresults. If you already have a results and a no_results template in the search template group, you can go ahead and delete these. 2. When creating the template, select to duplicate an existing template and duplicate search/index. Click Create and Edit. 3. Delete all the code from (and including) the
immediately above the opening tag down to (and including) the closing {/if} statement of the {if paginate} block of code. 4. Modify the You searched for… paragraph to read as follows:
[ 234 ]
Chapter 9 You searched for <em>{exp:search:keywords}. Unfortunately, nothing matching that search was found.
5. Click Update and Finished (ignoring any warnings about there being no closing tag) and now try searching for something that you know is not part of your website (for example, monkey). You will be redirected to your search/ noresults template.
Advanced search
In addition to the {exp:search:simple_form} that you used in your sidebar snippet, you also have the option of creating an advanced search form using the {exp:search:advanced_form} tag. The advanced search form allows visitors to select many of the settings that you set in the parameters of the simple search form. For example, on the simple search form, you specified which channels could be searched, whereas on the advanced search form, you can allow visitors to select which channels they can search in (although you can limit the choices they see by using parameters, just as you did with the simple search form).
[ 235 ]
Beyond the Basics
To build an advanced search form, you can create a template, such as search/ advanced, and then adapt the code from http://expressionengine.com/user_ guide/modules/search/advanced.html. This form looks much more complex than the simple_form, but most of that complexity comes from building all the form fields—how the form works is the same. Although an advanced search form on a small website like Ed & Eg would be overkill, an advanced search tool can enable power users to find what they are looking for on websites that have large amounts of content.
The Mailing List module
ExpressionEngine comes with a Mailing List module included. It is a very straightforward module that allows you to quickly and easily send e-mails to visitors who have signed up to receive e-mails or to specific member groups. You can have as many mailing lists as you want. Remember that if you are using a localhost environment such as WampServer or MAMP, ExpressionEngine will not be able to send outgoing e-mails. You will be able to follow the steps to set up a mailing list and make the sign-up box available on your website, but you will not be able to use the Mailing List module to send e-mails.
Setting up the Mailing List
The Mailing List module is included with ExpressionEngine, but is not installed by default. Installing it is easy. The following steps will show you how to do it: 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Mailing List and then click Install. 3. The Mailing List module name will turn into a clickable link. Click it to enter the Mailing List Manager. 4. To start with, there is one mailing list set up called Default Mailing List. You can change the name of the mailing list by clicking Edit next to the mailing list. You can also create multiple mailing lists by clicking Create New Mailing List at the top right.
[ 236 ]
Chapter 9
5. Click Edit Template to edit how the e-mails will look. By default, each e-mail has a footer with the unsubscribe URL (auto-generated by the Mailing List module for each e-mail address the e-mail is sent to). You can customize how this footer is worded or add text above the {message_text} variable in order to create a header for all your Mailing List e-mails. The conditionals {if plain_email} and {if html_email} allow you to distinguish between plain-text and HTML versions of an outgoing e-mail, so that people reading the e-mail in plain text do not see the HTML mark-up. For now, leave the default e-mail template as-is. 6. Also, within the Mailing List Manager, you can batch subscribe or unsubscribe people (for example, if you were transferring over a Mailing List from another application). You can also set up an administrator e-mail address, so when someone new subscribes to a Mailing List, the administrator gets notified. (Click Mailing List Preferences to do this). 7. To see who is signed up for any given Mailing List, click View next to the Mailing List name.
[ 237 ]
Beyond the Basics
Now that you have a mailing list defined, there are two more things you must do: 1. Allow people to subscribe to your mailing list 2. Send e-mails to people on your mailing list
Allowing members to sign-up
To allow visitors to sign themselves up to the mailing list, you are going to add an option to your sidebar snippet. 1. Modify the snippet called website_sidebar. 2. In the snippet, add the following code immediately after the final li> and before the final . This code is adapted from the mailing list documentation at http://expressionengine.com/user_guide/modules/ mailinglist/index.html. Notice that in the {exp:mailinglist:form} tag, you have a parameter called list that is used to determine which mailing list the member will be signed up for (in this case, default). The e-mail input box value is set to {email}, which is a global variable referring to the e-mail address of the currently logged in member. In this way, if a member wishes to register for the mailing list, they do not need to re-type their e-mail address. Mailing List
{exp:mailinglist:form list="default"}
{/exp:mailinglist:form}
3. Click Update and Finished. Visit Ed & Eg's home page and you will see the option to sign up for a mailing list. Note that any new visitors who sign up will receive an e-mail with a link which they must click within 48 hours in order to actually sign-up (remember that if you are using a localhost environment, you will not receive this e-mail). The mailing list is strictly an opt-in feature, with an opt-out link included in every e-mail that you send.
[ 238 ]
Chapter 9
You have set up your mailing list so that visitors can sign themselves up to it. Note that if you wanted to have multiple mailing lists, all you would need to do is change the list parameter to reflect the short-name of the mailing list that the person is signing up for. Of course, now that you have a mailing list with subscribers, how do you send them e-mails?
Sending e-mails
Before trying to send an e-mail, review your e-mail settings in Admin | Email Configuration. Here, you can define not only how e-mails are sent (PHP Mail, Send Mail, or SMTP), but you can also define which e-mail address they come from. If, for any reason, ExpressionEngine is not sending e-mails, you can also turn on Email Debugging, which will then display the error message explaining what is stopping the e-mail from being sent. The settings on this page apply to all e-mails sent by ExpressionEngine, including automated e-mails such as those that are sent as part of new member registration or when you sign up for a mailing list.
[ 239 ]
Beyond the Basics
To send e-mails, you must use the Communicate tool (under Tools in the main menu). This tool can be used in conjunction with the Mailing List module to send e-mails to people who have subscribed to a given mailing list, or it can be used on a standalone basis to send e-mails to certain member groups or specific e-mail addresses. Remember that if you are following along in a localhost environment, you will not actually be able to send outgoing e-mails.
The Communicate tool has lots of options, most of which are fairly self-explanatory. At the very top, there is a link to see previously sent e-mails. Underneath the message, you can choose between sending a plain-text or an HTML e-mail. If you choose HTML, you can optionally include a plain text alternative for recipients who cannot read HTML e-mails. On the right-hand side, you can choose which mailing lists or member groups get the e-mail (or manually type in your own recipients' e-mail addresses). If you are handtyping e-mail addresses, it is recommended that you use the BCC field so that you do not expose the e-mail addresses of recipients to other recipients. You can also define who the e-mail comes from (so that it is less likely to be treated as spam).
A checkbox at the very bottom allows you to suppress e-mails to members who have requested not to receive e-mails from administrators in their control panel settings—respecting this setting is recommended. [ 240 ]
Chapter 9
The Mailing List module is designed to make it easy to send e-mails to multiple recipients at once. If you want to send an e-mail to an individual member, you can also do so via the e-mail console, provided you have enabled this functionality for the member group you are in. Click on the Email button from either the individual member's profile or from the member list at http://localhost/member/list to access the e-mail console. See Chapter 6, Members for more information on member-facing functionality.
The Email module
The Email module gives you the ability to easily create contact forms (so that your visitors can e-mail you) and tell-a-friend forms (so that your visitors can e-mail their friends). In this section, you will see how to set up both of these forms for your website. If you installed the Agile Records example site, then the Email module will already be installed. Otherwise, it can be easily installed by going to Add-Ons | Modules and clicking Install.
Creating a contact form
Ed & Eg currently have an FAQs section, where they answer frequently asked questions from their customers and visitors. However, there is no easy way for visitors to submit their questions to Ed & Eg. In this section, you will create a new contact form so that visitors can submit their questions for Ed & Eg to answer. As you have done before, you will base the contact form template on the includes/404 template (which has the site header and other layout components, but does not have much in the way of content that needs to be changed). 1. From Template Manager, select the faqs member group and click New Template. 2. The new template will be called submit. The template type should be Web Page. Check the option to duplicate another template and select the includes/404 template to duplicate. Click Create and Edit. 3. Change the HTML to the following: Submit a Question - Ed & Eg Financial Advisors
[ 241 ]
Beyond the Basics
4. Change the title from Page Not Found to Submit a Question. 5. Delete the paragraph underneath the tag. 6. The following code is adapted from the example provided in the ExpressionEngine documentation for this module at http://
expressionengine.com/user_guide/modules/email/contact_form. html. The {exp:email:contact_form} tag displays your contact form. This tag has a parameter called recipients that allows you to specify the e-mail
address you want the final e-mail to be sent to—your visitors will not be able to see or change this address. The rest of the form is a standard HTML form with some values filled in, based on ExpressionEngine variables (the e-mail address of the member, their name, and the date/time). Add the following code underneath the header in the template, changing the recipient's e-mail address to match your own:
{exp:email:contact_form user_recipients="false" recipients="[email protected]" charset="utf-8"}
{/exp:email:contact_form}
7. Although the form is complete as-is, you can also add code to display a CAPTCHA. Even if you are not using the CAPTCHA system now, it does not hurt to put this code in; in case you want to use it in the future, you can quickly enable it (under Admin | Email Configuration) without changing your templates. You can do this because the {if captcha} conditional prevents the CAPTCHA from displaying, unless it is set to be required. Insert this code immediately before the Submit button (after the
) within the contact form: {if captcha} {captcha} [ 242 ]
Chapter 9
{/if}
8. Click Update and now visit your submission form at http://localhost/ faqs/submit. If ExpressionEngine is configured to send e-mails, visitors will be able to use the form to send you e-mails easily and seamlessly from within your website.
For more information about the parameters of this form and how they can be set, please see the ExpressionEngine documentation at http://expressionengine. com/user_guide/modules/email/contact_form.html. The documentation includes useful tips in case your server host does not allow e-mails to be sent from your domain with a "from e-mail address" that is not yours. [ 243 ]
Beyond the Basics
Creating a tell-a-friend form
The tell-a-friend form works very much like the Contact form, except that instead of e-mailing a person you specify, the person can e-mail a friend of their choice. The risk with this form is that spammers might use it to e-mail advertising or other junk to third parties. To prevent this, there are several options—you can restrict this functionality to signed-in members who have activated their membership via e-mail (and then pre-fill the From field with that member's e-mail address). You can fix the message text yourself so that it cannot be edited (visitors can either send or not send the message as-is). Finally, you can require CAPTCHAs (in Admin | Email Configuration) for visitors e-mailing a friend. You may also wish to consider independent social media solutions, such as adding Facebook's Like button to your website, which allows visitors to easily share that they like your website, without the concerns that the tell-a-friend form brings. Check out http://developers.facebook. com/docs/guides/web for more information.
For this example, you will create a tell-a-friend form for the FAQs channel that is only available to members. The From e-mail address will be set as the e-mail address of the logged-in member and the message will also not be editable.
Creating the tell-a-friend template
The tell-a-friend template will be based on the faqs/submit template, which you had created for your contact form. If you did not follow the steps to create a Contact form, remember that you can download the source code from either http://www. leonardmurphy.com/book2/chapter9 or from http://www.packtpub.com/support. 1. Create a new template in the FAQs template group called friend. When prompted to duplicate an existing template, select faqs/submit as the template to duplicate. Click Create and Edit. The tell-a-friend form can also be added to the bottom of the singleentry template for your channel (in this case, faqs/browse).
2. Change the HTML to: Tell a Friend - Ed & Eg Financial Advisors
3. Change the title to Tell a Friend. [ 244 ]
Chapter 9
4. Replace everything from {exp:email:contact_form} to {/ exp:email:contact_form} with the following conditional, which checks to see if the visitor is logged in. If they are not logged in, they will not be able to tell-a-friend. {if logged_out}
Sorry, you must be logged in to tell-afriend.
{if:else} {/if}
5. After the {if:else} and before the {/if}, insert the following tell_a_ friend form (adapted from http://expressionengine.com/user_guide/ modules/email/tellafriend.html). The tell-a-friend form is necessarily longer than the Contact form because there are more fields (for the send-to e-mail address and the name of the person the e-mail is coming from). Also, notice that some of the fields in the following code are read-only because the values are being populated from ExpressionEngine. {exp:email:tell_a_friend charset="utf-8" allow_html='no' status="open|premium"}
{/exp:email:tell_a_friend}
In this example, you use the {faqs_question} custom field to display data from your entry in the message. Indeed, ExpressionEngine is versatile enough that you can create a single tell-a-friend form for multiple channels, even if they have different custom fields. ExpressionEngine will suppress any custom fields that do not apply, based on the channel that is being sent to a friend. The status="open|premium" is because there are some entries that might have a premium status rather than open. Without this setting, any status that is not open would not render the tell-a-friend form.
6. As with the Contact form, add the following CAPTCHA code immediately before the Submit button (after the
) {if captcha} {captcha}
{/if}
7. Now you need to create a link to the tell-a-friend form. Edit the faqs/browse template and add the following link next to the Back to FAQs link. Like the form itself, this link will only be visible to members who are logged in. {if logged_in}Tell-aFriend | {/if}Back to FAQs
[ 246 ]
Chapter 9
8. Now if you visit a FAQs channel entry and click the Tell a Friend form, you will be brought to the faqs/friend form, where you can send an e-mail to a friend.
Word-of-mouth is one of the best marketing strategies available, and the tell-a-friend functionality allows visitors to share an entry on your site without having to a draft a special e-mail. Although this example is very locked-down, you can make it more flexible (such as by allowing visitors to edit the message). Before making changes such as that, always think of how easy it might be for a malicious person to use the form to send advertising or phishing e-mails to third parties.
[ 247 ]
Beyond the Basics
The Moblog module
So far, whenever you wanted to create content, you have had to log into the control panel and publish a new entry. The Moblog module provides a way to upload files to your website and create content directly from your Internet-enabled smart phone. The basic concept involves setting up an e-mail address which ExpressionEngine can access. When you e-mail from your phone to the e-mail address, the content can either be turned into a channel entry, or attached files can be saved to an upload location without a channel entry being created (making it an easy way to upload files to your website without FTP). The module includes ways to prevent spam or other e-mails that might also be sent to the same e-mail address from being published to your site. Unfortunately, the Moblog module can only add new content to text area custom fields. Since channels will often have other types of custom fields, does this mean that you cannot use the Moblog module? No. Take, for example, the Photos channel. There is one text area custom field (caption), but the photo itself is a File custom field. Although you cannot publish an entry to the photo channel without a photo, you can still use the Moblog module to create a closed entry with the caption you desire, and upload the photo(s) attached to your e-mail to the photo gallery upload destination. Then, when you log in to the control panel, all you have to do is edit the entry, select the photo from the file manager, and change the entry status to open. For the Moblog module to work, you must have an e-mail address that ExpressionEngine can access via POP3. Typically, an e-mail address associated with your website domain or your internet provider (ISP) would have POP3 access, but a free web-based e-mail service may or may not. Since ExpressionEngine is only reading incoming e-mails (and not sending e-mails), the Moblog module can be set up and tested even in a localhost environment.
Setting up the Moblog module
As with other modules, the Moblog module is not installed by default. Installing it is easy. 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Moblog and then click Install. 3. The Moblog module name will turn into a clickable link. Click it to enter the Moblog control panel. 4. When you first enter the control panel, no Moblogs exist. Click Create New Moblog. [ 248 ]
Chapter 9
5. First, the general settings need to be defined. Enter a full name of Photos Moblog and a short name of photos_moblog (remember that the short name is what will be used in templates). Leave the time between checks set at 15 minutes. This does not mean that the e-mail address will be checked every 15 minutes, but that if you set up a template with an {exp:moblog:check} tag, and someone visits that template and more than 15 minutes has passed since the last check, then the e-mail address will be checked. Set Moblog Enabled? to Yes and set File Archive Mode to No (File Archive Mode is where files attached to your e-mail are uploaded, but no channel entry is created).
[ 249 ]
Beyond the Basics
6. Next, choose the channel you want to post to—in this case, Photos. You can also select a default category, field, status, and author. This can be useful if, for example, you want your mobile photos to be in their own gallery or to have their own status. For this example, use a default category of None. Use a default field of Caption, a default status of Closed (since you do not want your entries to be visible until you have updated the File custom field with the photo), and a default author of you.
7. Say No to making the entry sticky (meaning that it always appears first on a multi-entry page) and Yes to allowing overrides in e-mail. This means that if you want to set the category or status differently as compared to the default, you can do so by using a special code in your e-mail—for a list of possible overrides, see http://expressionengine.com/user_guide/modules/ moblog/email_contents.html. 8. Select Photo Gallery as the upload directory. 9. The Moblog templates allow you to define exactly what will happen with your e-mails. The default is to display the text first, then any images in an img tag, and any other files as a Download File link—all within your text area. Since you do not want your images to be part of the caption, change the template to remove the {images} section as follows: {text} {files match="audio|files|movie"} Download File {/files}
[ 250 ]
Chapter 9
For more information on the different tags and parameters that are available, please visit: http://expressionengine.com/user_ guide/modules/moblog/control_panel/email_template.html.
10. Next up, you can define your e-mail settings. The e-mail server must support POP3—typically e-mail addresses associated with your website domain would have POP3 access, as would e-mail addresses from your ISP. Free e-mail services may or may not include support for POP3 access. If you already download your e-mail to your e-mail software using POP3, then the same settings that are in your e-mail client (server name, username, and password) would go here. Since the Moblog module is scanning for incoming e-mails and does not send e-mails, the Moblog module will work even if you are using a localhost environment. Simply set the settings to the e-mail address you want to scan.
11. Further down, you can specify a word or phrase that must appear in the subject of your Moblog e-mails. This allows ExpressionEngine to distinguish between a Moblog e-mail and all the other e-mails you may receive. The default setting is moblog:, meaning that any e-mail you want posted to your Photos channel needs to have moblog: in the subject. (When setting the title of the entry, this phrase will be stripped out and the rest of the subject will be used; for example, Moblog: Flower will result in an entry called Flower.) Changing the subject prefix is useful when you want multiple Moblogs to use the same e-mail address. However, for the purposes of this example, leave it set as moblog:. 12. For security, you can also set your Moblog e-mails to be from a certain e-mail address (or addresses) and you can require authentication (meaning your control panel username and password must be included in your Moblog e-mails). It is recommended to at least limit the e-mail addresses that can send Moblog e-mails. 13. The next option allows you to prevent certain text that might be included in your e-mails (such as your signature) from appearing in your channel entry.
[ 251 ]
Beyond the Basics
14. Next, you can set the parameters for any images you attach—you can require images to display with a certain height or width, you can resize, you can upload images automatically, and you can also create thumbnail images if desired. For now, say Yes to resize images on import, and resize any images to have a width of 555. Leave the height set to 0 to keep the image in proportion.
15. Finally, click Submit to create your Moblog.
Setting up your template
If you were using the Moblog module to post content directly to your website, you could set up a template to check for new Moblog entries automatically whenever it is accessed by a visitor. With the following tag, ExpressionEngine will check to see if 15 minutes have elapsed since the last check, and if so, ExpressionEngine will check again:
silent="true" means that the Moblog check will be invisible to the person viewing your template. For troubleshooting purposes, you could temporarily set this to false. If you do set this to be false, having the tag wrapped within an HTML comment, as shown, means that you can see any error messages by viewing the HTML source (by clicking View Source from your browser), while visitors see nothing unusual. [ 252 ]
Chapter 9
Since you are setting up your Moblog to act as an easy way to create entries without publishing them right away, this step does not apply.
Sending a Moblog e-mail
Now that the Moblog module is configured, you can try sending your first Moblog e-mail. 1. First, send an e-mail to the e-mail address you specified with an image attached. Be sure that the e-mail has a subject prefix as defined (moblog:) and comes from an e-mail address that is allowed to post Moblog entries. Do not forget the attachment!
2. Next, log into the control panel and select Add-Ons | Modules and then select Moblog. Click Check Moblog. If the Moblog module finds valid e-mails, you will see a green check mark at the top of the screen (which you can click to see more information).
[ 253 ]
Beyond the Basics
3. Now select Content | Edit and look for an entry with a title that matches the subject of the e-mail, a date/time of the current date/time, and a status of closed. Click the entry to edit it and you can see the body of your e-mail in the caption field.
4. Click Add File, select the Photo Gallery, and click on the file you uploaded. 5. Click on the Options tab and change the status to Open. Then click Submit. 6. Visit the photo album (http://localhost/photos) to see your new entry. Notice how the image was automatically resized to be 555 pixels wide, as specified in the Moblog preferences.
[ 254 ]
Chapter 9
The Wiki module
A wiki is an area of the website where visitors themselves can edit the content or create new content. One of the most famous wiki's on the web is Wikipedia (http://www. wikipedia.org/)—an online encyclopedia that anyone can contribute content to. Another example wiki is the ExpressionEngine wiki, located at http:// expressionengine.com/wiki/—a great tool for sharing how-tos and more with other ExpressionEngine users.
At first glance, it can be difficult to see the use for a wiki (especially for a website like Ed & Eg's). However, if you think of it as a collection of documents that can be shared among a group of people of any size, and updated in real time by the same group of people that actually use the content, the business advantages start to become clearer. As with any tool that requires active participation from others, it helps if you already have a group of people that is willing to participate. A wiki, more so than other tools (such as comments or a discussion forum), requires an unusually high commitment from end-users—first to build the content and then to be willing to edit and add to other people's content. To demonstrate how the Wiki module works, you will create a wiki for visitors to exchange money-saving tips and ideas. The Freelancer license does not include the Wiki module, so this section will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing.
Setting up the wiki
As with other modules, the Wiki module is not installed by default. Installing it is easy. 1. Select Add-Ons and then Modules from the main menu. 2. Scroll down to where it says Wiki and then click Install. 3. The Wiki module's name will turn into a clickable link. Click it to enter the wiki control panel. 4. Click on Create Wiki. 5. Change the full wiki name to Money Saving Wiki and change the short name to money_saving_wiki.
[ 255 ]
Beyond the Basics
6. Leave the text formatting as Xhtml, but Allow only safe HTML (meaning that people can use standard HTML tags to mark-up their content). 7. Choose a File Upload Directory where files associated with the wiki will be stored. (You may want to create a new directory under Content | File Manager that is specifically for wiki files). If you do not select a destination, uploading files will not be possible. 8. Select which member groups can administer the Wiki module, and which member groups can use it. Administrators can delete content, mark an article as locked (so that no-one can edit it), or mark an article as moderated (meaning that users can edit it but an administrator must approve the change before it becomes visible to others). Select Super Admins as your administrating member group, and select all your member groups as users. 9. You can set up how many revisions you keep for each article and how many edits a single individual can do in a single day. For now, leave these at their defaults. 10. Set up an e-mail address as the e-mail to receive notifications when an article marked as moderated is changed. 11. You can optionally set up a namespace for you to group articles. The main advantage to using a namespace rather than a category is to set up different member groups as administrators and users. For example, Ed & Eg cater to both businesses and individuals, so if they wanted, they could have created two namespaces so that their business articles and individual articles were separated. They could then have two member groups and allow members of the business member groups to add/edit content to articles in the Business namespace but not articles in the Individual namespace. For now, leave the namespace fields blank. 12. Click Update to create the wiki. 13. The final step is to create a new template and template group for your wiki. Go to Design | Templates | Edit | Create Group and call the new template group wiki. 14. Edit the index template of the wiki template group and add the following code. You do not need to include any other HTML or ExpressionEngine tags, as this tag will create the entire wiki. {exp:wiki base_path="wiki/index" wiki="money_saving_wiki" theme="azure"}
[ 256 ]
Chapter 9
If you use a different template group or template name, change the base_path parameter accordingly. The wiki parameter is the short name of the wiki. The theme can be either default or azure. You can also create your own themes by creating a new directory in your / themes/wiki_themes/ directory and copying and modifying the files from an existing theme. See http://expressionengine.com/user_ guide/modules/wiki/wiki_templates.html for more information.
15. Now view this template in a browser (http://localhost/wiki).
How does the wiki work? The next step is to create some content.
1. On the first page of the wiki, click Edit (at the top) to edit the page.
[ 257 ]
Beyond the Basics
2. You can type in whatever text you wish, using HTML for basic text formatting. To create a link to a new article, enclose the new article's name in double square brackets. For example: Welcome to our Money Saving Wiki. Here are some moneysaving ideas: <strong>[[Shopping]] Don't buy the name-brand of everything. Pick one or two items that you like, and for everything else, buy the store brand. Sometimes spending the extra 30 cents for the name-brand doesn't sound like much, but saving 30 cents on 30 items in a single trip, and doing 40 trips a year, will save you $360 this year!
For more money-saving tips when [[shopping]], click on the word [[shopping]].
3. In the notes section, write a brief description of the change you are making, such as "Added Tip on saving money when shopping". (This will show in the history log). Then click Submit.
4. You can now click on any one of the shopping links to be brought to a new article where you can create a new page with more text. Notice how you can have multiple links to the same article. Remember that a wiki is a multi-user environment. The intent is not to have one person create all the content, but for it to be a collaborative effort (although you may prefer to have one person add some content and develop the structure before making it more generally available).
5. The ExpressionEngine wiki also supports the use of categories. Use the following code anywhere in an article to assign the article to a Shopping category. [[Category:Shopping]] [ 258 ]
Chapter 9
You can assign an article to multiple categories. You can also assign articles to subcategories using a format such as: [[Category:Shopping:Store Brands]]
6. If enabled, you can also upload images, diagrams, and documents by clicking on File Upload on the left-hand menu. You can then embed uploaded files using either [[File:filename.txt]] (to create a link) or [[Image:image. jpg]] (to embed a picture). For more information on wiki syntax, visit http://expressionengine.com/user_ guide/modules/wiki/wiki_syntax.html.
Other ExpressionEngine modules
There are several other free modules that ExpressionEngine has which have not been covered here. •
The Discussion Forum is a module written by EllisLab but sold separately from ExpressionEngine (although it requires ExpressionEngine to run). The module leverages ExpressionEngine's Member module features, but has its own templating system and is styled via separate CSS. The best example of a discussion forum in action is the ExpressionEngine support forums (at http://expressionengine.com/forums).
•
Simple Commerce allows you to mark posts in channel entries as being for sale. You can create a channel of items for sale, set the price for each item and then accept payments through PayPal. All payment information is transferred directly between the visitor and PayPal—at no point does your website or ExpressionEngine handle payment information. Although Simple Commerce is not a fully-fledged e-commerce module, for smaller websites that do not need the complexity of a complete payment processing solution, Simple Commerce will likely meet your needs.
•
Blacklist/Whitelist is a spam prevention tool that allows you to block visitors by IP address, URL, or User-Agent. You can either block specific IP Addresses, URLs, or User-Agents, or you can enter a partial string to block anything that matches that string. You can also add items to your white-list (meaning that you could blacklist a certain IP address pattern, but make an exception for an IP address that you know is not spam). EllisLab provides a Blacklist and a Whitelist that you can download periodically to keep known spammers away.
[ 259 ]
Beyond the Basics
•
IP to Nation allows you to determine which country an IP address is associated with, and then ban visitors from that country from seeing your website (or display a flag next to comments or entries from visitors that come from that country).
•
Query is a very useful module for more advanced users, allowing you to run SQL queries against the ExpressionEngine database directly. Although it requires some familiarity with the ExpressionEngine database structure and with SQL syntax, it can allow you to display ExpressionEngine data in unique ways that might not otherwise be possible. See http:// expressionengine.com/user_guide/modules/query/index.html for examples of how to use this module within a template.
•
Referrer allows you to track which websites have links to your website that people are using to arrive at your site.
•
Statistics allows you to display certain facts about your website on a template (such as the number of people who are logged in, the date of the most recent comment, and the total number of comments that have been left on your site).
Multiple Site Manager
EllisLab also offers Multiple Site Manager for people who run multiple websites. Multiple Site Manager adds the ability to manage multiple websites from the same ExpressionEngine login (up to three sites are included with the initial purchase price, with the option to buy more if needed). The key licensing criterion is that you must be the owner of all the websites you manage. Each website is distinct in terms of templates, channels, and preferences, but addons, members, and member groups are shared across all three sites. In this way, members only have to register once for all the websites, as each of your websites can share the same modules and other add-ons (saving you from installing and configuring the same modules over and over again) and you can conveniently manage all your websites from the same control panel. Although not appropriate for everyone, Multiple Site Manager is a very powerful tool, making maintaining your websites much easier and at a lower cost than purchasing three separate licenses. More information can be found at http:// expressionengine.com/user_guide/cp/sites/index.html.
[ 260 ]
Chapter 9
Summary
In this chapter, you took a look at many of the modules that come bundled with ExpressionEngine. Some modules come pre-installed, some are included but not installed, and some have to be downloaded and installed separately. A typical module has a configuration screen (accessible via Add-Ons | Modules) and tags that can be used in templates to access the modules functionality. In the next chapter, you will be introduced to the other types of add-ons, including Accessories, Extensions, Fieldtypes, and Plugins. You will also learn about third party add-ons. Finally, you will learn key tips for running an ExpressionEngine website, including how to do database backups and version upgrades.
[ 261 ]
Extending ExpressionEngine So far, this book has taken a step-by-step approach to implementing the most popular modules in ExpressionEngine. In this chapter, you will not be building content for Ed & Eg's website, but rather looking at what else goes into maintaining an ExpressionEngine website. First, you will learn about essential maintenance tasks such as backups, restores, and upgrades. You will then be introduced to many of the most highly-rated addons that are available for ExpressionEngine before finally getting an overview of ExpressionEngine's spam controls, as well as ways to fine-tune ExpressionEngine. After completing this chapter (and the book), you will feel confident creating and maintaining an ExpressionEngine-powered website.
Backups and restores
ExpressionEngine is a database-driven application. So to back it up, you need to back up both the individual files on your web server and the database itself.
Backups
To back up ExpressionEngine, you need a tool such as phpMyAdmin. If your website is hosted by a website hosting provider, contact them and ask if phpMyAdmin or another tool is installed that will allow you to do MySQL database backups. If necessary, phpMyAdmin can be downloaded from http://www. phpmyadmin.net/. phpMyAdmin is included with local development environments, including WampServer, XAMPP, and MAMP, usually at an address such as http:// localhost/phpmyadmin (all in lower-case).
Extending ExpressionEngine
1. The first step to doing a backup is to clear all the unnecessary data from the database (such as cached templates). Log in to the control panel and select Tools | Data | Clear Caching. Select All caches and click Submit.
2. Access the phpMyAdmin control panel.
3. On the left-hand side, select the ExpressionEngine database (such as ee). After selecting the database, you are brought to a screen that shows all the ExpressionEngine tables on the left-hand side (beginning with exp). 4. In the main window, select Export from the top menu.
[ 264 ]
Chapter 10
5. On the Export page, at the top of the left column, verify that all the tables are selected.
6. All the options on the right-hand side can be left at their default settings. At the bottom, check the box Save as file. Select a Compression method of either zipped or gzipped and then select Go.
7. You are then prompted to save the file; save it to a safe place. Note that while phpMyAdmin is sufficient for smaller databases, the backup may time out when backing up very large databases. One option to work around this is to split out the database backup so that not all the tables are backed up into a single file. Another option is to look at the command line MySQL code or a utility such as My SQL Dumper (http://www.mysqldumper.de/en/).
In addition to backing up the MySQL database, it is also prudent to back up all the files on your web server, including any themes, language packs, and add-ons that may have been installed as well as any files that may have been uploaded to your File Upload Destinations (such as the /images directory).
[ 265 ]
Extending ExpressionEngine
Database restores
A backup is only useful if it is usable, and the only way to know if a backup is usable is to restore it. To test a database restore, it helps to have a second database created in phpMyAdmin (if your hosting package includes two databases). Alternatively, you can test a restore to a localhost environment. Testing a database restore using a different database or a localhost server is easy enough, but bringing up an entire ExpressionEngine website on a different database or server is more complicated. The guidelines on how you can accomplish this can be found in the ExpressionEngine wiki at http://www.expressionengine.com/wiki/.
1. If you are restoring a database to a test database, you can follow the instructions at the beginning of Chapter 1, Getting Installed to create a second database. 2. If you are restoring over the top of an existing ExpressionEngine database, you first have to delete the existing tables. In phpMyAdmin, select the database you are restoring to and select Structure from the menu at the top of the main window. Scroll all the way down and select Check All to check all the tables. In the drop-down box, select Drop. A confirmation window will appear—click Yes. Before doing this, be very sure that the database is well backed up or that losing all the data in all the tables will not be a problem.
3. Next, in the empty database, select Import from the menu in the top window. 4. Browse to the location where the database backup was saved. Leave all the other options at their defaults and click Go. [ 266 ]
Chapter 10
5. When the import is complete, there will be a message that says Import has been successfully finished.
6. If you are restoring to the same database/server that the backup was made from, make sure that the corresponding files have also been restored (including the /system directory).
Upgrading ExpressionEngine
EllisLab is always working on new versions of ExpressionEngine. These versions are often packed full of new features as well as security updates and bug fixes. Occasionally, EllisLab will put a price on a new feature (such as the discussion forum). However, the prices are very fair, and reflect the cost of development and support. Doing this keeps the cost of ExpressionEngine itself lower for those users who have no interest in the new feature.
There are two types of releases that ExpressionEngine goes through: •
A new build contains bug fixes or minor updates. It is generally not necessary to upgrade to a new build unless it contains a bug fix that you have been waiting for. Builds are numbered by date, and you can see what build you have in the footer of any page in the control panel.
•
A new version contains new features and improvements to existing functionality. A new version will include all the bug fixes and minor updates of any intermittent builds. Versions are numbered sequentially (such as 2.0.0, 2.0.1, 2.0.2, 2.1.0, and so on).
[ 267 ]
Extending ExpressionEngine
When a new version is released, ExpressionEngine will indicate this prominently on the control panel home page.
When upgrading, you can skip builds, but it is not recommended to skip too many versions. Not only will you miss out on security updates, bug fixes and new features, but if you seek support in the forums and there are significant changes between your version and the current version, you may be asked to upgrade. The instructions for updating to the latest build can be found at http://www. expressionengine.com/user_guide/installation/update_build.html and the instructions for updating to the latest version can be found at http:// www.expressionengine.com/user_guide/installation/update.html. The
instructions are basically the same, except that for a new build, you do not have to run the server update wizard. The basic instructions for upgrading to a new version are as follows: 1. Download the latest version of ExpressionEngine. Read the version update notes (step 5 at http://www.expressionengine.com/user_guide/ installation/update.html) to verify there are no changes that might have a big impact on the specific website that is being updated—for example, a compatibility issue with an add-on that is used. 2. Perform a backup of the database and ideally back up your entire website, including the system, themes, and images directories as well as the index. php file (located in the root directory of your website—though it may have been renamed as part of the ExpressionEngine installation in Chapter 1, Introduction to ExpressionEngine). 3. Take your website offline. ExpressionEngine includes an offline.html template in the /system/expressionengine/utilities/ directory that you can modify and copy to the root of your website. Rename your index. php to index_old.php and then rename offline.html to index.php. 4. If you chose to rename index.php as part of your ExpressionEngine installation, then replace the renamed file with the offline.html template instead.
[ 268 ]
Chapter 10
5. Clear your cached data. Log in to the control panel and select Tools | Data | Clear Caching. Select All caches, and click Submit. 6. On your website, rename your system and themes directories to system_old and themes_old. By keeping the directories on the server for now, it makes it easier to roll back the update if, for some reason, an issue is encountered. The official update instructions recommend renaming the new files being uploaded first, then renaming the existing files after the new files are uploaded, and finally renaming the new files to the names of the original files. This is equally effective and potentially minimizes downtime (if you wanted to keep the website up while the new files are being uploaded).
7. Upload the system and themes directories from the new ExpressionEngine version to your website. You will upload the index.php file right before the upgrade so that, for now, your website continues to reflect that it is offline. If you use additional control panel themes, such as Corporate, Fruit, or the Mobile theme, you will also need to download these themes from http://www.expressionengine.com/ and upload them to the /themes/cp_themes/ directory.
8. From the backup of your old system directory, upload the following directories to your new system directory: /system/expressionengine/third_party/ /system/expressionengine/config/ /system/expressionengine/templates/
9. Set the file permissions for /system/expressionengine/config/config. php and /system/expressionengine/config/database.php to 666 (writeable). Set /system/expressionengine/cache to 777 (writeable). 10. Now upload the index.php file, overwriting the offline template that you earlier saved as index.php. [ 269 ]
Extending ExpressionEngine
11. If this is a version update rather than a build update, point your browser to / system (for example, http://localhost/system or http://www.example. com/system) and follow the on-screen instructions to perform the update to the latest version.
12. After you see a message saying that you are running the most current version of ExpressionEngine, delete the /system/installer directory. 13. If you renamed your system directory, you will need to edit the newly uploaded index.php and update the $system_path = './system'; line towards the top of the file to reflect your renamed system directory. 14. If you mask the location of your control panel by accessing your control panel from a URL other than http://localhost/system/index.php (such as http://localhost/admin.php), you will also have to copy /system/ index.php and replace your masked-access file (such as /admin.php). Once you have done this, you will also have to update the $system_path = ''; line towards the top of the file to reflect the path to your system directory. 15. Follow the Version Specific Notes for any versions between the version you are updating to and the version you are updating from. The Version Specific Notes will contain details on any changes that need to be made above and beyond the normal upgrade changes just listed. For example, if additional files need to be uploaded, a theme or language pack has been updated, or if a new setting in the control panel needs to be defined, the Version Specific Notes is where you will find that out. If you have customized your own themes and the Version Specific Notes indicate that a theme was updated, you will have to manually update your theme with the same changes that were made to the built-in themes. Luckily, EllisLab is very good at identifying these changes in a version upgrade and at outlining what needs to be done.
16. Verify that your website is working as expected, and then delete the system_ old and themes_old directories, as well as the index_old.php file at the root of your website. [ 270 ]
Chapter 10
When you first log into the control panel, you will be warned that one or more core files have been changed—click to accept these changes. You may also receive an e-mail saying the same thing.
17. Finally, in addition to ExpressionEngine itself, modules you install (such as the Discussion Forum and Multiple Site Manager) can also be subject to new versions. For example, the discussion forum version update instructions can be found at http://expressionengine.com/user_guide/modules/forum/ forum_update.html.
ExpressionEngine add-ons
Although not open source software, ExpressionEngine has many ways in which both EllisLab and the members of the ExpressionEngine community can add to it. ExpressionEngine 2 is built on CodeIgnitor—an open source PHP web application framework also by EllisLab. CodeIgnitor is a popular framework for PHP developers, allowing rapid development of PHP web applications. For ExpressionEngine users, this means that add-on developers have the ability to build more complex add-ons (even entire applications) for ExpressionEngine by using CodeIgnitor. It also means that there is a much larger base of developers who can build ExpressionEngine add-ons. More developers building more and more complex add-ons for ExpressionEngine can only mean one thing. If there is something you need to do that is not supported natively, there is likely an add-on for it. The add-on market has grown hugely in the last few years and there are now several companies that have either started or been able to branch into developing and selling ExpressionEngine add-ons. Although this means that some add-ons come at a cost, it also means those same add-ons are likely to be high-quality, reliable tools to expand the functionality of ExpressionEngine. The best resource for ExpressionEngine add-ons is http://www.devot-ee.com/—an official EllisLab community partner.
Types of add-ons
ExpressionEngine add-ons come in five flavors, namely, modules, accessories, extensions, fieldtypes, and plugins. All add-ons are managed through the Add-Ons menu in the control panel—here you can install, uninstall, or access the configuration screens (if applicable). [ 271 ]
Extending ExpressionEngine
Modules
Throughout this book, you have been working with ExpressionEngine modules, including the Channel module, the Member module, the Comment module, and the jQuery module. A module can be simple and focused (that is, do one thing and do it well), or they can be close to applications in their own right, complete with their own control panel configuration screens and their own library of tags. Some modules are aimed at control panel users and do not add any visible functionality to the frontend of your website—an example is the Blacklist/Whitelist module, which allows you to block spammers from your website but does not change anything on your website. Other modules are designed specifically to add functionality to your website—they provide tags that can be used within templates so that you can control where this functionality appears and how it looks. The Search module works like this—it does not add any functionality to the control panel, but it allows you to add integrated searching capabilities to your website. Finally, there are modules that add functionality to both the control panel and your website. For example, the Mailing List module provides a control panel configuration screen where you can set up mailing lists and manage subscribers, and it also provides tags that you can use in templates to allow visitors to sign themselves up. Modules can read and write data to your database, making them a very powerful tool in an ExpressionEngine installation.
Accessories
Accessories are new in ExpressionEngine 2. They are the tabs that appear on the bottom of each control panel page.
ExpressionEngine comes bundled with the ExpressionEngine Info accessory installed and three other accessories that are included but not installed (Learning EE, News and Stats, and Quick Tips).
[ 272 ]
Chapter 10
To install a new accessory, you can go to Add-Ons | Accessories, and then click Install on the accessory (or accessories) of your choice (third-party accessories must be uploaded to the /system/expressionengine/third_party/ directory before they appear in this list to install). Once installed, clicking on an accessory name will open a preferences page where you can define which member groups can see the accessory and on what control panel pages the accessory appears. In this way, an accessory that is useful when creating templates (for example) can be set to appear only on Design pages of the control panel, and only to member groups that would be working with templates.
Building your own accessory is a great way to start getting into ExpressionEngine add-on development. One use for an accessory (if you build websites for clients) is that it can be used to provide easily accessible help and tips to your client, right inside the ExpressionEngine control panel.
Extensions
Extensions are a type of add-on that uses hooks within ExpressionEngine to modify how ExpressionEngine itself works. Unlike modules, extensions do not have tags that are used in templates. Instead, they modify aspects of how ExpressionEngine works. For example, there are extensions that allow you to change how CAPTCHA works, that allow you to change the page ExpressionEngine loads after a member logs in, and that allow you to change system messages so that they use a regular template instead of the template found under Design | Message Pages | User Messages. [ 273 ]
Extending ExpressionEngine
Like accessories, third-party extensions need to be uploaded to /system/ expressionengine/third_party/ before they can be enabled from the Add-Ons | Extensions control panel page. Most extensions will come with instructions on how to install them. ExpressionEngine does not come bundled with any extensions that are ready to go, but extensions are a very common type of add-on.
Field types
ExpressionEngine comes bundled with several different types of fields that can be used in entries. Throughout this book, you have used Text Input and Textarea extensively. You used File when building the photo gallery and you also used the Relationship field when building the calendar so that you could relate events in one channel to event sponsors in another. Fieldtype add-ons allow you to expand the range of fields that you can use for your channels.
Plugins
Plugins are the most basic form of add-on for ExpressionEngine. Unlike a module, plugins cannot store data in the database (though they may still query the database), and do not have their own control panels. Unlike an extension, plugins do not change the functionality of ExpressionEngine itself. A plugin works by making one or more tags available that can then be used in templates. Like other add-ons, third-party plugin directories need to be uploaded to /system/ expressionengine/third_party/ before they can be enabled from the Add-Ons |
Plugins control panel page. Clicking on the title of an installed plug-in will give you instructions on how to use it.
[ 274 ]
Chapter 10
Plugins exist for lots of nifty purposes—replacing text with other text, creating random text, converting kilograms to pounds, the list is endless. For EE2 compatible plugins and other add-ons, please visit http://www.devot-ee.com/.
Third-party add-ons and add-on developers
While there are far too many add-ons to list them all, what follows are some prominent add-on developers whose add-ons are worth knowing. This is not a comprehensive list, and it can be expected that different people would have different ideas regarding which add-ons are the most useful. Devot:ee is the best place on the web to find up-to-date information about add-ons, and EE Insider (http://www.eeinsider.com/) is another good site to follow for tips, information, and interviews on all things ExpressionEngine.
Pixel & Tonic http://www.pixelandtonic.com/
Although Pixel & Tonic is a relatively new company, Brandon Kelly has been building add-ons for many years, including the FieldFrame extension that became the basis of the Fieldtype add-on in ExpressionEngine 2. Several of Pixel & Tonic's add-ons are considered essential by ExpressionEngine developers, including: •
•
•
Matrix: This adds the ability to have tables in your channel entries. This is a huge improvement over using repeated textarea and text input fields for as many "rows" as you are likely to need. With Matrix, you can define the columns and in each entry, create as many rows as you need. Matrix can be used whenever tabular data is involved. One common use is to create photo galleries where each channel entry represents a gallery containing multiple photos (one per row) as opposed to having one photo per-entry (like you did when building the photo gallery in Chapter 8, Creating a Photo Gallery). Playa: This is a field type that works very similarly to the Relationship field that is built into ExpressionEngine, but instead of only allowing you to relate only one entry in another channel to your entry, Playa allows you to relate multiple entries in many other channels to your entry. Using the calendar example from Chapter 7, Creating a Calendar, you could have multiple sponsors for each calendar event, instead of being limited to picking just one (or having to create multiple Relationship fields). Wygwam: This adds WYSIWYG (What You See Is What You Get) functionality to ExpressionEngine's publish page. Instead of plain-text fields on the Publish page, Wygwam allows you to create content using wordprocessor-like functionality—you can add images, format, and layout the text just like you would in a word processor. [ 275 ]
Extending ExpressionEngine
Solspace http://www.solspace.com/
Solspace is a leading add-on developer for ExpressionEngine. Their work includes: •
Tag: A module that allows you to tag channel entries and organize your content by tag. You can also build a tag cloud.
•
FreeForm: A module that makes it easy to create and manage forms that collect information from your visitors.
•
User: A module that overhauls ExpressionEngine's native member functionality, bringing the default member templates into regular templates and making them much easier to customize and brand.
•
Facebook Connect: A module that adds Facebook SSO (Single Sign-On) capabilities to your website.
•
Super Search: This is a module that overhauls ExpressionEngine's native search functionality, improving the performance and allowing results to be sorted by relevance.
•
Friends: A module that updates the member functionality to be more like a social network. Members can invite each other to become friends, they can restrict their profile so that it is only visible to their friends and they can post status updates similar to Facebook or LinkedIn (at the time of writing, this module was not yet compatible with EE2).
•
Calendar: A full-featured calendar that goes far beyond what is possible with ExpressionEngine's built-in calendar functionality (the main improvement being the addition of recurring events—a key requirement of most calendar applications) (at the time of writing, this module was not yet compatible with EE2).
Newism (Leevi Graham) http://www.expressionengine-addons.com/
Newism is the author of many very popular ExpressionEngine 1 add-ons. Newism's add-ons include: •
NSM Addon Updater (previously LG Addon Updater): This accessory works with other compatible add-ons to let you know when a new version of the add-on is released. Each compatible add-on is listed in an accessory tab, along with the installed version and the latest available version.
[ 276 ]
Chapter 10
•
NSM Better Meta (previously LG Better Meta): This extension makes it easy for you to generate unique HTML meta tags for each entry without having to create custom fields in each of your channels for the meta tags (such as description, keywords, author, and so on). By having unique meta tags on your pages, your website is more search-engine friendly, potentially making it easier for people to find you through search engines. The extension can also generate search engine XML sitemaps.
•
NSM TinyMCE (previously LG TinyMCE): This is a free WYSIWYG custom field type, similar to Wygwam.
•
NSM Transplant (previously LG Replace): When creating new entries on the Publish page, this plugin allows you to insert the contents of one custom field inside the contents of another custom field. For example, if you have one or more image fields and a textarea field, you could insert a tag (called a needle) inside the text area so that the images appear within your text. (In your template, you can only place custom fields before or after each other, not inside each other).
•
NSM Live Look (previously LG Live Look): This extension allows you to view what your entry will look like on your website, directly from the Publish page.
Low (Lodewijk Schutte) http://www.loweblog.com/software/
Low has created many ExpressionEngine add-ons, including Low NoSpam, which will check comments, forum posts, and wiki articles submitted to your site against a service such as Akismet or TypePad AntiSpam to see if the submission is spam. Low Variables is another add-on that builds upon and improves ExpressionEngine's native variable management, allowing you to hide variables from other control panel users on a per-variable basis, as well as allowing you to group, sort, and label them.
nGen works http://www.ngenworks.com/software/ee/
nGen Works have built a number of ExpressionEngine add-ons, of which one of the most popular is Structure (http://www.buildwithstructure.com/). Structure bypasses the template structure of the standard ExpressionEngine website and instead allows you to define static and dynamic pages in an easy-to-use site-map view.
[ 277 ]
Extending ExpressionEngine
Other notable add-ons
The following add-ons can also be useful when building ExpressionEngine websites: •
Template Variables (by Matthew Krivanek) is a third-party accessory that displays the custom field names, snippets, and global variables that are on your site, so that you never again forget what you called a particular field, snippet or variable. The accessory includes quick links to add or edit custom fields, snippets, and global variables. Clicking a name copies the syntax onto the clipboard for easy pasting into a template (http://www.devot-ee.com/ add-ons/template-variables/).
•
Image Sizer (by David Rencher) is plugin that makes a template tag available which, when wrapped around an HTML tag, will resize the corresponding image to the size specified in the parameters and cache the resized image. This means that instead of having to require images to be of a certain size when they are uploaded to ExpressionEngine, they can be dynamically resized from within the template the first time the template is accessed. The plugin has won Devot:ee's AcademEE Plugin of the Year award multiple times (http://www.devot-ee.com/add-ons/imagesizer/).
•
First Timer (by Ryan Irelan) is an extension that allows you to alter where members are redirected to after they log in (http://www.devot-ee.com/ add-ons/first-timer/).
•
Backup (by Thomas Myer) is a module that makes it easy to do a database backup and download the file right from within the ExpressionEngine control panel—no logging into phpMyAdmin needed (http://www.devotee.com/add-ons/backup/).
•
Accessible Captcha (by Greg Salt) is an extension that changes the graphic CAPTCHA to a random question & answer system that plays well with screen-readers in a way that image-based CAPTCHAs do not. It works in much the same way as a regular CAPTCHA—making it easy for a person to complete the question, but making it difficult for an automated script to do so (http://www.devot-ee.com/add-ons/accessible-captcha/).
•
MD Detect Page Type (by Ryan Masuga) is a plugin that can be used in a template to detect what type of page is being rendered. This makes it easy to build conditional statements based on whether a page is a basic multipleentry page, a category page, a paginated page, an archive page or a singleentry page, and therefore makes it easier to use a single template for some or all of these scenarios (http://www.devot-ee.com/add-ons/md-detectpage-type/).
[ 278 ]
Chapter 10
•
Custom System Messages (by Brian Litzinger) is an extension that allows you to change the template that system messages are displayed with, allowing your system messages to share the same layout as the rest of your website and allowing you to use the full range of ExpressionEngine tags on the page (http://www.devot-ee.com/add-ons/custom-systemmessages/).
•
Channel Images (by DevDemon) is a module/extension that improves upon ExpressionEngine's native file manager functionality, including features such as multi-select image uploads from the control panel (http://www.devotee.com/add-ons/channel-images/).
•
Search Results (by Planet/EE) is a module that improves upon ExpressionEngine's default search capabilities, allowing you to group and sort search results, highlight search terms, use custom fields in search results, and more (http://www.devot-ee.com/add-ons/search-results/).
•
Cartthrob (by Chris Newton) and FoxEE (by HCC Development) are both full-featured shopping cart modules. (At the time of writing, they are not yet available for ExpressionEngine 2; http://www.devot-ee.com/add-ons/ cartthrob/ and http://www.devot-ee.com/add-ons/foxee/).
There are many more add-ons available for ExpressionEngine—more than can possibly be listed here. If there is something you wish ExpressionEngine could do (or could do differently), search the add-on library at http://www.devot-ee.com/ first.
Optimizing ExpressionEngine
Out-of-the-box, ExpressionEngine works very well, but on larger sites that attract more traffic, there are several options to fine-tune that can help you keep ExpressionEngine humming.
[ 279 ]
Extending ExpressionEngine
Spam
One downside of any website that allows members of the public to submit content is spam. Spam can take many forms, including comment spam, forum spam, and member registration spam (where spammers register as new members on your site and then place links in their profile pages), Luckily, ExpressionEngine has several tools you can use to combat spam, many of which are outlined in the ExpressionEngine documentation at http://www.expressionengine.com/user_ guide/general/spam_protection.html. Suggestions include: •
Use the blacklist/whitelist module to keep known spammers from your website and prevent content (in comments or member profile fields) that matches anything in the blacklist from being submitted. There is a oneclick option to download the latest blacklist from ExpressionEngine and you can also add items to the blacklist/whitelist that may be unique to you (downloading the list will not overwrite anything you add manually). The bottom line is that there is no reason not to use this module. (This module can be found in Addons | Modules in the control panel).
•
Require all comments to be moderated, require membership in order to post comments, or enable CAPTCHA for comment postings. If nothing else, you should ensure that you are set up to receive e-mails whenever comments are posted. All these settings can be found under Admin | Channel Administration | Channels for each channel.
•
Enable membership CAPTCHA (under Members | Preferences) or require all new member registrations to be activated manually by an administrator (though even administrators may not be able to spot spam registrations).
•
Disable New Member Registrations entirely (under Members | Preferences) if you do not plan to use the member features of ExpressionEngine. Remember that this feature is enabled by default, meaning that even if your website does not link to the member URLs, the member URLs are active. [ 280 ]
Chapter 10
•
Use Word Censoring (under Admin | Security and Privacy | Word Censoring), which allows you to replace any user-submitted word (or partial word) with the # symbol (or a word of your choice).
•
Apply Rank Denial (under Admin | Security and Privacy | Security and Sessions). This makes your website less attractive to spammers because user-submitted links point to a redirect page on your own site rather than pointing directly to the spammer's site. This means that any links posted to your website will not improve the spammers search engine page rank.
•
To prevent Denial of Service attacks, ExpressionEngine has Throttling Preferences (under Admin | Security and Privacy) that allow you to set how many pages can be downloaded in a given time period by a single person before that person is temporarily locked out.
•
Other recommendations in the documentation include setting a longer Comment Time Interval in the preferences for each channel (to prevent spammers from submitting hundreds of comments in a short space of time), using Secure Form Mode in the Security and Session preferences to prevent the same form being submitted multiple times without being refreshed and Deny Duplicate Data (also in the Security and Session preferences) to prevent the same comment being made more than once.
•
Finally, in addition to ExpressionEngine's built-in features, there are also several add-ons including Accessible CAPTCHA, Low NoSpam, and No Follow, all designed to make your website less attractive to spammers. Search for these and others at http://www.devot-ee.com/.
In summary, none of these options are a perfect solution, and there is certainly a trade-off between functionality and anti-spam controls. For example, requiring membership to post comments does not prevent a member from posting spam in comments but it at least provides an extra layer of protection.
Performance
ExpressionEngine is database-driven, and for most websites, the performance is excellent out of the box. With that said, if you are expecting high traffic volumes, it is worth being aware of (and following) good design practices as you build your website. The most fundamental technique that you can use to reduce template load times is reducing the number of ExpressionEngine tags in a template. A template that uses multiple embedded templates, nested conditionals, add-ons, and so forth involves more database queries and so will take longer for ExpressionEngine to render than a simple template with only a handful of standard ExpressionEngine tags. [ 281 ]
Extending ExpressionEngine
Other techniques to reduce page load times include the following: •
Use embedded templates, snippets, and global variables appropriately. An embedded template comes with all the overhead of rendering a template, whereas a snippet does not. So, if a snippet can be used instead of an embedded template, it should be.
•
Use the Disable Parameter liberally. By default, the {exp:channel:entries} tag fetches all the information about the channel entry that is stored in your database (including category information, member data, and the data in the custom fields). In many cases, you do not use all this data, so there is no point in retrieving it from the database. The disable parameter allows you to reduce the number of database queries by turning off queries for certain types of data. For example, you used this parameter when retrieving the entry title for the HTML in your single-entry templates. Since you only needed the title of the entry (which is not a custom field), disabling all the extra database queries made sense: disable="categories|category_fields|custom_fieldsmember_ data|pagination".
For more information on the disable parameter, visit http://www. expressionengine.com/user_guide/modules/channel/ parameters.html#par_disable.
•
Use Simple Conditionals instead of complex conditionals. A simple conditional is an if statement that evaluates one condition and does not have any if:else clauses. A simple conditional is parsed early, meaning that any ExpressionEngine tags within the simple conditional are ignored if the condition is false. More complex conditional statements (involving multiple conditions or multiple else clauses) are parsed later, meaning any ExpressionEngine tags within them are parsed, even if the condition turns out to be false.
•
Consider enabling GZIP output. This option (under Admin | System Adminstration | Output and Debugging Preferences) compresses website pages (which are then decompressed seamlessly by most modern browsers). This can result in faster download speeds.
•
Optimize ExpressionEngine's SQL tables. Under Admin | Utilities | SQL Manager, select Manage Database Tables, select all tables, and click Optimize. When run from time to time, this can help make database queries faster by eliminating database fragmentation.
[ 282 ]
Chapter 10
ExpressionEngine also includes a variety of different types of caching that can help improve performance by minimizing the number of queries needed to render a template. The benefits of enabling these options can vary depending on the server the website is hosted on (if the server already has caching enabled, then enabling caching within ExpressionEngine may cause double-caching and therefore an increase in load). More information can be found at http://www. expressionengine.com/user_guide/general/caching.html. ExpressionEngine caching is useful to reduce the number of database queries that a specific URL creates (such as your home page). However, caching is done by URL, meaning that for each new URL, a new cache is created, even if the elements on the pages at two different URLs come from the same template. Given that a single template can be the basis of hundreds or thousands of URLs (depending on the number of channel pages), websites with a lot of traffic spread over a large number of URLs may not see much benefit in page load times by caching, even if the traffic is concentrated on a small number of templates.
For sites with high traffic loads, the documentation also includes information on how to further optimize ExpressionEngine by turning off tracking and minimizing Disk I/O. Please see http://www.expressionengine.com/user_guide/general/ handling_extreme_traffic.html for more information. Solspace offers a Site Performance Evaluation for ExpressionEngine sites (http://www.solspace.com/development/ performance/) that may be worth considering for large, high-traffic websites.
Summary
In this chapter, you learned about the routine maintenance tasks that come with running a powerful database-driven website (such as database backups and software upgrades). You learned about the different types of add-ons that ExpressionEngine accommodates, and about specific add-ons and add-on developers that are worth being aware of. Finally, you learned about optimizing ExpressionEngine to fight spam and improve page-load times. The key points to remember after working through this chapter (and the book) are: •
Back up your website, including the database.
•
Upgrade ExpressionEngine when new versions are released (or at least every few versions). If you continue to use an older version, you will not have all the latest features and bug-fixes, and newer add-ons may not be compatible. [ 283 ]
Extending ExpressionEngine
•
ExpressionEngine is highly extensible, and many of the add-ons are highquality commercial grade pieces of software. If there is something you wish ExpressionEngine could do, research the add-on library first.
•
The ExpressionEngine documentation is an excellent resource—clear, concise, accurate, and with plenty of examples. It is a great way to learn about a new feature (or to learn more about a feature you are already familiar with).
•
Visit the ExpressionEngine support forums often (http://www. expressionengine.com/forums). If there is something you are trying to accomplish, the chances are good that someone else has tried the same thing. A quick search can often reveal lots of ideas. The how-to forum is a great place to get ideas, seek advice, or even get feedback.
[ 284 ]
Installing WampServer In this appendix, you will walk through downloading, installing, and setting up WampServer. This will allow you to run ExpressionEngine on your own computer. If you already have WampServer installed (or an alternative product such as XAMPP or MAMP for Mac OS X), then you can skip these instructions. WampServer is a free package that includes an easy-to-set up web server (Apache), database server (MySQL), and server-side scripting language (PHP), all of which are requirements of ExpressionEngine. Installing WampServer lets you experiment with ExpressionEngine on your own computer instead of a live website. Setting up each piece of an Apache, MySQL, and PHP (AMP) environment individually can be complicated, but with WampServer, the system comes pre-configured and ready to go, so you can concentrate on learning ExpressionEngine. You are installing WampServer as a development (or testing) environment only. You will not be using WampServer to build a live server that presents your website to the outside world. Setting up and securing a production web and database server is a topic beyond the scope of this text.
WampServer is a Windows only package. If you are using Mac OS X, MAMP is a good alternative (http://www.mamp.info). XAMPP is another alternative that is available for Windows, Linux, Mac OS X, and Solaris. If you choose to use an alternative package, the installation instructions for that package are going to be different and there may be some differences when you install and configure ExpressionEngine on your server in Chapter 2, Getting Installed. However, ExpressionEngine itself will work exactly the same.
Installing WampServer
WampServer is free to download, and the package contains the following: •
The AMP environment of Apache, MySQL, and PHP (needed to install ExpressionEngine)
•
phpMyAdmin, which is the leading web-based interface to MySQL (needed to manage the ExpressionEngine database)
Installing WAMPServer First, you must download WampServer:
1. Visit http://www.wampserver.com/en 2. On that page, there will be a link to the download page of WampServer. Select it and you should see a link to download WampServer. 3. Clicking the download link will take you to SourceForge.net where you can download the file. The file download should begin automatically, but if it does not start, there should be a direct link that you can use to start the download. If you have Internet Explorer 7 or higher, it may block the site from downloading files to your computer. A warning will appear in a small bar at the top of your browser screen. Click on it and select Download File.
4. Next you will be prompted to save the file. Save it to your Downloads, Desktop, or My Documents area. Depending on the speed of your Internet connection, the file may take some time to download. Now that you have downloaded the software, the next step is to install it. If you are running the Skype VOIP application, or IIS Server, you will need to exit them before proceeding. Apache cannot start as a service if Skype or IIS is also running as they all use port 80. If you have Skype, you can set it to no longer use port 80 by going into the Advanced page of the options screen in Skype.
1. Double-click on the file that you downloaded in order to run it. If you get a Windows security warning, click on Run. 2. A welcome screen will display. Click on Next.
[ 286 ]
Appendix A
3. A license agreement screen will display. WampServer is an open source software package released under the GNU General Public License. Accept the license agreement. 4. WAMPServer, by default, installs in C:\wamp, and that is where this book will assume it is installed.
5. Select whether you would like a Quick Launch or Desktop icon, then click on Next. 6. A summary screen will display, showing where WampServer will be installed. Click on Install.
[ 287 ]
Installing WampServer
7. The installation will take a few minutes to run, during which you will see all the files being extracted. After all the files have extracted, a dialog box will appear asking you to pick your default browser (this is used by WampServer to know what browser to use when you use WampServer shortcuts to open your website; it does not prevent you from using other browsers installed on your machine if you later wish to do so). If you have Firefox installed, it will ask if you wish to use Firefox. If you do not, browse to Internet Explorer (typically located in C:\Program Files\Internet Explorer\iexplore. exe). Click on Open.
8. The installation will run for a little longer, and then you will be prompted for your PHP mail parameters. Although ExpressionEngine does make use of e-mail (for example, when registering new members), it is not an essential part of this book. If you have an SMTP server you can use, feel free to enter the information, otherwise accept the default settings. Click on Next.
[ 288 ]
Appendix A
9. Finally, leave the checkbox to launch WampServer checked and click on Finish.
WampServer is now installed and running.
Using WampServer
When WampServer is running, you should see a new icon on your taskbar next to the clock. Clicking on this will produce a menu with useful links. (If you do not see the icon, try launching WampServer again by clicking on start WampServer under WampServer in your Start menu).
[ 289 ]
Installing WampServer
Localhost will launch your website (you can also access your website by visiting http://localhost/ in your browser). phpMyAdmin is used to manage your website databases, and we will use it in Chapter 2 to set up the database that ExpressionEngine will use. www directory will open C:\wamp\www in Windows Explorer. Any files placed in this directory will be visible on your website. This directory is therefore where you will place your ExpressionEngine installation files. The other options allow us to control the different services individually. You can stop and start services individually (or stop and start all services). You can also switch between versions and change settings specific to each service. By default, when you visit http://localhost/, you will see a WampServer home page. If you are using Internet Explorer and see a message at the top of your screen that says Intranet settings are now turned off by default, left-click on it and select Don't show this message again.
In order for us to develop our website, you should delete this welcome page.
[ 290 ]
Appendix A
This welcome page displays configuration information about your PHP installation. A comprehensive view of the same information can be accessed from within the ExpressionEngine control panel (under Tools | Utilities | PHP Info).
1. Navigate to C:\wamp\www and delete the file index.php. 2. In your browser, navigate to http://localhost/, and you should now see an empty directory listing.
Allowing .htaccess files to be used
To take advantage of some features in ExpressionEngine (such as removing the index. php from ExpressionEngine URLs), you need to use a .htaccess file, which requires the Apache module mod_rewrite to be enabled. 1. Left-click the WampServer task bar icon, click Apache | Apache Modules, and then scroll down the list of modules until you see the rewrite_module. Left-click on the rewrite_module option to enable it.
[ 291 ]
Installing WampServer
It will take a few seconds for it to enable, but then your .htaccess files will be recognized; you will be using them in Chapter 2, Getting Installed.
Summary
In this appendix, you walked through the installation of WampServer, one of several products available for simulating an Apache, MySQL, and PHP environment on your computer. Other alternatives include XAMPP and MAMP (for Mac OS X). The key points to remember after working through this appendix: •
Your website can be accessed in a browser at http://localhost/.
•
To upload files to your local website, you have to save them in C:\wamp\www.
[ 292 ]
Solutions to Exercises Most of the exercises throughout this book have more than one solution. The following are the example solutions to some of the exercises in this book. Where a solution has not been provided, the instructions in the chapter can be adapted to complete the exercise. Chapter 3, Exercise 1 To limit the entries that are displayed to 2, you need to edit the channel tag to read as follows: {exp:channel:entries channel="news" limit="2"}
Chapter 3, Exercise 2 To post a new entry to a channel, log into the control panel at http://localhost/ admin.php (or http://localhost/system/index.php), and select Content from
the menu at the top of the screen. Highlight Publish and then select the channel you wish to post to (in this case, News), and type in the new entry. Select an image and then click Submit when you are done. Chapter 3, Exercise 3 To edit an entry, you can either select Content from the main menu, then select Edit, or you can select Entry under Modify or delete. Click on the entry you wish to edit and then edit away.
Solutions to Exercises
Chapter 3, Exercise 4 Try searching for html css tutorials in your favorite search engine. A couple of good resources include: • •
http://www.htmldog.com/guides/ http://www.w3.org/Style/Examples/011/firstcss
If you prefer learning from a book, pop down to your local bookstore's Computing & Technology section, and you will find plenty of books. Look for ones that focus on HTML and CSS, rather than other software applications (such as Dreamweaver). Chapter 4, Exercise 1 To create new pages, select Content | Publish | Website and copy in the text from the corresponding static HTML file. Add in HTML tags for the headings (), links (using {site_url}), and italic (<em>) where appropriate, and remember that you can choose the previously uploaded picture, rather than uploading the picture again. Make sure that the URL title for each entry matches the URL title in the table below. Next, create the following template groups and select to duplicate the site template group. Then edit the index template of each group and adjust the url_title parameter to be as follows: Template Group Name
URL Title
business
small_business
contact
get_in_touch
promotion
promotion
Notice how when you enter e-mail addresses into the Contact Us entry, they are automatically converted to links on your page. The links are automatically encrypted using JavaScript to make it harder to harvest by spambots.
Chapter 5, Exercise 1 To set the amount of time to show a comment, go to Admin | Channel Administration | Channels. Select the FAQs weblog and click Edit Preferences. Select Comment Posting Preferences and change the Comment Expiration field to 60. Optionally, check the box to update existing comments with this setting and then click Update.
[ 294 ]
Appendix B
Chapter 5, Exercise 2 To include the author and the date of a post, update the line of code that reads
<strong>Q: <em>{faqs_question}
in both the faqs/ index and faqs/browse templates to read as follows: <strong>Q: <em>{faqs_question}
<strong>Posted by {author} on {entry_date format="%m/%d"} p>
More information about the different types of dates that you can display in your entries can be found at http://www.expressionengine. com/user_guide/modules/channel/variables.html#date_ variables. More information about date formatting code can be found at http://www.expressionengine.com/user_guide/ templates/date_variable_formatting.html.
Chapter 5, Exercise 3 If your installation included Agile Records, then you will already have a custom status called Featured. If you are using the blank installation, then you will need to create such a custom status. To create it, go to Admin | Channel Administration | Custom Status Groups, click Add/Edit Statuses, and then click Create a New Status on the top right. Call the new status Featured and click Submit. Before you update your snippet, you should first make at least three of the entries in your channel Featured entries. To do this, edit an entry and select the Options tab. Under Status, change the status to Featured. Next, update the snippet code to include a new parameter which says that the status must be featured in order to display. {exp:channel:entries channel="faqs" limit="3" orderby="random" dy namic="off" status="featured"}
[ 295 ]
Solutions to Exercises
Finally, you have to update the faqs/index, faqs/browse (both in the title and in the body of the page), faqs/rss and faqs/atom to display featured entries in these templates. By default, ExpressionEngine will only display entries with an open status—if you want to display entries with a different status, you have to explicitly tell ExpressionEngine to do so. Modify any {exp:channel:entries} tags in these templates to have the status="Open|Featured" parameter as in this example: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Featured"}
Chapter 6, Exercise 1 To create a new member group that can only modify templates, go to Members | Member Groups and select Create a New Member Group. Call the new member group Designers. Click on Control Panel Access and say Yes to accessing the control panel, and Yes to the design section. Under Template Editing Privileges, select which templates can be edited (business, contact, faqs, includes, individual, promotion, and site). Click Submit. Next, select Members | Register Member and create a new member in the Designers member group. Log in as the new member and verify that it works as expected. Chapter 6, Exercise 2 To create a custom member field, you go to Members | Custom Member Fields. Select Create a New Member Field. Choose a field name of existing_customer and a field label of Are you an existing customer of Ed & Eg?. Change the field type to Select List and enter two options (one on each line)—Yes and No. Leave Text Formatting set to None. Say Yes to this being a required field, No to the field being visible in public profiles, and Yes to being visible in registration pages. Click Submit. Log out of the control panel, then visit your website and click Register. You should see the new field on the registration screen.
[ 296 ]
Appendix B
Chapter 6, Exercise 3 Copy the includes/404 template code and then edit the promotion/index template (created as part of the exercises in Chapter 4, Moving a Website to ExpressionEngine). At the top of the template, add a line of code that says {if logged_in}. Underneath the {embed} line, add in another line of code that says {if:else}. Underneath this, paste in the code from includes/404. Then modify the
and the to reflect that you are on the Promotions page rather than the 404 page and modify the paragraph of text to indicate that promotions are available to members who are logged in only. Finally, at the very end of the template, add a closing {/if} tag. The overall template structure will be as follows: {if logged_in} {embed="includes/.website_page" url_title="promotion"} {if:else} [Modified template code from includes/404] {/if}
Chapter 7, Exercise 1 To modify how the days of the week in the calendar are displayed, you need to edit the code in between the calendar_heading tags in the calendar/index template to read as follows: {calendar_heading}
{lang:weekday_short} {/calendar_heading}
Another alternative is to use {lang:weekday_long}, which will output the full name
of the day (such as Friday). Chapter 7, Exercise 2
To display the next event that is coming up underneath your calendar, you need to use the {exp:channel:entries} tag with two parameters, namely, dynamic="off" and start_on="{current_time format='%Y-%m-%d %H:%i'}".
[ 297 ]
Solutions to Exercises
The dynamic="off" parameter decouples the channel entries being displayed at the URL. By default, the channel tag will look at the URL of the page you are on to determine the entries to display. So, if you were viewing May 2012 (and the URL was http://localhost/calendar/2012/05), your {exp:channel:entries} tag would also only display entries from May 2012. dynamic="off" means that the channel will display any entry from your channel, regardless of the URL. The second parameter is start_on="{current_time format='%Y-%m-%d %H:%i'}". The current_time is a system global variable for the current time on the server. The start_on parameter says that you only want to display channel entries with an entry date on or after the date you provide—in this case, the current date. This means that events in the past will not be displayed—you will only display events that are yet to happen. Read more about global variables at http://www. expressionengine.com/user_guide/templates/globals/ single_variables.html and read more about the start_on parameter at http://www.expressionengine.com/user_ guide/modules/channel/parameters.html#par_start_on
Insert the following code after the {/exp:channel:calendar} tag and immediately before the tag in the calendar/index template: Upcoming Event
{exp:channel:entries channel="{my_channel}" limit="1" re quire_entry="yes" show_future_entries="yes" sort="asc" dynamic="off" start_on="{current_time format='%Y-%m-%d %H:%i'}"} {if no_results}
No Upcoming Events
{/if} <strong>{title}
<em>{entry_date for mat="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{if events_description} {events_description}
{/if} {if events_sponsor} {related_entries id="events_sponsor"} More About Our Sponsor: {title}
{if event_sponsors_about} {event_sponsors_about}
{/if} {/related_entries} {/if} {/exp:channel:entries} [ 298 ]
Appendix B
Chapter 8, Exercise 1 Limiting the number of photos and randomizing them simply requires adding parameters to the {exp:channel:entries} tag in the photos/index template. This also limits the number of photos that will display in each category, so you want to be sure not to add more photos in a given category than the limit you set here. Alternatively, you can use pagination so that if there are more photos than the limit, they display on separate pages. {exp:channel:entries channel="{my_channel}" or derby="random" limit="10"}
Chapter 8, Exercise 2 To track the number of single-entry page views, you must first add a parameter to the {exp:channel:entries} tag in your single-entry page template (photos/ comment). ExpressionEngine offers four view counters that can be added to different single-entry pages, helpfully numbered one through four. Since you only have one single-entry page, you can use view counter one. {exp:channel:entries channel="{my_channel}" limit="1" require_entry="yes" status="Open|Premium" track_views="one"}
Next, add a conditional statement to your multiple-entry page (photos/index), immediately after the code that displays how many comments there are and before the :
{if view_count_one>="10"}***Popular***{/if}
The second
helps keep the photo thumbnails aligned, when some are considered popular and some are not.
Note that the view counter is not incremented when a photo is viewed in the lightbox because the lightbox is displaying the actual image file and not the single-entry template.
[ 299 ]
Solutions to Exercises
For channel entry view tracking to work, it must be enabled in Admin | Security and Privacy | Tracking Preferences (by default, it is enabled). The single-entry template in question must also not have caching enabled (by default, caching is disabled). To change the caching preferences of a template, select Preferences from either the Template Manager or the Edit Template screens. For more information on entry view tracking, please see http://www.expressionengine.com/ user_guide/modules/channel/entry_tracking.html.
Chapter 8, Exercise 3 When extracting code that is repeated, you must decide on the best tool to use. In this case, since you use this repeated code in more than one template, Preload Text Replacements are automatically ruled out (since they can only be used in the template in which they are defined). Global variables are also not an option here because the code contains ExpressionEngine tags such as {exp:comment:form}. The choice, therefore, comes down to Snippets or Embedded Templates. Snippets are preferable if the code is identical, regardless of which template might be using it. Embedded Templates are useful if you need to pass in variables to account for small variances in the code. In this case, the {exp:comment:form} requires you to define the preview template. Since this is different for the FAQs channel versus the Photos channel, you will need to use an Embedded Template and pass in the preview template information as a variable. First, create a template called .comment in the includes template group. The preceding dot means that the template is hidden and cannot be accessed directly. The template type should be Web Page. In the .comment template, copy in all the code from photos/comment from Comments
all the way down to {/exp:comment:form}. Change the {exp:comment:form} line to read {my_template_group} and {my_single_entry_ template} as embedded variables rather than Preload Text Replacements: {exp:comment:form pre view="{embed:my_template_group}/{embed:my_single_entry_template}"}
Click Submit to save the new template. Now edit faqs/browse and photos/ comment and replace all the code from Comments
all the way down to {/ exp:comment:form} with the following: {embed="includes/.comment" my_template_group="{my_template_group}" my_single_entry_template="{my_single_entry_template}"}
[ 300 ]
Appendix B
Both the faq/browse and photos/comment templates have Preload Text Replacements for {my_template_group} and {my_single_entry_template}. This line simply passes these text replacements to the embedded template. In this way, even though both the Photos and FAQs channel are using the same chunk of code to display comments, if a member chooses to preview their comment, they are redirected to the appropriate template based on the channel. Visit both the FAQs and Photo sections of your website, and you should see no difference in the functionality of viewing, previewing, and posting comments. The only difference is that now your single entry templates contain a lot less code and if you ever want to change the comment form, you can do so in one template, instead of having to go through multiple templates. Reducing repetition in this way is a powerful feature of ExpressionEngine, and it makes websites easier to maintain.
[ 301 ]
Index Symbols 404 Page improving 140 404 Page not found 98 {exp:search:advanced_form} tag 235 .htaccess files allowing, to be used 291, 292 {site_url} variable 87
A Accessible Captcha extension 278 accessories 272, 273 add-ons, ExpressionEngine about 271 accessible Captcha extension 278 accessories 272, 273 add-on developers 275 backup module 278 Cartthrob module 279 channel images add-ons 279 channel images module/extension 279 custom system messages extension 279 extensions 273 field types 274 first timer extension 278 FoxEE module 279 image sizer plug-in 278 Low (Lodewijk Schutte) 277 MD detect page type plugin 278 modules 272 Newism (Leevi Graham) 276 nGen works 277 notable add-ons 278, 279 Pixel & Tonic 275
plugins 274, 275 resources, URL 271 search results module 279 Solspace 276 template variables accessory 278 third-party add-ons 275 types 271 advanced search form, Search module 235, 236 Agile Records website 37 Atom feed about 136 and RSS feed, differences 139 creating 139 setting up 136-139
B backup module 278 backups, ExpressionEngine 263-265 banned member group 155 Blacklist/Whitelist module 259 blank calendar template creating 179 Body field 46 build release 267
C caching 283 calendar blank calendar template, creating 179 calendar CSS template, creating 183, 184 creating 179-182 designing 173, 174 events, displaying 191-195 exercise 196
formatting, with CSS 183 solution 297 styles, adding to calendar CSS 184-187 weblog, creating 207 calendar CSS styles, adding to 184-186 calendar CSS template creating 183, 184 Calendar module, Solspace 276 calendar template blank calendar template, creating 210 blank calendar, creating 182 CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) 123 Cartthrob module 279 categories about 64 browsing page, distinguishing 132, 133 creating 108-111 data, organizing 129, 130 displaying, with entries 130, 131 related entries, displaying by 133, 134 categories, photo gallery channel creating 205, 206 category browsing page distinguishing 132, 133 channel categories 64 categories, creating 108-111 content, creating 75-77 creating 63 custom channel fields, creating 105-107 custom field group, creating 65 custom fields 64, 65 custom fields for event sponsors, creating 174, 175 custom statuses 64 designing 104, 105 events custom fields, creating 176, 177 event sponsors channel, creating 175, 176 example events, creating 177-179 first custom field, creating 66 Information Pages channel 45 new channel, creating 73, 74 new channel. creating 111, 112 News channel 45
setting up 174 templates, pointing to 82, 83 channel images module/extension 279 channel images, photo gallery add-ons 224 comments allowing, on entries 120 form, creating 125-128 previewing, by visitors 128, 129 spam, preventing 120-125 Constrain Proportions checkbox 49 contact form, Email module 241-243 content about 44 Body field 46 Constrain Proportions checkbox 49 Extended text field 48 Information Pages channel 45 new content, creating 45 News channel 45 selecting, from top menu 45 URL title 46 View Entry page 50 Write Mode 47 content management system (CMS) 7, 9 control panel, ExpressionEngine about 38 administrative control panel access 39 Corporate theme 44 Default Control Panel Theme 43 ExpressionEngine Info tab 39 Fruit theme 44 hide sidebar link 39 home icon 39 home page 39 logging into 29, 30 navigation 39 notepad 41 profile 39 Quick Links Manager link 42 Quick Links section 39 reveal sidebar 39 tab manager 40, 41 themes 42 website 39 CSS calendar, formatting with 183 custom field group
[ 304 ]
creating 65 custom fields about 64, 65 creating 66, 70, 71, 105-107 creating, for event sponsors 174, 175 options 72 custom fields, photo gallery channel creating 203-205 custom statuses 64 custom system messages extension 279
D data organizing, with categories 129, 130 Default Control Panel Theme 43 design, photo gallery changing 209, 210 single-entry page layout, creating 210 Devot-ee 275 Discussion Forum module 259 Duplicate an Existing Template Group option 53
E Ed & Eg 61, 62 Editors 155 Email module about 241 contact form, creating 241-243 tell-a-friend form, creating 244 tell-a-friend template, creating 244-247 embedded template 96-98 entries categories, displaying with 130, 131 editing, solution 293 limiting, solution 293 posting to channel, solution 293 events displaying, on calendar 191-194 solution 297, 298 events channel creating 177 events custom fields creating 176, 177 event sponsors custom fields, creating for 174, 175
event sponsors channel creating 175, 176 example events creating 177, 179 exercises solutions 293-301 ExpressionEngine 404 Page, improving 140 .htaccess files, allowing to be used 291, 292 about 9, 11 accessories 272, 273 add-ons 271 Agile Records website 37 assumptions 20 backups 263, 264, 265 business case 12 calendar 173 CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) 123 channel, designing 104, 105 control panel 38, 39 control panel, logging into 29, 30 database restores 266, 267 database, setting up 21, 22 documentation, URL 15 Email module 241 extensions 273 field types 274 file manager 200-203 files, downloading 22, 23 files, uploading 23, 24 image editing, features 221-223 installing, steps 24-28 Mailing List module 236 members, types 39 Moblog module 248 modules 272 official installation guide, URL 19 photo gallery channel, creating 203 photo gallery, designing 199, 200 phpMyAdmin 21 repetition, reducing 90, 91 requisites 20 resources, URL 16, 17 search box, adding to site 229, 230 Search module 228 [ 305 ]
technical case 12 templates, creating 209 templates 50 updating 19 upgrading 267 upgrading, steps 268-271 user-friendly URLs, creating 31 WampServer 21, 285 WampServer, downloading 286, 287 WampServer, installing 288, 289 wiki module 255 ExpressionEngine 2 15 ExpressionEngine database setting up 21, 22 ExpressionEngine documentation, URL 15 ExpressionEngine modules Blacklist/Whitelist 259 Discussion Forum 259 IP to Nation 260 Query 260 Referrer 260 ExpressionEngine modulesSimple Commerce 259 Statistics 260 ExpressionEngine, optimizing performance 281-283 spam 280, 281 ExpressionEngine page index.php 31 ExpressionEngine URLs index.php, hiding 32, 33 index.php, renaming 34, 35 Extended text field 48 extensions 273
F Facebook Connect module, Solspace 276 FancyBox setting up 187, 188 FAQ snippet 134-136 FAQ template creating 114-118 single-entry page, creating 118-120 field types, ExpressionEngine about 274 checkboxes 67
date 67 file 67 multi select 67 radio buttons 67 relationship 67 select dropdown 67 textarea 67 text input 67 file manager 200-203 first timer extension 278 FoxEE module 279 FreeForm module, Solspace 276 Friends module, Solspace 276
G guests member group 155
H hide sidebar link, ExpressionEngine control panel 39
I image editing features 221- 223 image sizer, photo gallery add-ons 223 image sizer plugin 278 includes, template group 78 index.php hiding, in ExpressionEngine URLs 32, 33 renaming, in ExpressionEngine URLs 34, 35 Information Pages channel 45 installing photo gallery 203 installing, ExpressionEngine files, downloading 22, 23 files, uploading 23, 24 steps 24-28 IP to Nation module 260
J jQuery module 173
[ 306 ]
L Low (Lodewijk Schutte) 277 Low NoSpam 277 Low Variables 277
M Mailing List module about 236 e-mails, sending 239, 240 mailing list, setting up 236, 237 member registration, allowing 238, 239 Make the index template in this group your site's home page? box 53 MAMP 285 Matrix 275 MD Detect Page Type URL 141 MD Detect Page Type plugin 278 member groups about 154 banned member group 155 Channel Assignment 159 Channel Posting Privileges 159 Comment Administration 159 configuring, options 155, 156 control panel access 158 Control Panel Email Privileges 159 creating, solution 296 custom member field, solution 296 editor member group, creating 155 guests member group 155 members member group 154 Module Access Privileges 159 new member group, creating 159 pending member group 154 site access 156 Template Editing Privileges 159 member-only content content, making visible to members 167-170 creating 166, 167 members creating 160 Editor Ed, logging in as 160-162 list 151, 152 member groups 154 member-only content, creating 166
new member, registering as 147-149 profile 149-151 templates, linking to 152-154 types 143, 144 with administrative control panel access 144 without administrative control panel access 144 membership designing 143 member groups 144, 154 member, list 151, 152 member, profile 149,-151 member templates, linking to 152-154 new member, registering as 147-149 preferences 144-147 members member group 154 menu, snippets creating 95, 96 Moblog e-mail, Moblog module sending 253, 254 Moblog module about 248 Moblog e-mail, sending 253, 254 setting up 248-252 template, setting up 252, 253 modules about 272 multiple-entry page content, adding 215-221 creating 213, 214 Multiple Site Manager 260
N Newism (Leevi Graham) NSM Addon Updater 276 NSM Better Meta 277 NSM TinyMCE 277 NSM Transplant 277 News channel 45 nGen works 277 no-results template 235 no-results template, Search module 234 notepad, control panel 41 NSM Addon Updater, Newism (Leevi Graham) 276
[ 307 ]
NSM Live Look, Newism (Leevi Graham 277 NSM TinyMCE, Newism (Leevi Graham) 277 NSM Transplant, Newism (Leevi Graham) 277
O official installation guide URL 19
P page load times reducing, techniques 282 pages adding 84, 85 creating, solution 294 second page, publishing 86, 87 second template, creating 88-90 Pages module URL 85 pending member group 154 photo gallery add-ons 223 advanced features 221 channel, creating 203 design, changing 209, 210 designing 199, 200 installing 203 photo gallerysolution 299 setting up 205 photo gallery, add-ons channel images 224 image sizer 223 photo gallery channel categories, creating 205, 206 creating 203, 207 custom fields, creating 203-205 photos, uploading 207-209 photos direct upload 208 uploading, to website 207 phpMyAdmin 21, 290 Pixel & Tonic about 275 Matrix 275 Playa field type 275
Wygwam 275 URL 200 Playa field type 275 plugins 274, 275 Pluralism 62 preload text replacements 91, 92 Publish page layout modifying 162-164 options, configuring 165
Q Query module 260 question set publishing 112, 113 Quick Links Manager, control panel 42
R Referrer module 260 repetition preload text replacements 91, 92 reducing, ways 90, 91 user-defined global variables 92, 93 resources ExpressionEngine documentation, URL 15 URL 17 restores, ExpressionEngine build release 267 database restores 266 releases, types 267 version release 267 RSS feed about 136 and Atom feed, differences 139 setting up 136-139
S search box Search module adding, to site 230 search box, Search module adding, to site 229 Search module advanced search 235 no-results template 234, 235 search results template, creating 231-233 search results module 279 [ 308 ]
setting up 252, 253 templates, ExpressionEngine about 10, 50 Access section 54 as files 99-101 content displaying, tags used 55-58 content, adding to multiple-entry page 215-221 creating 78-82, 290 Duplicate an Existing Template Group option 53 editing 54 group, creating 53, 54 index template 52, 55 Make the index template in this group your site's home page? box 53 multiple-entry page, creating 213, 214 pointing, to channel 82, 83 Preferences section 54 second template, creating 88 single-entry page, creating 210-213 tag 56 tag pair 57 Template Notes section 54 URL, relationship 52 URLs, relating to 51, 52 template variables accessory 278 themes, control panel corporate theme 44 Default Control Panel Theme 43 downloading 42 fruit theme 44 mobile theme 43 switching 43
search results template, Search module creating 231-233 Simple Commerce module 259 single-entry page creating 210-213 single-entry page, FAQ template creating 118-120 solution 299 single-entry page layout, photo gallery creating 210 photo comments, displaying 213 single-entry template creating 188-191 snippets about 93-95 menu, creating 95, 96 Solspace about 276 Calendar module 276 Facebook Connect module 276 FreeForm module 276 Friends module 276 Super Search module 276 Tag module 276 User module 276 solutions to exercises 293-301 spam 280, 281 Statistics module 260 styles adding, to calendar CSS 184-186 Super Search module, Solspace 276
T tab manager, control panel Template Manager screen 40, 41 Tag module, Solspace 276 tag pair 57 tags about 10, 56 used, to display content in templates 55-58 tell-a-friend form, Email module creating 244 tell-a-friend template, Email module creating 244-247 template, Moblog module
U upgrading, ExpressionEngine steps 268-71 URL title 46 user-defined global variables 92, 93 user-friendly URLs, ExpressionEngine creating 31 index.php, hiding 32, 33 index.php, renaming 34, 35 User module, Solspace 276
[ 309 ]
V version release 267 View Entry page 50 visitors allowing, to preview comments 128, 129
W WampServer about 285 downloading 286, 287 home page, URL 290 installing 288, 289 Localhost 290 package 286 using 289 welcome page, deleting 290 www directory 290 WampServer, package AMP environment 286 phpMyAdmin 286 website converting into ExpressionEngine, approaches 62, 63 wiki module about 255 wiki, setting up 255, 256 wiki, working 257-259 Write Mode 47 Wygwam 275
X XAMPP 285
[ 310 ]
Thank you for buying Building Websites with ExpressionEngine 2
About Packt Publishing
Packt, pronounced 'packed', published its first book "Mastering phpMyAdmin for Effective MySQL Management" in April 2004 and subsequently continued to specialize in publishing highly focused books on specific technologies and solutions. Our books and publications share the experiences of your fellow IT professionals in adapting and customizing today's systems, applications, and frameworks. Our solution based books give you the knowledge and power to customize the software and technologies you're using to get the job done. Packt books are more specific and less general than the IT books you have seen in the past. Our unique business model allows us to bring you more focused information, giving you more of what you need to know, and less of what you don't. Packt is a modern, yet unique publishing company, which focuses on producing quality, cutting-edge books for communities of developers, administrators, and newbies alike. For more information, please visit our website: www.packtpub.com.
Writing for Packt
We welcome all inquiries from people who are interested in authoring. Book proposals should be sent to author@packtpub.com. If your book idea is still at an early stage and you would like to discuss it first before writing a formal book proposal, contact us; one of our commissioning editors will get in touch with you. We're not just looking for published authors; if you have strong technical skills but no writing experience, our experienced editors can help you develop a writing career, or simply get some additional reward for your expertise.
CodeIgniter 1.7 Professional Development ISBN: 978-1-849510-90-5
Paperback: 300 pages
Become a CodeIgniter expert with professional tools, techniques and extended libraries 1.
Learn expert CodeIgniter techniques and move beyond the realms of the User Guide
2.
Create mini-applications that teach you a technique and allow you to easily build extras on top of them
3.
Create CodeIgniter Libraries to minimize code bloat and allow for easy transitions across multiple projects
CodeIgniter 1.7 ISBN: 978-1-847199-48-5
Paperback: 300 pages
Improve your PHP coding productivity with the free compact open-source MVC CodeIgniter framework! 1.
Clear, structured tutorial on working with CodeIgniter for rapid PHP application development
2.
Careful explanation of the basic concepts of CodeIgniter and its MVC architecture
3.
Use CodeIgniter with databases, HTML forms, files, images, sessions, and email
4.
Full of ideas and examples with instructions making it ideal for beginners to CodeIgniter
Please check www.PacktPub.com for information on our titles
jQuery 1.4 Reference Guide ISBN: 978-1-849510-04-2
Paperback: 336 pages
A comprehensive exploration of the popular JavaScript library 1.
Quickly look up features of the jQuery library
2.
Step through each function, method, and selector expression in the jQuery library with an easy-to-follow approach
3.
Understand the anatomy of a jQuery script
4.
Write your own plug-ins using jQuery's powerful plug-in architecture
Drupal 6 Content Administration ISBN: 978-1-847198-56-3
Paperback: 196 pages
Maintain, add to, and edit content of your Drupal site with ease 1.
Keep your Drupal site up to date: easily edit, add to, and maintain your site's content, even if you've never used Drupal before!
2.
Covers the full range of content that you might want on your site: richly formatted text, images, videos, as well as blog posts, calendar events, and more
3.
Get to grips with managing users, slaying spam, and other activities that will help you maintain a content-rich site
4.
Concise, targeted information with easy-tofollow hands-on examples
Please check www.PacktPub.com for information on our titles
Recommend Documents
Building Websites with ExpressionEngine 2
A step-by-step guide to ExpressionEngine: the web-publishing system used by ...
Building Websites with ExpressionEngine 2
A step-by-step guide to ExpressionEngine: the web-publishing system used by ...
Building Websites with XOOPS A step-by-step Tutorial
Get your XOOPS website up fast using this easy-to-follow guide
S...
Building Websites with Joomla! A step by step tutorial to getting your Joomla! CMS website up fast
Hagen Graf
BIRMING...
Building Websites with Joomla! A step by step tutorial to getting your Joomla! CMS website up fast
Hagen Graf
BIRMING...
Building Websites with XOOPS A step-by-step Tutorial
Get your XOOPS website up fast using this easy-to-follow guide
S...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Building Websites with PHP-Nuke
Douglas Paterson
BIRMINGHAM - MUMBAI
Building Websites with PHP-Nuke
Copyright © 2...
Sign In
Our partners will collect data and use cookies for ad personalization and measurement. Learn how we and our ad partner Google, collect and use data. Agree & close
{title}
<strong>Q: <em>{faqs_question}
<strong>A: {faqs_answer}
[ 119 ]
Creating a Fully-Equipped Channel {/exp:channel:entries}
Note the use of the path variable to provide a link back to the index template of the faqs template group. If you wanted a link to a template that was not index, you would have to write it as: {path=template_ group/template}. The difference between the permalink variable used to link to the single-entry page and the path variable used to link back is that the permalink variable automatically adds the URL Title of the entry to the template specified (so you are taken to the URL specific to the entry), whereas the path variable does no such thing (it simply takes you to the template group and template specified).
You now have a FAQs page that displays all your faqs (with built-in pagination once you post enough entries). You can also click on individual questions to see the answer. The next step is to add some user interactivity to the single-entry page by allowing visitors to leave comments or add their own suggestions to each question.
Allowing comments on your entries
Comments are one of the easiest ways for visitors to interact with your site. They are also an easy way to attract spammers, who will be glad to leave hundreds of comments linking to websites of dubious quality. Luckily, ExpressionEngine includes features designed to prevent abuse.
Preventing comment spam
1. Comment preferences are set on a per-channel basis, allowing you to have different preferences for different channels (although when you create a new channel, you can copy the preferences from an existing channel to make things simpler). Go to Admin | Channel Administration | Channels and select Edit Preferences for the FAQs channel. [ 120 ]
Chapter 5
2. Here are all the aspects of the channel that you can fine-tune, organized into expandable groups. The General Channel Preferences were set when you created the channel, and include the channel name and short name.
3. Click on Path Settings. The path settings are the URLs that are unique to this channel. When creating links in your templates, ExpressionEngine will use these settings to know what URL to link to. Set your Channel URL to http://localhost/faqs and set your Comment Page URL and Search Results URL both to http://localhost/faqs/browse. You have not yet created an RSS template, but you can set your RSS Feed URL to be http:// localhost/faqs/rss in anticipation. The Ping Return URL does not apply to this channel.
When the Live Look Template is set, you will see a new Live Look link after publishing a new entry, as well as a new View link on the Content | Edit page. When you click one of these links, you will be taken to the livelook template to see the entry. A live-look template is coded exactly like an ordinary single-entry page template, and although you can define your single-entry template to be your live-look template, the true power comes into play when you define a live-look template that displays entries that would not be visible in your single-entry page template (either because they are future-dated or because they do not have an open status). This allows you to draft an entry with a closed status, for example, and view what it will look like on your website before you publish it with an open status.
[ 121 ]
Creating a Fully-Equipped Channel
4. The Administrative Preferences sets up defaults for each entry. For example, if you know the channel does not have comments, instead of having to click No to Allow Comments on each entry, you can set the default for every new entry to be no here (leave it set to Yes right now). The field for the search excerpt allows you to define which custom field is displayed when a member searches your site—the excerpt will automatically strip out any HTML formatting. For now, leave this set to Question. 5. The Channel Posting Preferences determines what to do with URLs inside a channel entry—you can either automatically link to them or leave them as plain text. Since only trusted people (such as yourself, Ed & Eg) will be able to post to this channel, you can Allow ALL HTML and say Yes to allowing images as well as to converting URLs into links. If your channel will involve lots of example HTML code, you could Convert HTML into character entities, meaning that any HTML entered as part of an entry will display on screen as-is and not be interpreted by the browser. At this time, no changes are needed. 6. Next, click on Versioning Preferences and set Enable Entry Versioning to Yes. By doing this, you can keep old versions of a channel entry saved. This is useful as it provides a quick undo feature for edits which were made erroneously. Enabling this option creates a new Revisions tab on your channel Publish page where you can load previous revisions. This option is not a substitute for doing a full database backup at regular intervals. [ 122 ]
Chapter 5
7. Select Notification Preferences. These preferences allow you to set up individuals to receive e-mails whenever a new entry or comment is posted. Setting this is essential if you require a moderator to approve all comments but can also be useful if you do not moderate your comments, as a means to monitor comments for comment spam. If you are using a localhost environment, outgoing e-mails may not work. So for now, leave all the notification options set to No. 8. Select Comment Posting Preferences. This is where you can either lock down or open up who can post comments and how many hoops they have to jump through in order to do so. Right now, say Yes to allow comments and No to requiring membership in order to post comments. As you are not requiring membership, say Yes to enabling a CAPTCHA for comment posting and say Yes to requiring an e-mail address to be entered when a reader tries to post a comment, but say No to moderating comments. Comment moderation means that an administrator, such as you, must approve every comment before it actually appears on your website. CAPTCHA stands for a Completely Automated Public Turing test to tell Computers and Humans Apart and is a puzzle that is easy for a human to solve, but not easy for a computer to solve. It is designed to filter out real people posting comments from automated scripts that are posting comment spam. ExpressionEngine's CAPTCHA technology relies on an image of letters with a background that makes it difficult for a computer to identify the letters. The person submitting the comment must type in the letters from the image correctly in order to post their comment. The downside to using an image in CAPTCHA technology is that it is not very accessible for visually-impaired visitors who might be relying on screen-readers to navigate your website. There are add-ons that provide a solution to this, such as Accessible Captcha (available at http://devotee.com/add-ons/extensions/accessible-captcha/). This addon changes the graphic to a user-defined question and answer, such as 2+2. A human could easily answer 4, but an automated spam program would not be able to do so. Search for CAPTCHA at http://devotee.com/ for other add-ons [ 123 ]
Creating a Fully-Equipped Channel
9. Leave the Maximum number of characters allowed in comments at 5,000, but set a comment re-submission time interval of 30 seconds. This option prevents an automated script from submitting more than one comment every 30 seconds. It can be useful as a deterrent against comment spam (especially if you are not moderating your comments or using CAPTCHA technology). Leave the comment expiration setting at 0 (meaning comments do not expire). If desired, you can use this setting to stop accepting comments on entries after a certain number of days. This can be useful to reduce the number of places on your website where comment spam can be posted. For the Comment Text Formatting, select XHTML but Allow only safe HTML. This means that formatting HTML, such as <strong> and <em>, will work, but more complex HTML will be rendered in plain text rather than being interpreted by a browser (thereby preventing malicious code being executed on your website). Do not allow image URLs in comments and do not automatically turn URLs and e-mail addresses into links (these options discourage spammers because their comments do not become links that could drive traffic to their website).
[ 124 ]
Chapter 5
10. Finally, the Publish Page Customization allows you to set a default entry title or URL title prefix that will apply to all new entries. This can be useful if you want all your entries to have the same prefix. Right now, leave these blank. Also, leave the Display Rich Formatting Buttons option set to Yes. Setting this to No would turn off the HTML formatting buttons (such as bold and italics) on all your custom fields, regardless of each individual custom field setting. 11. Click on Update and Finished to save all your settings. The settings you have just seen are useful in combating comment spam, especially from automated scripts, and it's recommended to consider them carefully before enabling comments. Using some combination of either requiring membership to post comments, enabling CAPTCHA technology, and/or enabling comment moderation along with setting an administrator up to receive notifications of new comments allows you to minimize comment spam as much as possible and quickly identify it when it does occur. You are now ready to create a form to accept comments. More information on all of these preferences can be found in the ExpressionEngine documentation at http://expressionengine. com/user_guide/cp/admin/content_admin/channel_edit_ preferences.html.
Creating a comment form
The first step in accepting comments is to create a form where visitors can write and submit their comments. Comments have to be tied to a specific channel entry, and therefore, the comment form can only appear on single-entry pages. Therefore, you will add your comment form to the faqs/browse template. 1. Open the browse template in the faqs template group for editing and type in the following code after {/exp:channel:entries}. This code displays the comments that other people have submitted. The title of the section is Comments.
Comments
{exp:comment:entries} {if comments}{comment}
Posted by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/if} [ 125 ]
Creating a Fully-Equipped Channel {if no_results}
There are no comments at this time - be the first to share your thoughts!
{/if} {/exp:comment:entries}2. Next, add the code to create a comment form. Add this after the {/ exp:comment:entries} tag. First, this creates the fields for the visitors name and e-mail address. Since you would already have the name and e-mail address of any member who is logged in, you only need to ask for this information if the visitor is logged out. {exp:comment:form}
Post Your Own Comment
{if logged_out}
{/if}
{if logged_out}
{/if}
[ 126 ]
Chapter 5
{/if}
{/exp:comment:form}
You can also add fields for a visitor's location or website. Use the same format as the email field in the previous code, but replace the word email with either location or url.
3. Now try posting your first comment. In order to see the website as a visitor will see it, log out of the control panel by clicking on Logout at the top-right and confirming you want to log out. (Closing the control panel without logging out will leave you logged in). Now visit http://localhost/faqs and click on a question. 4. Fill in your name, e-mail, type in a comment, and leave the box to remember your personal information, and the box to notify you of follow-up comments unchecked. If you check Remember my Personal Information, then the next time you see a comment form, your name and e-mail address will be pre-filled. Note that if you are logged in when you visit this page (for example, if you were previously logged into the control panel), then you will not see the fields for the name or e-mail and you will not see the CAPTCHA.
5. Enter the CAPTCHA word. Notice that each time you refresh the page, a different image with a different word is shown for your CAPTCHA. When you have completely filled in the comment form, click Submit.
[ 127 ]
Creating a Fully-Equipped Channel
Note that currently the Preview button will not work as you have not yet set up a preview template. If you are using a localhost environment, posting comments can be more difficult than when using an installation on a real website. If you are unable to post comments in the localhost environment, try changing the setting Require IP Address and User Agent for Login to No. This setting can be found in the control panel under Admin | Security and Privacy | Security and Sessions.
6. The page will auto-refresh, and you should now see the comment that you submitted.
Allowing visitors to preview comments
One final aspect of comments that hasn't yet been covered is the ability to preview the comment before publishing. You may have noticed the Preview button on the comment form that does not work yet. 1. First, modify the faqs/browse template to include the following code after the {/exp:comment:entries} and before the {exp:comment:form} line. Notice how the code is almost exactly the same as the code to display an actual comment, except that you are using the {exp:comment:preview} tag instead of the {exp:comment:entries} tag. This means that the look and feel of the previewed comment is identical to how it would look if it were an actual comment. {exp:comment:preview}
{comment}
Being previewed by {name} on {comment_date format='%m/%d'} at {comment_date format='%h:%i %A'}
{/exp:comment:preview}
[ 128 ]
Chapter 5
2. Next, change the line {exp:comment:form} to include the preview parameter as follows. This parameter tells the form which template to load if the preview button is clicked. {exp:comment:form preview="{my_template_group}/{my_single_entry_template}"}
3. Now go to the FAQs page, type in a comment, and click Preview instead of Submit. You can see that the comment appears and looks exactly as if you had submitted it, except that instead of Posted by in the footnote, it says Being previewed by. You can keep editing the text and clicking on Preview as often as you like.
Organizing your data with categories
Although you have created custom categories and assigned your entries to some of your categories, you haven't yet used categories to help visitors browse the FAQs. You will now do this, but first set ExpressionEngine to use category names rather than ID numbers in the URL. This means that instead of category browsing pages having a URL such as http://localhost/faqs/C8, the category URL will be more like http://localhost/faqs/category/getting_married 1. In the control panel, go to Admin, Channel Administration, and then Global Preferences.
[ 129 ]
Creating a Fully-Equipped Channel
2. Say Yes to using category URL titles in links. Leave the Category URL Indicator as category. (If you do change this, bear in mind that whatever word you use here becomes a reserved word and cannot be used as a template name).
3. While you are on this page, also select No to auto-assigning category parents and click on Submit. Later in the chapter, you will use categories to show visitors who are viewing one question other related questions from the same categories. If all questions have the same two parent categories autoassigned, the related questions that are displayed are going to be less tightly coupled to the question being viewed.
Displaying categories with your entries
To encourage visitors to browse by category, it makes sense to display the categories that each entry belongs to underneath the questions on the faqs/index page. For this, you will use the channel {categories} tag, which allows you to list the categories, along with the {comment_total} tag to show how many comments each entry has and the {comment_url_title_auto_path} tag to link to your single-entry page for comments. Note that the {comment_url_title_auto_path} tag autogenerates the URL to your category template, as defined in Admin | Channel Administration | Channels, under Edit Preferences for the FAQs channel, then under Path Settings. The option Comment Page URL should be set to http://localhost/faqs/browse.
1. Edit the faqs/index page and add the following code underneath the Read the answer here! permalink and above the {paginate} line.
<strong>Categories: [ 130 ]
Chapter 5 {categories backspace="3"}{category_name} | {/categories}Comments ({comment_total})
Everything between the {categories} opening tag and the {/ categories} closing tag is repeated for each category that the channel entry is assigned to. In this code, there is a vertical bar (|) after the category name and before the next category name to separate the categories. To prevent this vertical bar appearing after the last category, we use the backspace parameter. This parameter removes the specified number of characters from the end of our code after the last category name only (in this case, the | and the surrounding two spaces). This parameter is specifically designed to remove separators or other code that it makes sense to have between categories, but not after the last category.
2. Click on Update and Finished and then visit the FAQs page. You should now see underneath each answer—a piped list of categories that the entry belongs to. Clicking on one of the categories takes you to a category browsing page where you can see other entries that have the same category. At the moment, given that you only have two entries right now, namely, your category browsing pages and your main multiple-entry page, it will not be substantially different unless you pick a category that is unique to just one entry. Once the number of entries starts getting higher, browsing by category will be a much faster way of finding related questions than simply browsing through all the questions.
[ 131 ]
Creating a Fully-Equipped Channel
Distinguishing your category browsing page
Currently your category browsing page and your main multiple-entry page look identical—they have the same page title and the same introduction. Within the faqs/ index template, you can tell if you are on the main multiple-entry page or a category browsing page by looking at the URL. If segment_2 (the part of the URL after faqs) is category, you are on a category browsing page. You can, therefore, use this condition to display slightly different content accordingly. 1. First update the HTML title (which appears on the title bar of the window). To do this, edit the faqs/index template and replace the
2. Next, you can replace the code appearing after
Questions About {category_name}
{category_description}
{/exp:channel:category_heading} {if:else}Frequently Asked Questions
<strong>Ed & Eg have been assisting people for over 30 years. If you have a financial question that's burning a hole in your pocket, email us at [email protected] and we will answer it here!
{/if}[ 132 ]
Chapter 5
This code says that if you are on a category-browsing page, then the page heading should be Questions About {category_name} and the introductory text should be the category description. To edit the category descriptions, you have to edit the individual category in question. Go to Admin | Channel Administration | Categories, then click on Add/Edit Categories for the FAQ Categories group, and edit the category you want.
Now your category browsing pages look markedly different to your main multipleentry browsing page. However, this setup still requires your visitors to deliberately click on a category that interests them in order to find other FAQs that might be of interest. A different approach would be to display, at the end of the single-entry page, a list of other FAQs that have the same category (and therefore, are likely to be of interest to the visitor). In this way, the visitor is encouraged to keep browsing without ever realizing they are using categories.
Displaying related entries by category
To display other entries in the same category on your single-entry page, you need to make use of the ExpressionEngine parameter related_categories_mode. This looks at the URL of your single-entry page and then brings back the data of other entries that are in the same category as the page you are on. 1. Edit the faqs/browse template. Insert the following code after the line {/ exp:comment:form}:
Other Questions Like This
{exp:channel:entries channel="{my_channel}" limit="5" related_categories_mode="yes" custom_fields="yes" orderby="random"} {if no_results}
There are no questions like this currently – check back soon though...we're always adding more!
{/if}<strong>Q: <em>{faqs_question}
[ 133 ]
Creating a Fully-Equipped Channel <strong>A: Read the answer here!
Here you are bringing back up to five entries that are in the same categories as the question being viewed. To ensure variety, the entries are displayed in a random order, meaning that if you have more than five entries, no two sets of related questions will be the same.
2. If you now visit http://localhost/faqs and click on an entry, you should see a link to the entry you did not click on at the bottom of the single-entry page. If you do not see a link to your entry, it means the entry you are viewing is the only one in that category.
Now, as Ed & Eg go through and start adding hundreds of questions and answers, ExpressionEngine will dynamically organize the content. In this way, you may catch a visitor's eye with a question they want to know the answer to, and then keep them hooked by dynamically showing them other questions that are similar to the question they initially clicked on.
The FAQ snippet
The final step in getting visitors into the Frequently Asked Questions section of the website is to display Frequently Asked Questions in the widebar at the bottom of each page. Currently, there are two, static FAQs that are displayed in the widebar. In this section, you will update the widebar to display three random entries from the FAQs channel. To do this, it makes sense to use a snippet. Why a snippet? If you recall from Chapter 4, a snippet is used when you want to reduce repetition. In this case, since the widebar will be used on lots of templates, it is a great candidate for becoming a snippet. Why not a global variable? Remember that global variables do not support ExpressionEngine tags. Since you are planning to show data from an ExpressionEngine channel, a snippet is required. [ 134 ]
Chapter 5
In this section, you are choosing to display three random entries in your widebar. If you wanted more control over which FAQs were displayed at the bottom of every page, you could manually set the status of three entries to a custom status such as Featured (instead of open). Then, in your snippet, you could specify in the {exp:channel:entries} tag that you only want to include entries where status="Featured". You would also have to add a parameter status="open|featured" to the {exp:channel:entries} tags in all your other templates that use the FAQs channel. ExpressionEngine does not display entries that do not have a status of open, by default.
1. In the control panel, click on Design, then Templates, and finally Snippets. Then click on Create a New Snippet. 2. Call the snippet website_faqs and type in the following code to display your random entries. Note the use of the switch parameter—this essentially says that for the first entry, use colA as the div id. The second entry should use colB and the third entry should use colC. If you were displaying more than three entries, the fourth entry would use colA again, which, in this case, does not make sense to do.
Frequently Asked Question
{faqs_question} Find out…
Remember that ExpressionEngine uses the URL to dynamically determine whether you are on a single-entry page or a multiple-entry page. (If the URL has the url_title of a specific entry after the template name, then ExpressionEngine recognizes that you are on single-entry page and will only display content from that entry). This means that you cannot display content from another entry (or another channel) on a single-entry page unless you tell ExpressionEngine to ignore the fact that you are on a single-entry page. This is what the dynamic="off" parameter does.
[ 135 ]
Creating a Fully-Equipped Channel
3. Next, edit all your existing templates that show the widebar (includes/. website_page, includes/404, faqs/index, and faqs/browse) and replace the widebar code with a reference to this snippet instead. For each template, delete all the code including and between
Your work with the FAQ page is almost complete. The next step is to provide a way for visitors to be notified about new FAQs, without having to constantly re-visit your website. For this, you will use a feed.
Setting up an RSS or Atom feed
RSS or Atom feeds are an alternative way of allowing visitors to keep up-to-date on your website. Essentially, the visitor subscribes to your feed through their e-mail software, browser, or other news readers, and then they get notified when you post new entries. This saves them from having to periodically revisit your website to see if there is new content or not. Having a feed available can make the difference between a visitor being someone who visited your website and liked it (but does not come back) and someone who visited your website and now reads every new post. When building a feed, the easiest approach is to start with a pre-built ExpressionEngine feed template. This will take care of the top portion of the feed (containing meta-information such as the date, the URL of the entry, and so forth), meaning you only have to make a few customizations so that the feed displays the content from your custom fields. An RSS 2.0 template can be found at http://expressionengine.com/wiki/RSS_ Template_for_EE2/. However, since Agile Records comes with both an RSS 2.0
and an Atom 1.0 template, you can also base your template on theirs. If you did not install Agile Records, using the template from the wiki will have the same results. 1. From the Template Manager, select the FAQs template group and create a new template called rss. The template type should be RSS Page and you should duplicate a template, namely, the news/rss template. Click on Create and Edit. [ 136 ]
Chapter 5
2. On the first line, change {exp:rss:feed channel="news"} to {exp:rss:feed channel="faqs"}. (If you are starting from the wiki template, then the channel on the first line is howto, but should still be changed to faqs). 3. About half-way down, you will see a familiar {exp:channel:entries} tag. In this tag, change news to faqs. The limit parameter limits the number of results to 10 and the disable parameter tells ExpressionEngine not to query the database for member data (reducing the amount of data that is queried). Finally, every time a news-reader polls your website for new entries, it provides the last date/time that it checked. The dynamic_start parameter tells ExpressionEngine to only return entries (if any) that have been posted since that particular last date/time. {exp:channel:entries channel="faqs" limit="10" dynamic_start="on" disable="member_data"}
4. Even further down, look for the XML tag <description>. On that line, you will see an ExpressionEngine tag {news_body} (or {body} if you are starting from the wiki template). This is a custom field, so you should change this line to use your own custom field—{faqs_question}. You could display both the question and the answer in the feed. However, in this example, you are going to display only the question, followed by a link to the answer page (using code you have already used on your multiple-entry page). <description>{faqs_question}]]>
[ 137 ]
Creating a Fully-Equipped Channel
5. Click on Update and Finished. If you now browse to the RSS template (http://localhost/faqs/rss), your browser will likely recognize it as an RSS feed.
If you get an error, you may not have set the template to be an RSS Page. Check the template preferences for your RSS template.
6. Now all you have to do is link to the feed from your FAQs page so that people know it is there. Edit the faqs/index template and add the following after the introductory paragraph and before the {/if}:
Don't forget to subscribe to our RSS feed to stay up-to-date with new FAQs as they are posted.
[ 138 ]
Chapter 5
You can now use your favorite RSS reader to view the content. If you do not have a favorite RSS reader, your e-mail client will likely already support it. For example, Mozilla Thunderbird 1.0 and greater and Outlook 2007 and greater, both have builtin support for feeds. Alternatively, Google Reader is a popular and free web-based alternative (http://www.google.com/reader). If you are following along in a localhost environment, then web-based feed readers will not be able to access your feed.
The instructions for creating an Atom feed are almost identical to those for creating an RSS feed: 1. Create a template faqs/atom and duplicate the news/atom template from the Agile Records example site into your new template. (The template type should still be RSS Page). 2. Change the feed channel on the first line to faqs. {exp:rss:feed channel="faqs"}
3. Change the channel in the exp:channel:entries tag to faqs. {exp:channel:entries channel="faqs" limit="15" dynamic_start="on" disable="member_data"}
4. Unique to Atom feeds, change the scheme to point to the single-entry template where the entry is: scheme="{path=faqs/browse}"
5. Change the custom fields inside the CDATA[] tag to reflect the content that you want to display inside your feed:
6. Save your template and verify that you can subscribe to your new feed (http://localhost/faqs/atom). What is the difference between an RSS and an Atom feed? RSS 2.0 is the older and more established feed. Atom 1.0 was designed as a modern alternative to RSS. For practical purposes, news readers can read either feed, so which one you choose is up to you or you can use both types of feed and let your visitors pick whichever they prefer.
[ 139 ]
Creating a Fully-Equipped Channel
Improving your 404 Page
In the last chapter, you created a 404 Page for your site. ExpressionEngine allows for great flexibility with URLs and the downside of that is that invalid URLs can often return valid content. As an example, if you type in an entry URL that does not exist (such as http:// localhost/faqs/browse/ihatetoast, you see an actual page with content instead of your 404 template. This can be confusing to visitors if they mistype the URL. Luckily, there are options available to fix this. ExpressionEngine comes with a redirect tag that you can use to redirect visitors to another template, based on a conditional. Typically, the syntax of this tag would be {redirect="template_group/template"}. However, when redirecting to a 404 Page, rather than redirecting to "includes/404", you can redirect to "404". This will return the template that you defined in chapter 4 as your 404 template (if you have not yet defined this template, you can do so in Design | Templates | Global Preferences). The difference between a redirect to the template directly and a redirect to 404 is that, if you redirect to just 404, the redirect also includes 404 Page headers, meaning that search engines visiting that URL will recognize it as invalid and will not index it. 1. First edit the browse template of the faqs template group. Change the HTML
3. Now visit http://localhost/faqs/browse/ihatetoast and you can see that your 404 template is now returned. 4. You can go one step further with your redirect. For example, you know that there should not be a segment in the URL after the URL of the entry (that is, http://localhost/faqs/browse/living_paycheck_to_paycheck is a valid URL, but http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus is not). Right now, the hippopotamus URL will still display your entry. If you add the following code to your faqs/browse template, immediately after the code you added above, it will cause a 404 redirect to take place instead: [ 140 ]
Chapter 5 {if segment_4!=""} {redirect="404"} {/if}
5. Now visit isit http://localhost/faqs/browse/living_paycheck_to_ paycheck/hippopotamus and you will see a 404 Page instead. What about your multiple-entry page? For example, a URL of http://localhost/ faqs/rubbish should return a 404 Page, but it currently displays your multiple-
entry page. If you were not using categories or pagination, you could safely say that there should not be a segment 2, and if there is, redirect to 404. However, category URLs (such as http://localhost/faqs/category/debt) also use the faqs/index template, so you would need to build in logic to say that if segment 2 is category, then do not redirect to a 404. However, this logic gets more complicated. Once you have more than 10 entries, your entries will paginate over different pages, and the URLs for the pages will also be category 2 segments (for example, http://localhost/faqs/P0). Entries can also be archived by date. For example, a URL of http://localhost/ faqs/2011/11 will only display entries from November 2011. If you are organizing your entries by date in this way, then any year could appear in segment 2. One solution is to use an add-on such as MD Detect Page Type (http://devot-ee. com/add-ons/plugins/md-detect-page-type/), which makes it easy to tell if
you are on a category page, paginated page, or archive page, and therefore makes it much easier to build a conditional statement to display a 404 Page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. You have suddenly started getting spam comments on old FAQs. Set the comments on the FAQ channel so that after 60 days, no more comments are accepted. 2. Your FAQs currently have no indication of when they were posted or who posted them. On both the single-entry and multiple-entry pages, modify the question to include who posted the question and the date of the post (although this is something that might not make sense on the FAQs channel, in most situations where articles are being posted regularly, displaying the date of the post is a common requirement). to include the date of the post. [ 141 ]
Creating a Fully-Equipped Channel
3. Update the snippet that displays the three FAQs on every page of your website so that instead of displaying three random entries, it displays three featured entries (based on a custom status of "Featured").
Summary
In this chapter, you got more practice in using custom fields, channels, and templates. You also got introduced to categories, comments, and feeds. In the next chapter, you will get an in-depth look at the built-in membership module, including registering members, managing members, setting member privileges and permissions, and creating parts of your website that only members can see. The key points to remember after working through this chapter: •
You used a FAQ example in this chapter. However, all the functionality covered in this chapter would equally apply to any dynamic content that your site might have—whether it's a blog, news articles, recipes, or the products you sell.
•
ExpressionEngine contains many options to help you control and filter comments. You can use CAPTCHAs, you can moderate all comments, and you can require membership for comments. You can also set it up so that you get e-mailed when new comments are posted.
•
Feeds are a great option to encourage repeat visitors—they are easy to set up and give people an alternative way to keep up with your website.
•
Preload Text Replacements, Global Variables, Snippets, and Embedded Templates are incredibly useful—it is definitely worth becoming comfortable using them.
•
Conditional {if} statements are also a powerful tool, allowing you to account for different situations in a single template such as redirecting to a 404 Page if there are no entries or displaying category-specific information if the URL segment is a category.
[ 142 ]
Members You have now used ExpressionEngine to build a fully-functional website for Ed & Eg. So far, however, you are the only one who has logged into ExpressionEngine on your website and the only one who has been making any changes. Now is a good time to explore the member functionality of ExpressionEngine. The Freelancer license does not include member management, so this chapter will not apply. For a complete list of what the Freelancer license includes, please see http://expressionengine.com/overview/pricing. In this chapter, you will: •
Allow visitors to register on your website and see what they see
•
Create a member group for Ed & Eg, so they can log into the control panel and publish and edit entries (but not edit template code or change administrative options like you can)
•
Use conditional statements to create content that only members can see
First, however, it makes sense to review how membership management works in ExpressionEngine and what all your options are.
Designing your membership ExpressionEngine allows two types of members:
1. Members who can log in to your website, but not into the administrative control panel. These members can see any content that you have coded in your templates as member-only as well as perform any actions that you have set to require membership (such as post comments).
Members
2. Members who can log into your website and also the administrative control panel. Depending on the permissions you give these members, they may be able to complete tasks such as creating or modifying channel content, creating or modifying templates, or changing global settings. If you have an ExpressionEngine-powered website, allowing members is not a requirement. If you do not intend to support members on your website, it is recommended to turn off new member registrations completely (the first option under Members | Preferences in the main menu). Membership in ExpressionEngine is based on member groups, which are what determine the permissions a member has. Each member can only be in a single member group. For members with administrative control panel access, ExpressionEngine offers a huge amount of granularity over what the members can see and do inside the control panel. You can define which channels they can post to (if any), which template groups they can modify (if any), and much more. For members without administrative control panel access, ExpressionEngine offers a member control panel, where members can post a profile, see other members' profiles, as well as send an e-mail or a private message to another member. As with the administrative control panel, you have control over what different member groups can actually do. To make joining your website attractive, you can make some or all of your content member-only by using conditional statements in your templates. You can look to see if a member is logged in and then display different content based on that, or you can display different content to different member groups. In this chapter, you will create a new member group for Ed & Eg that allows them to edit and post channel entries, but that does not allow them to edit templates. Then, to encourage members to join your website, you will update the FAQs channel so that some FAQs are viewable only to members. First, though, you will explore the membership preferences, and then explore the member profile screens as if you were a new member.
Membership preferences
There are many options you can set for your members on a global level that will impact their experience on your site. 1. First, log in to the control panel (http://localhost/admin.php) with your administrator login. [ 144 ]
Chapter 6
Note that you are also assigned to a member group—the Super Admins group. This group gives you access to everything. ExpressionEngine also comes with a Members member group, which does not have administrative control panel access, but can do everything in the member control panel. The permissions of the Members member group can be modified in Members | Member Groups, but the Super Admins group cannot be altered.
2. From the top menu, select Members and then select Preferences. 3. The first section is called General Configuration. Here, you can set whether you want members to be able to register themselves or not and the hoops they have to jump through in order to register. For example, you can require member account activation. If you do not require this, then any new members automatically become assigned to the Default Member Group (which is Members, but can be changed further down). If you require activation (either by an administrator or by requiring the new member to click on a link in their e-mail), then members will be placed into a Pending member group until they are actually activated (by selecting Members | Activate Pending from the main menu). For now, if you are using a localhost environment, say Yes to allow new members and select No activation required (since a localhost environment does not include an e-mail server and so cannot send activation e-mails). If you are following along on an actual website, it is recommended that you require activation of some kind.
4. Further down, you can require new members to accept a terms of service (if you say No, the terms of service will still display) or to complete a CAPTCHA form when they register. You can also allow members to set their own localization preferences (that is, members can set what time zone they are in and then see all times in their local time zone). Ensure that all these are set to Yes.
[ 145 ]
Members
5. Further down, you can set the member group that new members are assigned to (for now, leave this set to Members). You can also change the Default Member Profile Theme. You have two choices: Agile Records or Default. Since the Agile Records theme is designed specifically for the Agile Records website, select Default here. Finally, you can change the Profile Triggering Word, which changes the URL for the member control panel. (For example, if you changed this to guest, then all member control panel URLs would include the word guest instead of member). Leave this set to member for now and click Update. If you do not see any options for the default member profile theme (not even default), then you may be using the Freelancer license, which does not include member management.
6. The Member List Preferences allows you to change the default sort and order of your public member list page (which lists all the members on your site). Do not make any changes right now. 7. The Notification Preferences allows you to receive an e-mail whenever a new member registers at your site. This can be useful if you require an administrator to activate all new member registrations, or if you simply want to monitor new member registrations. If you are using a localhost testing environment, do not make any changes to this screen right now (as the localhost environment does not include an e-mail server, meaning such e-mails cannot be sent). If you are following along on a live website, type in your e-mail address here.
[ 146 ]
Chapter 6
8. ExpressionEngine includes functionality to allow members to contact each other via your website through Private Messages. The Private Messaging Preferences allows you to restrict the number of characters or the size of the attachments that can be attached to private messages. 9. ExpressionEngine includes the ability for members to associate an avatar (image) with themselves, which you can then display next to comments or forum posts that the member makes. The Avatar Preferences allows you to control whether avatars are enabled and whether members can upload their own images. 10. You can also choose whether you want to allow members to upload photos of themselves (which are then displayed on their profile). 11. Finally, you can choose whether or not you want to allow signatures, which appear after every forum post. Signatures are enabled by default, though signature images are turned off. 12. If you have not already done so, click Update to save any changes you have made. Now that you have made these modifications, the next step is to walk through registering as a member and explore the member control panel.
Registering as a new member
The membership functionality in ExpressionEngine is very rich, so rather than having to design your own membership templates from scratch, ExpressionEngine comes with pre-built member templates that you can use for members to login, register, share profiles, change settings, and send e-mails/private messages to other members. When following along in this section, remember that you are a member of your own website. This means that in order to register as a new member, you must first log out of the control panel by clicking Logout at the top right. 1. After logging out of the control panel, visit http://localhost/member/ register. (Remember, if you have the Freelancer license, this URL will not work). 2. You will be presented with a standard Member Registration screen, complete with a generic terms of service. Fill in the form with settings different than the administrator login that you have been using up to this point.
[ 147 ]
Members
Note that, by default, there can only be one username per e-mail address, so you cannot use the same e-mail address for this member as you did for your administrator login. This setting can be changed in Admin | Security and Privacy | Security and Sessions, although it is recommended not to change this setting as it can cause issues if a member with two accounts associated with their e-mail address forgets their password.
3. Select the check box to agree to the terms of service, fill in the CAPTCHA, and click Submit.
[ 148 ]
Chapter 6
4. As long as there were no errors with the information provided, you should be presented with a registration complete message and a link to go back to the main website. You are now registered as a new member!
The member profile
Now that you have walked through registering as a new member, you can see what the member control panel looks like. For this section, you can either be logged in as the member you just created or logged in using your Super Admin username. 1. Go to http://localhost/member/profile. If you are prompted to log in, log in first. 2. You should see a screen with your account statistics: your e-mail address, when you became a member, when you last visited the website, how many channel entries you have posted, and how many comments you have made. Along the top are links to log out or to see the member list. Along the left are links that allow the member to modify and personalize their account.
3. Click Edit Profile on the left-hand side and you can change what other members see about you. Go ahead and fill it in so that when you later visit your profile screen, you can see how it looks. 4. As mentioned earlier, Edit Signature and Edit Avatar are more relevant if you have purchased the forum module. If enabled, members can set their signature and avatar here. ExpressionEngine comes with a default set of avatars that members can select from. [ 149 ]
Members
5. With Edit Photo, you can also associate a member photo that other members can see when they visit your profile (although this option is not enabled by default).
6. Select Email Settings from the left-hand side. This allows members to finetune what notification e-mails they receive. By default, ExpressionEngine allows members to e-mail other members—a member can turn this off here. You can also change your e-mail address on this page. 7. Username and Password allows you to change your username, your screen name, or your password. 8. Edit Preferences allows members to determine whether avatars, signatures, or smiley images are displayed. Members can also prevent Private Messages from being sent to them on this screen.
[ 150 ]
Chapter 6
9. The Localization Settings allow a member to specify their Time Zone, their Time Formatting (US or European), and their Language (if you have multiple language packs installed). By selecting a different time zone, the member can see times in their local time zone. If the times on your website do not appear correct, it may be that either the server timezone or the daylight savings (summer) time setting has been set wrongly. These can be set in Admin | Localization Settings.
10. If a member has posted comments and selected to be notified of follow-up comments, then they are considered subscribed to that channel post. The Subscription Manager shows which posts a member is subscribed to and allows them to unsubscribe if desired. 11. The Ignore List allows members to ignore other members. As a result, any forum posts made by them will not display. 12. The Private Messages section is where members can send private messages to each other and view the ones they have received. 13. Finally, the Notepad is a scratch pad—any text typed into the notepad will be there next time the member logs in. This is most useful for members with administrative control panel access, as the notepad contents also appears on the right-hand side of the administrative control panel. The member control panel is very feature rich, allowing for a lot of functionality and configurability right out of the box. Members can send messages to other members, control what other members can see about them, and personalize settings such as their signature, avatar, or photo to suit their preferences.
The member list
Another option your members have access to is the member list. This can be used for members to browse other members and find their profiles or to send messages. 1. Click on Member List at the top-right of the member control panel or go to http://localhost/member/memberlist. Here, you are provided with a list of all active members. If there are lots of members, you can use filters or searches to find the person you are looking for.
[ 151 ]
Members
2. Click on a specific member and you can see the member profile, including any information the member may have personalized on their profile page.
3. Notice how the member's e-mail address is not publicly displayed. Click on the EMAIL button and you are brought to a form that you must fill in to send an e-mail. It is up to the recipient to decide whether they want to reply (and thereby reveal their e-mail address). With all this functionality, it is easy to build a website that members can use as a springboard to interact with other like-minded people. If you want to customize the member screens so that they share the same look and feel as the rest of your website, the templates can be edited in Design | Themes | Member Profile Templates and the corresponding files can be found in the /themes/profile_themes directory. (Note that it is best to make a backup of the templates before modifying them, in case you need to undo a change). Since each member page is made up of multiple templates, one technique (that you can see in the Agile Records templates) is to put an HTML comment in each template with the template name. In this way, you can view the source of the member pages and more clearly see which templates make up the page.
Linking to the member templates
As you have just seen, all the member functionality is pre-built. All you have to do is link to the pre-existing member URLs on your website and members can start registering and using your website.
[ 152 ]
Chapter 6
Next, you will set up the links in the sidebar on the right-hand side. If the visitor is logged out, there will be links to log in, register, or reset their password. If they are logged in, there will be links to log out, go to the member profile pages, or see the member list. 1. Log in to the control panel as a Super Admin. From the top-menu, select Design | Templates | Snippets. Select the website_sidebar snippet that you created in Chapter 5, Creating a Fully-Equipped Channel. 2. Add the following code to create the links immediately before the last in the snippet. Notice the use of the ExpressionEngine path variable (that you first saw in chapter 5)—this auto-generates a URL to the specific template group and template you specify. In this case, member is not a traditional template group, but rather the keyword you have defined in member preferences. If you do not feel like typing this in, remember that the finished code for each chapter can be downloaded at either http://www.packtpub. com/support or http://www.leonardmurphy.com/book2.
Member Links
- {if logged_out}
- Login
- Forgot Password?
- Register {/if} {if logged_in}
- Profile [ 153 ]
- Member list
- Logout {/if}
Members
3. Click Update and Finished and now visit the main website home page. Underneath Key Services, you should now see Member Links (depending on whether you are logged in or out will determine which links you see). Try the links to make sure they work.
You have now enabled the ability for visitors to register themselves on your website.
Introduction to member groups
By default, there are five member groups. You are already familiar with the Super Admins member group (which you are a member of). The Members member group is the group that approved members are put into (unless you have changed the default member group in the member preferences). By default, members in this group can do everything available on the member screens (such as sending private messages) as long as you have not disabled the option in the global Member Preferences. However, members cannot log into the control panel. The Pending members group is for members who have registered but have either not activated their membership via e-mail (if you allow self-activation by e-mail) or have not yet been manually approved (if you require members to be approved by an administrator). If you do allow self-activation by e-mail, it is a good idea to review the members of this group periodically and delete stale applicants (do this via Member | Activate Pending). [ 154 ]
Chapter 6
Members in the Banned member group cannot see your ExpressionEngine website, and the Guests member group is used for members who are not logged in. Since Super Admins can do anything and everything in ExpressionEngine and cannot be restricted, you should be very cautious about which members you assign to the Super Admin group. For example, while Ed & Eg need to be able to post and modify channel entries, it would be better not to give them access to templates, where they might accidentally change something. To accomplish this, you can create a new member group for Ed & Eg.
Creating a member group
In this section, you will create a new new member group called Editors for Ed & Eg. This will allow them to be able to log into the main control panel and publish or edit entries but will not allow them to view templates or change administrative preferences. After you create the member group, there will be two sets of options to configure. The first set of options applies to the member profile screens (and controls such things as whether they can send private messages). The second set of options control what the members can do within the control panel. For most members, you would not even allow them access to your control panel, so this second set would not apply. Throughout the configuration process, any options that you would not want to assign to someone you do not know and trust is bolded and colored red. 1. The first step is to create the member group. Log into the control panel as a Super Admin and go to Members | Member Groups. 2. Rather than creating a member group from scratch, you will base the new member group on the Super Admins member group. Underneath the member group listing is the option Create a new group based on an existing one. Select the Super Admins group from the drop-down box and click Submit.
[ 155 ]
Members
3. You will be brought to a new screen where you can give the new group the name Editors. Optionally, you can type in a description.
4. Continuing down the screen, the next option is Security Lock. If you allow groups, other than Super Admins, to administer members, you can control which member groups they can assign users to. As editors and owners of the website, you would want Ed & Eg to be able to approve and manage their members, but you would not want them to be able to assign members to the Super Admin or Editors group (for example). To accomplish this, leave this group Locked (meaning only Super Admins can assign members to the Editors group). To allow Ed & Eg to be able to assign members to the Members group, you would have to edit the Members group and adjust the group security lock to be Unlocked (by default, the Members group is locked, meaning only Super Admins can assign members to it).
5. The next option is Site Access. Since you would want Ed & Eg to have access to the website when it is offline, leave both options as Yes. (If you were creating a member group for members of the public, you would typically set this to No). [ 156 ]
Chapter 6
Within Admin | General Configuration, you can choose whether your system is on or not. You might choose to turn it off if you are doing updates and do not want members of the public to stumble across an incomplete site while the changes are in progress.
6. In the next option, Member Account Privileges, say No to allowing Ed & Eg to be able to delete their own account—if they accidentally did this, it would cause any content they had created to be deleted as well.
7. Comment Posting Privileges, Search Privileges, and Private Messaging Privileges allow you to control whether this member group can use these functions (and allows you to set member group-specific restrictions on their use). Since Ed & Eg own this website, do not make any changes to these screens.
[ 157 ]
Members
8. Control Panel Access is where you can allow (or prevent) the member group from accessing either the entire control panel or specific sections within the control panel. Since you want Ed & Eg to only have access to options they can safely use, say No to the following sections: DESIGN, add-ons (all five sections), ADMIN (all three sections), and say No to TOOLS (Utilities, Data, and Logs only). Leave the TOOLS section and the TOOLS: Communication set to Yes. Ed & Eg will only have access to the options set to yes here.
9. Under Control Panel Administration, say No to all the options except administrating member accounts, changing member groups, and banning users.
[ 158 ]
Chapter 6
10. Control Panel Email Privileges allows you to prevent Ed & Eg from sending e-mails through ExpressionEngine. Since there is no reason to do this, leave all the options as Yes. If you have a website where a large number of people will have control panel access (such as in a larger business), you might want to set this setting to No. 11. The Channel Posting Privileges allows you to decide what Ed & Eg can do with channel content (for example, if they can delete entries or edit other peoples' entries). Since Ed & Eg are the owners of the website, do not make any changes. 12. The Channel Assignment allows you to choose which channels Ed & Eg can publish to and edit. If you have Agile Records installed, you would want to ensure that Ed & Eg cannot see the Agile Record channels. Therefore, only say Yes to FAQs and Website—say No to Information Pages and News if they are there.
13. Comment Administration allows you to configure what comments Ed & Eg can view, moderate, edit, or delete. Leave all these options set to Yes. 14. Template Editing Privileges allows you to control which template groups Ed & Eg can edit. Since you do not want Ed & Eg editing any templates, say No to all of them. 15. Module Access Privileges allows you to control which modules Ed & Eg can access. Since you are not giving Ed & Eg access to the Add-On screens, you can say No to all modules (if there are any listed). 16. Click Submit to create the member group. You will be returned to the Member Groups page, where you will see your new member group in red and bold (because it has access to the control panel). You have now created an Editors member group, and all your changes have been saved. Next, you can log into the control panel as Ed or Eg and see what it looks like.
[ 159 ]
Members
Creating a member
Earlier in this chapter, you saw how to register yourself as a new member. Thankfully, as Super Admins, you can bypass this process and create new members directly in the control panel. In this section, you will create your first editor group member, Ed the Editor. 1. From the top menu, select Members | Register Member. 2. Fill in the username (edward), password, screen name (Ed), and e-mail address for your new member. (Remember that, by default, only one e-mail address can be used per member). Be sure to select the Editors member group as the member group assignment and then click Register a New Member.
3. You will be returned to a list of members in the Editors member group (right now, Ed is your first and only editor). Do not close this listing.
Logging in as Editor Ed
Another advantage of being a Super Admin is that you can log in as any other member without having to know that member's password. This allows you to see your website as they see it—which is helpful when you are developing new features or troubleshooting reported issues. 1. From the View / Search Members screen that you are on, click on the edward hyperlink.
[ 160 ]
Chapter 6
2. You will be taken to the member control panel for this member. From the left-hand side, select Login as Member (the second option from the bottom).
3. You can now choose which page of your website you want to see as Editor Ed. Select the Control Panel radio button and click Submit.
[ 161 ]
Members
4. You will then be logged in as Editor Ed. Although it looks like the control panel you have been working in so far, notice that there are far fewer options, both in the menu and on the main screen. Essentially, all Ed can do is publish new entries, edit existing entries, and administer members. ExpressionEngine has many options that allow you to decide how much access other people have to the control panel—you could set up a member group that can only post entries to a single channel or you could set up a member group that can do everything but post entries to a given channel. You can also set up member groups that do not have control panel access such as a trusted members group, which is exempt from comment moderation or that can search more frequently than regular members. You have now created a member group specifically for Ed & Eg to be able to create content without risk. However, there is one more area that can be customized by the member group: the Publish Page.
Modifying the Publish page layout
By default, the Publish page contains lots of options, spread across several tabs, some of which you will be unlikely to use for a given channel (such as the expiration date for an entry) and some of which you will intend to use, but will be liable to forget about (such as selecting the categories for an entry). Luckily, as a Super Admin, you can customize the Publish page so that the workflow better suits your needs. In the FAQs channel, you know you must select the category for a new entry, so instead of having the categories on a separate tab, you will move it to the bottom of the main tab so that you must scroll past it in order to submit your entry. In this way, you are less likely to forget to fill it in. 1. Log into the control panel as a Super Admin, and go to the Publish screen for the FAQs channel (Content | Publish | FAQs). 2. Towards the top-right (just to the left of the Notepad on the right-hand side), you should see an option that says show toolbar. Click this. (If you are not logged in as a Super Admin, you will not see this).
[ 162 ]
Chapter 6
3. A toolbar will appear with a list of fields, tabs, and authors. First, notice the eye on the right-hand side of each field name. If the eye is open, it means the field is visible. If the eye is closed, it means the field is not visible. (If there is no eye, it means the field is mandatory and cannot be made invisible). Click on the eye to toggle between open and closed. Close the following fields that Ed or Eg will be unlikely to modify on a per-entry basis in the FAQs channel: Expiration Date, Comment Expiration Date, Pings, Channel, and Options.
[ 163 ]
Members
4. The Tabs section allows you to delete tabs or create your own. For example, there are several tabs that have only one or two options on them. Rather than having all these tabs, you could delete all of them, and create a new tab for all your lesser-used options (such as the URL title and entry date, which you may want to alter for an entry, but not every entry). First, click Add a New Tab and call it Rarely-Used Options. Then click Add a Tab.
5. Next, click on the newly created tab and drag fields from the list of fields in the toolbar onto the main window in the position you would like them. Move the following fields: Entry Date, URL Title, Author, Status, and Revisions. If you do not see the revisions tab, you may not have enabled entry versioning while following chapter 5—to do so, go to Admin | Channel Preferences | Channels and then Edit Preferences for the FAQs channel. 6. Since Categories is something you always want Ed or Eg to select when they publish an FAQ (because the content is organized by category), click on the Publish tab and drag the Categories field from the toolbar onto the Publish tab. 7. Next, you can delete all the other tabs that you no longer need. Click on the trash can to the right of each tab name (other than Publish and Rarely-Used Options).
[ 164 ]
Chapter 6
Finally, each field on the main screen also has a little triangle at the bottom right and a little rectangular tab on the left. The triangle allows you to modify the size of the field (for example, so that it does not take up the entire width of the screen) and the rectangle allows you to modify the position of the field in relation to other fields. In this way, for example, you can put two smaller fields beside each other or you can reorder the fields as you see fit. 1. Now you can save your updated layout. At the bottom of the toolbar, check the boxes to apply the layout to both the Super Admins and the Editors member groups and then click Save Layout.
2. Now click hide toolbar to hide the toolbar, and you can see that the Publish page is substantially simplified. Instead of six tabs and lots of options you never use, there are two tabs—the first tab with options that you always want to set for a new entry, and the second tab with options that you rarely need to set, but might want to on occasion. To summarize, there are three ways to configure options on the Publish page: 1. The Member Group options allows you to configure which member groups can publish to which channels (or even whether a given member group with control panel access can publish to any channels). 2. The Custom Field options (reviewed in previous chapters) allows you to configure which options appear for each field—such as the HTML formatting buttons, write-mode, the spell-check, and so forth (and also whether the fields are mandatory or not). 3. The toolbar on the Publish page allows you to configure which options are visible on a per-channel, per-member group basis. This level of flexibility allows you to build a website for someone else to maintain, and to keep the interface uncluttered for that person, so that they only see the options they need to use. [ 165 ]
Members
Creating member-only content
So far you have seen the options available to you in the control panel for different member groups. For members with control panel access, the options are very comprehensive—you can disable entire sections (such as template editing) or disable individual items within a section (such as which template groups can be edited or which fields on the Publish page are visible). For members without control panel access, it is up to you how attractive you make the membership of your site, because any member-only feature has to be specifically coded that way in your templates. There are two ways you can restrict what nonmembers can see: 1. You can configure templates to not be viewable by certain member groups. If a person in an unauthorized member group attempts to access one of these templates, you can redirect them to a different template that says the content is for members only. From the Template Manager, where you would normally click to edit the template, click Access to change who can view the template and what template they should see instead. This can be useful if you are creating a new section to your website and want to allow certain member groups to try it out before going live to everyone.
[ 166 ]
Chapter 6
2. Alternatively, you can use conditional tags within templates to display different content. This allows you much more control and flexibility over what your visitors see—you can display different content depending on whether the member is logged in, depending on the member group of the member or based on any number of variables (for example, the username of the member or how many comments a member has posted). Read more about conditional tags at http://expressionengine.com/user_guide/ templates/globals/conditionals.html. Next, you are going to create a new custom status called Premium. If an FAQ is marked with a premium status, only registered members will be able to see the answer. Non-members will be able to browse all the FAQs, but if they select a premium FAQ, they will only see the question, along with a message encouraging them to register to see the answer.
Making content visible to members only
You have already seen the {if logged_in} and {if logged_out} tags to display different links, depending on whether a member is logged in or not. You will now use these same tags to determine whether or not to show them member-only content. WARNING: If you use conditional statements {if logged_in} and {if logged_out} inside the {exp:channel:entries} tag on a template, do not enable caching on that template or the conditionals will not work. The first person to visit the template will have their logged in state cached, meaning every subsequent visitor will be treated as if they have the same logged in state as that first visitor. Caching can be set for each template on the Template Manager screen by clicking on Edit Preferences for the template in question—by default, template caching is not enabled.
1. Before you can assign any channel entries to a premium status, you must first create the premium status by going to Admin | Channel Administration | Custom Status Groups. You currently only have one status group (statuses), so click Add/Edit Statuses.
[ 167 ]
Members
2. Next, click Create a New Status at the top right. (The Featured status you see in the screenshot will only exist if you installed Agile Records).
3. Call the new status Premium. Leave the Highlight Color blank. This controls the color of the status in the control panel—for example, if you typed red, the status would be in red text. Leave the specific groups who can access the status set to Yes. Click Submit.
The ability to restrict status to members of specific groups allows you to use statuses as a workflow on your website. For example, if you have a member group called authors, you could allow them to publish to a channel, but restrict what status they can assign the new entry so that their work is not open (for example they might only be able to publish to a 'needs review' status). You can then have another member group (such as editors) that do have the right to change the status from 'needs review' to 'open'—thereby ensuring that anything published on your website has been reviewed by a member of the editors group.
[ 168 ]
Chapter 6
4. Now post a new entry to the FAQs channel, and before clicking Submit, ensure that you set the status to Premium (on the Rarely-Used Options tab if you customized your Publish Page layout in the previous section, otherwise on the Options tab).
5. If you now visit http://localhost/faqs you will notice that your new entry does not appear. This is because you must specify in the {exp:channel:entries} tag in each template if you want entries to appear that have a status other than open. Modify the four templates (faqs/index, faqs/browse, faqs/rss, and faqs/atom) and the website_ faqs snippet to include the status="Open|Premium" parameter in the {exp:channel:entries} tag. The | means OR—as in, you want to entries that have either the Open or the Premium status. If you just specified status="Premium", then any entries with a status of open would not display. •
faqs/index: {exp:channel:entries channel="{my_channel}" limit="10" paginate="bottom" status="Open|Premium"}
•
faqs/browse (in HTML
•
faqs/browse (after
•
faqs/rss: {exp:channel:entries channel="faqs" limit="10" dynamic_ start="on" disable="member_data" status="Open|Premium"}
•
faqs/atom: {exp:channel:entries channel="faqs" limit="15" dynamic_ start="on"disable="member_data" status="Open|Premium"} [ 169 ]
Members
•
website_faqs: {exp:channel:entries channel="faqs" limit="3" orderby="random" dynamic="off" status="Open|Premium"}
6. Now, modify the faqs/browse template and replace the line
<strong>A: {faqs_answer}
with the following conditional statement. This says to display the answer if either the status is not Premium or if the visitor is logged in. If neither of these conditions are true (that is, the status is Premium and the visitor is not logged in), then do not display the answer. {if status!='Premium' OR logged_in}<strong>A: {faqs_answer}
{if:else}<strong>A: This answer is available to registered members only. If you are already a member, please login. Otherwise, consider registering for free & unlimited access to all our advice.
{/if}7. Click Update and Finished, and now log out of the control panel (link in the upper-right-hand corner of the screen). 8. Now that you are not logged in, visit your premium content FAQ. Instead of seeing the answer, you should see a message telling you to log-in (as shown below). Verify that you can log in and see the answer.
[ 170 ]
Chapter 6
You have now given Ed & Eg the ability to make content Premium, encouraging visitors to register on the website. Although this is a simple example, ExpressionEngine's conditional statements are very flexible and very powerful. For example, you could show a promotion (5 percent off!) on your homepage, but only to registered members, or even only to registered members who have commented a set number of times. You could also show different content to different member groups. Each member group has a Group ID number, viewable under Members | Member Groups. Using this Group ID, you can use a condition such as {if member_group='6'} (where 6 is the Group ID of the Editors member group) and then create a draft status and allow Editors to see entries with a draft status, but keep them invisible to all other members and non-members. The choices are limitless.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. 1. Try creating a new member group called Designers that can only be used to modify templates. Members of this group should not be able to post or modify any channel entries. 2. When a member registers for the first time, you have the option to collect additional information (beyond the username, name, and e-mail address) in Custom Member Fields. For example, if you have a motorcycle website, you could have a custom field to ask new members what make/model of motorcycle they have. Alternatively, if you give a free t-shirt to new members, you could ask for their t-shirt size. For this exercise, create a custom member field that asks "Are you an existing customer of Ed & Eg?" with possible answers being Yes or No. 3. On the right-hand side of your website is a box with a title of Promotion! that links to a Promotions page. Ed & Eg have decided that they want promotions to be visible only to registered members of the website. Modify the promotions/index template to display the promotion if a visitor is logged in, but otherwise display a message asking the visitor to register. (The promotions/index template is created as part of the challenges in Chapter 4, Moving a Website to ExpressionEngine).
[ 171 ]
Members
Summary
In this chapter, you learned all about member functionality in ExpressionEngine, including the built-in member control panel. You also looked at setting up new member groups and customizing the administrative control panel for different member groups (that have control panel access). Finally, you looked at how to use conditional statements in your templates in order to make membership attractive to visitors. The key points to remember after working through this chapter are as follows: •
You can control what all members can or cannot do in the Member | Preferences screens. You can also make exceptions on a member group basis in Members | Member Groups. So, for example, you can require that all comments are moderated, but make an exception for members in a specific group.
•
Be cautious about who you assign to the Super Admins member group. If someone needs control panel access, but does not need access to everything in the control panel, it is a better practice to set up a new member group with only the permissions that the member group needs.
•
If you are building a website for a client, remember that you can modify the Publish page to make it more intuitive. You can hide fields that are not relevant and at the same time make other fields more prominent.
•
How attractive membership is on your site is up to you. Using conditional statements, you can control what content members can see, displaying different content for different member groups or based on different conditions.
•
If you have a template that uses the conditional statements {if logged_in} or {if logged_out} inside the {exp:channel:entries} tag to display different content to different members, do not enable caching for that template.
[ 172 ]
Creating a Calendar Many organizations have events, and a calendar is a very visual way of indicating what is going on and when. The built-in ExpressionEngine calendar functionality is limited (for example, it does not allow recurring appointments). However, you can use it to display event titles with clickable links for more information. If a calendar is a key part of your website, you may be interested in checking out Solspace's calendar module (at the time of publication, it is not yet available for ExpressionEngine 2). http://www. solspace.com/software/detail/calendar/. The module contains support for more sophisticated calendar functionality such as recurring appointments.
In this chapter, you are going to use the built-in functionality of ExpressionEngine to build a simple events calendar that is easy to post to using the Publish page in the control panel. You will use the jQuery module to display more information when an event is clicked. Finally, you will also be introduced to the concept of Related Entries (relating the post from one channel to a post in another channel)—a useful tool to reduce repetition in channel entries.
Designing the calendar
Ed & Eg frequently host free seminars for customers and members of the community in their conference room. These seminars are usually sponsored by another organization. Ed & Eg would like a calendar on their website that shows each seminar on the date that it is to take place, along with a link so that visitors can read more about the topic of a given seminar as well as who the sponsor company is.
Creating a Calendar
One way you can design such a calendar is to create an events channel, which contains all the information regarding both the event and the event sponsor. This would work, but because a single event sponsor is often associated with more than one seminar, this design would result in you having to include the same information about the same sponsors in more than one channel entry. For example, if Anytown Bank sponsors five seminars, there would be five entries where you would have to provide information about Anytown Bank. Related Entries is a way to reduce repetition in channel entries. (Not to be confused with relating entries by category—which you did when you built the FAQs channel). Essentially, if you have two kinds of data (events and event sponsors), you can create two channels and then include the data from one channel in the other. In this way, you can have an event_sponsors channel, which contains all the pertinent information on the event sponsors (such as their name, location, opening hours, and services offered). The event channel itself will then only contain information about the event (such as the date, time, and topic). When Ed or Eg creates a new event, they can simply select the sponsor (such as Anytown Bank) from a drop-down list of sponsors in the event_sponsors channel, and all the information about the event sponsor will automatically populate for them—no retyping necessary.
Setting up your channels
To set up an event and an event sponsors channel, you will first create the custom fields, then create the channels, then populate the channels with example data, before finally creating the templates that you will use to display the channel data. When creating two channels that are to be related, it's best to start with the channel whose data will be included in the other channel—therefore, start with the event sponsors channel.
Creating custom fields for event sponsors 1. Select Admin | Channel Administration | Custom Fields.
2. Select Create a New Channel Field Group and call the field group event_ sponsors. Click Submit. 3. Now select Add/Edit Custom Fields for the event_sponsors field group. 4. For now, keep things simple and create only one field—a generic about field. (You could, of course, create as many fields as you want). Select Create a New Custom Field. [ 174 ]
Chapter 7
5. The field type will be Textarea. The field label will be About and the field name will be event_sponsors_about. The field will be required, will not be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. The event_sponsors field group is now ready to go. The next step is to create the event_sponsors channel.
Creating the event sponsors channel
By now, you should be familiar with the process of creating a channel. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Event Sponsors with a short name of event_sponsors. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and event_sponsors for the field group (the category group can be left as none, as you will not be using categories with this channel). Remember, if you do not select a Status Group when creating a new channel, then only Super Admins can post open entries. If any other member group posts an entry, it will be closed by default (and therefore not visible on your website).
3. Finally, select No to creating new templates and then click Submit. 4. Now, go to the Content | Publish | Event Sponsors and create a couple of example sponsors (for example, Anytown Houses, Anytown Bank, and Anytown Law Firm).
[ 175 ]
Creating a Calendar
Now that you have your sponsors channel set up with some sponsors, you can go ahead and create the events channel.
Creating the events custom fields
As before, you will first create your channel custom fields, before creating the channel, and then some example content. 1. Select Admin | Channel Administration | Custom Fields. 2. Select Create a New Channel Field Group and call the new field group events. Click Submit. 3. Now select Add/Edit Custom Fields for the events field group. 4. You will create two fields for your events—Description and Sponsor. Select Create a New Custom Field. Note that you will not create a custom field for the date or the time of the event. This is because you can change the date/time of the entry to reflect the date/time of the event.
5. The field type will be Textarea, the field label will be Description, and the field name will be events_description. The field will be required, will be searchable, and will be shown by default. Use a Default Text Formatting of XHTML (with six rows) and do not allow an override on the Publish page. Show Formatting Buttons, Spellcheck, and Write mode. Click Submit. 6. Next you can create the relationship field. Click Create a New Custom Field. 7. From the drop-down of Field Types, select Relationship. The Field Label will be Sponsor, and the Field Name will be events_sponsor.
8. The field will not be required (some events might not be sponsored) and the field will not be searchable. Say Yes to show the field by default. [ 176 ]
Chapter 7
9. In the Custom Field Options, select the Event Sponsors channel and leave the display criteria at the default setting (Sort by Title in Descending Order). Click Submit.
Now all you have to do before you can start creating events is create the events channel.
Creating the events channel
Creating the events channel is a fairly straightforward process. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Events with a channel name of events. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Statuses for the status group and events for the field group (the category group can be left as none, as you will not be using categories with this channel). 3. Finally, select No to creating new templates and then click Submit. 4. Your channel is created! Now, you can bring together your Events and Event Sponsors by creating some events.
Creating example events
The final step in setting up these channels is to post some example events, so that when you create the calendar on your website, you have some events to see how it is working. Your first event is going to be a seminar called Common Pitfalls of Home Buying, sponsored by Anytown Houses. 1. Select Content, Publish, and select the Events channel. 2. Type in the title, Common Pitfalls of Home Buying. In the description field, type in some example topics that will be covered.
[ 177 ]
Creating a Calendar
3. Select Anytown Houses as the sponsor. That is all you need to do to associate the sponsor with the event.
4. Before clicking submit, select the Date tab at the top of the screen and select a date for your entry and a time of 6 p.m.
[ 178 ]
Chapter 7
5. Click Submit. 6. Go ahead and create a few more events with different sponsors, dates, and times, so that when you create the calendar, you have a few entries to play with. Now that you have the channels built and have some example events too, you can go ahead and create the calendar!
Creating the calendar
For the rest of this chapter, it will be useful to refer to the official ExpressionEngine documentation on the calendar tag at http://www.expressionengine.com/user_ guide/modules/channel/calendar.html, where much of the code in this section is adapted from. The first steps in creating a calendar are to create a calendar template group, add the basic HTML to construct the page, build the outline of the calendar, and add CSS to make the calendar look good.
Creating a blank calendar template
1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group calendar. Do not duplicate a group and do not make the index template in this group your home page. Click Submit. 2. Copy and paste the code from the includes/404 template (or any template that has all the normal page components such as the header, sidebar, widebar, and footer). Paste the code into the new calendar/index template. At the top of the template, add a my_channel preload replace as follows: {preload_replace:my_channel="events"}
3. Change the page title from Page Not Found to Calendar.
4. Change the h1 title to Seminar Calendar and delete the paragraph underneath that says the page does not exist (including the
and
tags). The content section should look as follows:Seminar Calendar
[ 179 ]
Creating a Calendar
Now you have a blank Ed & Eg themed template (viewable at http://localhost/ calendar) that you can use for your calendar.
Creating the calendar
The next step is to create a blank calendar—it will not display any events just yet. This code is adapted from the ExpressionEngine documentation. 1. In the calendar/index template, add the following code after the
Seminar Calendar
line. The first piece of code is the exp:channel:calendar tag. This is a pair of tags with a number of parameters. {exp:channel:calendar switch="calendarToday|calendarCell" channel="{my_channel}" show_future_entries="yes"} {/exp:channel:calendar}The channel parameter specifies that the entries on the calendar are coming from {my_channel}, where {my_channel} is a Preload Text Replacement corresponding to the events channel. The parameter show_future_entries="yes" means that the calendar will show future entries. In most channel applications, if you set an entry date in the future, ExpressionEngine does not make that entry visible until that date. This is useful if (say), you are going away but want to schedule new content to appear at a certain time while you are gone. In this case, if a calendar only showed entries that have already happened, it would not be a very useful calendar. The switch parameter is used to switch between two different stylesheet styles (you will create the calendar stylesheet next). If the day being displayed is not today, then the stylesheet's style will be calendarCell. If the day being displayed is today, then the stylesheet's style will be calendarToday. This allows today's date to be styled differently.
2. The next step is to start displaying the calendar itself. A calendar is a table with seven columns (one for each day of the week) so you will use the HTML table tag to display it. In the following code, you define the first row. In the top left cell, you will display << that can be clicked to move to the previous month. Likewise, in the top-right cell, you will display >> to navigate to the next month. The middle five cells will contain the name of the current month being displayed. The style calendarBG will be defined in the stylesheet that you will create in the next section. Add the following code after the {exp:channel:calendar} tag and before the closing {/ exp:channel:calendar} tag. [ 180 ]
Chapter 7
<< | {date format="%F %Y"} | >> |
---|
The previous and next path links both point to the current template (calendar/index). < is HTML for the < symbol and > is HTML for the > symbol. The format code to display the current month and year, %F %Y, is taken from ExpressionEngine's date formatting code, available at http:// expressionengine.com/user_guide/templates/date_ variable_formatting.html
3. Go to http://localhost/calendar and you can see the calendar beginning to take shape. Click on the arrows and you can see that the name of the month changes, as does the URL of the page. 4. The next row will display the weekdays. The code {lang:weekday_abrev} refers to the one letter weekdays. You could also use weekday_long or weekday_short to either spell out the entire weekday or the first few letters of the weekday respectively. This must be wrapped in a {calendar_ heading} variable pair. Insert the following code after the closing tag and before the closing tag.
[ 181 ]
Creating a Calendar
5. The next row will display the actual dates. There is no way to know how many rows might be needed for a given month (February might only require four rows; October might require six). ExpressionEngine dynamically determines how many rows to display using the {calendar_rows} variable pair, which repeats for as many rows as are necessary. Each row starts with the
You now have the beginnings of a calendar, although it looks a little basic.
[ 182 ]
Chapter 7
Before you start displaying your events on this calendar, first create some CSS to make the calendar look a little more calendar-like.
Formatting the calendar with CSS
Rather than adding the calendar styles to your main site/site_css stylesheet, it makes sense to create a separate stylesheet just for the calendar styles. This is because the calendar styles are only needed on the calendar page and do not need to be included on any other page.
Creating the calendar CSS template
First, you will create the template for the calendar CSS. Then you will point the calendar/index template to this new template. 1. From Design | Templates | Template Manager, click the calendar template group and select New Template. Call the new template calendar_css and choose a Template Type of CSS. Click Create and Edit.
2. The first line in your new template will import the main site/site_css template (so that the page outside the calendar continues to be formatted correctly). After typing this, click Update and Finished. @import url({site_url}includes/site_css);
[ 183 ]
Creating a Calendar
The {site_url} variable, which you have seen before, is converted to the actual URL to the root directory of your site, as stored in Admin | General Configuration. Note that the URL in this setting should have a trailing / (for example, http://localhost/ as opposed to http:// localhost) or the link above will not work (for example, it will resolve to http://localhostincludes/site_css instead of htttp:// localhost/includes/site_css).
3. The next step is to point the existing calendar/index template to use this new CSS template in place of site/site_css. To do this, edit the calendar/ index template and modify the stylesheet line to read as follows:
Now you can add some styles to your CSS.
Adding styles to your calendar CSS
In the calendar/index code so far, you have defined several styles: • • • • • •
calendarBG is used to format the overall table calendarHeader is used to format the month heading calendarDayHeading is used to format the weekday headings calendarCell is used for the calendar cells, except for today's date calendarToday is used for the calendar cell that represents today's date calendarBlank is used for calendar cells that are not for the dates this month
Helpfully, EllisLab provides a suggested stylesheet in the ExpressionEngine documentation (http://expressionengine.com/user_guide/modules/channel/ calendar_css.txt), which you can start with and then adapt to your own needs. 1. Open the template calendar/calendar_css for editing. Copy and paste the example code from the URL above into the CSS stylesheet (below the @ import line) and click Update.
[ 184 ]
Chapter 7
2. Next, modify the three cell styles (calendarCell, calendarToday, and calendarBlank) to position the date in the top-left of the cell (so that there is room for your event text). To do this, modify the following two styles for .calendarCell and .calendarToday and add them to .calendarBlank: text-align: left; vertical-align: top;
3. Now modify the same three cell styles to have a fixed width. Otherwise, as events are added to your calendar, some columns will expand and other columns will shrink. Add the following styles to .calendarCell, .calendarToday, and .calendarBlank: width: 60px; height: 60px;
4. Finally, you can create some styles for displaying your events. You want to keep the font clear to read but small. The following code will give each event a border, so that if there are two events on the same day, the text will not run together. Since all the events will be links (for more information), this code will also change the background color of the event when the mouse moves over it to make it clear that it is clickable. Add the following to the end of the calendar_css stylesheet: .calendarEvent a{ font-family: Arial, Trebuchet MS, Tahoma, Verdana, Sansserif; [ 185 ]
Creating a Calendar font-size: 10px; font-weight: normal; letter-spacing: 0em; text-decoration: none; border: 1px solid #666; vertical-align: top; text-align: left; margin: 5px; padding: 5px; display: block; } .calendarEvent a:hover{ background-color: #ccc; }
You now have a pretty, but blank, calendar. You can, of course, go further and change the styles so that it suits your site. It is all easily configurable within the CSS. The next step is to start displaying events on your calendar. Since space on the calendar is limited, you will only display the title of the event on the calendar itself, with a clickable link for more information. (In fact, only the title field from the channel is available in the {exp:channel:calendar} tag—none of the custom field tags will work). The basic way to build the clickable link is to simply create a new, single-entry page template that you link to (just as you did with the FAQs channel). However, to keep things interesting, a new approach is called for. You will still create a single-entry page template, but rather than just linking to it directly, you will use the jQuery module combined with the FancyBox plug-in (http://fancybox.net/) to display the single-entry page in an iFrame lightbox that floats over the calendar. To accomplish this, you must first download the FancyBox tool and upload the files to your website. (FancyBox is also used in the next chapter on photo galleries). If you are removing the index.php from your URLs, then you will likely have to modify your .htaccess file so that you can access the FancyBox files. You can then create your single-entry template (and a corresponding, simplified CSS file). Finally, using the jQuery module and FancyBox, you can create a link to your single-entry template from your calendar.
[ 186 ]
Chapter 7
Note that although this chapter is using a third party jQuery plugin, the focus of this book is on using ExpressionEngine—not on learning jQuery (or FancyBox). For more information about jQuery, please visit http://jquery.com/.
Setting up FancyBox
You can download the latest version of FancyBox directly from http://fancybox. net/, or a copy of the latest version is included in the code for this chapter at either http://packtpub.com/support or http://www.leonardmurphy.com/book2/ chapter7. 1. First, download FancyBox and extract all the files from the compressed directory into a directory on your computer. 2. Once extracted, you should see a directory called fancybox, complete with a number of images, JavaScript files (.js), and a CSS file. Upload this entire directory to the root of your website. Note that for the purposes of this chapter, you do not need any of the example files that ship with FancyBox. 3. Next, if you are removing the index.php from your ExpressionEngine URLs using the exclude method, you will have to add this new directory to your .htaccess file (otherwise it will be treated as an ExpressionEngine template group, rendering it inaccessible). Open .htaccess and add FancyBox to the end of the list of real directories and files as follows (but do not create a second RewriteCond line—modify the line you already have). RewriteCond $1 !^(images|system|themes|index\.php|admin\.php|fancybox) [NC]
For an example of a complete .htaccess file using the exclude method, please see either http://packtpub.com/support or http://www. leonardmurphy.com/book2/chapter2. Your .htaccess file may include other files or directories that you have in the root directory of your website (such as robots.txt or favicon.ico) that you should leave in place. 4. To verify that your .htaccess file is not blocking access to the fancy box directory, open http://localhost/fancybox in your browser. If you see your ExpressionEngine 404 page, then your .htaccess file is treating the fancybox portion of your URL as an ExpressionEngine template group. Review your .htaccess file.
[ 187 ]
Creating a Calendar
Troubleshooting problems that are due to the .htaccess file can be challenging. Many times you set up a .htaccess file when you install ExpressionEngine and then forget that it exists, so you do not even think of the .htaccess file. Remember that EllisLab does not provide support for removing the index.php using a .htaccess file (because there are so many ways to do it and every server works a little bit differently). If you suspect your .htaccess file is causing problems, you can temporarily remove it and add the index.php back into your website URLs (in Admin | Configuration, under Name of your site's index page). If you do this, it will at least confirm whether the issue you are seeing is due to your .htaccess file or something else entirely.
5. Finally, if you are using Internet Explorer, you may want to modify fancybox/jquery.fancybox-1.3.1.css to include a / at the start of the AlphaImageLoader sources. (This tells Internet Explorer that FancyBox is a directory at the root of your website and therefore enables it to find the images it needs). The easiest way to do this is to do a find and replace and replace AlphaImageLoader(src='fancybox/ with AlphaImageLoader(src='/fancybox/
FancyBox is now in place and ready to go. Next, you will create your single-entry template, along with a pared-down CSS file.
Creating your single-entry template
First, you will create a pared down CSS file, before creating your single-entry template. Both will be much smaller versions of your regular templates/CSS (since you would not view this template on its own, but rather as an overlay on an existing page, you do not need the usual Ed & Eg header, sidebar, or footer. As a result, the template and the CSS are smaller). 1. Create a new template in the calendar template group called event_css. The template type will be CSS. Duplicate an existing template, namely, includes/site_css. Click Create and Edit. 2. Delete the input, textarea style. Further down, delete everything that appears after the /* Wrapper */ comment (including /* Wrapper */ itself). 3. Now update the body style to read as follows (essentially removing the background and adding in a four percent padding so that the text in the popup overlay will not touch the sides of the pop-up overlay box): body { font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; [ 188 ]
Chapter 7 font-size: 12px; color: #6B6B6B; padding: 4%; }
4. Finally, remove the h2 from the h1,h2 style (not the h1, h2, h3, h4 style) and instead, add it to the h3 style. The styles should end up looking as follows: h1 { font-size: 28px; } h2, h3 { font-size: 16px; font-weight: bold; }
5. Click Update and Finished to save this CSS template. 6. Next, you will create your event template. In the calendar template group, click New Template and name the template event. The template type will be Web Page. Select to duplicate the calendar/index template and click Create and Edit. This template will be visible at http://localhost/calendar/ event. 7. Delete everything between the and tags. Also, change the
8. Next, change the stylesheet so that instead of pointing to calendar_css, it is pointing to the CSS stylesheet you just created (event_css).
9. Next, after the
{title}
<strong>Join us on {entry_date format="%F %j%S %Y"} at {entry_date format="%g:%i%a"}
{events_description}
{/exp:channel:entries} [ 189 ]Creating a Calendar
Notice that the show_future_entries parameter has to be included here, since this template is going to be displaying event entries that have an entry date after today's date. Also note the use of require_ entry and if no_results to ensure that only valid events can be displayed—all others will be redirected to your 404 page.
10. Next, you will display the sponsor information from the event_sponsors channel. Since you are displaying the content of the event_sponsors channel inside the events channel, ExpressionEngine needs a way to know which channel it is supposed to be displaying the data from (fields such as {title} could refer to either channel). To accomplish this, you wrap all your event_sponsors information in the tag {related_entries} using an ID that corresponds to the relationship field in the events channel (in this case, the events_sponsor custom field). You can then use the custom field names from the event_sponsors channel. The ID is a way for ExpressionEngine to support more than one relationship field in the same channel. Insert the following code after the
{events_description}
line: {if events_sponsor} {related_entries id="events_sponsor"}More About {title}
{event_sponsors_about}
{/related_entries} {/if}You have now completed this separate, pared-down single-entry template to show more information on your calendar entries. Although the plan is to only display this template in a pop-up overlay on your calendar page, you can see what the template looks like by itself by going to a URL like http://localhost/calendar/event/
common_pitfalls_of_home_buying.
[ 190 ]
Chapter 7
Notice how the information from the Event Sponsors channel is populated into the event information. Although you only have a few events right now, so the effort of creating two channels might not seem to outweigh the benefits, if you had tens or hundreds of events, all of which shared the same handful of sponsors, being able to simply select the sponsor information from the drop-down menu represents a significant time-savings over having to type in information about the sponsor in every event. The next step is to display these entries on your calendar.
Displaying events on your calendar
To display the event on your calendar, you will use an ordinary hyperlink to your single-entry template with a special class (pop-up). The pop-up class will correspond to JavaScript in your HTML header that will call upon the FancyBox jQuery plugin to display the single-entry template in an overlay dialog box. First, you need to enable the jQuery module in your template. 1. First, verify that the jQuery module is enabled. It is enabled by default if you have installed Agile Records. Select Add-Ons | Modules from the main menu and verify that jQuery is marked as installed. If not, click Install in the Status column to install it. 2. Edit the template calendar/index.
[ 191 ]
Creating a Calendar
3. The first change you are going to make is to activate the jQuery module. In the section of the template, add the following tag: {exp:jquery:script_tag}
When saving your template, if you see a warning that no closing tag was found, do not worry. The jQuery tag is a tag that does not require a closing tag.
4. Next, you are going to include the FancyBox jQuery files that are in the fancybox directory that you uploaded to the root of your website. You will link to the main FancyBox JavaScript files, plus the CSS file. Type this code in directly underneath the above tag. <script type="text/javascript" src="{site_url}fancybox/jquery.fancybox-1.3.1.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.mousewheel-3.0.2.pack.js"> <script type="text/javascript" src="{site_url}fancybox/jquery.easing-1.3.pack.js">
Note that if you downloaded the newest version of FancyBox, then the filenames and the version numbers in each of the filenames are subject to change.
5. Now you are going to include the FancyBox code for the pop-up class. This tells FancyBox how you want the lightbox to work. You want the box to be 75 percent of the width and height of the page, with no margin or padding. OverlayOpacity means that you want the calendar page underneath to still be visible, but dimmed. The hideOnContentClick means that if you click anywhere off the lightbox, the lightbox will close. The iframe type means that the lightbox will display the contents of another URL (in this case, your single-entry template URL). For more information on all the FancyBox parameters, please visit http://www.fancybox.net/api. Type this code in directly underneath the above tags (still in the section). <script type="text/javascript"> $(document).ready(function() { $(".popup").fancybox({ 'width': '75%', 'height': '75%', [ 192 ]
Chapter 7 'titlePosition': 'outside', 'autoScale': true, 'margin': 0, 'padding': 0, 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none', 'type': 'iframe' }); });
6. Finally, add your link with the class of popup (that corresponds to the .popup used in the above JavaScript so that FancyBox knows that you want to use FancyBox, and not actually open the link like you normally would). Add the following code after {if entries}, deleting the existing
7. As one date can contain multiple events, this variable pair {entries} applies to each entry. Since this hyperlink applies to each entry, you include it within the {entries} variable pair.
[ 193 ]
Creating a Calendar
8. Go to your calendar and navigate to a month that has events to verify that you can see the hyperlinks.
9. Finally, click on one of the events to verify that your single-entry template appears with the correct information in a FancyBox overlay. If your event does not appear in a pop-up window, but rather opens in a separate window or tab, there are a number of things you can check. First, verify that the fancybox directory is at the root of your website and that you can access the files in your browser (if not, check your .htaccess file). Next, verify that the paths in the calendar/ index template point to the script/CSS files in the fancybox directory and check the filenames for misspellings.
[ 194 ]
Chapter 7
Your calendar is now complete. As you can see, the calendar functionality in ExpressionEngine is limited in what it can do and is certainly not as flexible as specialized calendar applications. However, for simpler designs, it is quite functional.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. [ 195 ]
Creating a Calendar
1. Currently, your calendar displays the days of the week using single letters (for example, M, T, W). Modify this so that the first three letters of each weekday are displayed (for example, Mon, Tue, Wed). 2. Underneath your calendar, display the next event that is coming up (no matter what month is being displayed on the calendar).
Summary
In this chapter, you took a look at the calendar functionality in ExpressionEngine. You also got to see a working example of related entries and how it can help you reduce repetition in your channels. The calendar functionality can be daunting for beginners, as there is a lot of code involved. However, once mastered, the calendar is very flexible in terms of what you can display on it, how it is displayed, and how it all works together. The key points to remember after working through this chapter: •
The calendar functionality uses all the usual channel features that you know and love—custom fields, categories, status groups, and the Publish page. You can create channels with as many custom fields as you want, although you can only display the title field on the calendar itself.
•
Related Entries is when the contents of one channel are included in another channel. Although the events calendar was a natural choice, it could be used for any kind of channel. For example, if you have a recipes channel, you may have a second channel for common sub-recipes (such as making a pie-crust). In this way, you can have 14 different recipes that call for a pie-crust and you do not need to type out the instructions to make the pie-crust 14 times. Reducing repetition by using related entries also makes your website easier to maintain and update (for example, if you wanted to adjust your standard pie recipe, you only have to do it in one spot instead of in 14 places).
•
Related Categories has nothing to do with Related Entries. Related Categories is when two entries in a channel share a category and can therefore be considered to be related.
[ 196 ]
Chapter 7
•
The jQuery module allows you to use jQuery on your website without having to download it yourself (it comes included with ExpressionEngine). ExpressionEngine also masks where the jQuery file is, so it does not reveal the location of your system directory. Teaching jQuery is beyond the scope of this book, but when used thoughtfully, it can enhance the usability of a website.
In the next chapter, you will be building a photo gallery in ExpressionEngine.
[ 197 ]
Creating a Photo Gallery Although ExpressionEngine 2 does not come with a built-in photo gallery module, it does have many features designed to make working with photos easier. In this chapter, you will create a photo gallery channel, use file manager to manage your photos, and use jQuery to display the photos on your website. This chapter uses the FancyBox jQuery plugin that you set up in the previous chapter. If you did not follow the previous chapter, please follow the instructions in Chapter 7, Creating a Calendar under Setting up FancyBox
Although this chapter focuses on building a tool for Ed & Eg to share their personal photos, the techniques in this chapter will be useful in any situation where you want to display images—whether personal photos, a portfolio of your work or items for sale.
Designing your photo gallery
There are many different ways you can approach creating a photo gallery in ExpressionEngine. At the most basic level, you have a choice between each channel entry containing only one photo (and a description) or each channel entry containing a set of photos. If you allow only one photo per entry, you can use categories to organize the photos into galleries (and you can even include the same photo in more than one gallery). If you allow multiple photos per channel entry, each entry represents a photo gallery by itself. One way to accommodate multiple photos per entry is to create as many custom fields as the photos you think you will have in a gallery. For example, if you know each gallery will have a maximum of 20 photos, then you could create 20 custom fields for the photos and 20 custom fields for the descriptions. This solution works, but is not the most flexible (that is, to add 21 photos to a gallery, you would have to modify your custom fields and your templates).
Creating a Photo Gallery
An alternative approach to accommodate multiple photos per entry without creating an abundance of custom fields is to use a third party add-on such as Matrix by Pixel & Tonic (http://pixelandtonic. com/matrix). This add-on allows for tabular data in channel entries— you define the column headings (such as the photo and the description) and then add a row in the table for each photo. In each channel entry, you can create as many rows as you need. For example, you can create one entry with 12 photos and another entry with 25 photos.
Rather than creating lots of custom fields, or using a third party add-on, this chapter will show you a simple and elegant way to create a photo gallery using the one photo per entry design and then will use categories to organize the photos into galleries. Before you create your photo gallery channel, you first need to define where your photos will be stored.
File manager
The file manager is where you can upload new photos or crop, resize, rotate, or delete the images you have already uploaded; all from within the ExpressionEngine control panel. For this photo gallery, you will create a new upload destination—this is the directory on your server where ExpressionEngine will store your photos. 1. The first step in creating a new upload destination is to create the new directory on your server. Create a new directory called photos in /images. If you are following along on an actual web server, ensure that the new directory has 777 permissions (usually right-clicking on the directory in your FTP client will allow you to set permissions). If, instead of creating a new sub-directory inside the /images directory, you prefer to create a new top-level directory and you are using the .htaccess exclude method to remove the index.php from ExpressionEngine URLs, then be sure to add the new directory to your .htaccess file.
2. Next, you need to tell ExpressionEngine where this directory is. Inside the control panel, select Content and then File Manager.
[ 200 ]
Chapter 8
3. On the left-hand side of the screen, you will see the directory or directories where you can currently upload files to (if any), along with the files currently in each directory. In the toolbar on the right-hand side, underneath File Tools, select Create New Upload Destination.
4. Enter a descriptive name of Photo Gallery. The Server Path and URL may be pre-filled, however, you should make sure they point to the actual directory you just created (/images/photos). If you are following along in a localhost environment, the URL would be http://localhost/images/ photos. Leave Allowed File Types as Images only.
[ 201 ]
Creating a Photo Gallery
5. All the fields that begin with maximum can be left blank. These fields allow you to restrict the size, height, and width of photos. If you do enter values in here, and then later try to upload a file that exceeds these limits, you will see an error message such as The file you are attempting to upload is larger than the permitted size. 6. Set the Image Properties, Image Pre Formatting, and Image Post Formatting to be blank. These fields allow you to enter code that appears inside, before, and after the img tag. However, you can format your img tag as needed inside your template.
7. The File Properties, File Pre, and Post Formatting can be ignored for now as they only apply to non-image files that you upload (and you have specified that you are only allowing images in your photo gallery). 8. If desired, you can allow certain member groups to upload files. The member groups you see listed (if any) will depend on the member groups you have. Set all the member groups to Yes except for Members, which should be set No.
[ 202 ]
Chapter 8
9. Click Submit and your new upload destination will be ready to go. Go back to the file manager and you can see the new photo gallery upload destination with no files.
Creating your photo gallery channel
Now that you have created a place to store your photos, you can create your photo gallery channel. As with every other channel you have created in this book, you will follow the same basic steps—creating custom fields and categories, creating your channel, publishing some entries, and then building your templates.
Creating your custom fields
Since you are going to have one photo per channel entry, you have a lot of flexibility to create as many custom fields for each photo as you see fit—for example, you could have fields to capture the location of the photograph, the subject of the photo, the type of camera that was used, the name of the photographer, and so forth. However, to keep things simple, you will only create two custom fields right now—one for the photo itself and one for the description. 1. From the main menu of the control panel, select Admin, Channel Administration, and then Custom Fields. 2. Select Create a New Channel Field Group and call the new group photos. Click Submit. 3. Next to the new group, select Add/Edit Custom Fields and then select Create a New Custom Field.
[ 203 ]
Creating a Photo Gallery
4. The field type will be File. The field label will be Photo and the field name will be photos_photo (the first part representing the field group name). In the instructions for the field, indicate that photos in the photo gallery should be no more than 600x800 pixels (so that they fit on a typical computer screen without scrolling). You could also prevent photos that are bigger than 600x800 pixels from being uploaded by specifying the maximum width and height in the File Upload Preferences for the photo gallery upload destination. You have not done this here because it would prevent you from being able to upload a larger photo and then re-size it using file manager.
5. The field should be required, but not searchable, and should be shown by default. The field display order should be 1 and the file type should be Image. Click Submit. 6. Click Create a New Custom Field again. This time, the field type should be Textarea, the field label Caption, and the field name photos_caption. The field instructions can be left blank. Answer Yes to it being a required field, being searchable and being shown by default. The Field Display Order should be 2. 7. The number of rows can be left as 6 and the default text formatting should be set to Auto
(this will prevent unwanted whitespace in your captions due to extra paragraph tags being added, but will also allow multi-line captions). Say No to allowing an override on the Publish page. The text direction can be left as left-to-right. [ 204 ]
Chapter 8
8. Finally, say Yes to Formatting Buttons, Spellcheck, and Write mode. Say No to Smileys, Glossary, and the File Chooser. Click Submit to create the new field. Now that you have your custom fields, you can define your categories.
Creating your categories
As discussed at the beginning of this chapter, you are going to use categories to distinguish between photo galleries. To start with, you are going to create two photo galleries—one for vacation photos and one for local photos. You can always come back and add more galleries later. 1. Still in the control panel, select Admin, Channel Administration, and then Categories. 2. Select Create a New Category Group and name it Photo Categories. Select Allow All HTML in the category field formatting and check the boxes to allow other member groups to edit (or delete) categories as appropriate. (If you see a message saying that there are no member groups allowed to edit/ delete categories, this is fine too). Click Submit.
3. Back on the Category Management screen, select Add/Edit Categories for the Photo Categories category group.
[ 205 ]
Creating a Photo Gallery
4. Click Create a New Category. The first category will be called Local Photos. The Category URL will default to local_photos. Type in a category description (you will later display this on your website), leave the Category Image URL blank, leave the Category Parent set to None, and click Submit.
5. Select Create a New Category again. This time call the new category Vacation Photos, with a URL of vacation_photos. Type in a category description such as A selection of vacation photos taken by Ed & Eg. Leave the category image URL blank and the category parent as None. Click Submit.
Now that you have your category group and custom field group defined, you can go ahead and create your channel. [ 206 ]
Chapter 8
Creating your channel
The process of creating your channel is straightforward. 1. Select Admin | Channel Administration | Channels. 2. Select Create a New Channel. Call the new channel Photos with a short name of photos. Do not duplicate an existing channel's preferences. Select Yes to Edit Group Preferences and select Photo Categories for the category group, Statuses for the status group, and photos for the field group.
3. Answer No to creating new templates and then click Submit. Your channel is created! Now you can start creating some content and displaying the photos on your website.
Uploading your first photos
There are three ways to upload photos to your website. Your first option is to go to File Manager (under the Content menu) and select File Upload on the right-hand toolbar. Alternatively, you can go to publish an entry in the Photos channel, click on Add File, and upload a file. Both of these options are convenient since they use the built-in ExpressionEngine file manager to upload your file—you never have to leave the control panel. However, you can upload only one photo at a time and you may run into issues if you try and upload very large photos (greater than 2 MB).
[ 207 ]
Creating a Photo Gallery
The third option for uploading photos is to do so directly, using FTP, just as you would upload any files to your website. Since this requires another tool, it is less convenient than uploading a single photo from within ExpressionEngine, but if you are uploading lots of photos, then using FTP is a lot faster to do. That is the method we will use here. The built-in file manager also allows you to crop, resize, and rotate images (although you can take advantage of these tools even if you do not use file manager to upload the files).
1. Download the example photos (local1.jpg through local8.jpg and vacation1.jpg through vacation8.jpg) from either the Packtpub support page at http://www.packtpub.com/support or from http://www. leonardmurphy.com/book2/chapter8. (Or you can substitute your own photos). 2. Copy or FTP the photos into the /images/photos directory that you created earlier in the chapter. 3. Back in the ExpressionEngine control panel, select Content | Publish and then select the Photos channel. 4. Type in a title of Fireworks and a caption Fireworks exploding with a bang. Then select Add File. 5. The first screen to appear in the Upload File screen. Since you have already uploaded the files, you can simply select the photo gallery option in the lefthand menu. If no photos appear under the photo gallery, or the files appear but no thumbnails appear, try logging out of the control panel and logging back in. (This helps to refresh ExpressionEngine so it recognizes the new files—the first time you access the files after uploading via FTP, ExpressionEngine has to create the thumbnails).
[ 208 ]
Chapter 8
6. Select local1.jpg.
7. On the Categories tab, select Local Photos. Then click Submit. 8. Now, repeat the same steps to create entries for the rest of the photos, using appropriate captions that describe the photos. Be sure to select a category for each photo. There are 16 example photos (eight local and eight vacation photos). Having several example photos in each category will demonstrate how the photo gallery works better.
Creating your templates
As with everything in ExpressionEngine, everything that appears on your website must be coded in a template. Your photo gallery is no exception. You will now create new templates in a design very similar to the one used by the FAQs channel—a single-entry template called comment so that visitors can leave comments on individual images, and a multiple-entry page where visitors can browse and view images by category. You will start with the single-entry page.
[ 209 ]
Creating a Photo Gallery
Creating the single-entry page
The single-entry page is where an individual photograph is displayed, along with the caption and any comments. In this section, you will create a new template group called photos and then create a new template called comment (since the primary reason to visit the single-entry template will be to view and post comments). 1. From the main menu, select Design, Templates, Edit, and then Create Group. Call this template group photos. Do not duplicate a group and do not make the index template in this group your homepage. Click Submit. 2. Next, with the photos group highlighted on the left-hand side, select New Template. Call the template comment and leave the template type as Web Page. Since your single-entry page here will be very similar to the singleentry page you created for the FAQs channel, select Duplicate an existing template and then choose the faqs/browse template to duplicate. Click Create and Edit.
[ 210 ]
Chapter 8
If you did not follow Chapter 5, Creating a Fully-Equipped Channel completely and do not have an faqs/browse
template to duplicate, it can be downloaded from http:// www.packtpub.com/support or from the chapter 5 page at http://www.leonardmurphy.com/book2/chapter5.
3. Whenever you copy a template, the first thing to update is the Preload Text Replacements at the top. Update them to the following: {preload_replace:my_channel="photos"} {preload_replace:my_template_group="photos"} {preload_replace:my_single_entry_template="comment"}
4. Further down in the template, delete all the code between (but not including) the
{title}
and the {/exp:channel:entries}. 5. Replace the deleted code with the following code to display your image and your image caption (centered), along with a link to your multiple-entry photos/index template (which is still blank):
<em>{photos_caption}
The limited class is defined in your site/site_css stylesheet as having the property max-width: 555px;. This value matches the width of the #content ID container. Although the channel field instructions ask that photos be no bigger than 600x800, they may still be too big to fit nicely into the #content area without overlapping the sidebar. The max-width property proportionally shrinks images if they are too big, but otherwise leaves the image alone.
6. A lot further down, underneath the line {/exp:comment:form}, remove the Other Questions Like This section: everything from the
to the {/exp:channel:entries} inclusive.
[ 211 ]
Creating a Photo Gallery
7. Click Update and visit an example photo (such as http://localhost/ photos/comment/fireworks). If you uploaded photos with different titles, then remember that because this is a single-entry page, the last part of the URL (in this case, fireworks) is actually the URL Title from the entry to be displayed. You can replace this with the URL Title of another entry in your channel, and that entry will appear instead. Refer to Chapter 5, Creating a FullyEquipped Channel for more information on single and multiple-entry pages and how they work. If something does not look right in your single-entry page page, compare your code with the final code for the template, downloadable at either http://www.packtpub.com/support or http://www. leonardmurphy.com/book2/chapter8.
[ 212 ]
Chapter 8
Your single-entry page is complete! Go ahead and try adding comments if you like— both as a member and a visitor. Next up, you will create your multiple-entry page where visitors will be able to browse photos by category.
Creating the multiple-entry page
The multiple-entry page needs to attractively display a series of photos so that your visitors can quickly browse to the photos they are most interested in. A visitor browsing your photo gallery will likely spend a lot of time on this page. Although you will use thumbnails to display the photos on your multiple-entry page, you do not have to force visitors to go to your single-entry page in order to view a larger image. Instead, you can use jQuery and the FancyBox plugin that you used in the previous chapter. When a visitor clicks on a photo, a full-size version will appear in a FancyBox overlay, complete with caption. Visitors will be able to quickly scroll through the larger images directly from the FancyBox plug-in. Underneath each thumbnail, a link can take visitors who wish to leave comments to the singleentry page where they can do so. If you did not follow the previous chapter, please, at least, follow the instructions under the heading Chapter 7, Creating a Calendar under the Setting up FancyBox section.
Rather than re-inventing the wheel, you can base the multiple-entry page template on the calendar/index template that you created in the last chapter. (If you did not follow the previous chapter, you can download the template from http:// www.packtpub.com/support or from http://www.leonardmurphy.com/book2/ chapter7). 1. In the ExpressionEngine control panel, copy the calendar/index template code and paste it into the photos/index template. You will see a message indicating that no closing tag was found for {exp:jquery. Ignore this message as this tag is one of those that do not require a closing tag. 2. Update the Preload text replacement at the top to the following: {preload_replace:my_channel="photos"}
3. Update the
[ 213 ]
Creating a Photo Gallery
4. The calendar/index template used its own stylesheet with extra calendar formatting—since you do not need to do this, change the stylesheet back to includes/site_css:
5. Your calendar uses a pop-up class attribute to display links in a pop-up iFrame FancyBox. Since you will be displaying images rather than an entire page in this FancyBox, you can set different options. Specifically, you should remove the type of iFrame, display the caption inside the pop-up box (on the calendar you had it display outside so that it did not blend in with the iFrame content), and set cyclic to true—meaning that as someone cycles through the images, once they reach the end of the set, the images will loop back to the start. Finally, do not set any limitations on the width or height of the FancyBox—you can allow the pop-up to auto-size itself to the size of the image being displayed. To accomplish all this, replace everything currently between <script type="text/javascript"> and with the following (leave the <script> tags as-is): $(document).ready(function() { $("a.gallery").fancybox({ 'cyclic': true, 'titlePosition': 'inside', 'overlayShow': true, 'hideOnContentClick': true, 'overlayOpacity': 0.7, 'transitionIn': 'none', 'transitionOut': 'none' }); });
For more information on FancyBox, including what the different options mean, you can visit http://fancybox.net/.
6. Finally, remove all the code that appears between (and including)
Seminar Calendar
and {/exp:channel:calendar}. This is where your photo gallery thumbnails will eventually go. Click Update to save your work so far. At this point, you have a blank page (with a relevant page title and a FancyBox script that is ready for you to start using). Now you can start adding content.[ 214 ]
Chapter 8
Adding content to your multiple-entry page
There are going to be two ways to browse your photos—visitors may go to the main photos/index page, where they will see all your photos. Alternatively, they can go to a category-specific page, where they will only see photos that fall into that category. Just like you did with your faqs/index template, you are going to use conditional statements to distinguish between when a visitor is on a category browsing page versus when they are not. Remember that a category browsing page will have the word category in segment 2 of the URL. 1. Still in the photos/index template, add the following code after
{category_name}
{category_description}
Browse all photos
Photo Galleries
<strong>Instructions: Select a gallery to view or click on a photo to see enlarged. When viewing in enlarged mode, use your left & right arrow keys to scroll between photos and the escape key to exit enlarged mode.
{/if}[ 215 ]
Creating a Photo Gallery
2. Next, you can create a drop-down category selector to allow visitors to jump quickly to a given category. This code is adapted from the Channel Categories Tag documentation viewable at http://expressionengine. com/user_guide/modules/channel/categories.html#dropdown. It essentially uses a standard HTML drop-down form, populated with options from the channel categories tag that link to the photos/index template (though you specify only the template group photos, ExpressionEngine knows you mean photos/index because the index template is the default template). Add the following immediately after the previous code:
3. Click Update and then visit your photo gallery (at http://localhost/ photos). Verify that you can browse between categories and that when you are on a category page, you see the category information, and when you are not, you see the generic instructions. JavaScript must be enabled in your browser for the drop-down menu to work.
[ 216 ]
Chapter 8
4. It makes sense to display the thumbnails in a table. Since every gallery could have a different number of thumbnails, it is impossible for you to know in advance how many rows your table might need. You will therefore use a suggestion from Mark Bowen in the ExpressionEngine wiki (http:// expressionengine.com/wiki/Entries_In_Table/) to use the {switch} variable to insert a row break (
5. Add the following code immediately after the :
***Image will go here*** | {if count!=total_results}{switch="||||
[ 217 ]
Creating a Photo Gallery
6. If you visit your website now, you will see a table where your images will go as well as some placeholder text. If you browse between the different galleries, you will see a different number of table rows depending on the number of images that are in that category.
7. The next step is to replace the placeholder text with actual thumbnails. When designing your custom fields, you did not include a field for a thumbnail. Whilst you could include the full-size image with a small width/height, your visitors would then have to download all the full-size images in order to see this page—significantly impacting page load times. Instead, you can use thumbnails that are automatically generated by ExpressionEngine. 8. Whether you upload photos via FTP or via file manager, ExpressionEngine automatically creates thumbnails of any photos in a _thumbs subdirectory (/ images/photos/_thumbs) when you first view them in file manager. These thumbnails are used internally by ExpressionEngine, but you can also use them on your visitor-facing pages. To do this, you will use the custom File field (photos_photo) as a tag pair instead of as a single tag. This allows you to access the different components of each file (the path, the filename, and the extension) in each entry separately. By doing this, you can then insert the _thumbs subdirectory to the end of the path, and prefix the filename with the thumbs_ prefix that is automatically added to the thumbnails.
[ 218 ]
Chapter 8
For more information about using the File custom field as a tag pair instead of as a single tag, please visit http:// expressionengine.com/user_guide/modules/ channel/custom_fields.html#file_fields
9. Replace the ***Image will go here*** placeholder text with the following code:
If, after doing this, you have some thumbnails that are not showing up, you may need to log into ExpressionEngine, edit the entry in question, and re-add the photo using file manager. Make sure you can see the thumbnail in your entry before you submit it.
10. Visit your website again, and you will see thumbnails instead of the placeholder text you had before. Additionally, if you click an image, it will pop up in a FancyBox lightbox, with the caption underneath. This is because you gave the link a class attribute of gallery (which matches the class attribute you used in your FancyBox script). You can scroll through the photos in the FancyBox by clicking the left and right arrows or by using your mouse scroll wheel—this is because all the photos on the page have the same rel attribute, letting FancyBox know this is an image gallery. FancyBox treats whatever is in the title attribute as a caption—in this case, you included the {photos_caption} caption.
[ 219 ]
Creating a Photo Gallery
If your image does not appear in a pop-up overlay, but rather opens in a separate window or tab, you can check for a number of things. First, verify that the FancyBox directory is at the root of your website and that you can access the FancyBox files in your browser (if not, check your .htaccess file). Next, verify that the paths in the photos/index template point to the script/CSS files in the FancyBox directory and check the filenames for misspellings. Then, compare the photo/index template you have created with the photo/index template that is available for download from http://www.packtpub.com/support or http://www.leonardmurphy.com/book2/chapter8. Look carefully for any spelling mistakes or typos, especially in the code and <script> sections, as well as in the link code for the thumbnails. Finally, ensure that JavaScript is enabled in your browser.
11. The final step is to include a link to your single-entry page for visitors who want to leave comments. This can be accomplished by using a hyperlink underneath each photo that will mention how many comments have already been made. Add the following code immediately before the in your template:
{if comment_total=="1"}1 comment{if:else}{comment_total} comments{/if}
12. Now visit your photo gallery page and you will find the new hyperlinks. Click on one to confirm that you are taken to the single-entry page. Add a comment and verify the total increments correctly. If you have comment moderation turned on, you will have to mark the comments as open before they will be included in these counts (although if you are logged in as a Super Admin, you will be able to see the comments on the single-entry page). To mark a comment as open, select Recent Comments from the View section of the control panel home page, click on the comment you wish to open and then click View Comments. Here you can check all the comments you wish to open, and from the drop-down box, select Open Selected and click Submit.
[ 220 ]
Chapter 8
Your photo gallery is complete. You now have an easy way for visitors to browse your photos quickly, either from the main photos/index page or by gallery. It is also easy to see which photos already have comments and for visitors to add their own.
Image editing features
Now that you have gone through the process of creating a photo gallery, uploading images, and creating the corresponding templates, it is a good time to discuss how photos can be cropped, resized, and rotated all from within ExpressionEngine. 1. From the Content menu in the control panel, select File Manager. 2. If you have multiple upload destinations, it is good to know that if you click on the title of one (such as About), it will collapse the list of files. If you click again, the file list will expand. This can help reduce screen clutter. 3. If you select a filename (such as local6.jpg), a FancyBox pop-up will appear with the full size image. (Press escape or click the x in the top-right to close). 4. For the photo local6.jpg, select Edit (in the fifth column from the left).
[ 221 ]
Creating a Photo Gallery
5. At the top-right, there are three modes (Crop, Resize, and Rotate). Select Crop Mode.
6. The picture on the left will darken. To crop the photo, you can drag the rectangle over the picture until the part of the picture you want is framed. The rectangle can be resized or repositioned as needed. On the right-hand side, you can see information about the width, height, and X/Y coordinates of your crop.
[ 222 ]
Chapter 8
7. Once the rectangle is placed, click Save Image on the right-hand side to save your changes. 8. You can also resize the photo by clicking on the Resize option. In this case, setting a width will automatically adjust the height so the photo stays in proportion (and setting the height will automatically change the width). This feature is extremely useful if you want to upload a full-sized image, but then manually adjust it so the width is no more than a certain size (for example). When you upload a photo for the first time from the Publish page, you also have the option to resize an image. In this way, you can upload full-size images directly, and resize them on the fly in ExpressionEngine, rather than shrinking them in advance or uploading them and using the file manager to resize them.
Rotate mode is also fairly self-explanatory. However, be aware that selecting a different rotation (or flipping the image horizontally or vertically) automatically saves the image.
Photo gallery add-ons
In this chapter, you have walked through how to build a photo gallery in ExpressionEngine without using any third party add-ons. As you can see, the functionality in ExpressionEngine is very robust and flexible out of the box. That said, there are times when an add-on can be useful—especially if images are a large part of the content of your website. Pixel & Tonic's Matrix was already mentioned at the beginning of the chapter as a useful add-on for designing a photo gallery with multiple photos per channel entry. In addition, the following add-ons are specific to editing photos (though they are by no means representative of all the add-ons that are available. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available.).
Image sizer
http://devot-ee.com/add-ons/image-sizer/
Written by David Rencher, this plugin takes a large image, dynamically resizes it, and caches the resized image (to reduce page load times). Using this add-on in your template saves you from having to manually resize every image you upload (and eliminates the risk of breaking your page layout if you forget). Instead, images are resized on the fly. Please see Chapter 10, Extending ExpressionEngine for more information on the wide variety of add-ons that are available. [ 223 ]
Creating a Photo Gallery
Channel Images
http://devot-ee.com/add-ons/channel-images/
For a small fee, Channel Images by DevDemon allows you to batch-upload multiple files from within the ExpressionEngine control panel and simplifies image management on the Publish page.
Challenges
These challenges are designed to stretch your knowledge and get you to work handson with ExpressionEngine. The answers will not necessarily be found within the chapter, but with the knowledge gained from the chapter, plus the ExpressionEngine documentation, you should have all the tools you need at your disposal to figure them out. Since the photo gallery uses the same tools as all the other sections of your website, these exercises are not so much specific to photo galleries, but are a good reminder of the techniques learnt in previous chapters. 1. The main page of the photo gallery works great when there are only a handful of photos. However, over time, you could end up with hundreds and hundreds of photos in your channel, all of which would get displayed on your main page. Change the main page so that it limits the number of photos that are displayed and randomizes which photos are shown. 2. ExpressionEngine has the ability to track how many times a channel entry has been viewed on a single-entry page (Entry Views). Using a conditional statement, indicate on your multiple-entry template which photos are ***popular*** photos, based on the number of single-entry page views. For now, consider more than ten single-entry page views to be a sign of a popular photo. 3. The form for submitting comments and the code for displaying comments on your single-entry page are almost identical to the form for submitting comments and the code for displaying comments on your FAQs channel. In the spirit of reducing repetition, choose between a Preload Text Replacement, a Global Variable, a Snippet, or an Embedded Template and extract the code from both photos/comment and faqs/browse, so that both templates use the same code for submitting and displaying comments.
[ 224 ]
Chapter 8
Summary
In this chapter, you took a look at how to adapt the channel functionality of ExpressionEngine to a photo gallery. The lack of a formal photo-gallery module can make ExpressionEngine seem less functional. However, as you can quite clearly see, the standard channel functionality is more than adequate for the task, and indeed allows for a lot more flexibility than a separate photo gallery module might offer— with unlimited custom fields, a multitude of ways that you can organize photos within your channel (using categories and/or status groups), and with no restriction on how you can build your templates, the sky is the limit. This chapter wraps up the step-by-step introduction to ExpressionEngine. By now, you should be fairly comfortable with the basics of ExpressionEngine—channels, templates, tags, custom fields, categories, status groups, and so on. In the next chapter, you will be introduced to some more specialized first party modules that you may find useful.
[ 225 ]
Beyond the Basics So far, this book has introduced the basic concepts and the most commonly used features of ExpressionEngine. Many of the same basic skills have been used time and again such as setting up custom fields and categories, creating a new channel, posting entries to the channel, and building templates with HTML/CSS and ExpressionEngine tags. ExpressionEngine comes bundled with many other modules that may or may not be useful, given your website. The modules range from the simple to the complex—the simplest create additional tags that you can use in your templates, while the most complex include their own configuration pages and library of tags. This chapter looks at some of the offerings, including: •
The Search module
•
The Mailing List module
•
The Email module (create a contact form or a tell-a-friend form)
•
The Moblog module (submit new channel entries via e-mail)
•
The Wiki module The Mailing List and the Email modules rely on ExpressionEngine being able to send e-mails. If you are following along in a localhost environment such as WampServer, XAMPP, or MAMP, you will find that ExpressionEngine cannot send e-mails. This is because a localhost environment does not include an e-mail server. You can either follow along on an actual website server, or if you choose to follow along in your localhost environment, be aware that in places where you would expect ExpressionEngine to send an e-mail, you will not see such an e-mail.
Beyond the Basics
The Search module
ExpressionEngine comes with a pre-built search tool to allow visitors to search your site. Although technically a module, the search functionality comes pre-installed and does not have any special setup. This means that you can start using the search tags right away. There are two parts to enabling search on your website, namely: •
Creating a form that allows visitors to type in and submit search terms (this could be as simple as a search box that appears in your sidebar or it could be an entire template dedicated to an advanced search).
•
Creating templates to display the search results (or that there are no results). The Search functionality only searches channels. The Discussion Forum module and the Wiki module both have separate search functions.
When you design your search forms, you can use parameters to control what is searched. By doing this, you can limit searches to particular channels, status groups, or categories. You can also determine whether you want the search to include expired or future entries (this is important if you are searching a channel, like an events calendar, where all the entries might be in the future). Finally, you can set whether you want to search for words only in channel titles, in all the custom fields of a channel, or in the channel title, custom fields, and comments. Be very cautious if you enable your search to include future entries and the search form searches more than one channel. While one channel might routinely have entries in the future that you want to be searchable, another channel might have future-dated entries that you want to keep hidden until that date/time. The parameters you set for your search form (such as whether to include future-dated entries) apply to all channels that you allow to be searched from that form.
In addition to the search tags, there are three settings in the control panel that control how the search behaves:
[ 228 ]
Chapter 9
1. Is the field searchable? Each custom field in ExpressionEngine can be set to either be searchable or not searchable. Having this field set incorrectly on your custom fields can mean entries not being found that otherwise would be. As a general rule, fields that contain content such as sentences and paragraphs should be set to searchable, but fields such as drop-down boxes or files should not be searchable. To change the searchable setting for any individual field, go to Admin | Channel Administration | Custom Fields, and then select the field group and the field you wish to edit. You could create a custom field on a channel that is searchable, but that is not displayed on your website. This field could then be used to store likely search-terms for each individual entry that might not otherwise appear in the article (such as variations in spelling), thus improving the possibility that meaningful results are returned for people searching your website.
2. Search Page URL. Each channel has a path that is used to link the search results to the actual entries that were found. If this path is set incorrectly, clicking on a given search result will send the visitor to a wrong page. The field should be set to the single-entry template for the channel. (For example, the Photos channel should be set to http://localhost/photos/ comment). To change this setting for a given channel, go to Admin | Channel Administration | Channels, then click Edit Preferences for a specific channel, and look under Path Settings. 3. Which field should be used for search excerpt? This is also found under Channel Preferences, under Administrative Preferences. This defines the custom field from which the excerpt displayed on the results page comes from. To demonstrate the search functionality, you will create a search box in the sidebar that searches both the FAQs and the Photos channels. Before you begin, ensure that the Search Page URLs for these two channels are set to http://localhost/faqs/ browse and http://localhost/photos/comment respectively.
Adding a search box to your site
In this section, you will create a search box in the sidebar for Ed & Eg's website, thus allowing visitors to start a search from any page they like. 1. Go to Design | Templates | Snippets and edit the website_sidebar snippet.
[ 229 ]
Beyond the Basics
2. In the snippet, add the following code immediately after the final and before the final . Notice the parameters—the channel parameter restricts the search to the FAQs and Photos channels. The search_ in="everywhere" parameter means that you want the search to include titles, custom fields, and comments. The where="any" parameter means that entries containing any of the searched-for words will be returned (as opposed to requiring an exact match). The status parameter means that you will include entries with a status of open or premium (the premium status was one that you created in Chapter 6, Members, and if you did not include it explicitly, only entries with an open status would be searched). Finally, the result_page and no_result_page define which templates should be used when there are results or when there are no results (in this case, the search/ index and search/noresults templates, which you are yet to create). The rest of the code is a standard HTML form (although the input box must have the name="keywords" attribute for the search form to work). For more information on each of these parameters, including alternative settings for them and additional parameters not included here, please visit http://expressionengine.com/user_guide/modules/ search/simple.html.
{/exp:search:simple_form}
3. If you visit the home page of your website, you should now see the search box on the right-hand side. If you have the Agile Records example website template groups still installed, searching will result in the Agile Records themed advanced search template being returned—otherwise, you would get a 404 page. You will create the search result templates next.
[ 230 ]
Chapter 9
Creating a search results template
The search results template is specified in the parameters of the search form as search, which translates to the search/index template. Had you not defined a specific template, the search results template would be set to search/results. If Agile Records is installed, then you are likely to already have a search template group which you can adapt to display your results. Otherwise, go ahead and create a search template group now. 1. The first step is to start with your basic site outline (header, sidebar, and so on). You can accomplish this by copying the includes/404 template into the search/index template. Edit the search/index template and paste in a copy of the code from includes/404. 2. Change the title of the page to be:
3. Change the
heading to be Search Results: Search Results
4. Replace the next paragraph (that talks about the page not existing) with the following. The {exp:search:keywords} tag displays the keywords used for the search.
You searched for <em>{exp:search:keywords}.
If you see a warning about there not being a closing tag when you save your template, ignore it. The {exp:search:keywords} tag is one of those that does not have a corresponding closing tag.
[ 231 ]
Beyond the Basics
5. Underneath the preceding paragraph, insert the following code (adapted from the code found at http://expressionengine.com/user_guide/ modules/search/results.html). This displays your search results in a two-column table. The first column will have the entry title and the second column will have an excerpt from the entry (the first 50 words from the field designated as the search excerpt field in your channel preferences). First create the table and the header row.
Title | Excerpt |
---|
The pagination code at the end works similarly to channel pagination—allowing a long list of results to span multiple pages.
6. The following code uses the {exp:search:search_results} tag to display the actual results. This tag loops through once for each result you have. In this case, a new table row is created for each result. The switch tag makes the first row light-gray, the next white, the third light-gray, and so on. (Remember from the photo gallery chapter that the switch tag uses the first switch for the first result, the second switch for the second result, and so on, until it runs out of switches, when it starts over). Prior to the entry title, the channel name (such as Photos: or FAQs:) is added to make it clearer what kind of entry is being linked. Underneath the entry title, the number of comments that the entry has received is displayed. Add this code after the closing
Chapter 9 {exp:search:search_results}
{if comment_total=="1"} 1 Comment {if:else} {comment_total} Comments {/if}
Within the {exp:search:search_results} tag, there are some special variable tags you can use, including {auto_path} and {excerpt}. {auto_path} creates a path to the entry using the Search Page URL, defined in the channel preferences, and {excerpt} displays the first 50 characters of the excerpt field defined in the channel preferences. You can also use tags (such as {comment_total}, {author}, or {entry_date}), which are normally available in the {exp:channel:entries} tag. More information on search resultspecific tags can be found at http://expressionengine.com/user_ guide/modules/search/results.html and information on channel entry tag variables can be found at http://expressionengine.com/ user_guide/modules/channel/variables.html.
[ 233 ]
Beyond the Basics
7. Now click Update and Finished, go to your website, and search for something (for example, money). Your results will be displayed.
The no-results template
One other template you defined in your website_sidebar snippet was a no_ result_page of search/noresults. This can be a simple template that uses {exp:search:keywords} to display the search term and indicates that no results were found.
1. In the Search template group, create a new web page template called noresults. If you already have a results and a no_results template in the search template group, you can go ahead and delete these. 2. When creating the template, select to duplicate an existing template and duplicate search/index. Click Create and Edit. 3. Delete all the code from (and including) the
immediately above the
{lang:weekday_short} | {/calendar_heading}