The goal of this guide is to take you step by step through the full process of using Drupal’s CCK and Views modules (as well as a number of other supporting modules) to create customized content types (e.g. news posts, articles, etc), as well as “listing” pages and blocks to display teasers of your content, and then theming everything to look exactly as you intend.
For the purpose of this lesson, a new Content Type called “Article” will be created, and a number of custom fields will be added to it. You can, however, apply this lesson to any other content type you wish to create or have already created. For full control, specific fields will be set up ahead of time for the content type using CCK, so that certain specific fields will be displayed in the teaser view but not on the full page view of the Article content, and certain fields will show only on the full Article pages but not in the teaser views of the content.
Please do not be alarmed at the length of this guide - its length is only due to very thoroughly described steps to make this guide as beginner-friendly as possible. Each step is numbered so you can more easily keep track of your place in the guide.
After completing this lesson, you will have built up skills working with CCK, Views, theming (including theming of a specific content type, use of the Contemplate module, and Views theming), as well as knowledge of Pathauto and Custom Breadcrumbs.
A planned expansion of this article will include the addition of a thumbnail image in the teaser with the full size image in the article itself (using Imagefield and Imagecache), including all the theming code necessary.
highlighted. When you see highlighted text, you should copy/paste it into the specified settings field or template file on your site.This first section of the guide will help you construct a custom “Content Type” called Article using the CCK module, as well as a variety of custom fields.
After completing the CCK section of the guide, you will have developed skills working with CCK that you will be able to re-apply to your own site in the future. You’ll also have gained an understanding about how URL aliases (also known as Paths) work in Drupal, as well as how to make Custom Breadcrumb links for your content types.
If you have a WYSIWYG editor installed (such as the popular TinyMCE or FCKeditor, among others), it can potentially get in the way of the settings/configuration forms on many of Drupal’s administration pages (often inserting HTML code in places that break your settings). As such it is best to disable the WYSIWYG editor ahead of time for all areas of your site “except” for the content creation/publication pages where it is actually required. Though the process for doing this varies between editors, fortunately most include the means to allow you to choose whether they should be enabled or disabled for any given area of your site. It’s much better to choose the few places where the WYSIWYG editor “should” show up, rather than the countless places where it should “not”.
include.node/*user/*comment/*Similar steps may be necessary for other WYSIWYG editors. Please refer to the documentation as well as the settings page of your WYSIWYG editor module.
Begin by going to Administer > Content management > Content types (admin/content/types) and clicking the “Add content type” link at the top of the page.
ArticlearticlePromoted to front page option.The custom fields will include article_teaser_text to serve as a custom-written teaser which will be displayed only in the context of teaser views of the content but not on the full article, and article_subtitle, which is a sub-title about the article that will only be shown on the full version of the page but not in the teaser. You can of course add as many additional fields as you need.
article_teaser_text, and for Label enter: Article Teaser.Text and press “Continue”.Text field, and press “Continue”.Text area (multiple rows). Keep in mind that with most WYSIWYG editors, setting a text field to be “multiple rows” usually activates the editor on that text area, which is probably excessive in this case (though your WYSIWYG settings page may allow you to selectively disable these). Generally for a small text field of this sort I don’t recommend HTML, and especially not WYSIWYG. If you change your mind you can always adjust this setting later.Required option, and enter a number for Maximum length such as 100 (it’s usually ideal to set a maximum number of characters for the teaser to ensure it fits within the area you allot to teasers in your theme, and to enforce keeping teasers short and to the point for your readers). It’s worth noting that Maximum length can only apply to a Text field kind of field — the HTML textarea tag that the Text area (multiple rows) option creates is not capable of having a maximum length set (which is a limitation of HTML itself, not Drupal - you can however impose a maximum length on this tag using JavaScript).Filtered HTML (again not recommended, as the HTML counts towards the character limit, not to mention the purpose here is just a short bit of teaser text so ideally it should be kept simple… save the fancy stuff for the full article).article_subtitle, and for Label enter Article Subtitle.Text and press “Continue”.Text field, and press “Continue”.Required option, but you can choose to make this optional if you prefer.Hidden, Teaser to Hidden, and leave Full Node set to Default.Hidden (the reason for this is because this field will “only” ever be used within the context of Views module, which will call it up in its own way, so we want to hide it in every other case).Before continuing, it will help you to understand a bit about “how” URL paths in Drupal work, and how that applies to what you’re trying to accomplish in following this gude. The terms URL, path, and alias are often used interchangeably in Drupal.
Our goal in this guide is to set up URL paths like this:
example.com/articles
This will be for the index/listing of all the articles, and will be handled by the Views module, covered in a later section of this guide.
example.com/articles/name-of-article
This is the path for the pages (nodes) created for the “Article” Content type. Nodes receive their URL paths through the Path or Pathauto module. Path is a module that comes with Drupal by default and lets you manually make up URLs for pages as you create them, while Pathauto is an add-on module which automates this process, following pre-determined settings which you customize ahead of time before creating the content. In this lesson the Pathauto module will be used.
Although they appear “connected” (similar to how files are placed inside a folder), the example.com/articles path made by Views module and the example.com/articles/name-of-article paths for content are not actually connected to each other internally (however, so long as they’re set up correctly, they will “appear” and function as if seamlessly connected to each other).
Think of it along the lines of the “files inside a folder” analogy. The files are the Article content/nodes you create, and the folder is the index or listing of those Articles (articles/), which is created separately by the Views module. This isn’t how it actually functions beneath the surface (files and folders), but should help you understand the structure of the URL path.
After you’ve created a Content Type (and before you create any content for it), the first stop you should make is Pathauto. In Drupal 6, the settings for Pathauto have been joined into the URL aliases setting page, and are located at Administer > Site building > URL aliases > Automated alias settings (admin/build/path/pathauto). In Drupal 5, Pathauto’s settings can be found at Administer > Site configuration > Pathauto
(admin/settings/pathauto).
In case you’re wondering why it’s best to set up Pathauto “before” making content, it’s because the creation of content adds a URL alias to Drupal - if you haven’t customized how the alias should be set up, Drupal (or Pathauto if installed) uses the default settings (e.g. Drupal makes node/# and if Pathauto is installed it instead makes content/page-title). Once an alias is made, it has to be deleted in order for Pathauto to “remake” it the way you prefer.
Note: In case you do have pre-existing URL aliases which were made before installing Pathauto and/or before reading this, then it’s simple to clear the old ones out and automatically generate the new customized ones. If you do not have “custom” aliases that you wish to keep (e.g. written by hand), you can simply click on the “Delete aliases” link at the top of the URL aliases page (admin/build/path/delete_bulk). From here you can check the content checkbox and press the “Delete aliases now!” button. Don’t worry - in the next step with Pathauto you’ll be able to regenerate aliases for every page on the site, according to your exact settings, with the click of a button. If you happen to have hand-written custom URL aliases and can’t delete them all like this, consider switching to allow Pathauto to handle all of your paths to make things easier for yourself - if not you can still delete aliases on a case by case basis from the List view of “URL aliases”.
articles/[title-raw]
Note: This is where what was explained earlier on this page in “Understanding Drupal Paths” comes into play - the articles/ part of the path here is just a placeholder for the View, making the article both appear and function as if it were “within” the articles/ listing page (“folder”). In this way, the paths will also behave logically the way a site visitor would expect them to (like files inside a folder), allowing them to remove the end of an article’s path and arrive at the index/listing of all the articles.
Bulk generate aliases for nodes that are not aliased option.Breadcrumbs are a valuable and well-understood way to improve navigation on a website. Breadcrumbs allow you to “leave a trail” from the page you are currently on (e.g. an Article), up the structure of your site and back to the home page. You can see an example of them in action on this site even (have a look at the top of the page below the logo).
If your theme has included them (as most do - if not, you should add <?php print $breadcrumb; ?> to your page.tpl.php file), Article content that you create will already show breadcrumbs. However by default they will show only as “Home” (which is not all that helpful). The Custom Breadcrumbs module will allow you to customize this so that a link to the “Articles” listing page will be included: “Home › Articles” (in both cases the Name of the Article is shown below as the page title/heading). The breadcrumbs are not limited to a single level either (if you have a reason to, you could include as many levels of links as you’d like).
Article from the Node type drop down menu.Articles, and in the Paths field, enter articles. Leave the Breadcrumb visibility field empty. Press the “Submit” button to proceed.Now that the Content Type is complete, you should now go ahead and create one or more pages of Article content to use for testing throughout the remainder of this gude (they can just be fake/test pages for now). Go to Create Content > Article, fill in all of the fields, and “Save” the content.
After saving the Article, you’ll notice that:
Later in the guide you’ll learn how to theme these Article pages to look exactly the way you want them to.
In this second section of the guide, you will be introduced to the powerful Views module.
You will create an Articles View, which will be used to show a full page listing of all the Article content you’ve created (the /articles page referred to in the preceding section), as well as a smaller listing of the latest Articles in the form of a Block, which you can include in the sidebar of your site, on your home page, or anywhere else you can imagine.
After completing this section of the guide you will have gained experience working with the Views 2 module for Drupal 6, and will be able to apply the knowledge you gain towards creating custom Views for a nearly unlimited number of purposes on your site. Once you have learned to use both CCK and Views, your outlook on developing websites will never be the same.
The next step is to set up a new View using Views module, to generate a list of the latest Articles, making use of the fields that were set up in the Article content type. Of course, Views module can export/import Views, but going through the full process below will help you learn how Views works so you will be able to work with it and create your own custom Views.
articles. Optionally add a short View description for your own reference, and a View tag of article to help you find the View in the future. Leave View type set to Node. Press “Next” to continue.Views version 2 now offers the ability to define multiple “Displays” for a single View, each of which can present the same View in a different way.
The first thing to do when creating a new View is to set up the Defaults configuration. The options you set for Defaults apply to all other custom Displays you create later. However, all of the options set for Defaults can be overridden with your own custom settings by each Display. This saves you time by defining some or all of the settings that will be shared by every Display.
Articles. Press the “Update” button to save the new setting.Full pager option, and press the “Update” button.Content: Text: Article Teaser (field_article_teaser_text)Node: Post dateNode: TitleNone.Custom and enter the Custom date format as F jS, Y.Link this field to its node option.Node: Post date item. In the following screen choose Descending for the Sort order and press the “Update” button.Node: PublishedNode: TypePublished (which ensures only content that is marked as Published will be shown).Article under “Node type”.You will be creating two custom Displays: the first, a “Page” Display, which will be a full-size listing of the articles, and a second “Block” Display, which will be a small sub-listing of article teasers which will be placed in the sidebar of the site (or on your home page). So let’s begin first with the “Page” Display:
Page, click on the “Add Display” button. A new tab with the name “Page” will appear below the Default Display.Page: Articles. Press the “Update” button, and then press the “Save” button at the bottom of the Views interface to save the View - you should now see that the Page Display is now named Page: Articles (Display name changes aren’t updated until you save the View). Click on the new Page: Articles tab to make it the active tab again.articles if you want the URL to be example.com/articles). Press the “Update” button.Normal menu entry option, enter the menu item title in the field (e.g. Articles), and press the “Update” button. Menu items generated by Views modules appear by default in Drupal’s Navigation menu. You can adjust this (e.g. to move it to your Primary Links menu) though you MUST first save your View before navigating away from it. Go to Administer > Site building > Menus > Navigation (admin/build/menu-customize/navigation), locate the name of your menu item, click edit, and choose the Primary links menu under the “Parent item” option.Now you’ll create the second Display, this time as a “Block” type, which will be a small sub-listing of article teasers which will be placed in the sidebar of the site (or on your home page):
Block, and click on the “Add Display” button. A new tab with the name “Block” will appear below the Default and Page: Articles Displays.Block: Articles. Press the “Update” button, and then press the “Save” button at the bottom of the Views interface to save the View. Click on the new Block: Articles tab to make it the active tab again.Create more link, and press the “Update” button.
Note: Since the “More link” option only applies to Block Displays, you could turn this setting on in the Defaults Display - however it’s included in this way here as at least one example of using the Override feature of Views Displays. You can use this feature to do all kinds of interesting things within a single View, including adding specific fields, filters, and arguments to one Display of the View, and completely different ones to a different Display (thereby creating a separate Display that is based on the same underlying Default values, but otherwise an entirely different View).
The View and its Displays are now complete. However, you can return to edit and adjust the View at any time.
Ensure that you click the “Save” button for the View (make sure you see the “The view has been saved” message at the top of the screen). Pay a visit to http://www.example.com/articles to see the output of the Page: Articles Display you’ve created.
When you’re ready proceed to the next section of the guide, where you will activate the Block: Articles Display to be used in the sidebar of your site.
The Block: Articles Display you just created has now become automatically available to the rest of Drupal as a “Block” at Administer > Site building > Blocks (admin/build/block).
Right sidebar). The articles block will immediately move out of the Disabled category and up into the Right sidebar category higher up on the page. You can adjust its position relative to the other blocks in that Region using the move icon at the far left.More info to add…
- You are not limited to only the blocks that are pre-defined for your theme.
- Short mention of the possibility of adding blocks to your front page (and link to article on making front pages).
At this point the majority of the underlying “functionality” for your Article content type and the Views that will display the Article listings/teasers are now complete. However, it’s very unlikely that things are “looking” the way you want them to quite yet. That’s where Theming comes into the picture (customizing the “look and feel” of your site). First you’ll learn how to customize the theme of the full Article pages (nodes), and then how to theme the Articles: Page and Articles: Block Displays from Views module. You will learn how to gain complete control over the HTML and CSS of every field of information, allowing you to customize them in any way you’d like.
Until I get a chance to finish this page, this post I made on drupal.org should provide a little help:
http://drupal.org/node/299406#comment-978324
While the page.tpl.php file of your theme is the “highest level” template which controls the layout of your site overall and by default is consistent through all the pages of your site, there are a number of more specific template files that control how sub-elements of pages are themed “within” page.tpl.php, such as the different content that appears on each page throughout the site. The template file in your theme responsible for theming content is called node.tpl.php.
This guide will use the Garland theme to present its examples, however feel free to follow along with your own theme if you prefer.
One of the great features of Drupal’s flexible theming system is the ability to create separate “versions” of templates to affect only a specific Content Type. Since the goal is to theme the “Article” pages in a way that may be completely different than other types of pages on the site, this is definitely a useful feature.
Note: you can create a custom template in this way for any Content Type you’ve created. Simply copy the node.tpl.php file and rename it, adding -content_type_name after the word node in the file name. For Content Type names consisting of multiple words, separate each word with an underscore.
Here is a before and after screenshot to illustrate how an Article page looks right now “out of the box”, as well as how it will look after completing the customizations to the theme that will follow in this guide.
[insert screenshot image]
Open up the new node-article.tpl.php file you just created, and locate <?php print $content ?> in the code. This one PHP variable is what is responsible for displaying just about every field of the content on the page (the exception being the node’s Title field, which is usually displayed by the page.tpl.php template).
<?php print $content ?> displays a combination of the Body of the node, as well as all of your custom CCK fields.
Since the goal is to achieve more flexible control over the HTML of all the custom CCK fields in the Article Content Type, what needs to happen is for the $content variable to be broken up into each individual field, instead of combined all into one which you cannot control.
If you’d like, the Contemplate module can be a useful tool to help you “look inside” the $content variable, and pick and choose the code for the fields you want to copy and paste into your template file. If you’d prefer to use Contemplate, please see the guide on How to use Contemplate module.
However, it is often (and most likely) the case that using Contemplate for this purpose is unnecessary (and more unwieldy than it is worth). Simply copy the bits of code below, and you’ll be able to use them in future Content Type template files as well simply by changing the name of the field (in most cases). In any case, it doesn’t hurt to have Contemplate around for reference, in situations where certain types of fields use different code than below.
Several short bits of code will be used to replace the $content variable, providing you with essentially the same output, only now with direct control over each field.
<?php print $content ?> line. This new line displays the content of the Body field (note that the code for displaying the Body field is a bit different than the code for displaying custom CCK fields):<?php print $node->content['body']['#value'] ?><?php if ($submitted): ?> (note that a div tag has been added around the field_article_subtitle field, so that it will be easy to style with CSS later):<div id="article-subtitle">
<?php print $node->field_article_subtitle[0]['view'] ?>
</div>For instance, if you had a field in your Content Type called field_drupal_rules you would change field_article_subtitle instead to field_drupal_rules. This often works, though for some other field types you might need to use Contemplate to acquire the code (or Devel module can assist you with this as well if you prefer). Be sure to surround every field with a unique CSS ID or Class in a div or span tag, since that will make it much easier to add your own custom style/design to each field.
If you need to add a CCK field that has “multiple values” (for example has the Number of values setting set to Unlimited or a number other than 1), you can use the following bit of code, customizing just the field name (feel free to customize or remove the div tag):
<?php foreach ((array)$field_drupal_rules as $item) { ?>
<div class="field-item"><?php print $item['view'] ?></div>
<?php } ?>There is a line in your node-article.tpl.php file which contains <?php print $submitted; ?>, which is what produces the “Submitted by…” line. By default, the line it creates looks something like this (how the date is formatted depends on the settings at admin/settings/date-time):
Submitted by Username on August 7, 2008 - 4:05pm
If your goal is simply to remove the “time of day” portion of the date (a common request), have a look at this excellent article which covers how to do that in both Drupal 5 and 6: No time of day in node date (scroll down to the line “To modify the medium-size format for dates…” above the first screenshot). In Drupal 6 it can be done with the Custom format setting under Medium date format, located at Administer > Site configuration > Date and time (admin/settings/date-time), while in Drupal 5 some copy/paste code into your theme is required.
If your goal involves more detailed customization of $submitted, then pasting in a bit of code is necessary.
If you’d like your $submitted line to read as: Posted August 3rd, 2008 by Username
Then replace <span class="submitted"><?php print $submitted; ?></span> with the below code:
<span class="submitted"><?php print t('Posted ') . format_date($node->created, 'custom', "F jS, Y") . t(' by ') . theme('username', $node); ?></span>With a tiny bit of understanding of a simple PHP feature called concatenating strings (the name of which sounds much more complicated than it really is), you can easily “rearrange” the various words and bits of code to however you need. The key to how it works is the period (.) which separates each part of the code.
In Drupal 6, the above method still works, but you can also accomplish this for every Content Type on your site overall in one step, by pasting the following into the template.php file of your theme (or changing the pre-existing function if your theme, such as Garland which is Drupal’s default theme, already has this function… since you cannot have the same function twice):
function phptemplate_node_submitted($node) {
return t('Submitted by !username on @datetime',
array(
'!username' => theme('username', $node),
'@datetime' => format_date($node->created),
));
}In the return t('Submitted by !username on @datetime', line, rearrange !username and @datetime however you prefer. You can also feel free to customize the date format by exchanging $node->created for $node->created, 'custom', "F jS, Y" (or any other custom date format).
If you’d like to remove the $submitted line altogether (in case you don’t want it included at all on the page), you can either simply delete the $submitted line from node-article.tpl.php or you can turn it off for the Article content type at admin/build/themes/settings under the “Display post information on” setting.