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. This is a "mega guide" that is intended to take you step by step from a beginner level through every step to learn the majority of skills, concepts, and modules you need to make a relatively advanced Drupal site. It is not "all inclusive" by any means, but should be a valuable learning tool.
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.
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.
After completing this lesson, you will have built up skills working with CCK, Views, theming both individual content (nodes) as well as Views, and knowledge of Pathauto and Custom Breadcrumbs. You will also gain experience working with images in Drupal using Imagefield and Imagecache (in this lesson you will learn to add images to your CCK types, and control exactly how and where those images show up, such as adding a thumbnail image in the teaser with the full size image on the article's full page).
This guide is still in the process of being written. Though not yet complete, it is still a very valuable learning resource. Currently support for Images is being added to the guide.
highlighted. When you see highlighted text, you should copy/paste it into the specified settings field or template file on your site.The following modules should be installed before following along with the guide:
You also need these modules for image handling. Some may be alpha or beta versions, but are fine to use:
These modules will be used in the lesson, but are optional:
Before beginning, ensure that you have installed and enabled the required modules listed above (and the optional modules if you wish to). Many of the modules have additional "sub-modules" that come with them. You should enable "all" of these sub-modules for this guide EXCEPT as outlined below.
Sub-modules not to enable:
Some sub-modules do not become available for installation until after you first enable the parent module, or enable another module which that module is dependent on (dependencies are shown in green and red text next to every module). Continue enabling modules in multiple passes until every module required has been enabled.
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.
If you have installed Drupal but have not yet begun working with uploaded files, it's possible that you have not yet configured Drupal's "File system" settings. Go to Administer > Site configuration > File system (admin/settings/file-system). The default File system path setting should generally be fine, but if you wish to change it, now is the time. Ensure that a functional temporary directory is set (on a remote web host this is often /tmp). Unless you have a specific reason not to, you should choose the Public download method.
If Drupal presents any error messages, follow any instructions given on the screen, and seek help on drupal.org if you get stuck. It's very important that Drupal is able to upload and read/write files and folders within the directories specified here.
Go to Administer > Site configuration > ImageAPI (admin/settings/imageapi). If your server offers ImageMagick (and the option is available), then you should use that (it has more capabilities than GD), though if not, then leaving GD selected is fine.
Click on "Configure". Choose a value for the JPEG quality setting, and if you want to choose a Crop background color besides the default, enter the color value. If you have ImageMagick installed, you can configure its settings here as well.
Go to Administer > Site configuration > Image toolkit (admin/settings/image-toolkit). You will instantly notice that there is "another" JPEG quality setting here. What?! The setting in ImageAPI will take care of nearly every image on the site, but one spot that it doesn't is for the preview image that appears on the Create or Edit content page for images that you upload. This probably won't affect viewers of your site, but will affect how you see the preview image as you upload it. You can leave this setting alone, or set it to match the value you chose in ImageAPI.
ImageCache is a module that allows you to take a single image, and generate an unlimited number of scaled and/or cropped versions of it (or process it in other various ways), without changing the original source file. In this step you will create several image presets that will be used later on in the lesson. You can use different width/height settings if you prefer, or use the ones provided in the example, as you can go back and change them easily at any time (when you change them, all of your images will automatically show at the new adjusted size).
small and the click the "Create New Preset" button.150 for both the Width and the Height. This will scale your image so that neither its width or height is more than 150 pixels. Leave the Weight and Allow Upscaling options alone. Click the "Update Action" button, and on the following screen you will see that the Scale action has been added to your preset. A sample image is shown at the bottom to illustrate how your image will be affected by this action.150 for the Width, and 100 for the Height. For X offset and Y offset, enter the word center. The Crop action is like a cookie cutter - in this case it is a 150 x 100 cookie cutter being placed in the center of a 150 x 150 area. Once you've set the values (you can leave Weight alone), click the "Add Action" button.medium which will be shown on the content page itself. This image will be larger than the small preset, and will not be cropped.medium for the Preset Namespace.250, and leave Height blank. Click "Update Action". This will scale the original image down so that its width is no more than 250px and its height will be whatever height is correct to maintain the image's original aspect ratio.Repeat the process one more time to create a large preset. The only difference from the medium preset is the name, and and to use a Width of 970. This image will appear "outside" of the boundaries of your website layout in a hovering window known as a "lightbox" so it is fine for the width to exceed the size of your site layout. 970 is a relatively good choice, since it should be about full screen on a 1024x768 display. Setting the value too high will lead to longer download times.
Now that the preparations in the previous section are complete, this 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 which you will be able to re-apply to your own site in the future, creating your own custom Content Types, and any type of field your Content Type needs. 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.
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.Since Path and Pathauto module create "aliases" to content on your site, the original paths to those pages such as node/2 still exist as well (an alias is just a "mask" of sorts that covers up the original URL with a more friendly one. If you are concerned about possible penalties from search engines due to duplicate content (e.g. two different URLs with the same content) then you should install the Global Redirect module. What it does is ensures that all other URLs that lead to a piece of content get forwarded to your friendly Pathauto URLs.
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.
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'] ?>Important: though ['#value'] is used in this specific case, it should never be used in other fields unless you know how to make it secure (e.g. using the check_plain() function). Other fields should always use ['view'].
<?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.
Multi-value fields
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 } ?>Adding a field label
When you manually print out a CCK field in your template, the Label defined for it does not appear by default (only the content of the field itself is included). Here is a code example to use if you'd like to print out the Label:
<?php print $node->content['field_drupal_rules']['field']['#title'] ?>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.
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