Sei sulla pagina 1di 459

3 Aug 2007 Drupal Handbook

Table of Contents
Installation and configuration . . . . . . . . . . . . . . . 1
System requirements . . . . . . . . . . . . . . . . . 2
Client System Requirements . . . . . . . . . . . . . . 3
Javascript . . . . . . . . . . . . . . . . . . 3
CSS . . . . . . . . . . . . . . . . . . . . 4
RSS . . . . . . . . . . . . . . . . . . . . 4
Browser Specifics . . . . . . . . . . . . . . . . 4
Browser Popularity . . . . . . . . . . . . . . . . 4
Known Problems . . . . . . . . . . . . . . . . 4
Validation . . . . . . . . . . . . . . . . . . 4
Caveats . . . . . . . . . . . . . . . . . . . 4
HOWTO: Server requirement recommendations for your consulting clients . . . 5
Message to the Client . . . . . . . . . . . . . . . 5
Benchmark . . . . . . . . . . . . . . . . . . 6
What Drupal.org runs on . . . . . . . . . . . . . . 6
Requirements - older versions . . . . . . . . . . . . . . 6
Installing Drupal, modules and themes . . . . . . . . . . . . 8
Installing Drupal . . . . . . . . . . . . . . . . . 8
Formatted Drupal 5.x Installation instructions for better readability . . . . 13
Installation . . . . . . . . . . . . . . . . . 13
Changes . . . . . . . . . . . . . . . . . . 14
Requirements . . . . . . . . . . . . . . . . . 14
Optional Requirements . . . . . . . . . . . . . . 14
Installation . . . . . . . . . . . . . . . . . 14
Drupal Administration . . . . . . . . . . . . . . 16
Customizing your theme(s) . . . . . . . . . . . . . 16
Multi-site configuration . . . . . . . . . . . . . . 16
More Information . . . . . . . . . . . . . . . . 17
Formatted Drupal 4.7.x Installation instructions for better readability . . . . 17
Installation . . . . . . . . . . . . . . . . . 17
REQUIREMENTS . . . . . . . . . . . . . . . . 18
SERVER CONFIGURATION . . . . . . . . . . . . . . 18
OPTIONAL COMPONENTS . . . . . . . . . . . . . . 18
INSTALLATION . . . . . . . . . . . . . . . . 19
1. DOWNLOAD DRUPAL . . . . . . . . . . . . . . 19
2. CREATE THE DRUPAL DATABASE . . . . . . . . . . 19
3. LOAD THE DRUPAL DATABASE SCHEME . . . . . . . . . 20
4. CONNECTING DRUPAL . . . . . . . . . . . . . 20
5. CONFIGURE DRUPAL . . . . . . . . . . . . . . 21
6. CRON TASKS . . . . . . . . . . . . . . . . 22
DRUPAL ADMINISTRATION . . . . . . . . . . . . . 22
CUSTOMIZING YOUR THEME(S) . . . . . . . . . . . . 22
UPGRADING . . . . . . . . . . . . . . . . . 23
MORE INFORMATION . . . . . . . . . . . . . . . 23

i
Drupal Handbook 3 Aug 2007

10 minute install using PuTTY SSH/Telnet client . . . . . . . . . 23


.
How I installed Drupal: The Eightfold Way . . . . . . . . . . 24
.
Installing virtual hosts for Drupal sites and subsites . . . . . . . . 25
.
Mac OS X-specific guidelines . . . . . . . . . . . . . . 26
.
Important notes for MySQL install: . . . . . . . . . . . . 27
.
HOWTO: Create a local server environment for drupal using MAMP . . . . 28
.
HOWTO: Installing PostgreSQL and MySQL on the same Mac OS X machine . . 29
.
Installing Drupal on Mac OS X 10.4 Tiger . . . . . . . . . . 30
.
Installing and Configuring MySQL . . . . . . . . . . . 30
.
Sending mail . . . . . . . . . . . . . . . . . 32
.
Creating the Drupal Database and Database User . . . . . . . . 32
.
Installing using CVS repository . . . . . . . . . . . . 33
.
Prefixed database.mysql for search and replace . . . . . . . . . . 36
.
Setup Drupal on Windows XP Pro using IIS . . . . . . . . . . 51
.
Basic /sites directory setup . . . . . . . . . . . . . . 52
.
Special cases . . . . . . . . . . . . . . . . . . 53
.
Compilation failed: this version of PCRE is not compiled with PCRE_UTF8 support 53
.
Configure .htaccess to allow awstats to work with clean URL’s . . . . . 54
.
Configuring .htaccess to ignore specific subfolders . . . . . . . . 55
.
Ignoring Subfolders that exist in the DocumentRoot . . . . . . . 55
.
Ignoring subfolders that are included via Apache Alias directives . . . . 55
.
Create a custom php.ini . . . . . . . . . . . . . . . 56
.
How to create a custom php.ini file when nothing else works . . . . . 60
.
1. Get and modify your custom php.ini file . . . . . . . . . 60
.
2. Creating your CGI script . . . . . . . . . . . . . 60
.
3. Modifying your .htaccess file . . . . . . . . . . . . 61
.
4. Test your site . . . . . . . . . . . . . . . . 61
.
Create Drupal database using Plesk . . . . . . . . . . . . 61
.
Drupal with safe mode enabled and open basedir . . . . . . . . 62
.
Generic Mass SQL Import into Drupal . . . . . . . . . . . 65
.
DrupalCon site . . . . . . . . . . . . . . . . 67
.
How to degrade your Drupal db from MySQL 4.1.X/5.0.X to MySQL 4.0.X . . 67
.
How-To: Virtual Hosting with Drupal . . . . . . . . . . . 68
.
Introduction . . . . . . . . . . . . . . . . . 68
.
Environment . . . . . . . . . . . . . . . . . 68
.
Requirements . . . . . . . . . . . . . . . . . 69
.
Next pages . . . . . . . . . . . . . . . . . 69
.
How-To: Virtual Hosting with Drupal :: Prepare environment . . . . . 69
.
Introduction . . . . . . . . . . . . . . . . . 69
.
The drupal group . . . . . . . . . . . . . . . . 70
.
The temp directory . . . . . . . . . . . . . . . 70
.
The reference location . . . . . . . . . . . . . . . 70
.
Navigation . . . . . . . . . . . . . . . . . 70
.
How-To: Virtual Hosting with Drupal :: Solution Overview . . . . . 71
.
Introduction . . . . . . . . . . . . . . . . . 71
.
Safe mode . . . . . . . . . . . . . . . . . 71
.
Open Basedir . . . . . . . . . . . . . . . . . 71
.

ii
3 Aug 2007 Drupal Handbook

Plesk integration . . . . . . . . . . . . . . . . 72
.
Managed application . . . . . . . . . . . . . . . 72
.
eAccelerator . . . . . . . . . . . . . . . . . 72
.
Each individual vhost requirements . . . . . . . . . . . 73
.
Navigation . . . . . . . . . . . . . . . . . 73
.
HOWTO: copy a site to a local computer using XAMPP . . . . . . . 73
.
HOWTO: Copy site to another directory for testing . . . . . . . . 74
.
HOWTO: Install Drupal 5.x using cPanel . . . . . . . . . . 75
.
HOWTO: Install Drupal using cPanel . . . . . . . . . . . 77
.
HOWTO: Site to site transfer with phpMyAdmin and a FTP Client . . . . 80
.
Import a MySQL data dump with BigDump . . . . . . . . . . 82
.
What is BigDump? . . . . . . . . . . . . . . . 82
.
Setting up BigDump . . . . . . . . . . . . . . . 83
.
Uploading the sql file and bigdump.php to the webserver . . . . . . 83
.
Running BigDump . . . . . . . . . . . . . . . 84
.
Installing Drupal behind an Actiontec GT701-WG router . . . . . . . 84
.
Installing Drupal in a subdirectory in 4.6 . . . . . . . . . . . 85
.
More than one Drupal site on one machine . . . . . . . . . . 85
.
General rules for multiple Drupal deployments . . . . . . . . 86
.
Moving your Drupal installation to a new directory . . . . . . . . 86
.
PCRE_UTF8 solution for VPS servers | FreeBSD . . . . . . . . . 87
.
Known causes of PCRE server errors . . . . . . . . . . . 88
.
Redirecting specific pages to new URLs (301 redirects in Drupal) . . . . . 88
.
How to create 301 redirects in Drupal Apache mod_rewrite . . . . . 89
.
The tolerant base URL . . . . . . . . . . . . . . . 89
.
Using .htaccess to stop page caching . . . . . . . . . . . . 90
.
Linux specific guidelines . . . . . . . . . . . . . . . 90
.
Installing PHP, MySQL and Apache under Linux . . . . . . . . 90
.
XAMPP for Linux Packages . . . . . . . . . . . . . . 91
.
Installing XAMPP in Debian . . . . . . . . . . . . . 91
.
Download XAMPP Latest version from the following link . . . . . . 91
.
Start XAMPP Server . . . . . . . . . . . . . . . 91
.
Windows-specific guidelines . . . . . . . . . . . . . . 94
.
How to install Drupal for newbies using FTP and phpMyAdmin . . . . . 95
.
Change "/tmp" on your drupal site. . . . . . . . . . . . 95
.
Get Drupal ready . . . . . . . . . . . . . . . . 95
.
Upload the database . . . . . . . . . . . . . . . 96
.
HOWTO: Create an apache sandbox using Windows and Apache2Triad . . . 96
.
Before you begin . . . . . . . . . . . . . . . . 97
.
Installing Apache2Triad . . . . . . . . . . . . . . 97
.
Installing Drupal . . . . . . . . . . . . . . . . 98
.
Importing and exporting Drupal databases updated with PHPMyAdmin . . 100
.
To export a database with PHPMyAdmin . . . . . . . . . . 100
.
To import a database with PHPMyAdmin . . . . . . . . . . 101
.
Using bigdump.php to deal with large databases . . . . . . . . 102
.
Installing Apache (with PHP) on Windows . . . . . . . . . . 102
.
Installing MySQL on Windows . . . . . . . . . . . . . 104
.

iii
Drupal Handbook 3 Aug 2007

Installing PHP4 on Windows . . . . . . . . . . . . . 105


.
Drupal 4.7 on Windows/IIS Requires PHP in ISAPI mode . . . . . . 105
.
Installing PostgreSQL on Windows . . . . . . . . . . . . 105
.
Multiple Drupal Sites under Windows . . . . . . . . . . . 106
.
Running multiple sites on a local PC (localhost) from a single codebase, using Windows
106
Untar . . . . . . . . . . . . . . . . . . . 108
.
Installing Drupal on Windows . . . . . . . . . . . . . 109
.
PostgreSQL specific guidelines . . . . . . . . . . . . . 109
.
ERROR: DB connect failed . . . . . . . . . . . . . . . 109
.
ERROR: language "plpgsql" does not exist . . . . . . . . . . 110
.
ERROR: null value in column "uid" violates not-null constraint . . . . . 110
.
PostgreSQL support in Drupal 4.7.x . . . . . . . . . . . . 110
.
Drupal 4.5 and PGSQL 8 configuration . . . . . . . . . . . 110
.
Installing contributed modules . . . . . . . . . . . . . . 111
.
HOWTO: Install glossary module . . . . . . . . . . . . . 113
.
Where is the Glossary? . . . . . . . . . . . . . . . 113
.
What is the purpose of the Glossary Module, and what does it do? . . . . 113
.
Installing the Glossary Module . . . . . . . . . . . . . 114
.
Configuring the Glossary . . . . . . . . . . . . . . 114
.
Adding Full Page Definitions . . . . . . . . . . . . . 115
.
Adding Glossary To Menus . . . . . . . . . . . . . . 115
.
Leech - automating content addition . . . . . . . . . . . . 116
.
Relationships between modules . . . . . . . . . . . . . 116
.
Installing new modules (Drupal 4.6 or older) . . . . . . . . . . 117
.
Multi-site installation and set-up . . . . . . . . . . . . . . 118
.
10 Minute Multisite Install & Configuration . . . . . . . . . . 119
.
Access all multisites with www. only [.htaccess] . . . . . . . . . 121
.
Drupal as a library . . . . . . . . . . . . . . . . 121
.
Multi-site setup in 5.x using CPanel . . . . . . . . . . . . 123
.
Multi-Site, Single Codebase, Shared Database, Shared Sign-on 4.6 . . . . . 124
.
Apache (http) Configuration . . . . . . . . . . . . . 124
.
Download and Placement . . . . . . . . . . . . . . 124
.
SQL Setup . . . . . . . . . . . . . . . . . . 125
.
Individual Site Configuration & Theming . . . . . . . . . . 126
.
Some things which can be improved: . . . . . . . . . . . 127
.
Multi-Site, Single Codebase, Shared Database, Shared Sign-on 5.x . . . . . 127
.
1. Prepare database and database user . . . . . . . . . . . 128
.
1.1. create a database and user . . . . . . . . . . . . . 128
.
2. create and modify site configuration . . . . . . . . . . . 128
.
2.1. duplicate settings folder . . . . . . . . . . . . . . 128
.
2.2. Modify config files . . . . . . . . . . . . . . . 128
.
2.2.1. provide DB connection detail . . . . . . . . . . . . 128
.
2.2.2. set prefixes for table names . . . . . . . . . . . . 128
.
3. create static links . . . . . . . . . . . . . . . . 129
.
4. install drupal . . . . . . . . . . . . . . . . . 130
.
Multiple domains or vhosts using different databases . . . . . . . . 130
.
Sharing Drupal tables between databases using MySQL5 Views . . . . . 131
.

iv
3 Aug 2007 Drupal Handbook

Multiple domains using the same database . . . . . . . . . . . 132


.
Same codebase, completely different content and users . . . . . . . . 132
.
Setup of /sites directory for multi-site . . . . . . . . . . . . 135
.
Installing new themes . . . . . . . . . . . . . . . . 137
.
Basic site configuration . . . . . . . . . . . . . . . . 139
.
Settings . . . . . . . . . . . . . . . . . . . . 139
.
General settings . . . . . . . . . . . . . . . . . 140
.
Default front page . . . . . . . . . . . . . . . . . 140
.
Examples . . . . . . . . . . . . . . . . . . 141
.
Clean URLs . . . . . . . . . . . . . . . . . . 141
.
.htaccess for clean urls on specific shared hosts . . . . . . . . . 143
.
403 Permission denied error . . . . . . . . . . . . . . 146
.
A mod_rewrite bug causing occasional corruption of the query string . . . . 147
.
Apache 2 configuration of clean URLs on Debian . . . . . . . . . 147
.
Apache 2 on Ubuntu . . . . . . . . . . . . . . . 149
.
Editing apache2.conf . . . . . . . . . . . . . . . 149
.
Editing apache2/sites-available . . . . . . . . . . . . 150
.
Clean URL Support in Abyss . . . . . . . . . . . . . 151
.
Clean URL support in XAMPP . . . . . . . . . . . . . 153
.
Clean URLs in Mac OS X Server . . . . . . . . . . . . . 153
.
Clean URLs with different webservers . . . . . . . . . . . 154
.
Microsoft Internet Services Server . . . . . . . . . . . . 154
.
Lighttpd . . . . . . . . . . . . . . . . . . 154
.
Clean URLs with Easyphp. . . . . . . . . . . . . . . 154
.
Example Clean URL configuration of httpd.conf for performance . . . . . 155
.
Existing URLs for server overwrite Drupal paths . . . . . . . . . 156
.
IIS CleanURLs using some of the available ISAPI filters. . . . . . . . 156
.
Translating Apache’s rewrite rules . . . . . . . . . . . 156
.
Pathauto and Localizer . . . . . . . . . . . . . . . 157
.
Setting up clean URLs above web document root on virtual private servers . . 158
.
reboot vps after making change . . . . . . . . . . . . 159
.
Using Clean URLs with IIS . . . . . . . . . . . . . . 159
.
Alternate method . . . . . . . . . . . . . . . . 160
.
set your sites 403 and 404 Error pages . . . . . . . . . . . . 160
.
Configure your sites error reporting . . . . . . . . . . . . 161
.
Cache support . . . . . . . . . . . . . . . . . 161
.
Primary and secondary links . . . . . . . . . . . . . . 161
.
General Information: . . . . . . . . . . . . . . . 161
.
Setting Up Your Primary and Secondary Links: . . . . . . . . . 162
.
Theming Your Link Menus . . . . . . . . . . . . . . 162
.
Set length of trimmed posts and # of posts on front page . . . . . . . 162
.
URL Alias Optimization . . . . . . . . . . . . . . . 162
.
File system settings . . . . . . . . . . . . . . . . 163
.
Download method . . . . . . . . . . . . . . . . 163
.
Path settings . . . . . . . . . . . . . . . . . 164
.
Date and time settings . . . . . . . . . . . . . . . . 164
.
Customizing the interface . . . . . . . . . . . . . . . 164
.

v
Drupal Handbook 3 Aug 2007

Customizing user login . . . . . . . . . . . . . . . . 165


.
Beginner’s guide for Cron on a shared hosting provider . . . . . . . . 166
.
Check your filters . . . . . . . . . . . . . . . . . 167
.
Configure user registration . . . . . . . . . . . . . . . 168
.
Creating a menu structure . . . . . . . . . . . . . . . 168
.
Creating a menu . . . . . . . . . . . . . . . . . 169
.
Simplifying the workflow . . . . . . . . . . . . . . . 169
.
Helping search engines and robots.txt . . . . . . . . . . . . 169
.
Controlling what gets indexed -- the robots.txt file . . . . . . . . . 170
.
Add ’Disallow: /node/’ if your setup has aliases for all nodes . . . . . 171
.
Selective Bot Crawling . . . . . . . . . . . . . . . 171
.
Increase upload size in your php.ini . . . . . . . . . . . . . 175
.
Need images etc? - check Filtered HTML . . . . . . . . . . . . 176
.
Set default content options - Stop automatic promotion to the front page . . . . 177
.
Show/hide ’Submitted by’ on posts . . . . . . . . . . . . . 178
.
Blocks . . . . . . . . . . . . . . . . . . . . 178
.
Block configuration . . . . . . . . . . . . . . . . 178
.
Restricting blocks to certain pages . . . . . . . . . . . . 179
.
Preventing a block from appearing in Drupal 4.5 . . . . . . . . . 180
.
Custom blocks . . . . . . . . . . . . . . . . . 182
.
Increase memory in your php.ini . . . . . . . . . . . . . . 182
.
Database table prefix (and sharing tables across instances) . . . . . . . 183
.
Share tables across instances . . . . . . . . . . . . . . 184
.
Setup tip for Drupal 5 . . . . . . . . . . . . . . . 185
.
Using schema prefixes with PostgreSQL . . . . . . . . . . . 185
.
Define shared variables for all sites . . . . . . . . . . . . 187
.
Drupal Cookbook (for New Drupallers) . . . . . . . . . . . . 189
.
Purpose . . . . . . . . . . . . . . . . . . . . 189
.
Background . . . . . . . . . . . . . . . . . . . 189
.
Myths . . . . . . . . . . . . . . . . . . . . 189
.
Using the Drupal Web Site . . . . . . . . . . . . . . . 190
.
Typing Convention . . . . . . . . . . . . . . . . . 190
.
Some Preliminary Advice . . . . . . . . . . . . . . . 190
.
Drupal Is Supposed to be Easy? . . . . . . . . . . . . . . 191
.
A. Getting Started . . . . . . . . . . . . . . . . . 192
.
B. Basic Configuration . . . . . . . . . . . . . . . . 193
.
C. Creating Multiple Sites On Your Local Computer . . . . . . . . . 194
.
D. Error Pages . . . . . . . . . . . . . . . . . . 197
.
Page Not Found . . . . . . . . . . . . . . . . . 197
.
Access Denied . . . . . . . . . . . . . . . . . 197
.
E. Accessing Your Test Site(s) . . . . . . . . . . . . . . 198
.
F. Adding Modules and Themes . . . . . . . . . . . . . . 198
.
Installation . . . . . . . . . . . . . . . . . . 199
.
Modules . . . . . . . . . . . . . . . . . . . 199
.
Modules . . . . . . . . . . . . . . . . . . 199
.
This Site . . . . . . . . . . . . . . . . . . 200
.
Themes . . . . . . . . . . . . . . . . . . . 200
.

vi
3 Aug 2007 Drupal Handbook

Themes . . . . . . . . . . . . . . . . . . . 200
.
Logo and Favorite Icon . . . . . . . . . . . . . . . 200
.
G. Creating Content . . . . . . . . . . . . . . . . . 201
.
Content Types . . . . . . . . . . . . . . . . . 202
.
Page . . . . . . . . . . . . . . . . . . . . 202
.
Story . . . . . . . . . . . . . . . . . . . . 202
.
Book Page . . . . . . . . . . . . . . . . . . 202
.
Blog Entry . . . . . . . . . . . . . . . . . . 203
.
G1. Creating a Page . . . . . . . . . . . . . . . . 203
.
G2. Creating a Story . . . . . . . . . . . . . . . . 204
.
What’s a Teaser? . . . . . . . . . . . . . . . . 204
.
G3. Creating a Book Page . . . . . . . . . . . . . . . 205
.
G4. Creating a Blog entry . . . . . . . . . . . . . . . 205
.
H. Custom Blocks . . . . . . . . . . . . . . . . . 206
.
Address . . . . . . . . . . . . . . . . . . . 206
.
Last Updated . . . . . . . . . . . . . . . . . . 206
.
I. Working with the Menu . . . . . . . . . . . . . . . 207
.
Introduction . . . . . . . . . . . . . . . . . . 207
.
How To Menu . . . . . . . . . . . . . . . . . 207
.
Textual Menu . . . . . . . . . . . . . . . . . . 208
.
Tabbed Menu . . . . . . . . . . . . . . . . . . 208
.
Books . . . . . . . . . . . . . . . . . . . . 208
.
More . . . . . . . . . . . . . . . . . . . . 209
.
I2. The Contact Form . . . . . . . . . . . . . . . . 209
.
Set Up . . . . . . . . . . . . . . . . . . . 209
.
Make It Accessible . . . . . . . . . . . . . . . . 209
.
Add "Contact" to the Menu . . . . . . . . . . . . . . 210
.
Using It In Content . . . . . . . . . . . . . . . . 210
.
J. URL Aliases . . . . . . . . . . . . . . . . . . 210
.
K. Moving Entire Drupal Site with Databases . . . . . . . . . . . 211
.
Backup Process with phpMyAdmin . . . . . . . . . . . . 213
.
Backup Process with phpMyAdmin . . . . . . . . . . . . . 213
.
L. Moving Stuff to Your Web Site . . . . . . . . . . . . . 216
.
M. Setting Up Cron . . . . . . . . . . . . . . . . . 216
.
N. Categories (Taxonomy) . . . . . . . . . . . . . . . 217
.
O. Common Problems . . . . . . . . . . . . . . . . 219
.
P. Links and IMG . . . . . . . . . . . . . . . . . 219
.
Q. Additional Tips and Tricks . . . . . . . . . . . . . . 220
.
Q1. Tracking Module Status . . . . . . . . . . . . . . 220
.
Q2. Making Multiple Site Maintenance a Bit Easier . . . . . . . . . 220
.
Q3. Controlling User Log In . . . . . . . . . . . . . . 221
.
How do I disable "Create New Account?" . . . . . . . . . . 221
.
How do I disable User Log In entirely, and how would I get in if I do? . . . 221
.
R. Keeping Your Local and Remote Sites Synchronized . . . . . . . . 222
.
S. More Reading . . . . . . . . . . . . . . . . . . 222
.
T. Glossary . . . . . . . . . . . . . . . . . . . 223
.
Taking your site live . . . . . . . . . . . . . . . . . 226
.

vii
Drupal Handbook 3 Aug 2007

Moving from a temporary location . . . . . . . . . . . . . 226


.
Moving Drupal . . . . . . . . . . . . . . . . . . 226
.
Redirecting your server . . . . . . . . . . . . . . . . 226
.
Excluding paths from Drupal . . . . . . . . . . . . . . 227
.
Core modules . . . . . . . . . . . . . . . . . . . 228
.
Aggregator: publishing syndicated content . . . . . . . . . . . 228
.
Old page . . . . . . . . . . . . . . . . . . . 229
.
Open aggregator links in new browser window . . . . . . . . . 229
.
User Aggregator:user submitted feeds . . . . . . . . . . . . 229
.
What do I need to subscribe to a feed? . . . . . . . . . . . . 230
.
Configuring news feeds . . . . . . . . . . . . . . . 230
.
Filter feeds by keyword, time, by summary . . . . . . . . . . 231
.
Creating categories in the aggregator . . . . . . . . . . . . 231
.
Tagging individual items in the aggregator . . . . . . . . . . . 231
.
Using the news aggregator . . . . . . . . . . . . . . 231
.
RSS feed blocks . . . . . . . . . . . . . . . . . 232
.
Block: controlling content in the sidebars . . . . . . . . . . . . 232
.
Module blocks . . . . . . . . . . . . . . . . . 232
.
Administrator defined blocks . . . . . . . . . . . . . . 233
.
Blog: a blog for every user . . . . . . . . . . . . . . . 233
.
HOWTO: Configure user blogs . . . . . . . . . . . . . 233
.
Most recent blog post block . . . . . . . . . . . . . . 234
.
Navigate throught categories inside a blog . . . . . . . . . . . 234
.
What is a blog or weblog? . . . . . . . . . . . . . . . 234
.
Making user blogs more accessible . . . . . . . . . . . . . 235
.
Additional features . . . . . . . . . . . . . . . . 235
.
BlogApi: post from blog tools . . . . . . . . . . . . . . 236
.
Book: structured document publishing . . . . . . . . . . . . 236
.
Customising the book navigation menu . . . . . . . . . . . 237
.
Maintaining a FAQ using a collaborative book . . . . . . . . . . 238
.
Categories (taxonomy): A way to organize your content . . . . . . . . 239
.
Modules that do more with categories . . . . . . . . . . . . 242
.
Content Management System comparison focused on Taxonomy . . . . . 244
.
Taxonomy - some guidelines for effective design of taxonomies . . . . . . 244
.
Taxonomy Garden: Managing Categories . . . . . . . . . . . 246
.
Taxonomy Garden: Navigation by category . . . . . . . . . . 247
.
Taxonomy Garden: Organize content by category . . . . . . . . . 254
.
The taxonomy module for Drupal 4.x . . . . . . . . . . . . 260
.
Understanding categories for new users . . . . . . . . . . . 261
.
Using taxonomy to organize content . . . . . . . . . . . . 262
.
Using vocabularies for navigation . . . . . . . . . . . . . 265
.
Vocabularies and terms . . . . . . . . . . . . . . . 266
.
Creating a vocabulary . . . . . . . . . . . . . . . 267
.
Creating terms . . . . . . . . . . . . . . . . . 267
.
Advanced taxonomies: using hierarchies . . . . . . . . . . . 268
.
More about Taxonomy . . . . . . . . . . . . . . . 268
.
Creating a Block with links belonging to certain taxonomy terms . . . . . 270
.

viii
3 Aug 2007 Drupal Handbook

Taxonomy terms on a page . . . . . . . . . . . . . . 271


.
Comment: allow comments on content . . . . . . . . . . . . 272
.
Detailed comment documentation . . . . . . . . . . . . . 272
.
User control of comment display . . . . . . . . . . . . 272
.
Additional comment configurations . . . . . . . . . . . . 273
.
Notification of new comments . . . . . . . . . . . . . 273
.
Comment moderation . . . . . . . . . . . . . . . 274
.
Moderation votes . . . . . . . . . . . . . . . . 274
.
Moderator vote/values matrix . . . . . . . . . . . . . 274
.
Creating comment thresholds . . . . . . . . . . . . . 274
.
Initial comment scores . . . . . . . . . . . . . . . 275
.
Aggregator comments . . . . . . . . . . . . . . . 275
.
Contact: a way for users to get in touch . . . . . . . . . . . . 275
.
Make your site wide contact form look prettier . . . . . . . . . . 276
.
Drupal: Drupal sites directory server . . . . . . . . . . . . . 276
.
Old page . . . . . . . . . . . . . . . . . . . 277
.
Filter: Input formats for user content . . . . . . . . . . . . . 277
.
Forum: create threaded discussions . . . . . . . . . . . . . 278
.
HOWTO: Create a forum . . . . . . . . . . . . . . . 279
.
HOWTO: Create forum containers . . . . . . . . . . . . . 279
.
Help: context-sensitive guidance . . . . . . . . . . . . . . 279
.
More about the help module . . . . . . . . . . . . . . 280
.
Legacy: remapping of old-style URLs . . . . . . . . . . . . 280
.
Locale: multi-language support . . . . . . . . . . . . . . 280
.
Adjusting your php.ini settings for importing .po files . . . . . . . . 281
.
Editing text for translation . . . . . . . . . . . . . . . 282
.
How to create Drupal site in Marathi (Devnagari) . . . . . . . . . 282
.
How to install a different language . . . . . . . . . . . . 283
.
HOWTO: Creating a customized language set to replace Drupal terminology . . 283
.
HOWTO: Use a customized language set to change Drupal text and terminology . 284
.
Note for the curious . . . . . . . . . . . . . . . . 286
.
Menu: customize site navigation . . . . . . . . . . . . . . 286
.
Using named anchors with menus . . . . . . . . . . . . . 286
.
Node: the content . . . . . . . . . . . . . . . . . 287
.
Page: post static pages . . . . . . . . . . . . . . . . 288
.
Difference between page and story . . . . . . . . . . . . . 288
.
Specify page by title . . . . . . . . . . . . . . . . 289
.
Path: readable URLs . . . . . . . . . . . . . . . . . 289
.
Mass URL aliasing . . . . . . . . . . . . . . . . 290
.
Ping: notify services of changes . . . . . . . . . . . . . . 291
.
Write a custom module to ping a set of sites . . . . . . . . . . 291
.
Poll: community voting . . . . . . . . . . . . . . . . 292
.
Profile: extending user account information . . . . . . . . . . . 293
.
Enabling user pictures (avatars) . . . . . . . . . . . . . 294
.
HOWTO: Create new profile fields . . . . . . . . . . . . . 295
.
HOWTO: Make a field part of the registration process . . . . . . . . 295
.
Form Validation in plugin . . . . . . . . . . . . . . 295
.

ix
Drupal Handbook 3 Aug 2007

HOWTO: Create a ’country’ profile field . . . . . . . . . . . 295


.
CiviCRM: Tags, Profiles, Groups, advanced community member management . . 296
.
Search: an internal site search system . . . . . . . . . . . . . 297
.
Add searching to your custom module . . . . . . . . . . . . 298
.
Statistics: tracking referrers, page hits, etc. . . . . . . . . . . . 298
.
Story: post static pages . . . . . . . . . . . . . . . . 299
.
System: cron and caching . . . . . . . . . . . . . . . 299
.
Configuring cron jobs . . . . . . . . . . . . . . . . 301
.
Configuring cron jobs on DreamHost . . . . . . . . . . . 302
.
Cron Job configuration line by line . . . . . . . . . . . . 303
.
Cronjobs without wget/lynx or curl . . . . . . . . . . . . 304
.
Configuring cron jobs on Windows . . . . . . . . . . . . 305
.
Throttle: congestion control . . . . . . . . . . . . . . . 306
.
When to use the throttle module? . . . . . . . . . . . . . 307
.
Tracker: viewing new and updated content . . . . . . . . . . . 307
.
Upload: collaborate with files . . . . . . . . . . . . . . 308
.
User: access and management settings . . . . . . . . . . . . 308
.
Access Permissions reference . . . . . . . . . . . . . . 309
.
block module . . . . . . . . . . . . . . . . . 309
.
filter module . . . . . . . . . . . . . . . . . 309
.
menu module . . . . . . . . . . . . . . . . . 309
.
node module . . . . . . . . . . . . . . . . . 309
.
path module . . . . . . . . . . . . . . . . . 310
.
user module . . . . . . . . . . . . . . . . . 310
.
system module . . . . . . . . . . . . . . . . . 310
.
Access rules (email filters) . . . . . . . . . . . . . . . 310
.
Managing access control with permissions and user roles . . . . . . . 311
.
Assigning permissions and users to roles . . . . . . . . . . 312
.
Taxonomy_access: Restrict user roles to access specific categories only . . . 312
.
Adjusting permissions after adding modules . . . . . . . . . . 312
.
User authentication . . . . . . . . . . . . . . . . 313
.
Make a Drupal site use Basic Auth/ldap instead of the normal login block . . 313
.
NTLM Authentication . . . . . . . . . . . . . . . 315
.
User preferences and profiles . . . . . . . . . . . . . . 317
.
Using distributed authentication . . . . . . . . . . . . . 317
.
Distributed authentication . . . . . . . . . . . . . . 317
.
Drupal . . . . . . . . . . . . . . . . . . . 317
.
Watchdog: monitor your site . . . . . . . . . . . . . . . 318
.
End user guide . . . . . . . . . . . . . . . . . . 319
.
Registering as a user . . . . . . . . . . . . . . . . . 319
.
Logging in . . . . . . . . . . . . . . . . . . . 320
.
Changing your account settings . . . . . . . . . . . . . . 320
.
Creating new content . . . . . . . . . . . . . . . . 321
.
A step-by-step example . . . . . . . . . . . . . . . 321
.
Controlling Teaser Location . . . . . . . . . . . . . . 323
.
How to add a page to the Handbook . . . . . . . . . . . . 324
.
Types of content . . . . . . . . . . . . . . . . . 324
.

x
3 Aug 2007 Drupal Handbook

Topics, categories and terms . . . . . . . . . . . . . . 324


.
Permissions . . . . . . . . . . . . . . . . . . 324
.
Moderation and the submission queue . . . . . . . . . . . . 325
.
Creating comments . . . . . . . . . . . . . . . . 325
.
Alternative ways to enter content . . . . . . . . . . . . . 325
.
HOWTO: Posting and editing blog entries with TextMate . . . . . . 326
.
Posting and editing content with w.bloggar . . . . . . . . . . 327
.
Posting content with mailhandler . . . . . . . . . . . . 328
.
Preparing content offline . . . . . . . . . . . . . . 328
.
Editing and deleting content . . . . . . . . . . . . . . . 328
.
Search . . . . . . . . . . . . . . . . . . . . 329
.
Beyond the basics . . . . . . . . . . . . . . . . . 330
.
Sports . . . . . . . . . . . . . . . . . . . . . 331
.
football . . . . . . . . . . . . . . . . . . . . 331
.
Best practices guidelines . . . . . . . . . . . . . . . . 332
.
Back up your Drupal site . . . . . . . . . . . . . . . 332
.
Backing up the database . . . . . . . . . . . . . . . 332
.
Backing up the core files . . . . . . . . . . . . . . . 333
.
Backing up the non-core files . . . . . . . . . . . . . . 333
.
Test your backups . . . . . . . . . . . . . . . . . 334
.
Backup and restore using bash shell scripts . . . . . . . . . . 334
.
Functional Overview . . . . . . . . . . . . . . . 334
.
Usage notes and cautions . . . . . . . . . . . . . . 334
.
Site backup script . . . . . . . . . . . . . . . . 335
.
Usage notes and warnings: . . . . . . . . . . . . . 335
.
fullsitebackup.sh . . . . . . . . . . . . . . . . 336
.
Updated fullsitebackup.sh . . . . . . . . . . . . . 338
.
Site restore script . . . . . . . . . . . . . . . . 340
.
Usage notes and warnings: . . . . . . . . . . . . . 341
.
fullsiterestore.sh . . . . . . . . . . . . . . . . 341
.
Updated fullsiterestore.sh . . . . . . . . . . . . . . 344
.
Accounts and roles . . . . . . . . . . . . . . . . . 346
.
Configuring Apache and PHP for Drupal in a Shared Environment . . . . . 347
.
Creating a Test Site workflow . . . . . . . . . . . . . . 348
.
File and directory management . . . . . . . . . . . . . . 352
.
Other Tips . . . . . . . . . . . . . . . . . . 353
.
Test Sites . . . . . . . . . . . . . . . . . . . 353
.
Version update considerations . . . . . . . . . . . . . . 353
.
Do not modify core Drupal . . . . . . . . . . . . . . . 354
.
Security . . . . . . . . . . . . . . . . . . . . 355
.
Test php before putting it in blocks . . . . . . . . . . . . . 355
.
HowTo: The Advanced user’s guide . . . . . . . . . . . . . 356
.
HowTo: enable Imagemagick for the Image module . . . . . . . . . 357
.
Tips and Tricks . . . . . . . . . . . . . . . . . . 357
.
August 2005: Upgrade, Play B-I-N-G-O!, & E-commerce . . . . . . . 357
.
UPGRADE . . . . . . . . . . . . . . . . . . 357
.
PLAY B-I-N-G-O! . . . . . . . . . . . . . . . . 358
.

xi
Drupal Handbook 3 Aug 2007

E-COMMERCE . . . . . . . . . . . . . . . . . 358
.
Commentator array . . . . . . . . . . . . . . . . 358
.
June 2005: Custom Content Types, WYSIWIG Editors, Organize Your Content & Quick
Support . . . . . . . . . . . . . . . . . . . 359
.
September 2005: Newest modules, Change any string, Remote authentication, and
tracking project issues . . . . . . . . . . . . . . . . 360
.
Get the newest modules -- fast! . . . . . . . . . . . . . 360
.
Change any string . . . . . . . . . . . . . . . . 360
.
Remote authentication . . . . . . . . . . . . . . . 360
.
Keep tabs on project issues . . . . . . . . . . . . . . 361
.
Winter 2005/2006: Tracking projects with RSS and Module Linking . . . . . 361
.
Planning a web site . . . . . . . . . . . . . . . . . 361
.
Server tuning considerations . . . . . . . . . . . . . . . 365
.
Identifying Drupal performance goals . . . . . . . . . . . . 365
.
Analysing your site’s traffic and resource consumption . . . . . . . . 365
.
Understanding and configuring your stack for performance . . . . . . 365
.
Enable default 404 handling for some file types . . . . . . . . . . 367
.
Simple Decision Tree for Drupal Enterprise Scalability . . . . . . . . 368
.
Slow contributed modules determined using the developer module . . . . . 369
.
Squid Caching . . . . . . . . . . . . . . . . . 369
.
Tools, tips, and links on optimizing mysql . . . . . . . . . . . 370
.
Tuning MySQL for Drupal . . . . . . . . . . . . . . 372
.
Tuning PHP . . . . . . . . . . . . . . . . . . 372
.
Persistent database connections . . . . . . . . . . . . . 373
.
PHP caches . . . . . . . . . . . . . . . . . . 373
.
APC : Alternative PHP Cache . . . . . . . . . . . . . 374
.
eAccelerator . . . . . . . . . . . . . . . . . 374
.
Turck MMCache . . . . . . . . . . . . . . . . 374
.
Useful article on optimizing PHP . . . . . . . . . . . . . 376
.
Tuning Drupal on OS X Tiger . . . . . . . . . . . . . . 376
.
Upgrading from previous versions . . . . . . . . . . . . . . 378
.
Introduction to upgrading . . . . . . . . . . . . . . . 378
.
Getting started: Choosing your method and preparing the site . . . . . . 378
.
Preparing the site . . . . . . . . . . . . . . . . 379
.
Do I need to upgrade my database? . . . . . . . . . . . . 379
.
Important! : Backing up the database and existing files . . . . . . . . 379
.
Backing up your site (GUI) . . . . . . . . . . . . . . 379
.
Back up your site (command line) . . . . . . . . . . . . 380
.
Create a test site first or upgrade your existing site? . . . . . . . . 381
.
Copy your live site to a test site (GUI) . . . . . . . . . . . 381
.
Copying your live site to a test site (command line) . . . . . . . . 382
.
Downloading Drupal and installing the files . . . . . . . . . . 384
.
Downloading Drupal and installing the files (GUI) . . . . . . . . 384
.
Downloading Drupal and installing the files (command line) . . . . . . 385
.
Running update.php . . . . . . . . . . . . . . . . 386
.
Optional configuration steps . . . . . . . . . . . . . . 387
.
Post-upgrade steps . . . . . . . . . . . . . . . . 388
.

xii
3 Aug 2007 Drupal Handbook

Testing Your Newly Upgraded Site . . . . . . . . . . . . 388


.
Copy your test site to a live site . . . . . . . . . . . . . 389
.
Copying your test site to your live site (command line) . . . . . . . 390
.
Copy your test site to a live site (GUI) . . . . . . . . . . . 390
.
Differences from 4.7 to 5.x . . . . . . . . . . . . . . . 391
.
Important note on upgrading from 4.7 to 5.1 . . . . . . . . . . 391
.
Important note on upgrading from 4.7 to 5.1 . . . . . . . . . . 392
.
Version specific upgrades . . . . . . . . . . . . . . . 392
.
Upgrading from Drupal 4.4 to 4.5 . . . . . . . . . . . . . 392
.
Upgrading from Drupal 4.5 to 4.6.3 . . . . . . . . . . . . 393
.
Before you Start . . . . . . . . . . . . . . . . . 394
.
Step-by-step Upgrade from Drupal 4.5 to 4.6.3 . . . . . . . . . 394
.
Finalising your upgrade . . . . . . . . . . . . . . . 396
.
Rebuilding your Drupal Search Index. . . . . . . . . . . . 396
.
Blocks . . . . . . . . . . . . . . . . . . . . 396
.
Permissions . . . . . . . . . . . . . . . . . . 396
.
Forums . . . . . . . . . . . . . . . . . . . 397
.
Images . . . . . . . . . . . . . . . . . . . 397
.
Events . . . . . . . . . . . . . . . . . . . 397
.
Upgrading from Drupal 4.6.3 to 4.6.5 . . . . . . . . . . . . 397
.
Before you Start . . . . . . . . . . . . . . . . . 398
.
Step-by-step Upgrade from Drupal 4.6.3 to 4.6.5 . . . . . . . . . 398
.
Upgrading from Drupal 4.6.4 to 4.6.5 . . . . . . . . . . . . 398
.
Before you Start . . . . . . . . . . . . . . . . . 398
.
Step-by-step Upgrade from Drupal 4.6.4 to 4.6.5 . . . . . . . . . 399
.
Differences from 4.6 to 4.7 . . . . . . . . . . . . . . . 399
.
Block visibility settings . . . . . . . . . . . . . . . 399
.
Configure options centralized . . . . . . . . . . . . . . 399
.
core module help text linked to the handbook now . . . . . . . . . 400
.
Creating context sensitive menus with primary and secondary menus . . . . 400
.
Don’t turn off contributed modules that provide an .install file . . . . . . 400
.
Module .install files . . . . . . . . . . . . . . . . 401
.
Primary/secondary links now part of the menu system . . . . . . . . 401
.
queue module removed from core . . . . . . . . . . . . . 401
.
Removal of base href statement from header . . . . . . . . . . 402
.
Some HTML Tags stripped from mission statement . . . . . . . . 403
.
XTemplate engine removed from core . . . . . . . . . . . . 403
.
Troubleshooting FAQ . . . . . . . . . . . . . . . . . 404
.
How to troubleshoot (read this first) . . . . . . . . . . . . . 404
.
Stop and think . . . . . . . . . . . . . . . . . 404
.
Read the errors . . . . . . . . . . . . . . . . . 404
.
Validate your page . . . . . . . . . . . . . . . . 405
.
Read the README . . . . . . . . . . . . . . . . 405
.
Search the right way . . . . . . . . . . . . . . . . 405
.
Identify the source of the problem . . . . . . . . . . . . . 406
.
Dump some diagnostics . . . . . . . . . . . . . . . 406
.
Ask the right questions . . . . . . . . . . . . . . . 407
.

xiii
Drupal Handbook 3 Aug 2007

Identify the module that’s giving you problems . . . . . . . . . 407


.
My admin > modules page is blank . . . . . . . . . . . . . 407
.
How do I get the User Login block back . . . . . . . . . . . . 408
.
Client does not support authentication protocol requested by server... . . . . . 408
.
Webhosting issues for new Drupal users . . . . . . . . . . . . 409
.
Brief intro to Unix file permissions . . . . . . . . . . . . . 409
.
Host-specific error messages . . . . . . . . . . . . . . 411
.
SELinux may cause mysterious permission problems . . . . . . . . 411
.
Typical webhosting setups . . . . . . . . . . . . . . 412
.
Using PHP to change files on the webserver . . . . . . . . . . 413
.
What do all those Unix commands mean? . . . . . . . . . . . 413
.
Some Unix command you’ll see mentioned: . . . . . . . . . . 413
.
Special characters: . . . . . . . . . . . . . . . . 414
.
What permissions does Drupal need? . . . . . . . . . . . . 414
.
Why is this uploading stuff so difficult? . . . . . . . . . . . 416
.
"Headers already sent" error . . . . . . . . . . . . . . . 416
.
"LOCK TABLES sequences WRITE" error . . . . . . . . . . . 417
.
"Method POST is not allowed for the URL /index.htm" error (Error 405) . . . . 417
.
"Page Not Found" error when trying to access a subdirectory . . . . . . . 418
.
Block referrer spam . . . . . . . . . . . . . . . . . 418
.
.htaccess sample list plus domain blocking . . . . . . . . . . . 419
.
Color picker doesn’t appear on theme configuration page . . . . . . . . 420
.
Drupal 4.7 Install inserts CGI-BIN in URL . . . . . . . . . . . 420
.
Duplicate entry error . . . . . . . . . . . . . . . . 421
.
E-Mail from Drupal is bouncing or not being sent . . . . . . . . . 423
.
Relay SMTP mail to external mail server using smtp.class . . . . . . . 423
.
Error 1364 upon importing database.mysql with MySQL 5.0+ . . . . . . . 424
.
Error on installation step 3: Warning: Table ’[database].access’ doesn’t exist [...] . . 425
.
Fatal error: Allowed memory size of X bytes exhausted (tried to allocate Y bytes)... . 426
.
Fatal error: Call to undefined function . . . . . . . . . . . . 426
.
Fatal error: Call to undefined function: form_*() on Drupal 4.7 . . . . . . 426
.
Fatal error: Cannot redeclare blah_function() in ../modules/blah.module . . . . 427
.
Forgotten your Drupal account password . . . . . . . . . . . 427
.
Forum overview stopped working . . . . . . . . . . . . . 428
.
The Fix . . . . . . . . . . . . . . . . . . . 428
.
FTP uploads and file permissions using Transmit . . . . . . . . . . 429
.
Help! I enabled a buggy module and now I can’t disable it! . . . . . . . 429
.
How can I adminstrate my navigation on my Drupal site? (version 4.5 or older) . . 429
.
How do I get rid of the "Welcome to your new Drupal website" on the front page? . . 431
.
How do I get the Navigation block back . . . . . . . . . . . . 432
.
How do I unset the clean URLs? . . . . . . . . . . . . . . 432
.
How to login once you have turned your site off-line for maintenance . . . . . 432
.
HOWTO: Download a fresh copy of a missing or corrupted module/image/file . . 433
.
Installation/configuration . . . . . . . . . . . . . . . 434
.
406 Error when XMLRPC is used . . . . . . . . . . . . . 434
.
Junk {head} {styles} codes as output . . . . . . . . . . . . . 434
.
Login after disabling the User login block . . . . . . . . . . . 435
.

xiv
3 Aug 2007 Drupal Handbook

Login doesn’t work or must be done twice . . . . . . . . . . . 435


.
Cookies . . . . . . . . . . . . . . . . . . . 435
.
Cache Problems . . . . . . . . . . . . . . . . . 435
.
Logging in at www on a site with no www in the baseurl . . . . . . . 436
.
Login problems on PHP 5.2 . . . . . . . . . . . . . . . 436
.
My layout collapses - content appears below left column (IE) or overflows over the right
(FF) . . . . . . . . . . . . . . . . . . . . . 436
.
The content is too wide for the space it’s been given . . . . . . . . 437
.
Validation Woes . . . . . . . . . . . . . . . . . 437
.
Mysterious 403, 404, 406 or 500 errors depending on submitted content . . . . 438
.
Permission denied in includes/file.inc . . . . . . . . . . . . 438
.
Persistent ’Welcome to Drupal’ for anonymous users . . . . . . . . . 439
.
phpinfo . . . . . . . . . . . . . . . . . . . . 440
.
Plain unstyled HTML output . . . . . . . . . . . . . . 440
.
Setting up Clean URLs . . . . . . . . . . . . . . . . 441
.
unblocking account through SQL . . . . . . . . . . . . . 442
.
Weird behaviour - module-theme name collision . . . . . . . . . . 442
.
Where is the taxonomy choice when adding content? . . . . . . . . . 442
.
Miscellaneous . . . . . . . . . . . . . . . . . . 443
.
How can I change Drupal’s character encoding? (UTF-8 and Unicode) . . . . 443
.

xv
3 Aug 2007 Drupal Handbook

Installation and configuration


Here is a guide for installing and configuring a Drupal site. This guide includes extensive
How-to’s for using all core modules and installing themes. It also includes a guide for end users,
the people who visit a Drupal site.

Note: Feel free to add handbook pages relevant to this section.

1
Drupal Handbook 3 Aug 2007

System requirements
1. A Web Server that can execute PHP scripts

2. Recommended: Apache.

Drupal will work on Apache 1.3 or Apache 2.x hosted on Unices or Windows. The
majority of Drupal development is done using Apache so there is more community
experience and testing performed. Optional: You can use the Apache extension
mod_rewrite to allow for clean urls.

Optional: IIS

Drupal core will work using IIS5 or IIS6 if PHP is configured correctly. You will need to
use a third party solution to achieve Clean URLs. In view of Microsoft’s support life
cycle it is suggested you use IIS6.
To achieve clean_url’s you will need to use a third party product.

Drupal is being developed to be web server independent but we have limited or no reports
of successful use on web servers not listed here.

3. PHP

4. Drupal 4.7 and above require PHP version 4.3.3 or higher. PHP 5.2 is a special case; only
Drupal 4.7.5 (and greater) and 5.0 (and greater) run on PHP 5.2, older Drupal versions do
not. We recommend using the latest version of PHP 4.x. or 5.x for security and future
compatibility.

PHP memory of approximately 8MB for a Drupal core installation. In reality you will
probably need to use a higher setting depending on your site and contributed modules
you are using. A good starting point is 16-24 MB.
PHP XML extension (for blogapi, drupal, and ping modules). This extension is enabled
by default in a standard PHP installation; the windows version of PHP has built-in
support for this extension.
PHP needs the following configuration directives for Drupal to work (only directives
that differ from the default php.ini-dist / php.ini-recommended):
session.save_handler: user
error_reporting set to E_ALL & ~E_NOTICE. Work is ongoing to change this to
E_ALL for Drupal 6.
In addition, we recommend the following settings:
session.cache_limiter: none
Some of these settings are contained in the default .htaccess file that ships with Drupal,
so you shouldn’t need to set them explicitly. Note, however, that setting PHP
configuration options from .htaccess only works:

with Apache (or a compatible web server),

2
3 Aug 2007 Drupal Handbook

if the .htaccess file is actually read, i.e. AllowOverride is not None,


if PHP is installed as an Apache module.
See the PHP manual for how to change configuration settings for other interfaces to
PHP.
5. A PHP-supported Database Server

6. Recommended: MySQL 4.1 or MySQL 5.0.

Drupal will work on v3.23.17 and 4.0 but it is strongly suggested you use 4.1 or 5.0 for
future compatibility with Drupal 6 which will drop support for older versions of
MySQL.
NOTE: Drupal makes use of some features not available on some inexpensive hosting
plans so please check that your host allows database accounts with the following rights:

SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE


TEMPORARY TABLES, LOCK TABLES

Note: If your system/host is running MySQL 4.1 or newer and you receive the error
"Client does not support authentication protocol requested by server", address the
problem by following the instructions provided by MySQL AB. There is a minor OS
issue with some MySQL 5+ installations primarily on Windows but affecting some
Unices as well.

PostgreSQL, version 7.3 or newer.

Note, some of the contributed modules are not as abstracted from MySQL specific code
as everyone would like. If you are familiar with PostgreSQL please file issues with
those contributed modules as you find them.

Currently MS SQL and Oracle are not supported but various efforts are underway to supply
schemas. Please see discussions in the Enterprise Group if you are interested in working on
this.

Client System Requirements


Drupal aims to conform with internet standards and deviate where necessary to comply with
popular clients that are not standards compliant.

Javascript
For the Javascript, we currently test for all required API features (DOM APIs) and based on that,
enabled or disable all JS functionality. That way, we don’t care about particular browsers, only
what they support.

3
Drupal Handbook 3 Aug 2007

CSS
For CSS, the situation is quite similar to Javascript. The only difference is that here there is a
strong difference between the standard compliant browsers and Internet Explorer. We can use
CSS2 where needed and provide IE6 workarounds if necessary.

RSS
Drupal RSS feeds should work with any RSS feed reader. (note: could use more information).

Browser Specifics
In practice, this means that IE6, FF1.0/1.5, Opera 8-9 and Safari 1.x/2.0 get the whole experience.
Konqueror should work if it’s the latest version.

Browser Popularity
The general net usage is 85% IE, 10% Ffox, 3% Safari, 2% Opera or so. For Drupal.org, it is 50%
Ffox/Moz, 30% IE, 20% other.

Known Problems
IE5 and IE5.5 will experience some layout issues. IE5.0 will not do any Javascript. We can
assume that for Firefox and Opera, the users have a high chance of running the latest version.

IE4 and NS4, we no longer care about because they are no longer maintained and they are not in
widespread use.

Validation
Drupal HTML and RSS should validate using the W3C Markup Validation Service.

Caveats
These guidelines are the guide for Drupal core, modules, and themes but are not always
completely accurate. In practice, Drupal Core is expected to follow these standards more closely
than various contributed pieces of code. If you find a problem with client compatability that
deviates from the above client support guidelines, please try to find the root of the problem and
submit an issue ideally including a patch to fix the problem.

4
3 Aug 2007 Drupal Handbook

HOWTO: Server requirement recommendations for


your consulting clients
When thinking about the server hardware for a Drupal site, there are two important questions to
ask:

1. Which modules are you going to use? Certain modules require more server power than
others, but generally speaking more modules means more server requirements.

2. How many users will you have and what will they be doing? More users means more of a
demand on the server, but especially if these users login and make comments or nodes you will
need a more powerful server.

You need to consider these two answers together. For example, you could have a highly
complex site with very few users and be able to use a shared hosting environment. You could
also use very few modules, only have one editor, use the cache, and have reasonable traffic on a
shared environment.

If your project is a more interactive environment with more users logging in and posting to the
site you will need to consider more powerful hardware. As you move out of a shared
environment there are other options available to you like using the methods described in the
handbook to Tune Your Server for optimal Drupal performance. Tuning the server may allow
you to continue using the same hardware and not upgrade, but it comes at the cost of time
which can be more expensive than simply buying new hardware.

When deciding which parts of your server to upgrade, remember that "Apache is bandwidth
limited, PHP is CPU limited, and MySQL is memory limited and disk I/O bound".

Message to the Client


It’s probably best to give the message to the client of a "recommended" installation and a level
below that in case their budget is limited and a level above that to provide for future growth
with purchasing new hardware and services.

If you are rolling out a new service (as opposed to installing Drupal in place of an existing
solution) keep an eye towards a solid upgrade path. You can purchase a single server with the
intent of upgrading as your site grows. For example, start with the web server and database on
one server that is optimized for web serving. As the site grows in popularity and you need to
handle more users you can then move the database to it’s own server separate from the web
server. If your site grows beyond a two server "web server" and "database server" configuration
then you can consider using a single web server and multiple database servers in a cluster.

5
Drupal Handbook 3 Aug 2007

Benchmark
One benchmark of a server is MBR.org which required serious intervention for optimisation at
roughly the 2m pages per month mark, on a server running Apache1.3 and MySQL 4.1 with 1GB
of memory. MySQL indexing, database memory use tweaks and abandoning MyISAM for
InnoDB brought it under control - the jury’s out on using persistent connections.

There is a need for more case studies like this to be documented on this handbook page

What Drupal.org runs on


As of April 2007 (and for a long time before that) Drupal.org has been running on a group of 3
servers. For details on those servers see Dries post about the "future" drupal.org hardware as it
was being delivered.

Requirements - older versions


1. A Web Server that can execute PHP scripts
2.
Recommended: Apache. Development is done with version 1.3.x. Successfully tested
with version 2.0.x.
Optional: IIS. Drupal is being developed with IIS compatibility in mind, and IIS5 and
IIS6 work with a correctly configured PHP setup.
3. PHP
4.
As of Drupal 4.6, the CMS requires PHP version 4.3.3+ (PHP 5 is supported for the 4.6
release). Drupal 4.2 to 4.5.2 inclusive require PHP version 4.1+. Older versions of
Drupal will run on PHP 4.0.6+. We recommend using the latest version of PHP 4.x.
PHP XML extension (for blogapi, drupal, and ping modules). This extension is enabled
by default in a standard PHP installation; the windows version of PHP has built-in
support for this extension.
PHP memory of 8MB for a Drupal core install. If you install additional contributed
modules you may need to raise your php allowed memory. Prepackaged Drupal
distributions such as CivicSpace may have higher PHP memory requirements then a
Drupal core install.

PHP needs the following configuration directives for drupal to work:


session.save_handler: user
In addition, we recommend the following settings:
session.cache_limiter: none
(We only mention directives that differ from the default php.ini-dist /
php.ini-recommended starting with PHP 4.0.6)
These settings are contained in the default .htaccess file that ships with Drupal, so you
shouldn’t need to set them explicitly. Note, however, that setting PHP configuration options
from .htaccess only works:

6
3 Aug 2007 Drupal Handbook

with Apache (or a compatible web server),


if the .htaccess file is actually read, i.e. AllowOverride is not None,
if PHP is installed as an Apache module.
See here for how to change configuration settings for other interfaces to PHP.
Using a PEAR-supported Database (see below) requires (of course) PEAR to be installed.
A PHP-supported Database Server

Recommended: MySQL, v3.23.17 or newer (for our use of INNER JOIN’s with
join_condition’s). MySQL 4 is fine.
Drupal makes use of features not available on some inexpensive hosting plans, like
LOCK TABLE
Working well since 4.7: PostgreSQL, version 7.3 or newer (7.2 will probably work too,
but you’ll get some errors when updating from 4.6). Experiences with other databases
are greatly welcome.

Note: If your system/host is running MySQL 4.1 or newer, a link in the troubleshooting
section (http://drupal.org/node/35226) points to this page, which has some helpful info on
addressing this problem with PHP 4.x and PHP5. There is a minor OS issue with some
MySQL 5+ installations primarily on Windows but affecting some *nix installs as well.

Also, xTemplate (the default theme engine for Drupal 4.6.x and previous) is reported to
have issues with PHP 5.0.5 and 5.1. Converting your themes to the phpTemplate engine
(default in 4.7) will work around this issue.

7
Drupal Handbook 3 Aug 2007

Installing Drupal, modules and themes


Installing Drupal, new modules and themes uses roughly the same process so once you are
familiar with it you can repeat as needed.

After you successfully install Drupal, you will want to perform some basic site configuration
starting with the settings menu.

Installing and configuring your site is only part of your responsibilities. You must remember to
backup, test and maintain it as well. Please stop by the Best Practices section for some important
tips on this and sign up for the security newsletter

Installing Drupal
This page is autogenerated from the current development text in CVS. See the various other
provided instructions linked in the menu on the left for additional environments.
// $Id: INSTALL.txt,v 1.39 2007/01/08 11:59:16 dries Exp $
CONTENTS OF THIS FILE
---------------------
* Changes
* Requirements
* Optional requirements
* Installation
* Drupal administration
* Customizing your theme(s)
* Multisite Configuration
* More Information
CHANGES
-------
As of Drupal 5.0 installation has been automated by an install script.
It is no
longer necessary to manually edit the "settings.php" file, and database
tables
are created automatically.
REQUIREMENTS
------------
Drupal requires a web server, PHP4 (4.3.3 or greater) or PHP5
(http://www.php.net/) and either MySQL (http://www.mysql.com/) or
PostgreSQL
(http://www.postgresql.org/). The Apache web server and MySQL database
are
recommended; other web server and database combinations such as IIS and
PostgreSQL have been tested to a lesser extent. When using MySQL,
version 4.1
or greater is recommended to assure you can safely transfer the
database.

8
3 Aug 2007 Drupal Handbook

For more detailed information about Drupal requirements, see


"Requirements"
(http://drupal.org/requirements) in the Drupal Handbook.
Guidelines for setting up a server environment with a variety of
operating
systems and in special cases are available in the Drupal handbook
(http://drupal.org/node/260)
OPTIONAL REQUIREMENTS
---------------------
- To use XML-based services such as the Blogger API, Jabber, and RSS
syndication, you will need PHP’s XML extension. This extension is
enabled by
default.
- If you want support for clean URLs, you’ll need mod_rewrite and the
ability
to use local .htaccess files.
INSTALLATION
------------
1. DOWNLOAD DRUPAL
You can obtain the latest Drupal release from http://drupal.org/.
The files
are in .tar.gz format and can be extracted using most compression
tools. On a
typical Unix command line, use:
wget http://drupal.org/files/projects/drupal-x.x.tar.gz
tar -zxvf drupal-x.x.tar.gz
This will create a new directory drupal-x.x/ containing all Drupal
files
and directories. Move the contents of that directory into a
directory within
your web server’s document root or your public HTML directory:
mv drupal-x.x/* drupal-x.x/.htaccess /var/www/html
2. CREATE THE DRUPAL DATABASE
Drupal requires access to a database in order to be installed. Your
database
user will need sufficient privileges to run Drupal. Additional
information
about privileges, and instructions to create a database using the
command
line are available in INSTALL.mysql.txt (for MySQL) or
INSTALL.pgsql.txt
(for PostgreSQL).
To create a database using PHPMyAdmin or a web-based control panel
consult
the documentation or ask your webhost service provider.
Take note of the username, password, database name and hostname as
you

9
Drupal Handbook 3 Aug 2007

create the database. You will enter these items in the install
script.
3. RUN THE INSTALL SCRIPT
The install script will set the base URL, connect Drupal to the
database, and
create tables in the database.
To run the install script point your browser to the base url of your
website
(i.e. http://www.example.com). You will be presented with the
"Database
Configuration" page.
The install script will attempt to write-protect the settings.php
after
updating it with the information you provide in the installation
routine.
If you make manual changes to that file later, be sure to protect it
again
after making your modifications. Failure to remove write permissions
to
that file is a security risk. The default location for the
settings.php
file is at sites/default/settings.php, but it may be in another
location
if you use the multi-site setup, as explained below.
4. CONFIGURE DRUPAL
When the install script succeeds, you will be directed to the
"Welcome" page.
In "step one" click "create the first account" which will become the
main
administrator account with total control. Login as the administrator
and
complete the initial configuration steps on the "Welcome" page.
Consider creating a "files" subdirectory in your Drupal installation
directory. This subdirectory stores files such as custom logos, user
avatars,
and other media associated with your new site. The sub-directory
requires
"read and write" permission by the Drupal server process. You can
change
the name of this subdirectory at "administer > site configuration >
file
system".
5. CRON TASKS
Many Drupal modules (such as the search functionality) have periodic
tasks
that must be triggered by a cron job. To activate these tasks, call
the cron

10
3 Aug 2007 Drupal Handbook

page by visiting http://www.example.com/cron.php --this will pass


control to
the modules and the modules will decide if and what they must do.
Most systems support the crontab utility for scheduling tasks like
this. The
following example crontab line will activate the cron tasks
automatically on
the hour:
0 * * * * wget -O - -q http://www.example.com/cron.php
More information about the cron scripts are available in the admin
help pages
and in the Drupal handbook at drupal.org. Example scripts can be
found in the
scripts/ directory.
DRUPAL ADMINISTRATION
---------------------
A new installation of Drupal defaults to a very basic configuration
with only a
few active modules and minimal user access rights.
Use your administration panel to enable and configure services. For
example:
General Settings administer > site configuration > site
information
Enable Modules administer > site configuration > modules
Set User Permissions administer > users management > access control
Configure Themes administer > site building > themes
For more information on configuration options, read the instructions
which
accompany the different configuration settings and consult the various
help
pages available in the administration panel.
Community-contributed modules and themes are available at
http://drupal.org/.
CUSTOMIZING YOUR THEME(S)
-------------------------
Now that your installation is running, you will want to customize the
look of
your site. Several sample themes are included and more can be
downloaded from
drupal.org.
Simple customization of your theme can be done using only CSS. Further
changes
require understanding the phptemplate engine that is now part of
Drupal. See
http://drupal.org/handbook/customization to find out more.
MULTISITE CONFIGURATION
-----------------------

11
Drupal Handbook 3 Aug 2007

A single Drupal installation can host several Drupal-powered sites,


each with
its own individual configuration.
Additional site configurations are created in subdirectories within the
’sites’
directory. Each subdirectory must have a ’settings.php’ file which
specifies the
configuration settings. The easiest way to create additional sites is
to copy
the ’default’ directory and modify the ’settings.php’ file as
appropriate. The
new directory name is constructed from the site’s URL. The
configuration for
www.example.com could be in ’sites/example.com/settings.php’ (note that
’www.’
should be omitted if users can access your site at
http://example.com/).
Sites do not have to have a different domain. You can also use
subdomains and
subdirectories for Drupal sites. For example, example.com,
sub.example.com,
and sub.example.com/site3 can all be defined as independent Drupal
sites. The
setup for a configuration such as this would look like the following:
sites/default/settings.php
sites/example.com/settings.php
sites/sub.example.com/settings.php
sites/sub.example.com.site3/settings.php
When searching for a site configuration (for example
www.sub.example.com/site3),
Drupal will search for configuration files in the following order,
using the
first configuration it finds:
sites/www.sub.example.com.site3/settings.php
sites/sub.example.com.site3/settings.php
sites/example.com.site3/settings.php
sites/www.sub.example.com/settings.php
sites/sub.example.com/settings.php
sites/example.com/settings.php
sites/default/settings.php
If you are installing on a non-standard port, the port number is
treated as the
deepest subdomain. For example: http://www.example.com:8080/ could be
loaded
from sites/8080.www.example.com/. The port number will be removed
according to
the pattern above if no port-specific configuration is found, just like

12
3 Aug 2007 Drupal Handbook

a real
subdomain.
Each site configuration can have its own site-specific modules and
themes in
addition to those installed in the standard ’modules’and ’themes’
directories.
To use site-specific modules or themes, simply create a ’modules’ or
’themes’
directory within the site configuration directory. For example, if
sub.example.com has a custom theme and a custom module that should not
be
accessible to other sites, the setup would look like this:
sites/sub.example.com/:
settings.php
themes/custom_theme
modules/custom_module
NOTE: for more information about multiple virtual hosts or the
configuration
settings, consult the Drupal handbook at drupal.org.
MORE INFORMATION
----------------
For platform specific configuration issues and other installation and
administration assistance, please consult the Drupal handbook at
http://drupal.org/handbook. You can view the wide range of other
support options
available at http://drupal.org/support.

Formatted Drupal 5.x Installation instructions for better


readability
Installation
// $Id: INSTALL.txt,v 1.39 2007/01/08 11:59:16 dries Exp $

Table of Contents

1. Changes
2. Requirements
3. Optional requirements
4. Installation
5. Drupal administration
6. Customizing your theme(s)
7. Multisite Configuration
8. More Information

13
Drupal Handbook 3 Aug 2007

Changes
As of Drupal 5.0 installation has been automated by an install script. It is no longer necessary to
manually edit the "settings.php" file, and database tables are created automatically.

Requirements
Drupal requires a web server, PHP4 (4.3.3 or greater) or PHP5 (http://www.php.net/) and
either MySQL (http://www.mysql.com/) or PostgreSQL (http://www.postgresql.org/). The
Apache web server and MySQL database are recommended; other web server and database
combinations such as IIS and PostgreSQL have been tested to a lesser extent. When using
MySQL, version 4.1 or greater is recommended to assure you can safely transfer the database.

For more detailed information about Drupal requirements, see "Requirements"


(http://drupal.org/requirements) in the Drupal Handbook.

Guidelines for setting up a server environment with a variety of operating systems and in
special cases are available in the Drupal handbook (http://drupal.org/node/260)

Optional Requirements
- To use XML-based services such as the Blogger API, Jabber, and RSS syndication, you will need
PHP’s XML extension. This extension is enabled by default.

- If you want support for clean URLs, you’ll need mod_rewrite and the ability to use local
.htaccess files.

Installation
1. Download Drupal

You can obtain the latest Drupal release from http://drupal.org/. The files are in .tar.gz format
and can be extracted using most compression tools. On a typical Unix command line, use:

wget http://drupal.org/files/projects/drupal-x.x.tar.gz
tar -zxvf drupal-x.x.tar.gz

This will create a new directory drupal-x.x/ containing all Drupal files and directories. Move the
contents of that directory into a directory within your web server’s document root or your public
HTML directory:

mv drupal-x.x/* drupal-x.x/.htaccess /var/www/html

2. Create the Drupal database

Drupal requires access to a database in order to be installed. Your database user will need
sufficient privileges to run Drupal. Additional information about privileges, and instructions to
create a database using the command line are available in INSTALL.mysql.txt (for MySQL) or

14
3 Aug 2007 Drupal Handbook

INSTALL.pgsql.txt (for PostgreSQL).

To create a database using PHPMyAdmin or a web-based control panel consult the


documentation or ask your webhost service provider.

Take note of the username, password, database name and hostname as you create the database.
You will enter these items in the install script.

3. Run the install script

The install script will set the base URL, connect Drupal to the database, and create tables in the
database.

To run the install script point your browser to the base url of your website (i.e.
http://www.example.com). You will be presented with the "Database Configuration" page.

The install script will attempt to write-protect the settings.php after updating it with the
information you provide in the installation routine. If you make manual changes to that file
later, be sure to protect it again after making your modifications. Failure to remove write
permissions to that file is a security risk. The default location for the settings.php file is at
sites/default/settings.php, but it may be in another location if you use the multi-site setup, as
explained below.

4. Configure Drupal

When the install script succeeds, you will be directed to the "Welcome" page. In "step one" click
"create the first account" which will become the main administrator account with total control.
Login as the administrator and complete the initial configuration steps on the "Welcome" page.

Consider creating a "files" subdirectory in your Drupal installation directory. This subdirectory
stores files such as custom logos, user avatars, and other media associated with your new site.
The sub-directory requires "read and write" permission by the Drupal server process. You can
change the name of this subdirectory at "administer > site configuration > file system".

5. Cron Tasks

Many Drupal modules (such as the search functionality) have periodic tasks that must be
triggered by a cron job. To activate these tasks, call the cron page by visiting
http://www.example.com/cron.php --this will pass control to the modules and the modules
will decide if and what they must do.

Most systems support the crontab utility for scheduling tasks like this. The following example
crontab line will activate the cron tasks automatically on the hour:

0 * * * * wget -O - -q http://www.example.com/cron.php

More information about the cron scripts are available in the admin help pages and in the Drupal
handbook at drupal.org. Example scripts can be found in the scripts/ directory.

15
Drupal Handbook 3 Aug 2007

Drupal Administration
A new installation of Drupal defaults to a very basic configuration with only aw active modules
and minimal user access rights.

Use your administration panel to enable and configure services. For example:

General Settings administer > site configuration > site information


Enable Modules administer > site configuration > modules
Set User Permissions administer > users management > access control
Configure Themes administer > site building > themes

For more information on configuration options, read the instructions which accompany the
different configuration settings and consult the various help pages available in the
administration panel.

Community-contributed modules and themes are available at http://drupal.org/.

Customizing your theme(s)


Now that your installation is running, you will want to customize the look of your site. Several
sample themes are included and more can be downloaded from drupal.org.

Simple customization of your theme can be done using only CSS. Further changes require
understanding the phptemplate engine that is now part of Drupal. See
http://drupal.org/handbook/customization to find out more.

Multi-site configuration
A single Drupal installation can host several Drupal-powered sites, each with its own individual
configuration.

Additional site configurations are created in subdirectories within the ’sites’ directory. Each
subdirectory must have a ’settings.php’ file which specifies the configuration settings. The
easiest way to create additional sites is to copy the ’default’ directory and modify the
’settings.php’ file as appropriate. The new directory name is constructed from the site’s URL.
The configuration for www.example.com could be in ’sites/example.com/settings.php’ (note
that ’www.’ should be omitted if users can access your site at http://example.com/).

Sites do not have to have a different domain. You can also use subdomains and subdirectories
for Drupal sites. For example, example.com, sub.example.com, and sub.example.com/site3 can
all be defined as independent Drupal sites. The setup for a configuration such as this would look
like the following:

sites/default/settings.php
sites/example.com/settings.php
sites/sub.example.com/settings.php
sites/sub.example.com.site3/settings.php

16
3 Aug 2007 Drupal Handbook

When searching for a site configuration (for example www.sub.example.com/site3), Drupal will
search for configuration files in the following order, using the first configuration it finds:

sites/www.sub.example.com.site3/settings.php
sites/sub.example.com.site3/settings.php
sites/example.com.site3/settings.php
sites/www.sub.example.com/settings.php
sites/sub.example.com/settings.php
sites/example.com/settings.php
sites/default/settings.php

If you are installing on a non-standard port, the port number is treated as the deepest
subdomain. For example: http://www.example.com:8080/ could be loaded from
sites/8080.www.example.com/. The port number will be removed according to the pattern
above if no port-specific configuration is found, just like a real subdomain.

Each site configuration can have its own site-specific modules and themes in addition to those
installed in the standard ’modules’and ’themes’ directories. To use site-specific modules or
themes, simply create a ’modules’ or ’themes’ directory within the site configuration directory.
For example, if sub.example.com has a custom theme and a custom module that should not be
accessible to other sites, the setup would look like this:

sites/sub.example.com/:
settings.php
themes/custom_theme
modules/custom_module

NOTE: for more information about multiple virtual hosts or the configuration settings, consult
the Drupal handbook at drupal.org.

More Information
For platform specific configuration issues and other installation and administration assistance,
please consult the Drupal handbook at http://drupal.org/handbook. You can view the wide
range of other support options available at http://drupal.org/support.

Formatted Drupal 4.7.x Installation instructions for better


readability
Installation
// $Id: INSTALL.txt,v 1.6 2004/11/27 11:28:55 dries Exp $

This document outlines the standard installation process.

17
Drupal Handbook 3 Aug 2007

1. REQUIREMENTS
2. SERVER CONFIGURATION
3. OPTIONAL COMPONENTS
4. INSTALLATION
5. DRUPAL ADMINISTRATION
6. CUSTOMIZING YOUR THEME(S)
7. UPGRADING
8. MORE INFORMATION

REQUIREMENTS
1. Drupal requires a web server, PHP4 (http://www.php.net/) and either
MySQL, PostgreSQL or a database server supported by the PHP PEAR API
(http://pear.php.net/).
2. To Install you will need an FTP program to upload files to the server, or shell access if you
wish to install using the commands listed below; access to run database scripts directly or a
tool such as PHPMyAdmin to manage a database; knowledge of how to use either FTP
programs or shell access to set permissions on directories, and how to run database scripts.
3. NOTE: The Apache web server and MySQL database are strongly recommended;
other web server and database combinations such as IIS and PostgreSQL
are possible but tested to a lesser extent.

SERVER CONFIGURATION
Your PHP must have the following settings:

session.save_handler user

In addition, we recommend the following settings:

session.cache_limiter none

These values are set in php.ini and can be overwritten in a .htaccess


file; you can print out your local PHP settings with PHP’s phpinfo()
function.

OPTIONAL COMPONENTS
To use XML-based services such as the Blogger API, Jabber, RSS
syndication, you will need PHP’s XML extension. This extension is
enabled by default in standard PHP4 installations.
If you want support for clean URLs, you’ll need mod_rewrite and
the ability to use local .htaccess files. (More information can
be found in the Drupal handbook on drupal.org.)

18
3 Aug 2007 Drupal Handbook

INSTALLATION
1. DOWNLOAD DRUPAL
You can obtain the latest Drupal release from http://drupal.org/.
Download the current tar.gz format and extract the files:

$ wget http://drupal.org/files/project/drupal-x.x.x.tgz
$ tar -zxvf drupal-x.x.x.tgz

This will create a new directory drupal-x.x.x/ containing all


Drupal files and directories. Move the contents of that directory
into a directory within your web server’s document root or your
public HTML directory:

$ mv drupal-x.x.x/* drupal-x.x.x/.htaccess /var/www/html

2. CREATE THE DRUPAL DATABASE


These instructions are for MySQL. If you are using another database,
check the database documentation. In the following examples,
"dba_user" is an example MySQL user which has the CREATE and GRANT
privileges. You will need to use the appropriate user name for your
system.

First, you must create a new database for your Drupal site:

$ mysqladmin -u dba_user -p create drupal

MySQL will prompt for the dba_user database password and then create
the initial database files. Next you must login and set the access
database rights:

$ mysql -u dba_user -p

Again, you will be asked for the dba_user database password. At the
MySQL prompt, enter following command:

GRANT ALL PRIVILEGES ON drupal.*


TO nobody@localhost IDENTIFIED BY ’password’;

where

’drupal’ is the name of your database


’nobody@localhost’ is the userid of your webserver MySQL account
’password’ is the password required to log in as the MySQL user

19
Drupal Handbook 3 Aug 2007

If successful, MySQL will reply with

Query OK, 0 rows affected

to activate the new permissions you must enter the command

flush privileges;

and then enter ’\q’ to exit MySQL.

3. LOAD THE DRUPAL DATABASE SCHEME


Once you have a database, you must load the required tables:

$ mysql -u nobody -p drupal < database/database.mysql

4. CONNECTING DRUPAL
The default configuration can be found in the
’sites/default/settings.php’ file within your Drupal installation.
Before you can run Drupal, you must set the database URL and the
base URL to the web site. Open the configuration file and edit the
$db_url line to match the database defined in the previous steps:

$db_url = "mysql://username:password@localhost/drupal";

Set $base_url to match the address to your web site:

$base_url = "http://www.example.com";

In addition, a single Drupal installation can host several


Drupal-powered sites, each with its own individual configuration.
If you don’t need to run multiple Drupal sites, you can skip to the
next section.

Additional site configurations are created in subdirectories within


the ’sites’ directory. Each site subdirectory must have a
’settings.php’ file which specifies the configuration settings. The
easiest way to create additional sites is to copy the ’default’
directory and modify the ’settings.php’ file as appropriate. The new
directory name is constructed from the site’s URL. The
configuration for www.example.com could be in
’sites/example.com/settings.php’ (note that ’www.’ should be omitted
if users can access your site at http://example.com/).

Sites do not each have to have a different domain. You can use
subdomains and subdirectories for Drupal sites also. For example,
example.com, sub.example.com, and sub.example.com/site3 can all be

20
3 Aug 2007 Drupal Handbook

defined as independent Drupal sites. The setup for a configuration


such as this would look like the following:

sites/default/settings.php
sites/example.com/settings.php
sites/sub.example.com/settings.php
sites/sub.example.com.site3/settings.php
When searching for a site configuration (for example
www.sub.example.com/site3), Drupal will search for configuration
files in the following order, using the first configuration file it
finds:
sites/www.sub.example.com.site3/settings.php
sites/sub.example.com.site3/settings.php
sites/example.com.site3/settings.php
sites/www.sub.example.com/settings.php
sites/sub.example.com/settings.php
sites/example.com/settings.php
sites/default/settings.php

Each site configuration can have its own site-specific modules and
themes that will be made available in addition to those installed
in the standard ’modules’ and ’themes’ directories. To use
site-specific modules or themes, simply create a ’modules’ or
’themes’ directory within the site configuration directory. For
example, if sub.example.dom has a custom theme and a custom module
that should not be accessible to other sites, the setup would look
like this:

sites/sub.example.com/:
settings.php
themes/:
custom_theme
modules/:
custom_module

NOTE: for more information about multiple virtual hosts or the


configuration settings, consult the Drupal handbook at drupal.org.

5. CONFIGURE DRUPAL
You can now launch your browser and point it to your Drupal site.

Create an account and login. The first account will automatically


become the main administrator account.

21
Drupal Handbook 3 Aug 2007

6. CRON TASKS
Many Drupal modules have periodic tasks that must be triggered by a
cron job. To activate these tasks, you must call the cron page;
this will pass control to the modules and the modules will decide
if and what they must do.

The following example crontab line will activate the cron script
on the hour:

0 * * * * wget -O - -q http://HOSTNAME/cron.php

More information about the cron scripts are available in the admin
help pages and in the Drupal handbook at drupal.org. Example
scripts can be found in the scripts/ directory.

DRUPAL ADMINISTRATION
Upon a new installation, your Drupal website defaults to a very basic
configuration with only a few active modules, one theme, and no user
access rights.

Use your administration panel to enable and configure services. For


example, set some general settings for your site with "Administration -
configuration". Enable modules via "Administration - configuration -
modules". User permissions can be set with "Administration - accounts
- permissions".

For more information on configuration options, read through the


instructions which accompany the different configuration settings and
consult the various help pages available in the administration panel.

Note that additional community-contributed modules and themes are


available at http://drupal.org/.

CUSTOMIZING YOUR THEME(S)


Now that your server is running, you will want to customize the look
of your site. Several sample themes are included in the Drupal
installation and more can be downloaded from drupal.org.

Customizing each theme depends on the theme. In general, each theme


contains a PHP file themename.theme which defines a function header()
that can be changed to reference your own logos.

22
3 Aug 2007 Drupal Handbook

Most themes also contain stylesheets or PHP configuration files to


tune the colors and layouts; check the themes/ directory for README
files describing each alternate theme.

UPGRADING
1. Backup your database and Drupal directory - especially your
configuration file (www.example.com.conf or includes/conf.php).
2. Log on as the user with user ID 1.
3. Remove all the old Drupal files then unpack the new Drupal files
into the directory that you run Drupal from.
4. Modify the new configuration file to make sure it has the
correct information.
5. Run update.php by visiting http://www.example.com/update.php.

MORE INFORMATION
For platform specific configuration issues and other installation and
administration assistance, please consult the Drupal handbook at
http://drupal.org/. You can also find support at the Drupal support forum or through the
Drupal mailing lists.

10 minute install using PuTTY SSH/Telnet client


I’ve been developing best practices for my development company and wanted to
share/collaborate on some of them.

Development environment:

Server: LAMP
SSH/Telenet Client: PuTTY
Server Interface: WHM
Must have root access.

10 minute Install:

[login root via PuTTY]


# cd /home/youraccountname
# wget
http://ftp.osuosl.org/pub/drupal/files/projects/drupal-x.x.tar.gz
[Note: the "x.x" should be replaced with the version of drupal you’re
installing, e.g. "5.1"]
# tar -zxvf drupal-5.1.tar.gz
# mv drupal-x.x/* drupal-x.x/.htaccess
/home/youraccountname/public_html
[Note: See the note above regarding "x.x"]

23
Drupal Handbook 3 Aug 2007

# rm drupal-x.x.tar.gz
# cd public_html
# mkdir files
# chmod 777 files
# cd sites/all
# mkdir modules
# mkdir themes
# cd modules
# mkdir custom
# mkdir drupal-contrib
# cd ../
# cd themes
# mkdir custom
# mkdir drupal-contrib
# cd ../
# cd ../
# cd default
# chmod 777 settings.php
# mysql
mysql> CREATE DATABASE youraccountname_drupal;
mysql> GRANT ALL PRIVILEGES ON youraccountname_drupal.* TO ’your
accountname_yourusername’@’localhost’ IDENTIFIED BY ’yourpassword’;
mysql> \q
[open your browser. enter your site’s URL, and enter database
information]
[go back to PuTTY to chmod on "settings.php"]
# chmod 755 settings.php
# logout
[back to browser, refresh browser, and then "visit new site" (or
whatever the link says to new website), create first "superuser"
account, etc.]

How I installed Drupal: The Eightfold Way


Try this for a supereasy install.

This installation is for a test site.

The aim is to have a test site: \http://drupal.yoursite.com\

When the test site is functioning, the drupal subdomain prefix will be deleted. Therefore the
domain name in the root will be mysite.com The DNS servers will automatically point to this
(hopefully!). This is what worked for me:

1) Downloaded Drupal 5.0


2) Created a subdomain ("drupal") via my webhost’s control panel
3) Created a database ("dbname") via my webhost’s control panel (note the user name and

24
3 Aug 2007 Drupal Handbook

password). Noted the hostname, e.g., testsite.yoursite.com


4) Using browser, pointed to URL \http://drupal.yoursite.com\
5) The install.php script automatically installed Drupal
6) Entered information. Database name ("dbname"), username, password
7) Clicked "Advanced options"
8) Entered hostname (e.g., testsite.yoursite.com). Went to testsite.yoursite.com in browser.

Installing virtual hosts for Drupal sites and subsites


The purpose of this guide is to concisely summarize how to implement apache vhost settings for
each site or subsite.

All steps for this tutorial were implemented with Debian using Apache version 2.0.54.

1. Gain entrance into your shell system, and su to root or another user that can edit apache2
configuration files.
2. Go to your apache configuration files:
cd /etc/apache2/sites-available
3. Create a configuration file for your new site. For an example site, www.example.com, we
make the site as such:
nano example.com

<VirtualHost *:80>
ServerAdmin me@myserver
DocumentRoot /home/web/drupal/
ServerName www.example.com
ServerAlias example.com *.example.com
RewriteEngine On
RewriteOptions inherit
CustomLog /var/log/apache2/example.com.log combined
</VirtualHost>
<VirtualHost *:443>
ServerAdmin me@myserver
DocumentRoot /home/web/drupal/
ServerName www.example.com
ServerAlias example.com *.example.com
RewriteEngine On
RewriteOptions inherit
CustomLog /var/log/apache2/example.com.log combined
# SSL Specific options
SSLEngine on
SSLCipherSuite
ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/ssl/apache/CA.crt
SSLCertificateKeyFile /etc/ssl/apache/CA.key
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
</VirtualHost>

25
Drupal Handbook 3 Aug 2007

Activate the site’s configuration:


a2ensite www.example.com
Reload Apache’s configuration:
/etc/init.d/apache2 force-reload

Done!

Please post any changes or concerns,

Tarek : )

Mac OS X-specific guidelines


Install and configure Mysql and PHP, if necessary. Server Logistics provides nice pre-compiled
packages and instructions. PHP is also available from Marc Liyanage. PHP may already be
installed on your system, so check first.

The stock version of Apache should be fine (typically 1.33).

Turn on "personal web sharing" in the sharing panel of System Preferences to start Apache. Now
comes the more involved part- changing the webserver configuration.

To make changes to the Apache configuration you should NOT edit /etc/httpd/httpd.conf but
instead edit files in /private/etc/httpd/users/. Any file in the directory
/private/etc/httpd/users/ ending with â.confâ will effectively be appended to
/etc/httpd/httpd.conf. So any changes you want to make should be made in one or more
configuration files of your own construction. System updates will leave these files untouched.
You can create a file /private/etc/httpd/users/drupal.conf for all your Drupal-specific changes
(even if you have no user named Drupal) and they will be loaded when Apache starts up.

Note: for Mac OS X Server 10.4 (Tiger Server) and most likely previous versions as well, do not
make changes to /etc/httpd/httpd.conf expecting the AllowOverride All directive to
work. The correct file to add the AllowOverride All directive is in the directory
/etc/httpd/sites/. In that directory are the virtual host configuration files. Each virtual
server has a configuration file in that directory so it is in those files that you must enable
AllowOverride All. If you only have one web server on your server configured, then the file
you want to modify is /etc/httpd/sites/0000_any_80_.conf.

To enable clean URLs you will need the following code in your conf file. You’ll need to be root
(or sudo) to do this. Don’t forget to restart apache after modifying httpd.conf (turn personal web
sharing off, then back on again, or use /usr/sbin/apachectl restart).

#
# This controls which options the .htaccess files in directories can
# override. Can also be "All", or any combination of "Options",
"FileInfo",
# "AuthConfig", and "Limit"
#

26
3 Aug 2007 Drupal Handbook

# AllowOverride None
AllowOverride All

You may also need to edit this file to enable the PHP module for Apache. You have to
uncomment two lines. First in this section:

#
# Dynamic Shared Object (DSO) Support
#

Uncomment this line (around line 235) by removing the #:

#LoadModule php4_module libexec/httpd/libphp4.so

Then go below to this section:

# Reconstruction of the complete module list from all available


modules
# (static and shared ones) to achieve correct module execution order.

and uncomment this line (around line 278) by removing the #:

#AddModule mod_php4.c

Drupal goes into /Library/WebServer/Documents/, or ~/Sites. If you use ~/Sites, you may
also have to edit the .conf file in /etc/httpd/users that corresponds to your user account. You
must AllowOverride in this file for your ~/Sites for clean URLs to work there.

After any edits to your .conf files, be sure to restart Apache (as described above).

MacZeaolots has a good tutorial on installing Drupal on Mac OS X 10.4. The same tutorial
applies to 10.3 as well. While the tutorial talks about Drupal 4.6, the setup of the server
environment is the same for any version of Drupal.

Important notes for MySQL install:


The version of PHP that Apple included with Mac OS X 10.4.4 has mysql.default_socket set to
"/var/mysql/mysql.sock", while the binary version of MySQL from mysql.com uses
"/tmp/mysql.sock". This will cause PHP to fail to connect to mysql with a message in Drupal
like

can’t connect to local MySQL server through socket ’/var/lib/mysql/mysql.sock’ (2)

Make PHP look for "/tmp/mysql.sock" by setting this in /etc/php.ini:

; Default socket name for local MySQL connects. If empty, uses the
built-in
; MySQL defaults.
mysql.default_socket = /tmp/mysql.sock

27
Drupal Handbook 3 Aug 2007

You can instead set this in /etc/my.cnf.

#Name of the socket file to use.


socket=/var/mysql/mysql.sock

Both work, but the second one may make the MySQL preference pane stop working.

You may also need to restart apache to have this take effect.

Restart from the terminal:

$ sudo apachectl restart

or restart by disabling and re-enabling personal web sharing.

HOWTO: Create a local server environment for drupal using MAMP


MAMP creates a local server environment on Mac OS X by installing PHP, MySQL, and Apache
all at once. This will hopefully make Drupal much easier to install because the components don’t
have to be installed separately. This page is to be used in conjunction with the installation
instructions for Drupal on Mac OS X.

1. Download MAMP
(This will install Apache, MySQL, and PHP in one step.)
Find the latest version here: http://www.mamp.info/
Download and drag to Applications folder to install. Open MAMP and click "start servers," then
"Open start page."

2. Download Drupal
Find the latest Drupal release here: http://drupal.org/.

Move the directory containing the Drupal files into the MAMP htdocs directory:

mv drupal-x.x.x/* drupal-x.x.x/.htaccess /Applications/MAMP/htdocs/

3. Create the Drupal database

Go to the MAMP start page and click "phpMyAdmin." Create a new database and follow the
instructions in INSTALL.mysql.txt to upload the required files from your Drupal installation.

4. Connect Drupal
Set the database URL in the ’sites/default/settings.php’ file in your Drupal installation using the
information provided on the MAMP start page and the name you used for the database you
created in step 3.

$db_url = "mysql://username:password@localhost/databasename";

28
3 Aug 2007 Drupal Handbook

5. Start configuring Drupal!


Go to http://localhost:8888/drupal-x.x.x/ and create the first account.
Continue with instructions in INSTALL.txt.

HOWTO: Installing PostgreSQL and MySQL on the same Mac OS X


machine
If you’re interested in helping to ensure that Drupal and its contributed modules are compatible
with both MySQL and PostgreSQL (also known as "pgsql"), you should consider setting up local
test sites using both database back ends on the same machine. You can even configure both sites
to point to the same Drupal installation, using symbolic links.

Unfortunately, the version of PHP that ships with Mac OS by default is not compatible with
PostgreSQL, so to do this, you will need to compile both pgsql and php from source. While
you’re at it, you might want to upgrade to a newer version of MySQL, as well.

1. Make a directory where you can build all of these programs. For example:
mkdir /usr/local/src
cd /usr/local/src

Download the latest copies of everything you need:


PHP -- http://www.php.net/downloads.php
MySQL -- http://www.mysql.com/downloads
PostgreSQL -- http://www.postgresql.org/download
Unpackage all of these inside /usr/local/src
Configure and build MySQL. Good instructions can be found on this page: MySQL on Mac
OS X. The important thing is that when you run
configure you use a reasonable value for the --prefix flag. For example: ./configure
--prefix=/usr/local/mysql
Configure and build PostgreSQL. Once again, useful installation docs can be found here:
PostgreSQL on Mac OS X, though the section about "Postgres and PHP" isn’t what you want
to read. Again, be sure you use a reasonable value for the--prefix flag. For example:
./configure --prefix=/usr/local/pgsql
Configure and build PHP. After some trial and error, getting PHP working properly with
both MySQL and PostgreSQL required a carefully crafted configure line:
./configure --with-pgsql=/usr/local/pgsql
--with-mysql=/usr/local/mysql --with-apxs --with-kerberos=/usr
--with-zlib-dir=/usr --enable-cli --enable-trans-sid --with-xml
--enable-exif --enable-ftp --enable-mbstring --enable-mbregex
--enable-dbx --enable-sockets --with-iodbc=/usr --with-curl=/usr
--with-config-file-path=/etc --sysconfdir=/private/etc
--with-mysql-sock=/var/mysql/mysql.sock
Some noteworthy things about this command:

This matches the flags used for the default PHP installed on Mac OS X as closely as
possible, while also enabling PostgreSQL support.

29
Drupal Handbook 3 Aug 2007

The path you use for --with-pgsql must match whatever you specified for
--prefix when building PostgreSQL.
The path you use for --with-mysql must match whatever you specified for
--prefix when building MySQL.
The path you use for --with-mysql-sock should match whatever you specified for
--with-unix-socket-path when building MySQL.

Additional information about building PHP on Mac OS X machines can be found on the
developer.apple.com site: PHP on Mac OS X

Installing Drupal on Mac OS X 10.4 Tiger


Mac OS X 10.4 Tiger comes with PHP (though it’s disabled by default) and without MySQL.
Here’s how to get Drupal up and running from a stock Tiger installation.

Installing and Configuring MySQL

Downloaded the latest MySQL installer from dev.mysql.com. I chose the Mac OS X Installer
Package for 10.3.

I double-clicked the file that I downloaded


(mysql-standard-4.1.11-apple-darwin7.8.0-powerpc.dmg), then double-clicked the
mysql-standard-4.1.11-apple-darwin7.8.0-powerpc.pkg icon to run the installer and install
MySQL.

Next, I installed the MySQLStartupItem.pkg because I want MySQL to start up when I start my
Mac.

Then, I copied the MySQL.prefPane into the PreferencePanes folder in my Library folder at the
root level of my hard drive. Tiger asked me to authenticate when I did this. Upon opening my
System Preferences, I can indeed see a pretty MySQL icon.

I wanted to test to see if MySQL would really start up, so I restarted. Sure enough, MySQL was
running.

Next, it was time to set initial passwords for MySQL. To do that, I opened the Terminal (in the
Utilities folder). Then I typed in the following:

export PATH="$PATH:/usr/local/mysql/bin"

This tells your computer that when it interprets commands, it should also look in the freshly
created MySQL installation for MySQL commands. If you want it added permanently instead of
just for this terminal session, you could edit the third line of /etc/profile to read

PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/mysql/bin"

30
3 Aug 2007 Drupal Handbook

and then start a new Terminal window.

Next, we want to make MySQL secure by setting a MySQL root password. Fortunately a handy
utility is provided to make that easy. I typed in:

mysql_secure_installation

Interacting with the script looked like this (note that at the first prompt I just pressed enter since
no root password has been set yet:

Enter current password for root (enter for none):


OK, successfully used password, moving on...
Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.
Set root password? [Y/n] Y
New password: zoinks
Re-enter new password: zoinks
Password updated successfully!
Reloading privilege tables..
... Success!
By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.
Remove anonymous users? [Y/n] Y
... Success!
Normally, root should only be allowed to connect from ’localhost’.
This
ensures that someone cannot guess at the root password from the
network.
Disallow root login remotely? [Y/n] Y
... Success!
By default, MySQL comes with a database named ’test’ that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
Remove test database and access to it? [Y/n] Y
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
Reload privilege tables now? [Y/n] Y
... Success!
Cleaning up...
All done! If you’ve completed all of the above steps, your MySQL

31
Drupal Handbook 3 Aug 2007

installation should now be secure.


Thanks for using MySQL!

I verified that MySQL was running:

$ mysqladmin -u root -p status


Enter password: zoinks
Uptime: 938 Threads: 1 Questions: 16 Slow queries: 0 Opens: 21
Flush tables: 1 Open tables: 0 Queries per second avg: 0.017

It was running fine. Now on to the task of setting up MySQL for Drupal.

Sending mail

Current versions of OS X use Postfix as the mail server but you have to enable it.

For a detailed how-to, see:


http://www.stepwise.com/Articles/Workbench/eart.index.html

Or save yourself lots of frustration and time and spend $10 for Postfix Enabler and get running
in a couple of minutes.
http://cutedgesystems.com/software/PostfixEnabler/

Creating the Drupal Database and Database User

Now that MySQL is installed and we have a root password established for it, it’s time to create
the database that Drupal will use:

$ mysqladmin -u root -p create drupal


Enter password: zoinks

The database was created. Time to create the user. The user in this example will be called
drupaldbuser and the password for that user will be fuffy.

$ mysql -u root -p
Enter password: zoinks
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 15 to server version: 4.1.11-standard
Type ’help;’ or ’\h’ for help. Type ’\c’ to clear the buffer.
mysql> GRANT ALL PRIVILEGES ON drupal.* TO drupaldbuser@localhost
IDENTIFIED BY ’fuffy’;
Query OK, 0 rows affected (0.04 sec)

If you are using MySQL 4.1 or later, the following command is necessary because Tiger comes
with PHP 4, and the MySQL libraries for PHP 4 use a different authentication protocol.

mysql> SET PASSWORD FOR ’drupaldbuser’@’localhost’ =


OLD_PASSWORD(’fuffy’);
Query OK, 0 rows affected (0.00 sec)

32
3 Aug 2007 Drupal Handbook

Now we apply the new settings:

mysql> flush privileges;


Query OK, 0 rows affected (0.19 sec)
mysql> \q
Bye

Now I paused to rejoice. MySQL was installed and ready for Drupal. Now it was time to install
Drupal itself.

Installing using CVS repository

Development of the Drupal codebase is fairly quick, with a new release every six months or so.
So I decided to use the CVS repository to download Drupal. That way I can use the "cvs update"
command to keep my Drupal installation current with bug fixes and improvements.

I have the cvs option available to me because I installed the developer tools that were included
on the OS 10.4 DVD. If you don’t have them installed, or don’t want to install them, you could
always download Drupal directly and place the resulting directory inside

/Library/WebServer/Documents

First, I navigated to where I want my Drupal installation. Just to be consistent with Mac OS 10.4,
I used /Library/WebServer/Documents:

cd /Library/WebServer/Documents

And now I pulled down the latest version of the Drupal 4.6 release:

cvs -z9 -d:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal


checkout -r DRUPAL-4-6 drupal

This created a directory called drupal that contains the latest code for version 4.6. If, next week, I
hear that a bugfix has been issued for 4.6, all I have to do is

cd /Library/WebServer/Documents
cvs update

By default, Apache on the Mac runs as user ’www’ with group ’www’, so you probably need to
do the following in order to allow drupal to create directories and files:

chown -R www drupal


chgrp -R www drupal

Now it was time to create all the database tables that Drupal needs:

$ mysql -u drupaldbuser -p drupal <


/Library/WebServer/Documents/drupal/database/database.mysql
Enter password: fuffy

33
Drupal Handbook 3 Aug 2007

Now I had MySQL running, and had a Drupal database populated by Drupal’s fields. It was
time to tell Drupal how to find that database.

In the Finder, I went to /Library/WebServer/Documents/Drupal/sites and duplicated the


folder called default, and renamed it localhost. Then inside the new localhost directory I edited
the settings.php file, changing line 81 to read:

$db_url = ’mysql://drupaldbuser:fuffy@localhost/drupal’;

and changing line 90 to read:

$base_url = ’http://localhost/drupal’;

The reason I duplicated the "default" settings folder was to avoid conflicts when I update CVS in
the future, since CVS would have seen the changed settings.php file and tried to merge it with
the original one. By keeping my settings file separate, I avoid this. As long as I access my Drupal
installation through the URL http://localhost/drupal it will use the settings in the localhost
folder.

PHP is not enabled by default on OS 10.4. So I enabled it by editing Apache’s configuration file. I
used BBEdit, but you can use any text editor you want. For example, you could choose Go To
Folder from the Finder’s Go menu and type in /etc/httpd, then double-click on httpd.conf and
OS 10.4 will prompt you for an application to edit the file with. Here’s me opening the file for
editing in BBEdit:

sudo bbedit /etc/httpd/httpd.conf

Then I removed the # from in front of line 240:

#LoadModule php4_module libexec/httpd/libphp4.so

and line 284:

#AddModule mod_php4.c

and line 406:

AllowOverride All

After changing the configuration file, I stopped, then started the Personal Web Sharing service in
the Sharing pane of System Preferences. This forces Apache to reread the configuration file and
apply the changes. So now PHP was enabled.

Now, with my hands shaking from excitement, I entered http://localhost/drupal into my web
browser. I was greeted with Drupal’s welcome page:

34
3 Aug 2007 Drupal Handbook

I clicked on the link entitled "create the first account", and saw:

Since this was the first account I created on Drupal, I knew it would have special privileges, so I
named it admin and typed in my e-mail address. (Warning: naming your administrative account
"admin" is bad security! Don’t do this!) Then I clicked on the "Create new account" button.
Drupal responded with a randomly generated password and an opportunity to log in
immediately:

35
Drupal Handbook 3 Aug 2007

I took the opportunity to log in immediately by clicking the "Log in" button. On the resulting
screen I changed my password to something I could remember and clicked Submit.

Now I’ve got Drupal running on Mac OS 10.4. Time to celebrate with a swig of flavinoid-laden
grape juice.

Prefixed database.mysql for search and replace


Use a texteditor with search & replace functionality to replace ’prefix’ with your own eg. site1,
site2.
This is database.mysql from 4.6.5. Contributed by Shane Birley.

-- MySQL dump 8.22


--
-- Host: localhost Database: drupal_devel
-- Server version 3.23.52-nt
--
-- Table structure for table ’access’
--
CREATE TABLE prefix_access (
aid tinyint(10) NOT NULL auto_increment,
mask varchar(255) NOT NULL default ’’,
type varchar(255) NOT NULL default ’’,
status tinyint(2) NOT NULL default ’0’,
PRIMARY KEY (aid)
) TYPE=MyISAM;
--
-- Table structure for table ’accesslog’
--
CREATE TABLE prefix_accesslog (
aid int(10) NOT NULL auto_increment,
title varchar(255) default NULL,
path varchar(255) default NULL,
url varchar(255) default NULL,

36
3 Aug 2007 Drupal Handbook

hostname varchar(128) default NULL,


uid int(10) unsigned default ’0’,
timestamp int(11) unsigned NOT NULL default ’0’,
KEY accesslog_timestamp (timestamp),
PRIMARY KEY (aid)
) TYPE=MyISAM;
--
-- Table structure for table ’aggregator_category’
--
CREATE TABLE prefix_aggregator_category (
cid int(10) NOT NULL auto_increment,
title varchar(255) NOT NULL default ’’,
description longtext NOT NULL,
block tinyint(2) NOT NULL default ’0’,
PRIMARY KEY (cid),
UNIQUE KEY title (title)
) TYPE=MyISAM;
--
-- Table structure for table ’aggregator_category_feed’
--
CREATE TABLE prefix_aggregator_category_feed (
fid int(10) NOT NULL default ’0’,
cid int(10) NOT NULL default ’0’,
PRIMARY KEY (fid,cid)
) TYPE=MyISAM;
--
-- Table structure for table ’aggregator_category_item’
--
CREATE TABLE prefix_aggregator_category_item (
iid int(10) NOT NULL default ’0’,
cid int(10) NOT NULL default ’0’,
PRIMARY KEY (iid,cid)
) TYPE=MyISAM;
--
-- Table structure for table ’aggregator_feed’
--
CREATE TABLE prefix_aggregator_feed (
fid int(10) NOT NULL auto_increment,
title varchar(255) NOT NULL default ’’,
url varchar(255) NOT NULL default ’’,
refresh int(10) NOT NULL default ’0’,
checked int(10) NOT NULL default ’0’,
link varchar(255) NOT NULL default ’’,
description longtext NOT NULL,
image longtext NOT NULL,
etag varchar(255) NOT NULL default ’’,
modified int(10) NOT NULL default ’0’,

37
Drupal Handbook 3 Aug 2007

block tinyint(2) NOT NULL default ’0’,


PRIMARY KEY (fid),
UNIQUE KEY link (url),
UNIQUE KEY title (title)
) TYPE=MyISAM;
--
-- Table structure for table ’aggregator_item’
--
CREATE TABLE prefix_aggregator_item (
iid int(10) NOT NULL auto_increment,
fid int(10) NOT NULL default ’0’,
title varchar(255) NOT NULL default ’’,
link varchar(255) NOT NULL default ’’,
author varchar(255) NOT NULL default ’’,
description longtext NOT NULL,
timestamp int(11) default NULL,
PRIMARY KEY (iid)
) TYPE=MyISAM;
--
-- Table structure for table ’authmap’
--
CREATE TABLE prefix_authmap (
aid int(10) unsigned NOT NULL auto_increment,
uid int(10) NOT NULL default ’0’,
authname varchar(128) NOT NULL default ’’,
module varchar(128) NOT NULL default ’’,
PRIMARY KEY (aid),
UNIQUE KEY authname (authname)
) TYPE=MyISAM;
--
-- Table structure for table ’blocks’
--
CREATE TABLE prefix_blocks (
module varchar(64) DEFAULT ’’ NOT NULL,
delta varchar(32) NOT NULL default ’0’,
status tinyint(2) DEFAULT ’0’ NOT NULL,
weight tinyint(1) DEFAULT ’0’ NOT NULL,
region tinyint(1) DEFAULT ’0’ NOT NULL,
custom tinyint(2) DEFAULT ’0’ NOT NULL,
throttle tinyint(1) DEFAULT ’0’ NOT NULL,
visibility tinyint(1) DEFAULT ’0’ NOT NULL,
pages text NOT NULL,
types text NOT NULL
) TYPE=MyISAM;
--
-- Table structure for table ’book’
--

38
3 Aug 2007 Drupal Handbook

CREATE TABLE prefix_book (


nid int(10) unsigned NOT NULL default ’0’,
parent int(10) NOT NULL default ’0’,
weight tinyint(3) NOT NULL default ’0’,
log longtext,
PRIMARY KEY (nid),
KEY parent (parent)
) TYPE=MyISAM;
--
-- Table structure for table ’boxes’
--
CREATE TABLE prefix_boxes (
bid tinyint(4) NOT NULL auto_increment,
title varchar(64) NOT NULL default ’’,
body longtext,
info varchar(128) NOT NULL default ’’,
format int(4) NOT NULL default ’0’,
PRIMARY KEY (bid),
UNIQUE KEY title (title),
UNIQUE KEY info (info)
) TYPE=MyISAM;
--
-- Table structure for table ’cache’
--
CREATE TABLE prefix_cache (
cid varchar(255) NOT NULL default ’’,
data longtext,
expire int(11) NOT NULL default ’0’,
created int(11) NOT NULL default ’0’,
headers text,
PRIMARY KEY (cid),
INDEX expire (expire)
) TYPE=MyISAM;
--
-- Table structure for table ’comments’
--
CREATE TABLE prefix_comments (
cid int(10) NOT NULL auto_increment,
pid int(10) NOT NULL default ’0’,
nid int(10) NOT NULL default ’0’,
uid int(10) NOT NULL default ’0’,
subject varchar(64) NOT NULL default ’’,
comment longtext NOT NULL,
hostname varchar(128) NOT NULL default ’’,
timestamp int(11) NOT NULL default ’0’,
score mediumint(9) NOT NULL default ’0’,
status tinyint(3) unsigned NOT NULL default ’0’,

39
Drupal Handbook 3 Aug 2007

format int(4) NOT NULL default ’0’,


thread varchar(255) NOT NULL,
users longtext,
name varchar(60) default NULL,
mail varchar(64) default NULL,
homepage varchar(255) default NULL,
PRIMARY KEY (cid),
KEY lid (nid)
) TYPE=MyISAM;
--
-- Table structre for table ’node_last_comment’
--
CREATE TABLE prefix_node_comment_statistics (
nid int(10) unsigned NOT NULL auto_increment,
last_comment_timestamp int(11) NOT NULL default ’0’,
last_comment_name varchar(60) default NULL,
last_comment_uid int(10) NOT NULL default ’0’,
comment_count int(10) unsigned NOT NULL default ’0’,
PRIMARY KEY (nid),
KEY node_comment_timestamp (last_comment_timestamp)
) TYPE=MyISAM;
--
-- Table structure for table ’directory’
--
CREATE TABLE prefix_directory (
link varchar(255) NOT NULL default ’’,
name varchar(128) NOT NULL default ’’,
mail varchar(128) NOT NULL default ’’,
slogan longtext NOT NULL,
mission longtext NOT NULL,
timestamp int(11) NOT NULL default ’0’,
PRIMARY KEY (link)
) TYPE=MyISAM;
--
-- Table structure for table ’files’
--
CREATE TABLE prefix_files (
fid int(10) unsigned NOT NULL default ’0’,
nid int(10) unsigned NOT NULL default ’0’,
filename varchar(255) NOT NULL default ’’,
filepath varchar(255) NOT NULL default ’’,
filemime varchar(255) NOT NULL default ’’,
filesize int(10) unsigned NOT NULL default ’0’,
list tinyint(1) unsigned NOT NULL default ’0’,
PRIMARY KEY (fid)
) TYPE=MyISAM;
--

40
3 Aug 2007 Drupal Handbook

-- Table structure for table ’filter_formats’


--
CREATE TABLE prefix_filter_formats (
format int(4) NOT NULL auto_increment,
name varchar(255) NOT NULL default ’’,
roles varchar(255) NOT NULL default ’’,
cache tinyint(2) NOT NULL default ’0’,
PRIMARY KEY (format)
) TYPE=MyISAM;
--
-- Table structure for table ’filters’
--
CREATE TABLE prefix_filters (
format int(4) NOT NULL default ’0’,
module varchar(64) NOT NULL default ’’,
delta tinyint(2) DEFAULT ’0’ NOT NULL,
weight tinyint(2) DEFAULT ’0’ NOT NULL,
INDEX (weight)
) TYPE=MyISAM;
--
-- Table structure for table ’flood’
--
CREATE TABLE prefix_flood (
event varchar(64) NOT NULL default ’’,
hostname varchar(128) NOT NULL default ’’,
timestamp int(11) NOT NULL default ’0’
) TYPE=MyISAM;
--
-- Table structure for table ’forum’
--
CREATE TABLE prefix_forum (
nid int(10) unsigned NOT NULL default ’0’,
tid int(10) unsigned NOT NULL default ’0’,
PRIMARY KEY (nid),
KEY tid (tid)
) TYPE=MyISAM;
--
-- Table structure for table ’history’
--
CREATE TABLE prefix_history (
uid int(10) NOT NULL default ’0’,
nid int(10) NOT NULL default ’0’,
timestamp int(11) NOT NULL default ’0’,
PRIMARY KEY (uid,nid)
) TYPE=MyISAM;
--
-- Table structure for table ’locales_meta’

41
Drupal Handbook 3 Aug 2007

--
CREATE TABLE prefix_locales_meta (
locale varchar(12) NOT NULL default ’’,
name varchar(64) NOT NULL default ’’,
enabled int(2) NOT NULL default ’0’,
isdefault int(2) NOT NULL default ’0’,
plurals int(1) NOT NULL default ’0’,
formula varchar(128) NOT NULL default ’’,
PRIMARY KEY (locale)
) TYPE=MyISAM;
--
-- Table structure for table ’locales_source’
--
CREATE TABLE prefix_locales_source (
lid int(11) NOT NULL auto_increment,
location varchar(255) NOT NULL default ’’,
source blob NOT NULL,
PRIMARY KEY (lid)
) TYPE=MyISAM;
--
-- Table structure for table ’locales_target’
--
CREATE TABLE prefix_locales_target (
lid int(11) NOT NULL default ’0’,
translation blob NOT NULL,
locale varchar(12) NOT NULL default ’’,
plid int(11) NOT NULL default ’0’,
plural int(1) NOT NULL default ’0’,
KEY lid (lid),
KEY lang (locale),
KEY plid (plid),
KEY plural (plural)
) TYPE=MyISAM;
--
-- Table structure for table ’menu’
--
CREATE TABLE prefix_menu (
mid int(10) unsigned NOT NULL default ’0’,
pid int(10) unsigned NOT NULL default ’0’,
path varchar(255) NOT NULL default ’’,
title varchar(255) NOT NULL default ’’,
description varchar(255) NOT NULL default ’’,
weight tinyint(4) NOT NULL default ’0’,
type int(2) unsigned NOT NULL default ’0’,
PRIMARY KEY (mid)
) TYPE=MyISAM;
--

42
3 Aug 2007 Drupal Handbook

-- Table structure for table ’moderation_filters’


--
CREATE TABLE prefix_moderation_filters (
fid int(10) unsigned NOT NULL auto_increment,
filter varchar(255) NOT NULL default ’’,
minimum smallint(6) NOT NULL default ’0’,
PRIMARY KEY (fid)
) TYPE=MyISAM;
--
-- Table structure for table ’moderation_roles’
--
CREATE TABLE prefix_moderation_roles (
rid int(10) unsigned NOT NULL default ’0’,
mid int(10) unsigned NOT NULL default ’0’,
value tinyint(4) NOT NULL default ’0’,
KEY idx_rid (rid),
KEY idx_mid (mid)
) TYPE=MyISAM;
--
-- Table structure for table ’moderation_votes’
--
CREATE TABLE prefix_moderation_votes (
mid int(10) unsigned NOT NULL auto_increment,
vote varchar(255) default NULL,
weight tinyint(4) NOT NULL default ’0’,
PRIMARY KEY (mid)
) TYPE=MyISAM;
--
-- Table structure for table ’node’
--
CREATE TABLE prefix_node (
nid int(10) unsigned NOT NULL auto_increment,
type varchar(16) NOT NULL default ’’,
title varchar(128) NOT NULL default ’’,
uid int(10) NOT NULL default ’0’,
status int(4) NOT NULL default ’1’,
created int(11) NOT NULL default ’0’,
changed int(11) NOT NULL default ’0’,
comment int(2) NOT NULL default ’0’,
promote int(2) NOT NULL default ’0’,
moderate int(2) NOT NULL default ’0’,
teaser longtext NOT NULL,
body longtext NOT NULL,
revisions longtext NOT NULL,
sticky int(2) NOT NULL default ’0’,
format int(4) NOT NULL default ’0’,
PRIMARY KEY (nid),

43
Drupal Handbook 3 Aug 2007

KEY node_type (type(4)),


KEY node_title_type (title,type(4)),
KEY status (status),
KEY uid (uid),
KEY node_moderate (moderate),
KEY node_promote_status (promote, status),
KEY node_created (created),
KEY node_changed (changed),
KEY node_status_type (status, type, nid)
) TYPE=MyISAM;
--
-- Table structure for table ‘node_access‘
--
CREATE TABLE prefix_node_access (
nid int(10) unsigned NOT NULL default ’0’,
gid int(10) unsigned NOT NULL default ’0’,
realm varchar(255) NOT NULL default ’’,
grant_view tinyint(1) unsigned NOT NULL default ’0’,
grant_update tinyint(1) unsigned NOT NULL default ’0’,
grant_delete tinyint(1) unsigned NOT NULL default ’0’,
PRIMARY KEY (nid,gid,realm)
) TYPE=MyISAM;
--
-- Table structure for table ’profile_fields’
--
CREATE TABLE prefix_profile_fields (
fid int(10) NOT NULL auto_increment,
title varchar(255) default NULL,
name varchar(128) default NULL,
explanation TEXT default NULL,
category varchar(255) default NULL,
page varchar(255) default NULL,
type varchar(128) default NULL,
weight tinyint(1) DEFAULT ’0’ NOT NULL,
required tinyint(1) DEFAULT ’0’ NOT NULL,
register tinyint(1) DEFAULT ’0’ NOT NULL,
visibility tinyint(1) DEFAULT ’0’ NOT NULL,
options text,
KEY category (category),
UNIQUE KEY name (name),
PRIMARY KEY (fid)
);
--
-- Table structure for table ’profile_values’
--
CREATE TABLE prefix_profile_values (
fid int(10) unsigned default ’0’,

44
3 Aug 2007 Drupal Handbook

uid int(10) unsigned default ’0’,


value text,
KEY uid (uid),
KEY fid (fid)
);
--
-- Table structure for table ’url_alias’
--
CREATE TABLE prefix_url_alias (
pid int(10) unsigned NOT NULL auto_increment,
src varchar(128) NOT NULL default ’’,
dst varchar(128) NOT NULL default ’’,
PRIMARY KEY (pid),
UNIQUE KEY dst (dst)
) TYPE=MyISAM;
--
-- Table structure for table ’permission’
--
CREATE TABLE prefix_permission (
rid int(10) unsigned NOT NULL default ’0’,
perm longtext,
tid int(10) unsigned NOT NULL default ’0’,
KEY rid (rid)
) TYPE=MyISAM;
--
-- Table structure for table ’poll’
--
CREATE TABLE prefix_poll (
nid int(10) unsigned NOT NULL default ’0’,
runtime int(10) NOT NULL default ’0’,
polled longtext NOT NULL,
active int(2) unsigned NOT NULL default ’0’,
PRIMARY KEY (nid)
) TYPE=MyISAM;
--
-- Table structure for table ’poll_choices’
--
CREATE TABLE prefix_poll_choices (
chid int(10) unsigned NOT NULL auto_increment,
nid int(10) unsigned NOT NULL default ’0’,
chtext varchar(128) NOT NULL default ’’,
chvotes int(6) NOT NULL default ’0’,
chorder int(2) NOT NULL default ’0’,
PRIMARY KEY (chid),
KEY nid (nid)
) TYPE=MyISAM;
--

45
Drupal Handbook 3 Aug 2007

-- Table structure for table ’queue’


--
CREATE TABLE prefix_queue (
nid int(10) unsigned NOT NULL,
uid int(10) unsigned NOT NULL,
vote int(3) NOT NULL default ’0’,
PRIMARY KEY (nid, uid)
) TYPE=MyISAM;
--
-- Table structure for table ’role’
--
CREATE TABLE prefix_role (
rid int(10) unsigned NOT NULL auto_increment,
name varchar(32) NOT NULL default ’’,
PRIMARY KEY (rid),
UNIQUE KEY name (name)
) TYPE=MyISAM;
--
-- Table structure for table ’search_index’
--
CREATE TABLE prefix_search_index (
word varchar(50) NOT NULL default ’’,
sid int(10) unsigned NOT NULL default ’0’,
type varchar(16) default NULL,
fromsid int(10) unsigned NOT NULL default ’0’,
fromtype varchar(16) default NULL,
score int(10) unsigned default NULL,
KEY sid (sid),
KEY fromsid (fromsid),
KEY word (word)
) TYPE=MyISAM;
--
-- Table structure for table ’search_total’
--
CREATE TABLE prefix_search_total (
word varchar(50) NOT NULL default ’’,
count int(10) unsigned default NULL,
PRIMARY KEY word (word)
) TYPE=MyISAM;
--
-- Table structure for table ’sessions’
--
CREATE TABLE prefix_sessions (
uid int(10) unsigned NOT NULL,
sid varchar(32) NOT NULL default ’’,
hostname varchar(128) NOT NULL default ’’,
timestamp int(11) NOT NULL default ’0’,

46
3 Aug 2007 Drupal Handbook

session longtext,
KEY uid (uid),
PRIMARY KEY (sid),
KEY timestamp (timestamp)
) TYPE=MyISAM;
--
-- Table structure for table ’sequences’
--
CREATE TABLE prefix_sequences (
name varchar(255) NOT NULL default ’’,
id int(10) unsigned NOT NULL default ’0’,
PRIMARY KEY (name)
) TYPE=MyISAM;
--
-- Table structure for table ’node_counter’
--
CREATE TABLE prefix_node_counter (
nid int(11) NOT NULL default ’0’,
totalcount bigint(20) unsigned NOT NULL default ’0’,
daycount mediumint(8) unsigned NOT NULL default ’0’,
timestamp int(11) unsigned NOT NULL default ’0’,
PRIMARY KEY (nid),
KEY totalcount (totalcount),
KEY daycount (daycount),
KEY timestamp (timestamp)
) TYPE=MyISAM;
--
-- Table structure for table ’system’
--
CREATE TABLE prefix_system (
filename varchar(255) NOT NULL default ’’,
name varchar(255) NOT NULL default ’’,
type varchar(255) NOT NULL default ’’,
description varchar(255) NOT NULL default ’’,
status int(2) NOT NULL default ’0’,
throttle tinyint(1) DEFAULT ’0’ NOT NULL,
bootstrap int(2) NOT NULL default ’0’,
PRIMARY KEY (filename)
) TYPE=MyISAM;
--
-- Table structure for table ’term_data’
--
CREATE TABLE prefix_term_data (
tid int(10) unsigned NOT NULL auto_increment,
vid int(10) unsigned NOT NULL default ’0’,
name varchar(255) NOT NULL default ’’,
description longtext,

47
Drupal Handbook 3 Aug 2007

weight tinyint(4) NOT NULL default ’0’,


PRIMARY KEY (tid),
KEY vid (vid)
) TYPE=MyISAM;
--
-- Table structure for table ’term_hierarchy’
--
CREATE TABLE prefix_term_hierarchy (
tid int(10) unsigned NOT NULL default ’0’,
parent int(10) unsigned NOT NULL default ’0’,
KEY tid (tid),
KEY parent (parent)
) TYPE=MyISAM;
--
-- Table structure for table ’term_node’
--
CREATE TABLE prefix_term_node (
nid int(10) unsigned NOT NULL default ’0’,
tid int(10) unsigned NOT NULL default ’0’,
KEY nid (nid),
KEY tid (tid),
PRIMARY KEY (tid,nid)
) TYPE=MyISAM;
--
-- Table structure for table ’term_relation’
--
CREATE TABLE prefix_term_relation (
tid1 int(10) unsigned NOT NULL default ’0’,
tid2 int(10) unsigned NOT NULL default ’0’,
KEY tid1 (tid1),
KEY tid2 (tid2)
) TYPE=MyISAM;
--
-- Table structure for table ’term_synonym’
--
CREATE TABLE prefix_term_synonym (
tid int(10) unsigned NOT NULL default ’0’,
name varchar(255) NOT NULL default ’’,
KEY tid (tid),
KEY name (name(3))
) TYPE=MyISAM;
--
-- Table structure for table ’users’
--
CREATE TABLE prefix_users (
uid int(10) unsigned NOT NULL default ’0’,
name varchar(60) NOT NULL default ’’,

48
3 Aug 2007 Drupal Handbook

pass varchar(32) NOT NULL default ’’,


mail varchar(64) default ’’,
mode tinyint(1) NOT NULL default ’0’,
sort tinyint(1) default ’0’,
threshold tinyint(1) default ’0’,
theme varchar(255) NOT NULL default ’’,
signature varchar(255) NOT NULL default ’’,
created int(11) NOT NULL default ’0’,
changed int(11) NOT NULL default ’0’,
status tinyint(4) NOT NULL default ’0’,
timezone varchar(8) default NULL,
language varchar(12) NOT NULL default ’’,
picture varchar(255) NOT NULL DEFAULT ’’,
init varchar(64) default ’’,
data longtext,
PRIMARY KEY (uid),
UNIQUE KEY name (name),
KEY changed (changed)
) TYPE=MyISAM;
--
-- Table structure for table ’users_roles’
--
CREATE TABLE prefix_users_roles (
uid int(10) unsigned NOT NULL default ’0’,
rid int(10) unsigned NOT NULL default ’0’,
PRIMARY KEY (uid, rid)
) TYPE=MyISAM;
--
-- Table structure for table ’variable’
--
CREATE TABLE prefix_variable (
name varchar(48) NOT NULL default ’’,
value longtext NOT NULL,
PRIMARY KEY (name)
) TYPE=MyISAM;
--
-- Table structure for table ’vocabulary’
--
CREATE TABLE prefix_vocabulary (
vid int(10) unsigned NOT NULL auto_increment,
name varchar(255) NOT NULL default ’’,
description longtext,
help varchar(255) NOT NULL default ’’,
relations tinyint(3) unsigned NOT NULL default ’0’,
hierarchy tinyint(3) unsigned NOT NULL default ’0’,
multiple tinyint(3) unsigned NOT NULL default ’0’,
required tinyint(3) unsigned NOT NULL default ’0’,

49
Drupal Handbook 3 Aug 2007

module varchar(255) NOT NULL default ’’,


weight tinyint(4) NOT NULL default ’0’,
PRIMARY KEY (vid)
) TYPE=MyISAM;
--
-- Table structure for table ’vocabulary_node_types’
--
CREATE TABLE prefix_vocabulary_node_types (
vid int(10) unsigned NOT NULL DEFAULT ’0’,
type varchar(16) NOT NULL DEFAULT ’’,
PRIMARY KEY (vid, type)
) TYPE=MyISAM;
--
-- Table structure for table ’watchdog’
--
CREATE TABLE prefix_watchdog (
wid int(5) NOT NULL auto_increment,
uid int(10) NOT NULL default ’0’,
type varchar(16) NOT NULL default ’’,
message longtext NOT NULL,
severity tinyint(3) unsigned NOT NULL default ’0’,
link varchar(255) NOT NULL default ’’,
location varchar(128) NOT NULL default ’’,
hostname varchar(128) NOT NULL default ’’,
timestamp int(11) NOT NULL default ’0’,
PRIMARY KEY (wid)
) TYPE=MyISAM;
--
-- Insert some default values
--
INSERT INTO prefix_system VALUES
(’modules/block.module’,’block’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/comment.module’,’comment’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/filter.module’,’filter’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/help.module’,’help’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/node.module’,’node’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/page.module’,’page’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/story.module’,’story’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/system.module’,’system’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES

50
3 Aug 2007 Drupal Handbook

(’modules/taxonomy.module’,’taxonomy’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/user.module’,’user’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’modules/watchdog.module’,’watchdog’,’module’,’’,1,0,0);
INSERT INTO prefix_system VALUES
(’themes/bluemarine/xtemplate.xtmpl’,’bluemarine’,’theme’,’themes/engines/xtemplate/xtemplate.engine’,1,0,0);
INSERT INTO prefix_system VALUES
(’themes/engines/xtemplate/xtemplate.engine’,’xtemplate’,’theme_engine’,’’,1,0,0);
INSERT INTO prefix_users (uid, name, mail) VALUES (’0’, ’’, ’’);
INSERT INTO prefix_users_roles (uid, rid) VALUES (0, 1);
INSERT INTO prefix_role (rid, name) VALUES (1, ’anonymous user’);
INSERT INTO prefix_permission VALUES (1,’access content’,0);
INSERT INTO prefix_role (rid, name) VALUES (2, ’authenticated user’);
INSERT INTO prefix_permission VALUES (2,’access comments, access
content, post comments, post comments without approval’,0);
REPLACE prefix_variable SET name=’update_start’,
value=’s:10:"2005-03-21";’;
REPLACE prefix_variable SET name=’theme_default’,
value=’s:10:"bluemarine";’;
REPLACE prefix_blocks SET module = ’user’, delta = ’0’, status = ’1’;
REPLACE prefix_blocks SET module = ’user’, delta = ’1’, status = ’1’;
INSERT INTO prefix_sequences (name, id) VALUES (’menu_mid’, 1);
INSERT INTO prefix_node_access VALUES (0, 0, ’all’, 1, 0, 0);
INSERT INTO prefix_filter_formats VALUES (1,’Filtered HTML’,’,1,2,’,1);
INSERT INTO prefix_filter_formats VALUES (2,’PHP code’,’’,0);
INSERT INTO prefix_filter_formats VALUES (3,’Full HTML’,’’,1);
INSERT INTO prefix_filters VALUES (1,’filter’,0,0);
INSERT INTO prefix_filters VALUES (1,’filter’,2,1);
INSERT INTO prefix_filters VALUES (2,’filter’,1,0);
INSERT INTO prefix_filters VALUES (3,’filter’,2,0);
INSERT INTO prefix_variable (name,value) VALUES
(’filter_html_1’,’i:1;’);
INSERT INTO prefix_locales_meta (locale, name, enabled, isdefault)
VALUES (’en’, ’English’, ’1’, ’1’);

Setup Drupal on Windows XP Pro using IIS


While trying to install Drupal on stand alone machine with Windows XP Pro & IIS I was unable
to find all the installation information at one place therefore I am sharing my experiences and
solutions to the problems. I think it will be useful for people who are new to Drupal because
Drupal on stand alone machine reduces the learning curve.

Setup Drupal on Windows XP Pro using IIS:


1. Download Mysql server and install. (I have used ver. 5.0)
2. Download PHP and install. (I have used ver. 4)
3. Download Drupal (I have used ver. 4.7.3).

51
Drupal Handbook 3 Aug 2007

4. Create a folder with any name for example Drupal in Inetpub folder in C: drive.
5. Open IIS and create virtual folder giving alias and path of the Drupal folder which you have
just created in Inetpub.
6. Untar (you can use Winrar for this) the downloaded drupal file contents in Drupal folder.
7. Create a schema/database with any name example drupaldata and create a user.
8. Now grant privileges to this user.
Grant ALL ON databasename.*
TO ’username’@’localhost’ IDENTIFIED BY ’password’;
Flush privileges;

9. Modify the file C:\Inetpub\wwwroot\[YOURDIRNAME]\sites\default\settings.php by


giving user name, password and database name.

10. Now browse this virtual folder with its alias name in IE example
http://localhost/"aliasname"

11. If following error is displayed;


Client does not support authentication protocol requested by server; consider upgrading
MySQL client

Then use these commands;


SET PASSWORD FOR ’some_user’@’some_host’ = OLD_PASSWORD(’newpwd’);
Flush privileges;

12. Repeat step 10, I hope its working â¦.

Have a look at one of the pretty clean theme implementation in drupal - ENJOY . . .

Basic /sites directory setup


Version 5.x supports a new /sites/all directory. Best practice for basic initial setup is the
following placements in the /sites directory:

Directory Contents
/modules
/drupal/sites/all
/themes
/drupal/sites/default settings.php
/tmp
/drupal/sites/example.com /files
(but see below)

Understand the different common locations. The /sites/all and the /sites/default directories are
exclusive, and are intended for the above items. The critical principle is to keep all your site
customizations within the /sites directory so that it is easy to upgrade when a new minor
version of the Drupal core code is released (e.g. to update from 5.1 to 5.2).

52
3 Aug 2007 Drupal Handbook

Contributed and custom modules should be placed in /drupal/sites/all/modules. Additional


and custom themes should be placed in /drupal/sites/all/themes.

The /files directory is usually best placed in the /sites/example.com directory, which you will
have to create. Then set the ’File system path’ at administer > site configuration > file system. This is
ideal if a second site will likely need a separate /files directory; just create a second site-specific
/files directory at /sites/example2.com/files. The same applies for the /tmp directory.

Upon initial installation the /files directory is set to /sites/default/files (you will need to create
the actual directory). It can be fine to leave it there (or even to use /sites/files) if you are 100%
you will never want to use multi-site features. However, this location shares the /files directory
in a multi-site setup , which may or may not be desired. See "Setup of /sites directory for
multi-site."

Backup is simplified by use of the /sites directory for all customizations. You can then easily
backup all non-core material by backing up the /sites directory and the database.

For multi-site setup, see Multi-site installation and set-up, the sub-topic Setup of /sites directory
for multi-site, and the installation instructions (INSTALL.txt). As stated above, there are two
common locations in Drupal 5.x and above: /sites/default (for settings.php) and/sites/all (for
common /modules and /themes). This allows a new site to be set up using the multi-site
features by simply copying the /sites/default directory to /sites/example2.com

Version 4.6 and 4.7: To simplify backups and updates, the best practice (for a single-site install)
is to place contributed modules in /sites/default/modules/, contributed or custom themes in
/sites/default/themes/, and files in /sites/default/files (or even /sites/files). The /sites/all/
feature was added in Drupal 5.x. It will also work, but be more difficult to update your site, if
contributed modules are placed in /drupal/modules, additional themes were placed in
/drupal/themes, and files are stored in /drupal/files. If you expect to use multi-sites, then you
should make use of /sites/example.com as explained in the "Setup of /sites directory for
multi-site." Using /drupal/modules and /drupal/themes will also still work in 5.x, but the best
practice above allows easier backup and expansion to multi-site.

Special cases
Various special situations (e.g., installing Drupal behind a firewall, installing Drupal in a
subdirectory of the webserver’s document root) are discussed in this section. Information
specific to particular operating systems or database platforms may be found elsewhere.

Compilation failed: this version of PCRE is not compiled with


PCRE_UTF8 support
This error occurrs on release 4.6.1 onwards.

Note: This issue is fixed by default on all VPS3 and new VPS2 servers, resolve-able on VPS1 and old
VPS2 (with some updating).

53
Drupal Handbook 3 Aug 2007

This fix works for Verio VPS2 Servers which are installed with PCRE 6.4 by default (at this time).
I see no reason why it should not work for all unix servers (perhaps with directory changes etc).

The fix is to uninstall pcre and install the correct version as follows:

login as root
Type:
# pkg_info
which will show you the installed packages.
type:
# pkg_delete pcre-6.4 (assuming you see pcre-6.4 as the installed
version, change as required)
change to the directory where your ports collection is.
on FreeBSD it is:
/ports/devel/pcre-utf8
so type into your shell prompt:
# cd /ports/devel/pcre-utf8
# make
# make install
# make clean
then restart the apache server...
something like this (this is a VPS2 specific script, yours may be different):
# restart_apache

Configure .htaccess to allow awstats to work with clean URL’s


When I installed Drupal with clean url’s it made my Awstats (within the cgi-bin) not work and
just return a Drupal page not found error.

Drupal is installed in the root directory (public_html) of my web space so is the cgi-bin folder
that Awstats is in.

I fixed the problem by changing the protect files and adding 1 rewriteCond line to the .htaccess
file as follows:

In the FilesMatch section, find " |code-style\.pl " without the quotes and remove it from the
following code:

# Protect files and directories from prying eyes.


<FilesMatch
"(\.(engine|inc|install|module|sh|.*sql|theme|tpl(\.php)?|xtmpl)|Entries.*|Repository|Root)$">
Order deny,allow
Deny from all
</FilesMatch>

Now add this line (RewriteCond %{REQUEST_URI} "!cgi-bin/") to the following:

54
3 Aug 2007 Drupal Handbook

# Rewrite current-style URLs of the form ’index.php?q=x’.

RewriteCond %{REQUEST_URI} "!cgi-bin/"


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

This was all done on the default install of Drupal w/.htaccess.

Configuring .htaccess to ignore specific subfolders


Ignoring Subfolders that exist in the DocumentRoot

With clean URL’s enabled, when running other software applications in subfolders
(subdirectories) of a Drupal root installation. your .htaccess file may rewrite those URL’s to
Drupal. This may be a particular problem for those with a Drupal installation in the root of their
domain using Cpanel and Fantastico where Fantastico installs other software into subfolders.
For example, phpSurveyor’s admin interface as installed by Fantastico will not work with
Drupal’s default .htaccess settings. The URL for the admin interface is inaccessible and will
return a "page not found" page in your Drupal site.

The trick is to modify .htaccess to ignore specific files/folders. So for example, if you have two
folders, <folder1> and <folder2> in the root of your Drupal installation, modify your .htaccess
file by inserting the following code:

=========[ start of .htaccess snippet]==========


<IfModule mod_rewrite.c>
RewriteEngine on
#
# stuff to let through (ignore)
RewriteCond %{REQUEST_URI} "/folder1/" [OR]
RewriteCond %{REQUEST_URI} "/folder2/"
RewriteRule (.*) $1 [L]
#
====================[ end ]=====================

For each folder you want to bypass, add a RewriteCond line, and end all but the final
RewriteCond with [OR]. Note that the [L] in the rewrite rule tells it to stop there and bypass the
rest of the rewrite rules.

Ignoring subfolders that are included via Apache Alias directives

As of 4.7, files and directories should be automatically allowed through in drupal’s .htaccess
setup. Thats what the !-f and !-d lines do.

However if you are working with Apache Alias or similar directives the file doesn’t actually
exist so drupal will take over like it should. The best way around it is to just add one more
conditional that matches your location and make it skip it too. Thats what the ! means. Please see

55
Drupal Handbook 3 Aug 2007

below:

RewriteCond %{REQUEST_URI} !^/yourDirectoryName


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

It essentially means Apply this rule if the REQUEST_URI doesn’t start with
/yourDirectoryName and the REQUEST_FILENAME isn’t a real file or a real folder. Which is
exactly what you want. There is an implied "AND" between the lines of that rule. The ! says "not
like this".

Special thanks to Mike Smullin for help on this fix.

Create a custom php.ini


This article explains how to set up a custom php.ini that overides your servers default php.ini,
providing an easier alternative (in the long run) than using .htaccess to overide php.ini settings.
Itassumes that you have a ssh account set-up and are using a ssh client (e.g. putty - link to be
added). You are also expected to logically replace directory structures given here, with your
own, if they are different.

Procedure for allowing php.ini configuration for a website (shows changing file upload max)

1/ Create a cgi-bin Directory

First you’ll need a cgi-bin directory:

mkdir ~/[your website directory]/cgi-bin/

This directory will be hosting your copy of php and your php.ini file.

2/ Create a script to retrieve the latest copy of php.cgi and php.ini

Make a file in ~/ called php-copy.sh containing the following, where 100M contains whatever
file size limit you like, and [your website directory] is appropriately substituted.

For PHP4:

#!/bin/sh
CGIFILE="$HOME/[your website directory]/cgi-bin/php.cgi"
INIFILE="$HOME/[your website directory]/cgi-bin/php.ini"
rsync -a /dh/cgi-system/php.cgi "$CGIFILE"
# REMOVE THE FOLLOWING LINE TO CREATE THE UPDATE-ONLY SCRIPT:
cp /etc/php/cgi/php.ini "$INIFILE"
perl -p -i -e ’
s/.*post_max_size.*/post_max_size = 100M/;
s/.*upload_max_filesize.*/upload_max_filesize = 100M/;
’ "$INIFILE"

56
3 Aug 2007 Drupal Handbook

For PHP5:

#!/bin/sh
CGIFILE="$HOME/[your website directory]/cgi-bin/php.cgi"
INIFILE="$HOME/[your website directory]/cgi-bin/php.ini"
rsync -a /dh/cgi-system/php5.cgi "$CGIFILE"
# REMOVE THE FOLLOWING LINE TO CREATE THE UPDATE-ONLY SCRIPT:
cp /etc/php5/cgi/php.ini "$INIFILE"
perl -p -i -e ’
s/.*post_max_size.*/post_max_size = 100M/;
s/.*upload_max_filesize.*/upload_max_filesize = 100M/;
’ "$INIFILE"

A more general script with options (for references purposes only, do not do this):

#!/bin/sh
test $# = 0 && exit 1
while test "$1";do
case $1 in
-php5) PHP=php5 ;;
-sm) shift; SM=$1 ;;
-rg) shift; RG=$1 ;;
-pms) shift; PMS=$1 ;;
-umfs) shift; UMFS=$1 ;;
-mqg) shift; MQG=$1 ;;
-met) shift; MET=$1 ;;
-mit) shift; MIT=$1 ;;
-ml) shift; ML=$1 ;;
*) D=$1 ;;
esac
shift
done
test "$D" || exit 1
test -d "$HOME/$D" || exit 1
CGI="$HOME/$D/cgi-bin"
mkdir -m0755 -p $CGI || exit 2
PHP=${PHP:-php}
SM=${SM:-On}
RG=${RG:-Off}
PMS=${PMS:-8M}
UMFS=${UMFS:-7M}
MQG=${MQG:-Off}
MET=${MET:-30}
MIT=${MET:-60}
ML=${ML:-8M}
CGIFILE="$CGI/$PHP.cgi"
INIFILE="$CGI/php.ini"

57
Drupal Handbook 3 Aug 2007

echo "CGI=$CGI MQG=${MQG} UMFS=${UMFS} PMS=${PMS} RG=${RG} SM=${SM}


MET=${MET} MIT=${MIT} ML=${ML}" >&2
rsync -au /dh/cgi-system/$PHP.cgi "$CGIFILE"
[ -s /etc/$PHP/cgi/php.ini ] && \
sed -e "s/^safe_mode[ ]*=.*/safe_mode = $SM/" \
-e "s/register_globals[ ]*=.*/register_globals = $RG/" \
-e "s/magic_quotes_gpc[ ]*=.*/magic_quotes_gpc = $MQG/" \
-e "s/.*post_max_size.*/post_max_size = $PMS/" \
-e "s/.*upload_max_filesize.*/upload_max_filesize = $UMFS/" \
-e "s/.*max_execution_time.*/max_execution_time = $MET/" \
-e "s/.*max_input_time.*/max_input_time = $MIT/" \
-e "s/.*memory_limit.*/memory_limit= $ML/" \
# REMOVE THE FOLLOWING LINE TO CREATE THE UPDATE-ONLY SCRIPT:
/etc/$PHP/cgi/php.ini > "$INIFILE"
chmod 0755 "$CGIFILE"
chmod 0644 "$INIFILE"
[ -s $CGI/.htaccess ] || echo "Options -Indexes" > $CGI/.htaccess
touch $HOME/$D/.htaccess
if grep -q ’^Options’ $HOME/$D/.htaccess; then
grep -q ’+ExecCGI’ $HOME/$D/.htaccess || \
sed -i ’s/^Options\(.*\)/Options\1 +ExecCGI/’ $HOME/$D/.htaccess
else
echo "Options +ExecCGI" >> $HOME/$D/.htaccess
fi
grep -q ’^AddHandler[ ]\+php-cgi[ ]\+.php’ $HOME/$D/.htaccess ||
echo "AddHandler php-cgi .php" >> $HOME/$D/.htaccess
if grep -q ’^Action[ ]\+php-cgi’ $HOME/$D/.htaccess; then
sed -i "s@^Action[ ]\+php-cgi.*@Action php-cgi /cgi-bin/$PHP.cgi@" \
$HOME/$D/.htaccess
else
echo "Action php-cgi /cgi-bin/$PHP.cgi" >> $HOME/$D/.htaccess
fi

3/ Prepare script for execution

Execute the following commands into the shell. This will give you permission to execute the
php-copy.sh that we just created.

chmod +x php-copy.sh

This calls our new shell script to copy the php.cgi and php.ini files into our cgi-bin directory.

./php-copy.sh

If you get the error message: "bad interpreter: No such file or directory", there is probably an
unseen problem with the formatting of the file.

58
3 Aug 2007 Drupal Handbook

Run the following command to convert it to proper Unix format before calling the script again:
dos2unix php-copy.sh

4/ Test your new PHP setup

Open one of your existing PHP pages in your browser to ensure that your newly-installed local
copy of PHP is functioning properly. If there is a problem, go back over the prior steps and use
your debugging skills and your mastery of PHP, shell scripts and Linux to get your
newly-copied PHP interpreter working! Once everything works properly, go on to the next step.

5/ Create a shell script to make a fresh copy of php (for future use)

cp php-copy.sh php-update.sh

Open the newly-created php-update.sh script in your favorite text editor and find this line:

# REMOVE THE FOLLOWING LINE TO CREATE THE UPDATE-ONLY SCRIPT:

Delete that line as well as the line following it. Then save php-update.sh

If you got a "bad interpreter: No such file or directory" error message when you executed
./php-copy.sh previously, remember to convert the new file to unix format by running the
following command: dos2unix php-update.sh

6/ Set up a cron task to keep php up to date

Type:

crontab -e

And then enter the following in the text editor that shows up (replacing ’myusername’ with
your specific username):

@weekly /home/myusername/php-update.sh

This will update the php binary and config file once a week.

7/ Configure your website to use new the php.ini that we just set up

Create the file ~/[your website directory]/.htaccess which contains the lines:

Options +ExecCGI
AddHandler php-cgi .php
Action php-cgi /cgi-bin/php.cgi

This is telling Apache (the webserver) to use the php.cgi and php.ini that php-update.sh copied
into ~/[your website directory]/cgi-bin.

59
Drupal Handbook 3 Aug 2007

How to create a custom php.ini file when nothing else works

I recently needed to increase the memory_limit, upload_max_filesize and


post_max_size values to something higher than the measly amount set by a particular
webhost’s default php.ini file. This account was set up with cPanel and overriding the php.ini
defaults the usual way (by adding various lines to the .htaccess or settings.php files) didn’t work
at all. If you’ve had the same experience, you may find that this how-to works for you.

This how-to is for any version of Drupal running on Linux and Apache. No Drupal modules are
needed, but the devel module certainly helps.

1. Get and modify your custom php.ini file

It’s best to use a php.ini file that somewhat resembles the one already running on your server.
You can probably find one at /usr/local/lib/php.ini or /usr/local/Zend/etc/php.ini and just copy
it into your account’s web folder (it may be called "public_html" or "www" or "htdocs" -- you
know the one).

Edit your php.ini file and save your changes. There are handbook pages on increasing memory
and upload size if you need help on the syntax.

2. Creating your CGI script

Now create a small script and put it in your cgi-bin directory. In your web folder, create another
folder called "cgi-bin" if it’s not there already. Using your preferred text editor, create a file
name "php.cgi" and put the following into it:

#!/bin/sh
exec /usr/local/cpanel/cgi-sys/php5 -c /path/to/drupal/

If you don’t have cPanel on your account, try /etc/php5 instead. In any case, replace the
/path/to/drupal/ part with the full path to your Drupal installation, such as
/home/youraccount/public_html/ or /home/youraccount/public_html/drupal/

Since this is a script that needs to run as an executable file, use the chmod command and type this
at the command line:

chmod -x php.cgi

Don’t have shell access? That’s outside the scope of this how-to, but you can use an FTP
program that can change permissions of files, ask your webhost to make the php.cgi script
executable for you, or make it executable with some PHP code (perhaps with the devel module’s
Execute PHP block).

60
3 Aug 2007 Drupal Handbook

3. Modifying your .htaccess file

Add this one line to your .htaccess file:

Action application/x-httpd-php5 /cgi-bin/php.cgi

This tells Apache to perform an action each time it encounters a file of file type
"application/x-httpd-php5" -- if you’re using a version of PHP older than PHP5, you’ll need to
change this to "application/x-httpd-php" (or upgrade to PHP5 -- ask your webhost).

Finally, scroll down to the part that says "# Protect files and directories from prying eyes" and
add "ini|" to the <FilesMatch> directive so it looks something like:

<FilesMatch
"(\.(ini|engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\.p
hp)?|xtmpl)|code-style\.pl|Entries.*|Repository|Root|Tag|Template)$">
Order allow,deny
</FilesMatch>

Notice the "ini|" on the first line? This will prevent your custom php.ini file (and anything else
ending in .ini) from being accessible to the entire world. (The character after the "ini" part is a
pipe, by the way, not an L.)

4. Test your site

Load up your website and see if it works. If it does, good job! If it doesn’t, go back to step 2 or 3
and check to see what version of PHP your site is using. You can also ask your webhost for help.

If you increased your post_max_size or upload_max_size, then look at your


admin/settings/uploads admin page and see how big your uploads can be. If you
increased your memory_limit, check phpinfo or devel module’s phpinfo() page at
admin/logs/status/php

Create Drupal database using Plesk


Create the database
Login and select Services » Databases

This loads a page with an overview of databases. Depending on your host a database may
already have been created. This is often the case with low-budget hosts, where you are limited to
one database. In that case, use table prefixing. If no limits exists it is best to create a new
database for Drupal via: Add New Database.

Click on the name of the database you wish to use. In the overview page you’ll see all users for
this database. Again, depending on your host, you need to create a new user via: Add New
Database User.

61
Drupal Handbook 3 Aug 2007

If you do not have the option to create new database users, use a pre-existing one.

Load the Drupal database scheme


From the database users overview page click DB WebAdmin

The icon is a blue stack with a monkey wrench. Note that this opens phpmyadmin in a pop-up
that may be blocked by your browser.

First make sure the relevant database is selected. If necessary, click Databases in the
phpmyadmin start screen and then the database name.

Go to the SQL screen via a small button labelled SQL in the left pane of the phpmyadmin screen.

If you’ve created a new user for the Drupal database, you need to grant priviliges to the user:
execute the SQL query:

GRANT ALL PRIVILEGES ON databasename.* TO username@localhost IDENTIFIED


BY ’password’;
where

’databasename’ is the name of your database


’username@localhost’ is the username of your MySQL account
’password’ is the password required for that username

This may not complete successfully; in that case you’ll have to assume / hope the user was
created with the necessary privileges.

To create the database layout, select the tab import files. Upload the file
database/database.mysql with the database scheme.

Drupal with safe mode enabled and open basedir


This is still undergooing some changes as I’m doing more tests...
But it works on a clean drupal 4.7.3 install...

I haven’t tested all modules yet, so please help me out...

Simply: use safe mode based on groups rather then owner and give access to my central code
base for virtual hosts so that open base dir works...

You need to be logged in using ssh as root...


And mind you my examples are from a plesk based system...
With a central code base located in /var/www/apps/drupal
and the virtual hosts directory in /var/www/vhosts/{domain}.{tld}/httpdocs/

1) create a group and a user called drupal...


After -d you can put any home directory you like, but I choose the directory where my drupal
code is installed...
after the passwd you need to give a GOOD password for the user...

62
3 Aug 2007 Drupal Handbook

groupadd drupal
useradd -d /var/www/apps/drupal -g drupal drupal
passwd drupal

2) Change the owner and the group of the single code base...
If you don’t have a single code base, only changing the group (chgrp) is enough

chgrp drupal -R /var/www/apps/drupal


chown drupal -R /var/www/apps/drupal

3) For the virtual hosts, change the group of the sites directory
Also all directories under sites should be chmod to 2775: 2 puts all new subfiles created
automatically into the group of the folder they are placed in (drupal in our case) + 7 for owner
(root or drupal or ftpusername) + 7 for group (drupal) + 5 for guests
If you have any more directories under sites, chmod them too

chgrp drupal -R /var/www/vhosts/{domain}.{tld}/httpdocs/sites


chmod 2775 /var/www/vhosts/{domain}.{tld}/httpdocs/sites
chmod 2775 /var/www/vhosts/{domain}.{tld}/httpdocs/sites/default

4) Add the users to the group


Plesk has a psaserv group don’t worry if you don’t have it...
The drupal group needs the psaadm and psaftp only if you run plesk

vi /etc/group
psaserv:x:2523:apache,psaftp,psaadm,drupal
drupal:x:10002:drupal,apache,psaftp,psaadm,{user_of_ftp_account_of_virtual_host}
restart service apache

5) correct the tmp dir by creating a sub directory and putting the drupal group and user on it...

mkdir /tmp/drupal
chmod 2775 /tmp/drupal
chgrp drupal /tmp/drupal
==> in admin change to /tmp/drupal

6) alter the code of file.inc so directories are made using 2775 rather then 775

find: @chmod($directory, 0775);


replace: @chmod($directory, 02775);
Actually my version of PHP has a bug and doesn’t put the 2!!!
I have to remember to chmod myself then...

7) change your virtual host settings of httpd.conf


In plesk this is done in: /var/www/vhosts/{domain}.{tld}/conf/vhost.conf
Other systems might have another place for the conf which is the configuration for your httpd
server..
With this code I have made sure that only the drupal directories benefit from group based safe

63
Drupal Handbook 3 Aug 2007

mode (safe_mode_gid)... all other directories still use the default safe mode
Remove the second DirectoryMatch in case you want all files and folders to benefit from group
based safe mode...
As I have a central code base in /var/www/apps/drupal, I need to add this dir to the open
basedir... and again only for the drupal directories off course...

#
# allow all documents below this dir access to drupal core
#
<DirectoryMatch "^/var/www/vhosts/{domain}.{tld}/httpdocs">
<IfModule sapi_apache2.c>
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid on
php_admin_value open_basedir
"/var/www/apps/drupal:/var/www/vhosts/{domain}.{tld}/httpdocs:/tmp"
</IfModule>
<IfModule mod_php5.c>
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid on
php_admin_value open_basedir
"/var/www/apps/drupal:/var/www/vhosts/{domain}.{tld}/httpdocs:/tmp"
</IfModule>
</DirectoryMatch>
#
# now limit for all directories below root that are not includes or
modules
# users want other apps installed too... so no access to drupal
#
<DirectoryMatch
"^(/var/www/vhosts/{domain}.{tld}/httpdocs/)(?!includes/|modules/).*/">
<IfModule sapi_apache2.c>
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid off
php_admin_value open_basedir
"/var/www/vhosts/{domain}.{tld}/httpdocs:/tmp"
</IfModule>
<IfModule mod_php5.c>
php_admin_flag safe_mode on
php_admin_flag safe_mode_gid off
php_admin_value open_basedir
"/var/www/vhosts/{domain}.{tld}/httpdocs:/tmp"
</IfModule>
</DirectoryMatch>

64
3 Aug 2007 Drupal Handbook

Generic Mass SQL Import into Drupal


# General Notes for Mass Import into Drupal
#
# The below is a template for an SQL import file to programmatically
# add nodes into Drupal version 4.7.0.
#
# - Currently not tested on 4.7.3, but there does not seem to be any
# radical changes in the Database structure that would break this.
#
# - You will probably need to create a separate program to parse
# your existing content and create the needed looping structures
# to properly create the SQL import file for you system.
#
# - You must follow SQL rules for data entry, see your SQL
# documentation. Incorrect escaping will cause truncated fields.
#
# - Copyright ReasonToFreedom.com
# - Personal use: Free of charge.
# - Professional use: Only with USD $20 donated
# to Drupal.org per domain you use it on.*
#
# - This header and all copyright notices must remain intact
# upon any reprint/redistribution.
#
# - *Don’t stiff Drupal.org, if you’re using this professionally
# on five domains, you can afford to send Drupal.org $100.
#
# ======== Set Once Vars ==========
set @uid_value = 7; # Author ID (User ID)
set @format = 3; # 1 => Filtered HTML | 2 => PHP code | 3 => Full HTML
# ======== End Set Once Vars ==========
# ======== Set Per Node Vars ==========
/* set some variables to zero */
set @node_value = 0, @node_rev_vid_value = 0; # load these values as we
execute.
/* Set some default values */
set @title_value = ’The Title’;
/* May also set entry_date_time like curr_date_time below */
set @entry_date_time = unix_timestamp(’2002-05-20 12:00:00’); # get
specific date and time as number of seconds from 01/01/1970.
set @url_dest = ’the_url.html’;
set @teaser_value = ’<P>Teaser Para 1.</P>
<P>Teaser Para 2.</P>
’;
set @body_value = ’<P>Body Para 1.</P>
<P>Body Para 2.</P>

65
Drupal Handbook 3 Aug 2007

<P>Body Para 3.</P>


<P>Body Para, ad nauseam</P>
’;
set @curr_date_time = unix_timestamp(); # get current date and time as
number of seconds from 01/01/1970.
START TRANSACTION;
/* Increment node_nid field in sequences. */
update sequences set id = id + 1 where name = ’node_nid’;
/* Get new node_nid value from sequences for later */
select @node_value := max(id) from sequences where name = ’node_nid’;
/* Increment node_revisions_vid field in sequences. */
update sequences set id = id + 1 where name = ’node_revisions_vid’;
/* Get node_revisions_vid value from sequences for later */
select @revisions_value := max(id) from sequences where name =
’node_revisions_vid’;
COMMIT;
START TRANSACTION;
Insert into node
(nid, type, title, uid, status, created, changed, comment, promote,
moderate, sticky, vid)
VALUES
(@node_value, ’story’, @title_value, @uid_value, 1, @entry_date_time,
@curr_date_time, 2, 1, 0, 0, @revisions_value);
Insert into node_comment_statistics
(nid, last_comment_timestamp, last_comment_name, last_comment_uid,
comment_count)
VALUES
(@node_value, @curr_date_time, NULL, @uid_value, 0);
Insert into node_revisions
(nid, vid, uid, title, body, teaser, timestamp, format, log)
VALUES
(@node_value, @revisions_value, @uid_value, @title_value, @body_value,
@teaser_value, @curr_date_time, @format, "");
Insert into history
(uid, nid, timestamp)
VALUES
(@uid_value, @node_value, @curr_date_time);
Insert into node_counter
(nid, totalcount, daycount, timestamp)
VALUES
(@node_value, 1, 1, @curr_date_time);
COMMIT;
set @url_src = concat( "node/", @node_value ) ;
Insert into url_alias
(src,dst)
VALUES
(@url_src, @url_dest);

66
3 Aug 2007 Drupal Handbook

# ======== End Set Per Node Vars ==========


# ======== Set multiple Terms per Node ==========
/* set term_value and insert as many times as you need */
set @term_value = 50;
Insert into term_node
(nid,tid)
VALUES
(@node_value, @term_value);
set @term_value = 48;
Insert into term_node
(nid,tid)
VALUES
(@node_value, @term_value);
# ======== End Set multiple Terms per Node ==========
# EOF #

DrupalCon site

design contest entry over at the DrupalCon site and become immortal in the Drupal community.

How to degrade your Drupal db from MySQL 4.1.X/5.0.X to MySQL


4.0.X
I came across this issue when was developing a site for a client. I have MySQL 5.0.X at my
localhost and staging host but client’s hosting still uses MySQL 4.0.X.

So here is the solution:

0. Always make backup first.

1. Drop tables "accesslog", "cache" and "watchdog"

(DROP TABLE accesslog, cache, watchdog;)

2. Recreate tables from Drupal mysql dump for v4.0

CREATE TABLE accesslog (


aid int(10) NOT NULL auto_increment,
sid varchar(32) NOT NULL default ’’,
title varchar(255) default NULL,
path varchar(255) default NULL,
url varchar(255) default NULL,
hostname varchar(128) default NULL,
uid int(10) unsigned default ’0’,
timer int(10) unsigned NOT NULL default ’0’,
timestamp int(11) unsigned NOT NULL default ’0’,
KEY accesslog_timestamp (timestamp),
PRIMARY KEY (aid)

67
Drupal Handbook 3 Aug 2007

);
CREATE TABLE cache (
cid varchar(255) NOT NULL default ’’,
data longblob,
expire int(11) NOT NULL default ’0’,
created int(11) NOT NULL default ’0’,
headers text,
PRIMARY KEY (cid),
INDEX expire (expire)
);
CREATE TABLE watchdog (
wid int(5) NOT NULL auto_increment,
uid int(10) NOT NULL default ’0’,
type varchar(16) NOT NULL default ’’,
message longtext NOT NULL,
severity tinyint(3) unsigned NOT NULL default ’0’,
link varchar(255) NOT NULL default ’’,
location varchar(128) NOT NULL default ’’,
referer varchar(128) NOT NULL default ’’,
hostname varchar(128) NOT NULL default ’’,
timestamp int(11) NOT NULL default ’0’,
PRIMARY KEY (wid)
);
3. Make a dump for MySQL 4.0.X
mysqldump -u root -p -h localhost --compatible=mysql40 mydatabase >
mydatabase.sql

4. Upload this dump to your MySQL 4.0.X server.

5. Refresh your browser a couple of times. Enjoy!

How-To: Virtual Hosting with Drupal


Introduction

This book explaines how I’ve enabled Drupal hosting for my customers.
I hope it is helpfull for other Drupal hosters...

Environment

this is the environment used to setup my drupal hosting

linux RHEL 4
plesk 8.0.1
php 4.3.9
mysql 4.1.12
apache 2.0.52

68
3 Aug 2007 Drupal Handbook

drupal 4.7.x

Requirements

keep safe mode on at all times without the need for chmod 777
keep base dir restriction on at all times
integrate into plesk so that backup, databases, quotas,
etc keeps working
drupal must run as managed application
updates done once for all vhosts :: use single code base
approved modules and themes available for vhosts to select from
pre-activate drupal modules that enhance basic content management:
SEO, security, ...
eaccelerator must speed up php processing efficiently :: use single code
base
Each individual vhost
should be able to use its own themes and modules
should be accessible trough different URLs ::
drupal multisite option
should also be able to use other applications then drupal within the
same site
should experience drupal no different as if we would install drupal
for each vhost seperatly
Enhance security if needed on the drupal package
Single code base should be included in the normal backup mechanism available in plesk

Next pages

As the book seems to order the sub pages by date, I list here the order of further reading:

1. Solution overview: http://drupal.org/node/90144


2. Prepare environment: http://drupal.org/node/90207

How-To: Virtual Hosting with Drupal :: Prepare environment

Introduction

On this page I will explain some preparations of the environment like creating the drupal group,
a tempory files location, application reference location, etc.

Please read previous pages:

Requirements: http://drupal.org/node/80472
Solution overview: http://drupal.org/node/90144

69
Drupal Handbook 3 Aug 2007

The drupal group

As we will enable the safe mode in group mode, we are in need of a system group.
SSH into the server as SU (super user or root)

add the group

$ groupadd drupal
add the apache, psaftp and psaadm users to the group
the group id (10002) could be different
$ vi /etc/group
drupal:x:10002:apache,psaftp,psaadm

The temp directory

Also within the temp directory we need a matching group because uploaded files are
temporarly saved there and then copied to the final destination.
Therefore we will create a seperate directory and chmod it so that each file created their
automatically receives the drupal group. The latter is achieved by addin 2000 to the chmod
command.

$ mkdir /tmp/drupal
$ chmod 2775 /tmp/drupal
$ chgrp drupal /tmp/drupal
You will see an s appear instead of the x at the group part:
drwxrwsr-x 2 root drupal 4096 Oct 16 15:09 drupal

The reference location

This is a directory where all symlinks are placed that point to the current version of an
application. It is this location that all vhosts will reference so that they don’t depend on the
current version.
When switching versions, we only need to alter the symlinks at this location and all vhosts will
be updated automatically. See further pages for more info.
SSH into the server as SU (super user or root)

$ mkdir /var/www/apps

Navigation

As the book seems to order the sub pages by date, I list here the order of further reading:

Previous: Solution Overview: http://drupal.org/node/90144


Next: Single code base: Comming soon...

70
3 Aug 2007 Drupal Handbook

How-To: Virtual Hosting with Drupal :: Solution Overview

Introduction

On this page I will explain in general what solutions are provided for the different requirements

Please read previous Requirements page: http://drupal.org/node/80472

Safe mode

Enabling Safe Mode imposes several restrictions on PHP scripts. These restrictions are mostly
concerned with file access, access to environment variables and controlling the execution of
external processes.
There are problems which may be encountered when this mechanism is turned on, notably
when attempting to work with files owned by different users and files which have been created
at runtime by the script (which will be owned by the owner of the web server process).

In Plesk (and most other virtual hosts system) each vhost gets its own owner (FTP user) that is
set when files are uploaded to the server. As we want a single code base located in a central
place, the owner of the files within that central place will be different then the owner of the files
in the vhost’s location.

In order to work around these issues, a relaxed form of the file permission checking is also
provided by Safe Mode. Using the php.ini directive safe_mode_gid, it is possible to relax the
user ID check to a group ID check.
That is, if the script has the same group ID as the file on which a file operation was requested,
the operation will succeed. If the script owners and the web server are members of the same
group, and all hosted files are owned by this group, the file operations will succeed regardless of
user ID.

Thus, we will create a group "drupal" that will cover all drupal
related files accross vhosts and enable the safe_mode_gid. By doing so
we will still have a more secure system then when we would disable the
safe mode.

Information taken from here: http://www.acunetix.com/websitesecurity/php-security-5.htm

Open Basedir

Open Basedir limits the files that can be opened by PHP to the specified directory-tree, including
the file itself. This directive is NOT affected by whether Safe Mode is turned On or Off.

When a script tries to open a file with, for example, fopen() or gzopen(), the location of the file is
checked. When the file is outside the specified directory-tree, PHP will refuse to open it. All
symbolic links are resolved, so it’s not possible to avoid this restriction with a symlink.

71
Drupal Handbook 3 Aug 2007

In Plesk (and most other virtual hosts system) each vhost gets its own open_basedir restriction
that restruicts the opening of files to the httpdocs directory and the /tmp directory. As we want
a single code base located in a central place, that location will not be accepted trough this
restriction.

Thus, we will alter the open basedir restriction so that it includes


the single code base location. But as we want other applications to be
installed within the same vhost, we will add the location only for
directories using drupal.

Plesk integration

The plesk control panel works great as long as you keep the directory structure and security as it
is provided by plesk. Therefore we need to merge the single code base and each vhost within the
provided structure.

The single code base will be installed as a normal vhost but limiting
web access to the domain. As such a backup of the single code base can
be sheduled and FTP can be enable to upload new modules and themes.
Each vhost will have his own local "sites" directory and will create
its database trough the plesk interface.

Managed application

As the single code base resides as a single vhost, we can upgrade the code, add modules and
themes into one location. To make upgrading easier we need to make sure that each vhost that
uses drupal, references one single point independend of the drupal version.

We will make subdirectories per drupal version in the single code base
location and have one single reference that we can switch when going to
a new version.
Thus their will be a symbolic link called "drupal" pointing towards a
drupal version "drupal-4.7.3" and each vhost that uses drupal will have
symbolic links pointing towards the "drupal" symbolic link. When we
change version, we only need to change the "drupal" symbolic link once
and all vhosts will be adjusted accordingly.

eAccelerator

The eAccelerator speeds up the execution of the php script by precompiling them and putting
them into memory. The dissadvantage is that you need to have the memory and the more you
have the more php files can be kept for fast execution.
Therefore we need to limit the number of php files on the server.

By using the single code base, every vhosts uses the same files and
thus memory usage can be limited and all php scripts run faster.

72
3 Aug 2007 Drupal Handbook

more on eAccelerator can be found here: http://eaccelerator.net

Each individual vhost requirements

as noted above in the "Plesk Integration" part, each vhost gets his own "sites" directory that
enables them to add their own modules and themes. Also as natavely available by drupal, the
multisites mechanism will work for the same reason.
Using symbolic links and this "sites" directory will give the user the feeling that it is a full drupal
install on their system.

The local "sites" directory will allow the flexability required

Navigation

As the book seems to order the sub pages by date, I list here the order of further reading:

Previous: Requirements: http://drupal.org/node/80472


Next: Prepare environment: http://drupal.org/node/90207

HOWTO: copy a site to a local computer using XAMPP


Here are the steps you need to take to get a copy of a Drupal website onto your local computer
for development purposes, using the XAMPP stack and a variety of tools. Many of the steps
taken here have been made so that you can keep your PHP files outside the standard htdocs
DocumentRoot directory of the Apache server while maintaining whatever else you have
running on your XAMPP installation.

1) Install XAMPP software. This gets you Apache, MySQL and PHP all set up in a few clicks.
Skip this step if you have them already set up (Drupal needs things like php and mod_rewrite in
your Apache build.)

2) Download a copy of your production ’drupal’ database to your local MySQL server. If your
production server has phpMyAdmin you can export your database using it and then import
using your local phpMyAdmin. You may also use a program like Navicat MySQL since it
handles UTF-8 data properly (unfortunately my favorite free MySQL client, SQLyog, seems to
lack proper UTF-8 support).

3) Create a user on your local mysql database to match the remote connection settings and give
them full permissions:
% mysql> GRANT ALL PRIVILEGES ON drupal.* TO ’drupaluser’@’localhost’
IDENTIFIED BY ’drupalpassword’ WITH GRANT OPTION; FLUSH PRIVILEGES;

4) Get a copy of the production Drupal site files and folders (In my case, I use a source control
system client like Perforce) and copy them to a location you want to do your work in. An
example: C:/p4/atlas-drupal/drupal. I will call this location %your_drupal_files%
from here out.

73
Drupal Handbook 3 Aug 2007

5) Edit %your_drupal_files%/sites/default/settings.php and change the base URL


to $base_url = ’http://localhost/drupal’; You should still be able to leave the
$db_url connection setting alone.

6) Edit %your_xampp_location%\apache\conf\extra\httpd-xampp.conf and add the


following lines according to where your copy of drupal lives on your computer:

Alias /drupal "%your_drupal_files%/"


<directory "%your_drupal_files%">
AllowOverride AuthConfig FileInfo
Order allow,deny
Allow from all
</directory>
You’ll need that "FileInfo" directive if you are getting 500 errors in your Apache error log like
"RewriteEngine not allowed here". You could also add these lines in standard httpd.conf if
you are not using XAMPP but just plain Apache.

7) (Skip this step if you are using regular Apache and not XAMPP)
Edit %your_xampp_location%\apache\conf\httpd.conf and uncomment out the line
LoadModule rewrite_module modules/mod_rewrite.so You need this so Drupal can
have "clean links".

8) Edit %your_drupal_files%/.htaccess and change the RewriteBase to /drupal.

9) Restart the Apache service (with the XAMPP control panel if you are using XAMPP)

You now should be able to navigate to your sandbox development copy of the site via
http://localhost/drupal

HOWTO: Copy site to another directory for testing


System: Apache + PHP + MySQL + Linux

I had my site at, say, example.com and wanted to set up beta.example.com as a duplicate site to
test some ideas. This meant duplicating the database and code to a separate database and code
tree. That way I could modify beta.example.com without harming example.com.

In my case I’m on a virtual-private-server (same thing as a dedicated server) and have full
control over the system. If you’re on a shared hosting account the steps will be different.
Unfortunately the details of how share hosting accounts are setup vary so widely, I’m not going
to try and generalize the instructions for that.

1. In the DNS, create the beta.example.com subdomain. Remember it can take a little while for
the DNS entries to propogate properly.
2. Duplicate the database tables ... I’m on Mac OS X and used the navicat program to do so,
but you should be able to use mysqldump or other similar programs. That is, create a new
database and copy the tables and data from the example.com database to the one for

74
3 Aug 2007 Drupal Handbook

beta.example.com.
3. Make a directory for the docroot of beta.example.com, and copy the files as so:
(cd example.com/ROOT; tar cf - .) | (cd beta.example.com/ROOT; tar
xvf -)
If you only have FTP access this is a little harder. First FTP the files to your local computer,
then FTP those files into the new docroot directory. You can also edit the files on your local
computer, and then re-FTP them whenever you change something.
4. Config apache’s httpd.conf for a second VirtualHost with beta.example.com in it. Make sure
the VirtualHost entry for beta.example.com preceeds the one for example.com. Make sure the
docroot for beta.example.com is a different directory.
5. Edit sites/default/settings.php and change base_url and the database URL.
$base_url = ’beta.example.com’;
$db_url = ’mysql://username:password@localhost/new-database’;
6. It’s also helpful to override the site name so that the heading on the site glaringly reminds
you that you’re on the BETA site:
$conf = array(’site_name’ => ’BETA this sites name’);

HOWTO: Install Drupal 5.x using cPanel


Many hosting providers use a control panel to shield users from the complexity of their servers.
cPanel is one of those control panels. This small guide explains how to setup Drupal with
CPanel.

Not everything in this guide may be applicable to your situation, because some hosting
providers limit the options available to their users.

The basic assumptions: you have a domain name (http://www.example.com) and want to
install Drupal at the document root, (usually public_html or htdocs), where it is reachable via
the URL http://example.com or http://www.example.com. In order to accomplish this, the
Drupal files such as .htaccess and index.php have to be placed into your server’s document root,
along with the Drupal subdirectories such as includes, modules, themes, etc.

Note that other files present may be overwritten. Make backups before installing Drupal and
remove files that may interfere with installation (e.g. index.php or .htaccess). If the
pre-existing .htaccess file is necessary for other parts of your site, merge it with the one
provided with Drupal.

If you have folders with names like admin/, image/, blog/, etc., these can conflict with Drupal
and stop you from accessing areas of your Drupal site.

If your version of CPanel comes with Fantastico, you can use it to easily install Drupal.
However, this installation does not come with update.php, a file necessary for updating your
database when newer versions of modules are uploaded into your site.

Upload the Drupal files and folders

75
Drupal Handbook 3 Aug 2007

Download the newest version of Drupal.

Upload this to your hosting space using an FTP Program or CPanel’s built in File Manager.

Using the File Manager, extract the contents of the file: click on the file’s name and then select
extract in the menu that pops up on the right.

This will extract the entire archive into a folder named drupal-x.x.x. You will then need to move
the files out of this directory and into your document root directory (such as www or
public_html).

You can also extract all the files and upload them this way; however, this takes much longer.

Create a database

1. Open cPanel
2. Go to MySQL Databases
3. Choose a databasename* for the new database and press "Add Database"
4. Choose a username* and password for the new database user and press "Add User"
5. Grant permissions to the user; select the username and database name, check ’ALL’ and
press ’Grant permissions’

*Note: cPanel usually adds the cPanel username as a prefix to the newly created names.

Install Drupal

Drupal 5.x now comes with an automated installer. You no longer have to manually load the
database tables -- Drupal does it for you.

Go to http://www.example.com/install.php

Here you will be asked for the database name, database user, and password.

If you need to use this database for more than one installation of Drupal (such as with hosting
packages with a limited number of MySQL databases), you may want to click on the Advanced
options and select a prefix for the tables you will be creating (such as "site_" or "main_"),

This will then install Drupal for you, creating and filling all needed tables in your database.

Once it is complete, you can go onto your site and set up the first user.

Setting up your first user account

The first user in your site (often referred to as user/1) is the "super user" on your site. It is
automatically granted all admin and view permissions for your site. As such, it is important to
immediately register on the site, which creates the first user.

76
3 Aug 2007 Drupal Handbook

After submitting your user name and e-mail, you’ll be given the option of changing the
password for the account from the one the Drupal created for you.

Cron tasks

Many Drupal modules (such as the search functionality) have periodic tasks that must be
triggered by a cron job. To activate these tasks, call the cron page by visiting
http://www.example.com/cron.php -- this will pass control to the modules and the modules
will decide if and what they must do. To call cron.php periodically you need to setup a cron job.

cPanel offers a way to set cronjobs via Server » Cron jobs. Carefully read the instructions on
the screen; they may differ from the following example.

To run cron.php every day set the Minute and Hour fields to 0 and the rest of the fields to *. The
command to run is:

GET http://www.example.com/cron.php > /dev/null

Additional modules

Drupal comes with a limited number of modules. To expand the functionality of your Drupal
site, you’ll need to download and add modules to your site.

View the listing of modules and download the ones you want to use.

Be careful to only download those that are for Drupal 5.x, as earlier modules will not work with
your site.

Also, be sure to read the description, as some modules require additional modules to be
installed in order for them to work.

HOWTO: Install Drupal using cPanel


Many hosting providers use a control panel to shield users from the complexity of their servers.
cPanel is one of those control panels. This small guide explains how to setup Drupal with
CPanel.

Not everything in this guide may be applicable to your situation, because some hosting
providers limit the options available to their users.

The basic assumptions: you have a domain name (http://www.example.com) and want to
install Drupal at the document root, (usually public_html or htdocs), where it is reachable via
the URL http://example.com or http://www.example.com. In order to accomplish this, the
Drupal files such as .htaccess and index.php have to be placed into your server’s document root,
along with the Drupal subdirectories such as includes, modules, themes, etc.

77
Drupal Handbook 3 Aug 2007

Note that other files present may be overwritten. Make backups before installing Drupal and
remove files that may interfere with installation (e.g. index.php or .htaccess). If the
pre-existing .htaccess file is necessary for other parts of your site, merge it with the one
provided with Drupal.

Upload the Drupal files and folders

The first step is to download the drupal distritbution archive "drupal-x.x.x.tar.gz" onto your
local computer, and then unpack it using a program such as 7zip, WinZip, WinRAR or tar.

The second step is to upload the drupal files to your server. There are three options for
uploading the files, two that use cPanel’s built-in File Manager, and one that uses an FTP-client.
The latter depends on FTP access provided by your host.

FTP (easiest) - After unpacking the drupal archive on your local computer, upload the files
and folders in the resulting drupal-x.x.x directory to the document root of your webspace.
cPanels built-in File Manager, option 1 - After unpacking the drupal archive on your local
computer, recompress the files and folders in the resulting drupal-x.x.x directory into a zip
file or into a new tar file. The result should be that the top-level directory "drupal-x.x.x" is
no longer present in this archive. Upload this new archive to the document root on the
server and extract its contents. The Drupal files and folders should now be located in the
document root.
cPanels built-in File Manager, option 2 - Upload the entire drupal distribution archive
"drupal-x.x.x.tar.gz" to the document root of the server and extract its contents. Then use
File Manager to move all the files and folders in the resulting drupal-x.x.x directory to the
the server’s document root.

Because you need some files from the drupal archive in a later stage, it’s a good idea to
decompress it locally anyway.

Create a database

This step may not be necessary; some hosting firms provide only one pre-made database.

Before you proceed you should know:

"username" - the username for connecting to the database


"password" - the password for that username
"databasename" - the name of the database

1. Open cPanel
2. Go to Server » MySQL Databases
3. Choose a databasename* for the new database and press "Add Database"
4. Choose a username* and password for the new database user and press "Add User"
5. Grant permissions to the user; select the username and database name, check ’ALL’ and
press ’Grant permissions’

78
3 Aug 2007 Drupal Handbook

*Note: cPanel usually adds the cPanel username as a prefix to the newly created names.

Create database layout

1. Open phpmyadmin (Server » PhpMyadmin)


2. Select the newly created database
3. Depending on the phpmyadmin version select the tab SQL or import
4. Choose the file database/database.mysql and press ’Go’
5. Alternatively copy-paste the contents of database/database.mysql in the query
textfield and press ’Go’

Connecting Drupal
The default configuration file can be found in sites/default/settings.php. Before you
can run Drupal you have to set the database URL and the base URL to the website.

$db_url = ’mysql://username:password@localhost/databasename’;

Set the $base_url to match your websites URL:

$base_url = ’http://www.example.com’;

See INSTALL.txt for more information.


Modify settings.php locally, then upload the modified file. Alternatively use cPanels text-editor
to change the file on the server. Make sure to delete all trailing whitespace from settings.php
when using the latter option or you will encounter the infamous ’headers already sent’
warnings.

Create the first account


Point your webbrowser to your site (http://www.example.com/) and follow the instructions on
the welcome screen.

Cron tasks
Many Drupal modules (such as the search functionality) have periodic tasks that must be
triggered by a cron job. To activate these tasks, call the cron page by visiting
http://www.example.com/cron.php -- this will pass control to the modules and the modules
will decide if and what they must do. To call cron.php periodically you need to setup a cron job.

cPanel offers a way to set cronjobs via Server » Cron jobs. Carefully read the instructions on the
screen; they may differ from the following example.

To run cron.php every day set the Minute and Hour fields to 0 and the rest of the fields to *. The
command to run is:

GET http://www.example.com/cron.php > /dev/null

79
Drupal Handbook 3 Aug 2007

HOWTO: Site to site transfer with phpMyAdmin and a FTP Client


Preparation:

1) Turn OFF Clean URL’s function

FTP Steps: (for downloading and uploading Drupal program files)


Going to assume you have one and know how to use an FTP Client. FileZilla is free and popular.
This is pretty easy stuff and you probably already know most of it. If you don’t know it. DO
ânotâ recommend transferring site, as first lesson with FTP’ing.

NOTE: Do not delete old site until you are 200% sure new site is ok.

1. Download all the Drupal program files from OLD site, to local Hard Drive, using FTP
program. (Don’t worry about mySQL files yet)

2.

3. Be sure to get .htaccess too (it’s a Hidden File that can be found by checking the View
Hidden Files Box on FTP Client.

4.

5. Edit settings.php and cron scripts to reflect new site.

6.

7. FTP files to new site

phpMyAdmin Steps: (for mySQL export and import)


We’re going to assume you know how to use phpMyAdmin for the basic stuff. This is pretty
easy stuff and you probably already know most of it. If you don’t know it. I would ânotâ
recommend transferring my site, as my first lesson with phpMyAdmin

NOTE: Do not delete old site until you are 200% sure new site is ok.

Export:

1. Find database in phpMyAdmin

2.

3. Click the Export Tab (we’re going to do a dump of data to local hard drive)

4.

5. In the âExportâ box â check âselect allâ and be sure the radio button is checked for SQL

6.

80
3 Aug 2007 Drupal Handbook

7. Check the âStructureâ and âDataâ boxes

8. (this ensures that both the structure of the database and the tables, and the content you have
on site - is with you!)

Check âdrop tableâ (so that if the new site is installed already, you can install database on
top of that. "drop table" simply ensures that if the table exists - it will be replaced by the one
you backed up.)

Check âcomplete insertsâ ( to make sure it does not miss anything when rebuilding the site )

Check âSendâ box (this makes the data go to a file instead of the screen)

You can modify the File Name if you wish. (don’t recommend deleting anything that might
be in the file name box already â just add something to it. I usually add MonthDay â Mar09)

You can check âcompressionâ if you so desire.

Click the âGOâ button and you will soon see a pop-up asking you where to save file.

Importing: (with phpMyAdmin)

1. Find NEW database with phpMyAdmin

2.

3. Click the tab SQL (just like when you are adding a module)

4.

5. Go to the âOr Location of the text file:â (just like you would for adding a module)

6.

7. âBrowseâ to local hard drive and find file.

8.

9. Click âGOâ

81
Drupal Handbook 3 Aug 2007

10.

11. It’s going to take a few minutes for everything to come over.

Final process:

1. Check new site and I do mean check everything, until you’re bored

2.

3. Since I usually do this stuff at night. I check everything that night and then I check once
more in the morning. !Checking data is a lot faster than repairing or re-entering data :-)

4.

5. Turn Clean URL’s back on

Problems you might encounter

with phpMyAdmin

1. phpMyAdmin has some limitations on the size of file that can be transferred. My Host
has it set to 10Mb, others might be lower or higher limits. If file is bigger than limits you
have to make some choices.
2. You can save the file as âcompressedâ (but you might time out on the upload)
3. You can âEmptyâ (NOT DROP) a few of tables. Below are some the tables you might
want to think about cleaning up before you make data dump. (Not in any order.)
a. Aggregator Items (the data from news feeds)
b. Accesslog
c. Cache
d. Watchdog
e. Search_Index

with FTP (still working on this section)

NOTES:

1. If you run cron make sure to change this also in /scripts/cron-lynx.sh - so it points to
cron at new site.

Import a MySQL data dump with BigDump


What is BigDump?

Importing large SQL dumps (when replicating or moving a database) can be difficult for those
with only web access to the MySQL server. phpMyAdmin has certain shortcomings when
importing files of more than a modest size. BigDump can be a helpful utility in such cases. From
the BigDump website:

82
3 Aug 2007 Drupal Handbook

Staggered import of large and very large MySQL Dumps (like phpMyAdmin 2.x Dumps)
even through the web-servers with hard runtime limit and those in safe mode. The script
executes only a small part of the huge dump and restarts itself. The next session starts
where the last was stopped.

Setting up BigDump

Download BigDump from http://www.ozerov.de/bigdump.php. Once downloaded you need


to open the file bigdump.php in any simple text editor (or php editor) to modify the variables
required for your server and database.

Commencing at line 78 with "// Database configuration" you need to setup the usual variables
to connect to your database (same as are required for Drupal). There is one extra piece of
information which the script needs to work well and that is the name of the sql file to be used to
setup the database.
Tip: Make sure you upload the file containing the SQL export of your database and
bigdump.php to the same directory (root is best) on your webserver.

<?php
// Database configuration
$db_server = "localhost";
$db_name = "your_DB_name";
$db_username = "your_DB_user_name";
$db_password = "your_DB_password";
// Other Settings
// Specify the dump filename to suppress the file selection dialog
$filename = "the_file_you_wish_to_execute";
// Lines to be executed per one import session
$linespersession = 3000;
// You can specify a sleep time in milliseconds after each session
// Works only if JavaScript is activated. Use to reduce server overrun
$delaypersession = 0;
?>

Save the file once you have set the above (best in the same folder as your sql file backup).

Uploading the sql file and bigdump.php to the webserver

Open your FTP program and open a new session connecting to your webserver root directory
and the folder where the sql file and prepared bigdump.php reside on your computer.

Upload both files in ASC11 mode to the webserver root directory.

83
Drupal Handbook 3 Aug 2007

Running BigDump

Once the files are uploaded you simply need to connect to the bigdump.php script by using the
URL
http://www.your_domain.com/bigdump.php

If successfully connected bigdump will greet you with a screen like the below.

BigDump: Staggered MySQL Dump Importer ver. 0.21b


<a>Start Import</a> from "the_file_you_wish_to_execute.sql" into
"your_DB_name" at "localhost"
© 2003-2005 Alexey Ozerov - BigDump Home

If it all looks good (ie: all the relavent names are correct) then click "Start Import" and the
database will be setup by running in short automated stages to prevent server timeouts.

At the completion BigDump will notify you that it is finished.

That’s it! You have now copied, moved, migrated, synchronized or duplicated your mySQL
database. Well Done!

Thanks go to markus_petrux for the original tip about BigDump

Installing Drupal behind an Actiontec GT701-WG router


The popular Actiontec GT701-WG (and possibly other routers) DSL modem/router has a
peculiar behavior that affects how base_url must be set up in
sites/default/settings.php. The solution is to replace the PHP code that sets base_url
with some code that is available below.

Here’s the scenario: you are using computer A to access and use your Drupal site, computer B is
the server that is hosting the Drupal site, and both computers are plugged into a GT701 router,
which in turn is linked to the Internet. Internet users can access your server from the outside by
typing in www.example.com (because you set up port forwarding on the GT701). However, the
GT701 will not allow you to type that address in from computer A, because the GT701 interprets
such an action as a request to view the GT701’a administrative interface. Instead, you must type
in the local network IP address (usually 192.168.0.xxx) of computer B to access and use your
Drupal site.

However, this causes a problem because base_url is used by Drupal to create all the site’s
links. If base_url is set for www.example.com, you will be unable to use the site from computer
A (even if you type in the local IP). If base_url is set for the local network IP address, Internet
users will not be able to use the site.

In other words, base_url has to be different for internal network users (computer A) and
Internet users. To do this, replace the line $base_url = "http://www.example.com";
with the following PHP code:

84
3 Aug 2007 Drupal Handbook

<?php
$ipaddress = getenv(REMOTE_ADDR);
$local= strpos($ipaddress, ’192.168.’);
if ( $local=== false ) {
$base_url = "http://www.yourdomain.com";
} else {
$base_url = "local network IP address";
}
?>

Here, replace www.example.com with the actual URL and local network IP address with the
proper IP address (something like 192.168.xxx.xxx). It is possible that your local network IP
addresses do not begin with 192.168; in that case, you would need to change the code to look for
the local IP range accordingly.

With this setup, you can access the Drupal site using computer A by typing in Computer B’s
local IP address in your browser, while Internet users can continue to access it by typing in
www.example.com

Installing Drupal in a subdirectory in 4.6


If you install Drupal in a subdirectory, you need to alter the .htaccess file in Drupal’s root.

Change ErrorDocument to:

# Customized server error messages:


ErrorDocument 404 /subdirectory/index.php

Change RewriteBase to:

# Modify the RewriteBase if you are using Drupal in a subdirectory


and the
# rewrite rules are not working properly:
RewriteBase /subdirectory
Remove any #’s in front of the RewriteBase line in case it’s commented out.

Make sure your $base_url in conf.php is set correctly as well.

More than one Drupal site on one machine


There are several possible configurations for running multiple Drupal servers on the same
hardware. You can separate them by directories or by vhosts, they can share configurations or
split them or, in some cases, have a mixture, but all of these methods have at their heart the
./sites/domain_or_host_name/settings.php configuration file and the
search-sequence where the Drupal program will search first for a configuration named for the
current page and then to the current host before settling for the default.

85
Drupal Handbook 3 Aug 2007

General rules for multiple Drupal deployments

Each of the possible multi-drupal scenarios is discussed in more detail in the sections that
follow, but the general form for the alternate configuration filename is:

./sites/<i>vhost.uri</i>/settings.php

Note how the path separator (’/’) must be changed to a dot. As an example, the vhost
drupal.mysite.net may have one primary drupal server at the DOCUMENT_ROOT location,
but a second site may begin at DOCUMENT_ROOT/altserver. For this case, the configuration
file would be ./sites/drupal.mysite.net.altserver/settings.php

Within that configuration file, the most common and minimal option is to set the $db_url that
specifies the host, database and login for the Drupal tables, as well as the $base_url. But you can
also include assignments to override anything in the VARIABLES table. This allows you to
redefine the theme, the site footer and contact email, blocks per-page limits, even the name you
use for anonymous.

Drupal IDs: When using multiple drupal servers on the same hardware, each new configuration
will result in a new host component for the username@<i>host</i> Drupal login ID (used
when logging into a foreign Drupal server). For example, if you have a directory partitioned
host at drupal.mysite.net/altserver your usename to login to some other Drupal server
would be USENAME@drupal.mysite.net/altserver.

Prefixing Database Tables to put them in One Database If you only have one database then it
is necessary to use database table prefixing. See this handbook page for details on how to
achieve that.

Moving your Drupal installation to a new directory


If for instance you need to move your installation from www.mysite.com/development/ to the
root directory of www.mysite.com, just follow these simple steps:

Copy Files

Copy the files of your Drupal installation from the old directory to your new directory.
Make sure you include .htaccess.

Change Path

In your new directory, open the file (4.5 or earlier) includes/conf.php or (4.6)
sites/default/settings.php

Look for a line that begins with "$base_url = ", update this so that $base_url equals the path
to your new directory. Save the file and close it.

86
3 Aug 2007 Drupal Handbook

You might need to modify the .htaccess file as well.

Update Cron

If you set up Cron on your old installation, make sure you update it to point to your new
installation.

Delete Old Directory

Test that everything is working in your new installation. If so, it is now safe to delete the
files in your old Drupal directory.

PCRE_UTF8 solution for VPS servers | FreeBSD


installation PROBLEMS? - PCRE_UTF8 support on VPS server accounts? Look here!
I receive the same error on every page with a basic install however everything seems to be
functioning otherwise fine.

warning: preg_match(): Compilation failed: this version of PCRE is not


compiled with PCRE_UTF8 support at offset 0 in
/home/brandform/www/drupal.brandform.net/includes/unicode.inc on line
32.

The solution was much more difficult to find than i had hoped so maybe this post will be
useful to some others as well.
I had to uninstall the pcre package and reinstall the proper one with utf-8.
heres the procedure:

login to server via shell,


on VPS2 accounts,
# su root
then type password
basically you want to be root user.
then type:
# pkg_info
which will show you the installed packages.
type:
# pkg_delete pcre-6.4
for me it was 6.4 but yours may be different. make sure to enter the proper version of pcre
displayed in pkg_info.
then you want to change to the directory where your ports collection is.
on FreeBSD it is:
/ports/devel/pcre-utf8
so type into your shell prompt:

# cd /
# cd ports/devel/pcre-utf8
# make

87
Drupal Handbook 3 Aug 2007

# make install
# make clean
then youll want to restart the apache server...
something like this:
# restart_apache

thats it...
fixed everything for me.
after over a day of pulling my hair out and almost abandoning the effort......

Known causes of PCRE server errors

In the event that you see the following error:

warning: preg_match: internal pcre_fullinfo() error -3 in


/SERVER_PATH/includes/common.inc on line 592.

Be aware that this issue exists at the server level, outside of Drupal code. Put plainly, the error
means that the server’s PCRE (Perl Compatible Regular Expression) library is not configured
correctly.

This error may be caused any time a Drupal module calls a PCRE function. Typically, the error
appears within common.inc, but this is not always the case.

Depending on the server environment, there are several different causes (including a reported
bug in some versions of PHP 5).

This manual page is designed to capture known instances of this bug,

Known Causes

An upgrade of RedHat included a bad library and required a patch. (Details to follow)

Recommendations

Send the content of the error to your system admin and have them debug your PHP’s PCRE
module.

Redirecting specific pages to new URLs (301 redirects in Drupal)


If you are porting over an existing website to Drupal, one consideration is how you redirect the
old page URLs to the appropriate pages on the Drupal version of the site. If you don’t want to
create custom rewrite paths within Drupal for those nodes -- or perhaps cannot due to clean
URLs or filename suffixes -- then 301 redirects are considered the best way to handle redirected
pages, for they inform search engines to update their databases with the new paths. This way,
you should not risk your search engine pagerank or lose site visitors with 404 "not found"
errors.

88
3 Aug 2007 Drupal Handbook

However, 301 redirects cannot be done using the common approach. Yet establishing 301
redirects is quite easy, provided you have mod_rewrite enabled in your .htaccess file.

How to create 301 redirects in Drupal Apache mod_rewrite

Edit your .htaccess file in a text editor. [Note: Be sure to save the file in "UTF-8" format.]

In the file, you will find the commands:

# Various rewrite rules.


<IfModule mod_rewrite.c>
RewriteEngine on
# Modify the RewriteBase if you are using Drupal in a subdirectory
and
# the rewrite rules are not working properly.
#RewriteBase /drupal
RewriteBase /

Immediately after that code -- and before the Drupal-provided "Rewrite old-style URLs"
commands -- add your rewrite rules using the following format:

#custom redirects
RewriteRule ^old/URL/path$ http://yourdomain.com/new/path [R=301,L]
#end custom redirects

Note the convention: The old path is simply the path off the root. The new path is the full path,
including the domain. The [R=301,L] code is the 301 redirect instruction. (axbom notes: "The 301
tells browsers and spiders it is a permanent redirect, and the L ensures that no other rewrites are processed
on the URL before it reaches Drupal; Hence place this code above Drupal ’s own URL rewrite, but below
the command RewriteEngine on.")

If you have more paths to add, insert the rewrite commands as their own line as above.

For more information, see the forum thread at http://drupal.org/node/16084 [from where I
drew this information]

The tolerant base URL


Note: 4.7 already has this feature built in

Instead of using a hard coded domain as your $base_url in the settings.php file, you might want
to use

<?php
$base_url = ’http’ . (isset($_SERVER[’HTTPS’]) ? $_SERVER[’HTTPS’] ==
’on’ ? ’s’ : ’’ : ’’);
$base_url .= ’://’ .$_SERVER[’HTTP_HOST’];
if ($dir = trim(dirname($_SERVER[’SCRIPT_NAME’]), ’\,/’)) {

89
Drupal Handbook 3 Aug 2007

$base_url .= "/$dir";
}
?>

This has the advantage that whatever domain the user used to get to the site, he will maintain
throughout his session.

Warning

Email notifcations may be issued under the domain which is used by the poster. If you
access your site using http://localhost, you could send emails with that invalid URL. The
only module which behaves this way today that I know of is subscription.module from
Contrib.

Using .htaccess to stop page caching


If your Drupal site is being accessed on a LAN with a proxy server to cache pages, you may find
that user identities become confused. A user may login under their username, but when they
access another page, the proxy server sends the cached page of another user, effectively
switching the identities of the user as far as Drupal is concerned.

Proxy servers can be instructed to stop caching pages for a Drupal site using HTML Meta Tags
and/or HTTP Headers. While using meta tags may be more convenient (one need only modify
the theme header), some proxy servers only respond to instructions embedeed in the HTTP
headers sent by the webserver. Apache webservers can use mod_expires to send this instruction.
Assuming that mod_expires is enabled on your web server, try adding the following lines to
your .htaccess file to stop the proxy server from caching Drupal pages:

ExpiresActive on
ExpiresDefault "access plus 0 seconds"

Linux specific guidelines


Installing PHP, MySQL and Apache under Linux
Installing MySQL shouldn’t be too much of a burden, when using a Linux distribution that can
handle RPMs. All you have to do is grab the RPMs from the MySQL website. Please do note that
you’ll also need the MySQL client RPM, not only the MySQL server one. Once MySQL has been
installed, download Apache and PHP, and unpack them in the same directory. To install Apache
together with PHP and MySQL, follow the "quick install"-instructions in the INSTALL-file
located in your PHP directory. When configuring PHP do not forget to replace ’apache_1.3.x’
with your version of Apache.

After the compilation process you have to set the DocumentRoot in Apache’s httpd.conf to the
path of your drupal-directory. Make sure your Apache is setup to allow .htaccess files so drupal
can override Apache options from within the drupal directories. Therefore, set AllowOverride to
"All" instead of "None". Somewhat down httpd.conf they ask you to set Directory to whatever

90
3 Aug 2007 Drupal Handbook

you set DocumentRoot to. The last thing to do is to add index.php in IfModule mod_dir.c behind
DirectoryIndex. Apache will then look for index.php in the DocumentRoot and will display it as
its main page.

XAMPP for Linux Packages


The distribution for Linux systems (tested for SuSE, RedHat, Mandrake and Debian)
contains: Apache, MySQL, PHP & PEAR, Perl,ProFTPD, phpMyAdmin, OpenSSL, GD,
Freetype2, libjpeg, libpng, gdbm, zlib, expat, Sablotron, libxml, Ming, Webalizer, pdf class,
ncurses, mod_perl, FreeTDS, gettext, mcrypt, mhash, eAccelerator, SQLite and IMAP
C-Client.

Installing XAMPP in Debian

Download XAMPP Latest version from the following link

http://sourceforge.net/project/showfiles.php?group_id=61776&package_id=6...

At the time of writing this article XAMPP version is 1.5.3a

#wget http://kent.dl.sourceforge.net/sourceforge/xampp/xampp-linux-1.5.3a.tar....

Now you should be having xampp-linux-1.5.3a.tar.gz file in your downloaded location

Go to a Linux shell and login as root:

$su -

Extract the downloaded archive file to /opt

#tar xvfz xampp-linux-1.5.3a.tar.gz -C /opt

XAMPP is now installed below the /opt/lampp directory.

Start XAMPP Server

To start XAMPP simply call this command:

#/opt/lampp/lampp start
Starting XAMPP for Linux 1.5.3a...
XAMPP: Starting Apache with SSL (and PHP5)...
XAMPP: Starting MySQL...
XAMPP: Starting ProFTPD...
XAMPP for Linux started.

Test Your XAMPP Installation

91
Drupal Handbook 3 Aug 2007

OK, that was easy but how can you check that everything really works? Just type in the
following URL at your favourite web browser:

http://localhost

XAMPP Security Configuration

As mentioned before, XAMPP is not meant for production use but only for developers in a
development environment. The way XAMPP is configured is to be open as possible and
allowing the developer anything he/she wants. For development environments this is great but
in a production environment it could be fatal.

Here a list of missing security in XAMPP:

The MySQL administrator (root) has no password.

The MySQL daemon is accessible via network.

ProFTPD uses the password "lampp" for user "nobody".

PhpMyAdmin is accessible via network.

Examples are accessible via network.

MySQL and Apache running under the same user (nobody).

To fix most of the security weaknesses simply call the following command:

#/opt/lampp/lampp security

It starts a small security check and makes your XAMPP installation more secure.

Start And Stop Server Services

start

Starts XAMPP.

stop

Stops XAMPP.

restart

Stops and starts XAMPP.

startapache

92
3 Aug 2007 Drupal Handbook

Starts only the Apache.

startssl

Starts the Apache SSL support. This command activates the SSL support permanently, e.g. if you
restarts XAMPP in the future SSL will stay activated.

startmysql

Starts only the MySQL database.

startftp

Starts the ProFTPD server. Via FTP you can upload files for your web server (user "nobody",
password "lampp"). This command activates the ProFTPD permanently, e.g. if you restarts
XAMPP in the future FTP will stay activated.

stopapache

Stops the Apache.

stopssl

Stops the Apache SSL support. This command deactivates the SSL support permanently, e.g. if
you restarts XAMPP in the future SSL will stay deactivated.

stopmysql

Stops the MySQL database.

stopftp

Stops the ProFTPD server. This command deactivates the ProFTPD permanently, e.g. if you
restarts XAMPP in the future FTP will stay deactivated.

security

Starts a small security check programm.

For example: To start Apache with SSL support simply type in the following command (as root):

#/opt/lampp/lampp startssl

You can also access your Apache server via SSL under https://localhost.

Important Configuration Files And Directories

opt/lampp/bin/ - The XAMPP commands home. /opt/lampp/bin/mysql calls for example the
MySQL monitor.

93
Drupal Handbook 3 Aug 2007

/opt/lampp/htdocs/ - The Apache DocumentRoot directory.

/opt/lampp/etc/httpd.conf - The Apache configuration file.

/opt/lampp/etc/my.cnf - The MySQL configuration file.

/opt/lampp/etc/php.ini - The PHP configuration file.

/opt/lampp/etc/proftpd.conf - The ProFTPD configuration file. (since 0.9.5)

/opt/lampp/phpmyadmin/config.inc.php - The phpMyAdmin configuration file.

If you want to confiure apache2 you have to use /opt/lampp/etc/httpd.conf(If you want to
change Apache DocumentRoot directory you can chage in this file).If you want to configure
namebased and ip based virtual hosts check here

If you want to configure proftpd check here

If you want to configure mysql check here

Stopping XAMPP

To stop XAMPP simply call this command:

#/opt/lampp/lampp stop

You should now see:

Stopping LAMPP 1.5.3a...


LAMPP: Stopping Apache...
LAMPP: Stopping MySQL...
LAMPP: Stopping ProFTPD...
LAMPP stopped.

And XAMPP for Linux is stopped.

Uninstall XAMPP From your Machine

To uninstall XAMPP just type in this command

#rm -rf /opt/lampp

Windows-specific guidelines
Several packages exist which install Apache, PHP, and MySQL in one easy download. These
include the following:

94
3 Aug 2007 Drupal Handbook

ApacheFriends XAMPP
Miniserver
Foxserv
PHPHome

If you want to install them separately, see the guidelines below.

How to install Drupal for newbies using FTP and phpMyAdmin


There are three things to do: upload the database, get drupal ready and change "/tmp" on your
drupal site.

Change "/tmp" on your drupal site.

1. Open a browser and go to your new drupal site, whatever its domain is.
2. Create a new user account. You enter a username and password and now you are the admin
for your new site.
Important: the first user you create has access to every administration setting on your
Drupal site.
3. On the left side of your screen, there is a link, "administer." Click "administer," then
"settings."
4. Scroll down to "File system settings" and in the "Temporary directory" field you will see
"/tmp." Remove the "/" from in front of "tmp." So now in "Temporary directory" the field
should only contain "tmp." Click "Save configuration," at the bottom of the screen.

Get Drupal ready

1. Download Drupal
2. Extract Drupal to your desktop (or wherever you like on your computer). You need to have
a program like 7-zip or Winzip installed first. You will have to extract the files twice.
3. Edit conf.php. It’s in the drupal-4.5.2/includes directory after you extract the files. You have
to edit two lines in this file.
4.
To edit the file, you may need to load your text editor (Windows comes with Notepad
and Wordpad, either of which will do fine) first then find the file by clicking the File
menu, then Open.
5. Change: $db_url = "mysql://user:password@localhost/drupal";
You must replace "user" and "password" with your username and password for your
phpMyAdmin login and "drupal" with your database’s name.
6. Change: $base_url = "http://www.example.com";
You must replace "example.com" with your domain name.
7. Put drupal on your server. You need an FTP program like FileZilla.
Open your FTP program and navigate to the directory where your index.htm file
would normally go. This is usually called public_html/ or www/ This is where you
put the drupal files. The drupal files that go there are the contents of drupal-4.5.2, that
you extracted. You don’t put the folder itself on the server, just the contents. That

95
Drupal Handbook 3 Aug 2007

means you are uploading six folders (database, includes, etc.) and ten files (.htaaccess,
cron.php, etc.).
8. Create a new directory on your server.
In your FTP program, right click on the server side, select "create directory" and name
the new directory "files." You want "files" in the main directory. After you create it, you
should see it in between "database" and "includes."
9. Now you open up your new directory, "files," and create a new directory inside called,
"tmp."
10. Change the file attributes of both "files" and "tmp" by right clicking on them one at a time,
selecting "file attributes" and entering "755" in the "numeric value" field (if you see errors on
your drupal site later saying "files" and "tmp" are not writeable you have to change the file
attributes to "777," which is less secure).

Upload the database

1. Login to your phpMyAdmin (on your server).


2. Click "Create new database."
3.
- name it "drupal" (or whatever you like).
4. You should see "drupal" at the top of the left column. Click "drupal."
5. In the center column you should see some tabs to choose from. Click "SQL."
6. At the bottom of the box that comes up it says, "Location of the textfile:" and there’s a button
that says, "Browse". Click "Browse" and navigate to the file "database.mysql." Its on your
computer inside the folder you extracted, "drupal.4.5.2," inside the "database" folder. Select
"database.mysql" and click "open."

HOWTO: Create an apache sandbox using Windows and


Apache2Triad
One of the most useful and productive techniques for working with Drupal is to install it on
your own computer. Having Drupal installed on your local computer allows you to rapidly
prototype Drupal sites using any combination of contributed modules and themes, dry-run
upgrade installations of Drupal without interrupting production sites, and perform any other
Drupal task much more quickly by allowing you to work locally instead of remotely. This
tutorial addresses a simple method of setting up a web server on your own computer that
functions identically to many commercial web hosting services, however it is not intended as a
tutorial for turning your computer into a web server or using it to host a site. This tutorial
focuses on installing the web server software as a means of working on a copy or prototype
Drupal site, i.e. the result is not part of the internet, and can’t be accessed from the internet. The
advantage is that the software runs much faster on your own computer.

While Drupal will work with Microsoft’s Internet Information Services (IIS), this tutorial will
focus on a specific package, apache2triad, available for download from sourceforge.net. Though
all that is needed to run Drupal is a web browser, apache, PHP4 (4.3.3) or higher and mySQL,
apache2triad comes with a variety of other features that will not be covered in this tutorial.

96
3 Aug 2007 Drupal Handbook

Best of all, however, apache2triad requires no additional configuration in order to set up and
install Drupal, making it an ideal choice for novice web site creators wishing to learn to set up
and use a Drupal site with only very modest skills and almost no previous experience.

Tools needed to complete this tutorial:


A web browser.
An archive program capable of extracting .tar and .gz files, such as 7-Zip.
An FTP client like coreFTP (optional).

Before you begin

Apache2Triad comes in three different configurations; a legacy version for Windows 9x systems,
and PHP4 and PHP5 versions for Windows XP. If you intend to work on a copy of Drupal that
you plan to transfer to a production server provided by your web hosting service, you may wish
to find out which versions of PHP and MySQL are installed. If your web hosting service is
currently providing PHP/MySQL 4.x, you may wish to download the corresponding version of
Apache2Triad, in order to avoid compatibility issues. If so, you may also wish to inquire your
hosts’ timetable for upgrading PHP and MySQL since 4.x versions are no longer supported by
their respective development teams.

As of this writing, the following versions of Apache2Triad were available for download from
Sourceforge:

Edge (Apache2.2 PHP5 MySQL5) v1.5.4 95.8MB space required 348.7MB


Stable (Apache2.0 PHP4 MySQL4) v1.4.4 75.3MB (somewhere between "edge" and "legacy")
Legacy for Win9X (limited Apache2.0 PHP4 MySQL4) v1.2.3 48.0MB space required 200.3MB

While each version of Apache2Triad shown has been tested with various versions of Drupal in
recent years, this tutorial focuses on using the "edge" version as installed under Windows XP.

Installing Apache2Triad

1) Download the version of Apache2Triad that best suits your needs.


2) Double-click the icon from the file you downloaded. This opens a small configuration window
to begin the Apache2Triad installation. Leave the default settings as they are and click the button
labeled "next".
3) The next dialog window allows you to set the destination folder, which for most people will
be "C:\apache2triad", but it works equally well installed wherever you like (provided there is
room available, see space requirements above). It is recommended that Apache2Triad be
installed at the "root level" of the drive chosen, for example, "C:\apache2triad" as opposed to
"C:\Program Files\apache2triad\", as this will save you typing later on.
4) The next dialog asks you to set a password of no less than eight characters. It will be
important to know this password as you will need it later on. Select an eight character password
(ideally one easily remembered), write it down, then click the button labeled "next", then the
button labeled "I Agree" on the following dialog to complete the license agreement and begin the
installation.
5) After the files have been installed to the directory of your choice, a dialog will open that alerts
you that post configuration is needed. Click the button labeled "OK" to continue. Several

97
Drupal Handbook 3 Aug 2007

windows will open and close as the installer automatically configures most options for you,
eventually stopping at a CMD window asking you to type your password from step 4. Do so
now and press the "enter" key; post-configuration will complete itself, and at last open a window
requesting that you reboot, which is necessary to start apache, php and mysql as Windows
services.

Note that depending on how Windows is configured for your computer, you may notice that
there is now a "user" account named apache2triad; ignore this and log on with your regular
account.

Installing Drupal

1) Obtain a copy of Drupal 4.6x, 4.7.x or 5.0 (cvs) from drupal.org as well as any contributed
modules or themes you wish to use.
2) Use your archive program to extract any files from step 1; note that because the files are stored
in both .gz and .tar formats, it may be necessary to extract them twice. You may wish to create a
directory named DrupalX, where ’X’ is the version of Drupal, and unarchive your files to this
location in order to stay organized; by copying the files you wish to use instead of using the
originals, it is safe to move the archived versions to the recycle bin if you like.
3) Browse to the location you installed Apache2Triad and open it’s folder, then look for the
folder labeled "htdocs". This folder is where you will place your Drupal files in order to access
them through apache and your web browser. You may wish to place a shortcut to htdocs on
your desktop, or create a shortcut in a toolbar with bookmarks and other shortcuts to tools. See
the Support and Help Center under the Start Menu for details about how to accomplish these
tasks.
4) For purposes of this tutorial, Drupal was extracted to drupal-4.7.3 and drupal-cvs in order to
illustrate their installation. Note that the installation procedure for Drupal 4.6.9 is identical to the
one for Drupal 4.7.3. Note that in doing so, Drupal is being installed to a sub directory and
follows installation procedure accordingly. If Drupal were to be installed at the "document root"
level of the server, the files inside the drupal-x folder extracted themselves would be place in the
htdocs folder inside the Apache2Triad installation. In this tutorial, the whole folder is placed in
htdocs (for simpler organization) and this affects how Drupal will be configured in later steps.

Note that you may also use the folder name of your choice, such as the sub directory used on
your web hosting server, "sandbox" or anything else that makes sense for your project.

Copy the folder you have created (or the files inside it to htdocs, if you want to install to the
"document root") now.

5) Open your favorite web browser, select the text in the address bar and type:

http://localhost/phpmyadmin/

This will load the PHPMyAdmin logon page, which will ask for a username and password; the
username is "root" and the password is whatever you selected when Apache2Triad was
installed. Enter these now.
6) This will load the PHPMyAdmin main page. At this stage of this tutorial, it is useful to
provide a brief introduction to PHPMyAdmin, which is also discussed in the Drupal handbook

98
3 Aug 2007 Drupal Handbook

section How to install Drupal for newbies using FTP and phpMyAdmin. For intents and
purposes, PHPMyAdmin is a tool used to create, backup and restore MySQL databases.
Although it has considerably more sophisticated features, this tutorial focuses only on those
needed to complete a given task.
7) Select a database name and type it into the text field labeled "create database", then click the
button labeled "create". The next steps vary depending on whether 5.0 or 4.7.x or earlier is being
installed. If you are installing 5.0 from scratch, you may skip the next step. For purposes of this
tutorial, databases named drupal-4.7.3 and drupal-cvs were created (if creating multiple
databases, click the ’home’ button to the left of the PHPMyAdmin page to return to the database
creation page). Minimize your browser (we’ll come back to it, later) before moving on to the next
step.
8) Open your htdocs folder and look for the folder labeled "sites" if you installed Drupal to your
document root, or inside the Drupal folder you created earlier, if you are installing Drupal 4.7.x
or earlier. Here it is necessary to open the settings.php file and specify the installation options
described in the INSTALL.TXT file that came with Drupal. Note that if you require multiple
Drupal installations to use the same copy of Drupal, you should modify the settings.php file
according to your configuration requirements. For single-version Drupal sites, the settings.php
file you’ll want to use is in the folder labeled "default". Right-click the settings.php file with your
mouse, select "open with" from the context menu, and select "notepad" from the application list.

Depending on how you have Drupal configured, your settings.php file entries will vary,
however the entry:
$db_url = ’mysql://root:password@localhost/drupal-4.7.3’
will use "root" in place of the username and the password you selected when installing
Apache2Triad. Don’t forget to set the entry for $base_url if you did not install Drupal to
document root to the folder name you installed Drupal to. For example:
$base_url = ’http://localhost/drupal-4.7.3’; // NO trailing slash!

IMPORTANT
"localhost" must be substituted for "www.example.com" in order to work on your local machine.

For those working on copies of Drupal that will be hosted on production servers, it is handy to
keep two copies of your settings.php entries, one for local use and one for remote use. This way,
you can switch between configurations just by commenting or uncommenting the appropriate
lines, for example:

# Remote setting:
# $base_url = ’http://www.example.com/drupal-4.7.3’; // NO trailing
slash!
# Local setting:
$base_url = ’http://localhost/drupal-4.7.3’; // NO trailing slash!

Once your settings.php file’s entries are correct, restore your browser window and locate the
PHPMyAdmin page tab labeled "import" and click the button labeled "browse". For Drupal 4.7.x
and earlier, the database that will be imported will be in the database folder, which will be in
htdocs under the Apache2Triad installation you created earlier. Browse to that folder and select
the appropriate sql file: database.mysql for Drupal 4.6.x, database.4.0.mysql for Drupal 4.7.x and

99
Drupal Handbook 3 Aug 2007

MySQL4 (Apache2Triad "stable" installation), and database.4.1.mysql for PHP5. Note that it is a
good practice not to mix MySQL 4 and MySQL 5 databases in order to avoid potential
compatibility conflicts. Click the "Go" button on the MySQL database to import the database
you’ve selected.
9) The next step will depend on where you installed Drupal in your htdocs folder. Select the text
of your address bar in your web browser and type:
http://localhost/drupal-cvs/
substituting "drupal-cvs" for the folder name you used in htdocs or omitting it if you installed to
document root.

If you are installing Drupal 5.x, this will open the Database configuration page for your new site,
which will prompt you for a database name (the one you created with PHPMyAdmin earlier), a
username (root) and a password (the one you created when you installed Apache2Triad). Enter
these now: if your Drupal installation uses a database prefix, select the advanced option and
enter the prefix at this time. Select the appropriate radio button, depending on if you are
installing the MySQL or PGSQL version of the database (most likely MySQL). Click the "save
configuration" button and your installation is complete. You will be taken to the welcome screen
where you will create the first user logon for your new site.

Drupal 4.7.x users will be taken directly to the welcome page to create the first user logon
directly.

Importing and exporting Drupal databases updated with PHPMyAdmin

There are certain circumstances when you may wish to work on a site that is a copy of one
running on a production server, backup the database, and perform other tasks specific to
making changes to your databases. This section of the tutorial focuses on using PHPMyAdmin
to do so. If PHPMyAdmin is not available on your hosting provider’s server for you to use, you
may be able to install it yourself if it is unavailable; check with your hosting service to find out
what your options are if you are unsure.

Because any possible task is going to entail some permutation of exporting, copying and/or
importing databases from one a remote server to your personal computer, this section of our
tutorial focuses on two basic operations within PHPMyAdmin that have tabs labeled
accordingly; "import" and "export".

To export a database with PHPMyAdmin

1) Using your web browser, browse to the PHPMyAdmin location of the server where the
database you wish to export resides. For example:
http://www.example.com/phpmyadmin/
for a remote database and
http://localhost/phpmyadmin/
for a database hosted on your Apache2Triad installation. Select the name of the database you
wish to export from the combo box on the left side of the page and you will be taken to that
database’s main operations page. Next, click the tab labeled "Export" and you will be taken to
the Export database page.
2) Fill out the sections of the form located on the Export database page as follows:

100
3 Aug 2007 Drupal Handbook

a) Click the link marked "select all" in the group labeled "Export" to select all of the tables in the
database for export. The radio button selected below should be "SQL".
b) Select the check box labeled "add DROP TABLE" in the group labeled "Structure". The check
boxes labeled "Add AUTO_INCREMENT value"
and "Enclose table and field names with backquotes" should be selected as well as the checkbox
next to "Structure", leave them as they are if already selected or set if needed.

IMPORTANT
Selecting "add DROP TABLE" means that if the copy of the database created is later imported to
another Drupal installation, the tables in the imported copy will overwrite them if they exist in
the target database. You should be careful to keep track of your databases, and make sure you
only import and export the correct databases for your task.

c) Under the group labeled "Data" select the check box marked "Complete inserts". The checkbox
labeled "Use hexadecimal for binary fields" may be selected (select it if not) and the combo box
labeled "Export type:" should be set to "INSERT" (select if needed).
d) Put a check in the box in the "Save as file" group, then type a name for the database and click
the button labeled "Go". Note if a radio button other than "None" is enabled in the group
"compression". Uncompressed databases may be larger, but are sometimes easier to work with.
e) Select a location to save your database to (preferably something easy to remember, like the
database folder of your Drupal installation in htdocs, for example).

To import a database with PHPMyAdmin

1) Using your web browser, browse to the PHPMyAdmin location of the server where the
database you wish to import resides. For example:
http://www.example.com/phpmyadmin/
for a remote database and
http://localhost/phpmyadmin/
for a database hosted on your Apache2Triad installation. Here you will either need to select an
existing database name in the combo box on the left side of the PHPMyAdmin page, or create a
new one. Note that if you are setting up a database on a remotely hosted site, your host may
have prohibitions on the creation of MySQL databases that require they be created outside of
PHPMyAdmin by means of a control panel or other mechanism; check with your web hosting
service for specific details of their requirements.
2) One you have selected or created the appropriate database name, select the tab labeled
"Import" on the PHPMyAdmin page to be taken to the import page.
3) Find the control group in the Import page form labeled "Location of the text file" and click the
button labeled "Browse", following the resulting dialogs to select the database file of your choice.

IMPORTANT
If you are importing a database that you exported using the instructions in this tutorial,
remember, the tables of the imported database will overwrite any that exist in the database you
are importing to, overwriting them. Therefore it is important to double-check that the database
you are selecting and the target you are importing to are correct before proceeding. If uncertain,
you should back up the target database before importing a new one into it.

101
Drupal Handbook 3 Aug 2007

4) Click the button labeled "Go" to import your new database.

Using bigdump.php to deal with large databases

While bigdump.php is not included with Apache2Triad, it is a useful tool that greatly simplified
working with large databases and Drupal. Used correctly, it can greatly speed importing large
databases under Apache2Triad, and will also assist in importing large databases hosted on
remote servers where restrictions are placed on the size of databases that may be imported. This
is done by breaking up one big import operation into several small ones, reducing load on the
computer and avoiding import file size limitations.

1) Download a copy of bigdump.php, unzip the file, and open the file "bigdump.php" by right
clicking it with your mouse, selecting "Open with" from the context menu and then "Notepad"
from the list of applications.
2) Find the following section of the file:

// Database configuration

$db_server = ’localhost’;
$db_name = ’drupal’;
$db_username = ’root’;
$db_password = ’password’;

The entries should be as shown above, substituting the correct values depending on where the
database that is to be imported is located. Close this file and save a copy of it to your desktop or
somewhere it will be easily remembered.
3) If you are using bigdump to import a database into your Apache2Triad installation, you
should place a copy of the file you just edited in your htdocs folder along with a copy of the
database you intend to support. If you are importing the database to a remotely hosted Drupal
installation, you will need to transfer copies of the database and the bigdump.php file you
edited to your server.
4) Open your web browser, select the text in the address bar, and type:
http://localhost/path-to-my-drupal-folder/bigdump.php
if you are importing to Apache2Triad and
http://www.example.com/path-to-my-drupal-folder/bigdump.php
5) Bigdump.php should run unattended after it has run, and will inform you of it’s success when
the database has been completely installed.
6) If you are importing to a remote database, you should delete the bigdump.php file for security
purposes with your ftp program or other utility as suggested in the bigdump.php
documentation, and you may wish to remove the old database at this time as well, to free up
server space.

Installing Apache (with PHP) on Windows


As of this writing, the current version of Apache is 2.2.4 and PHP is 5.2.2.

102
3 Aug 2007 Drupal Handbook

1. Download the Apache Windows MSI Installer from Apache.org


2. Download the PHP Windows Zip Package from PHP.net.

The first step to getting Drupal running on your Windows machine is to set up the Apache web
server by running the Apache MSI installer. The following steps will walk you through the
installation:

1. Select Next
2. Select "I accept the terms in the license agreement"
3. Select Next
4. Fill in your server information if it is known. A typical setup will use the "for All Users, on
Port 80, as a Service" option. If this is being setup as a test machine, you may use localhost
as the Network Domain and the Server Name. Select Next.
5. Select the Typical Setup
6. Choose a Destination Folder for the Installer to place the program files into. Note: the
default Apache Installer location is C:\Program Files\Apache Software
Foundation\Apache2.2. Because of the spaces in the directory name, using this folder may
cause cgi and php scripts to not find the paths correctly.
7. Select Finish
8. If a Firewall is enabled, make sure that port 80 is unblocked and open.
9. To test if the Apache server is running, open up http:\\localhost in a browser. A plain black
and white page should come up that reads "It Works!"

Configuring Apache:

1. Using a text editor such as Notepad, open the httpd.conf file. This file is found in the /conf
sub-directory under the directory that was set up during installation. Alternatively, a
shortcut may be found in the start menu under the Apache HTTP Server folder.
2. Note: Windows based systems uses backslashes \ and Unix based systems use slashes / for
paths. In the Apache configuration files, slashes / should be used in path names.
3. Change the DocumentRoot to point to the location of the root document folder. In the
default httpd.conf file, this is found on line 149 and if the defaults were used during the
installation, it would point to "C:/Program Files/Apache Software
Foundation/Apache2.2/htdocs".
Note: Wrapping the path name in quotes will escape out any spaces that are used.
4. Change the Directory path to match the one used in the previous step. This is found on line
177 of the default httpd.conf file.
5. Add to index.php to the DirectoryIndex. This is found on line 212 of the default httpd.conf
file.
6. Append the following lines to the end of the httpd.conf file:
LoadModule php5_module "c:/php/php5apache2_2.dll"
AddType application/x-httpd-php .php
PHPIniDir "C:/php"
7. Save and Close

103
Drupal Handbook 3 Aug 2007

Installing PHP:

1. Unzip the PHP files to C:\php


2. Copy c:\php\php-ini-recommended.ini and rename itc:\php\php.ini
3. Uncomment the Windows include_path on line 506
Note: In the PHP.ini file, semicolons are used to denote that something is commented out.
To uncomment a line, simply remove the semicolon.
4. Update the doc_rootto match the one that was set up in the httpd.conf file on line 513.
Note: The PHP INI files uses the Windows style backslash \ for path names.
5. Update the extension_diron line 520 to "C:\php\ext"
6. Uncomment php_gd2.dll extension on line 637.
7. Uncomment mysql.dll extension on line 651.
8. Update the sessions.save_pathto the Windows temporary files directory (i.e. C:\Temp).
9. The PHP directory needs to be added to the Path Environment Variables
1. Open the Control Panel
2. Open System > Advanced > Environment Variables
3. Append ;C:\php to the end of the Path System Variables list and Click OK.
10. Restart Apache
11. To test PHP on Apache, go to the root directory (i.e. C:\Program Files\Apache Software
Foundation\Apache2.2#92;htdocs) and create a new php file in it. In this file, use PHP’s
phpinfo() function to see the server’s configuration information. For example:
<html>
<body>
<?php phpinfo() ?>
</body>
</html>
Open this file in a browser (i.e. http:\\localhost\filename.htm).

Alternative Options: Bundled Packages

Apache2Triad
Apache Friends - XAMPP

Installing MySQL on Windows


1. After downloading the latest stable release version of MySQL, locate the setup.exe, and
execute it. When prompted choose custom install.
2. Choose a path to install it. I recommend keeping to the default, which is c:\mysql.
3. Select all components, and continue until done.
4. Go to the MySQL folder, and start winmysqladmin.exe
5. Choose a username and password for yourself.
6. In the console, click on the my.ini tab, and choose "create shortcut in startmenu" option.
7. In the my.ini tab, also chck that all the configurable options are correct in accordance to
your computer.
8. Close the admin console and restart it. If admin program runs with a green light, everything
fine.

104
3 Aug 2007 Drupal Handbook

Installing PHP4 on Windows


After obtaining the latest stable release of PHP, extract the archive to c:\php or something
similar.
Copy php.ini-optimized to php.ini

Make the following modifications:


Change include_path to ’’.’’
Change sendmail_from to ’’your@email.address’’
Change SMTP to ’your.smtp.mail.service’ If you don’t know your smtp server, use the
same configuration as your email client uses.
Change session.save_path to a temporary folder (’’drive:pathtotemp’’) and make sure
the temporary folder exists.
Change doc_root to your preferred work folder (’’drive:pathtofiles’’). Make sure it
exists and is the same folder your specified in the Apache setup procedure.
Set register_globals to equal "On"
Save the changes, and copy the php.ini file to your Windows directory.
Create a basic php file, for example test.php which contains the following:
<?PHP phpinfo(); ?>

and save it in your work folder.

Open your web browser, and type in: http://localhost/test.php. If you get the PHP
information page, then everything is set up correctly. If not, just go over the settings again
for PHP to make sure everything is ok.

Drupal 4.7 on Windows/IIS Requires PHP in ISAPI mode

When installing Drupal version 4.7 and later on Windows servers running IIS rather than
Apache, PHP must be run in ISAPI rather than CGI mode.

A relatively obscure bug in IIS discards PHP session information when the PHP script that sets
the session also redirects to another page. In Drupal 4.7 and later, the user login screen
automatically redirects to the home page on a successful login. The IIS bug is triggered,
preventing the new session data from being sent to the user’s browser, and making it impossible
for users to log in.

As the bug only affects IIS when PHP is running in CGI mode, switching to ISAPI mode will
solve the problem.

Installing PostgreSQL on Windows


Postgres is easily installed and administered on Windows. See PostgreSQL on Windows for the
options you have.

105
Drupal Handbook 3 Aug 2007

As of this writing, the apparently easiest choice for PostgreSQL on Windows is "UltraSQL
by PeerDirect" mentioned at above link. It is available from here. See the README file
enclosed in the download and Installing the PeerDirect PostgreSQL beta for Windows for
more instructions. After completing installation, the username for your DB is your windows
login name and there is no password.
You might want to install phpPgSQL in order to admin your database. It will save you
frustation at the command line. A more complete list of all known PostgreSQL GUI tools is
available at PostgreSQL GUI’s
Go ahead and create your database tables via phpPgSQL or via the command line as
described here.

Multiple Drupal Sites under Windows


One troublesome area in Drupal-on-Apache/Windows is multiple Drupal sites. Nowhere is this
documented as being possible to do using a single code base. The weakness is in the fact Drupal
uses symbolic links to point to the directory where Drupal’s code resides. In Linux, this is easy
by creating a symbolic link to Drupal’s root directory:

\Drupal\Site1 -> \Drupal


\Drupal\Site2 -> \Drupal
In Windows, this isn’t that easy. Shortcuts in Windows are not usable except when browsing the
file system. What not many people know, is that Windows DOES support symbolic links. What
Windows doesn’t have is a built in capability to build symbolic links. That’s where a 3rd party
utility is required. I use Junction by Sysinternals. Using the tool is similar to the ln command in
Linux.
c:\> junction.exe c:\drupal\Site c:\drupal
Will make a link to c:\drupal from c:\drupal\site

Using this, AND the directions located elsewhere on this site regarding the strutcure of the
drupal\sites directories, you can make an attempt at getting multiple drupal sites running under
Windows.

Running multiple sites on a local PC (localhost) from a single


codebase, using Windows
Here’s how to get mutltiple sites working on localhost using Windows XP. This should work
with Drupal 4.6.x and assumes that you have PHP, Apache, MySQL, phpMyAdmin and Drupal
all installed and working.

There are four stages to go through, but it’s not difficult:

1. Set up your databases, one for each website


2. Set up each website in Drupal
3. Edit the virtual host settings in Apache
4. Update the Windows hosts file

106
3 Aug 2007 Drupal Handbook

In the following example we will add a local site"http://testsite1" in addition to the default site.
We’ll assume Drupal is installed in c:/www (and that your web root is set to c:/www in the
apache confic file).

Databases
=========

Firstly we will set up a new database for ’testsite1’

1. Open your phpMyAdmin page

2. Type a name for your database in the ’create database’ textbox (’testsite1’ is as good as
anything) then click the create button. You should get a message to say your database is created.

3. Next we need to add the necessary tables. Click the ’sql’ tab, then use the browse option to
navigate to the ’includes’ folder of your Drupal installation, e.g. c:/www/drupal-4.6.3/includes.
Select the file ’database.mysql.inc’ then ’go’.

4. phpMyAdmin will run the script and install the necessary tables.

Drupal
======

1. Make a copy of the folder /sites/default and call it /sites/testsite1. i.e. you should now have
two folders in your sites folder, default and testsite1.

2. Open file sites/testsite1/settings.php using notepad. Edit the $db_url line to match the
database defined in the previous steps:

$db_url = "mysql://username:password@localhost/database";

where ’username’, ’password’, ’localhost’ and ’database’ are the


username, password, host and database name for your set up.

3. Set $base_url to match the address to your Drupal site:

$base_url = "http://testsite1";

4. Save the file.

Apache
======

1. Open the apache config file ’http.conf’ (it’s in the apache/conf folder in Apache 1. I think it
has moved somewhere else in Apache2)

2. Scroll to the end of the file, where you will find the virtual hosting setup. Assuming your
websites are all located in the folder c:/www then add the following lines (edit the paths as
necessary)

107
Drupal Handbook 3 Aug 2007

NameVirtualHost 127.0.0.1:80
<VirtualHost 127.0.0.1:80>
DocumentRoot "C:/www/"
ServerName localhost
</VirtualHost>
<VirtualHost testsite1>
DocumentRoot "C:/www/Drupal-4.6.3"
ServerName testsite1
</VirtualHost>

There are lots of other things you can add into your VHost settings - see the Apache
documentation.

Windows
=======

We now need to tell Windows that the domain ’testsite1’ is hosted locally, i.e. not to look on the
Internet for it. Open the ’hosts’ file with notepad. It can usually be found in
c:/windows/system32/drivers/etc

Edit the end of the file to read:

127.0.0.1 localhost
127.0.0.1 testsite1

Save the file.

Apache, again
=========

OK, that’s (almost) it. All that is left is to restart the Apache webserver. You could reboot your
computer but a better way is to open a command prompt window (a DOS window as we used
to call it) and type ’net stop apache’. When the service has stopped, restart it using ’net start
apache’

Now when you open your favourite browser and enter ’http://testsite1’ you should see your
shiny new Drupal site, just waiting to be customised.

You can add as many sites as you need by following the process above.

Untar
When you download Drupal packages you will need to decompress the files. Drupal packages
are double compressed ’tar’ and ’gz’. To untar packages in Windows several programs are
recommended.

108
3 Aug 2007 Drupal Handbook

7zip
Winzip
Winrar
Winace

Installing Drupal on Windows


[this page used to contain verbose windows installation guidelines. they got removed because
they were a) just a copy of the general installation guidelines, b) misleading ("start by extracting
the archive to the PHP working folder"), and c) we don’t want to maintain redundant
documentation. this page should only contain windows specific guidelines that differ significantly
from the general guidelines. preferably, latter would be put so generally that we don’t need
anything here (eg. don’t rely on "wget" and "tar" etc.)]

PostgreSQL specific guidelines


1. Create a PostgreSQL database for your site. createdb -U <i>username</i> -W
<i>dbname</i>where username is the owner of the database (this user must have
permission to create databases) and dbname is the name of your database. You will be
prompted for that user’s password. On success, the following is displayed:
CREATE DATABASE
.
The user must also have the correct PSQL Grant privileges to use the database correctly.
2. Once you have a proper database, dump the required tables into your database:
psql -U username -W dbname < database/database.pgsqlYou will be
prompted for your database password. You should see a progress report as the tables are
created. All has gone well if there are no lines marked "Error:" printed to the screen.
3. Set the database options in includes/conf.php so Drupal can access the database you have
created. Edit
the following line in includes/conf.php:
$db_url = "pgsql://username:password@hostname/dbname";

ERROR: DB connect failed


You may need to update pg_hba.conf file, to support access for loopback connections:

host drupal drupal 127.0.0.1 255.255.255.255 password

When getting this type of error, it may help to look into apache error log. Postgresql 7.3.4 does
not enable tcp/ip sockets per default, so you have to either enable it by uncommenting:

tcpip_socket = true
port = 5432

109
Drupal Handbook 3 Aug 2007

in postgresql.conf, which may not be a good solution for security concerned people, or enable
unix domain sockets:

$db_url = "pgsql://admin:password@unix(/tmp)/drupal"

/tmp works on a slackware 9.0 Linux 2.4.21, no commas needed.

ERROR: language "plpgsql" does not exist


If you get an error about plpgsql being an invalid language, you just need to install by running
the following at the command line:

createlang plpgsql drupal

(substitute your database name for "drupal")

Then go back and rerun the final part of the database.pgsql file - where the "greatest" function is
created.

ERROR: null value in column "uid" violates not-null constraint


Try the following to fix:

psql -U drupalDbOwner -d drupalDbName -ec "alter table sessions alter


uid set default 0;"

PostgreSQL support in Drupal 4.7.x


The PostgreSQL support in Drupal 4.7.x has improved dramatically. This page lists remarks and
points to remember when installing and using Drupal 4.7.x with PostgreSQL database.

The installation instructions, specific for PostgreSQL, are in INSTALL.pgsql.txt file


PL/pgSQL is no longer required for Drupal working
You should not use schema as a $db_prefix. For example, use foo_, but not foo.. If you
use schema prefix, you will run into errors when upgrading to the next stable release (e.g.
from 4.7.x to 4.8.x). The errors are easy to fix, but it’s impossibile to support both foo_ and
foo. type prefixes

Drupal 4.5 and PGSQL 8 configuration


The exact order of commands I used to get drupal working on PostgreSQL 8.0.0 beta[345].

Differences to the (excellent) supplied documentation:

Create the db user first


createdb -O instead of -U. This sets the owner of the new database to the user, but that
user need not have create database permissions.
Remember the createlang command as pointed out (thank goodness!) by another user

110
3 Aug 2007 Drupal Handbook

psql expects -U instead of -u. Use -f to load the file.

1) Create a new database user (I used "drupal").

As the postgres user:

postgres$ createuser --pwprompt


Enter name of user to add: drupal
Enter password for new user:
Enter it again:
Shall the new user be allowed to create databases? (y/n) n
Shall the new user be allowed to create more new users? (y/n) n

2) Create the new drupal database owned by the user created in 1) above

As the postgres user:

postgres$ createdb -O drupal drupal

3) Add the plpgsql language to the database

As the postgres user:

postgres$ createlang plpgsql drupal

4) Finally, read in the supplied database.pgsql file.

As root postgres user:

postgres$ psql -U drupal -d drupal -f database/database.pgsql

5) Set $db_url as mentioned in above documentation.

Installing contributed modules


Once you have the Drupal core files installed, you can begin adding third-party contributed
modules to extend or alter Drupal’s behavior.

The basic instructions are as follows: Download the module, extract the files, upload the
resulting folder, and enable the module in administer > site building > modules (version 5.x) or
administer > modules (version 4.7 or under).

The detailed instructions are:

1. Download the module. Make sure the version of the module matches your version of
Drupal. Note that modules labeled "CVS" are in a development stage. They may be written
for a previous/current/future version of Drupal, and they are considered unstable and
should be handled with care.
2. Extract the files. When you first get the module, it will appear in a compressed file format

111
Drupal Handbook 3 Aug 2007

such as ’tar.gz’. On Windows, use a program like WinZip to extract it. On the Mac, you can
use Stuffit Expander. To extract the file using the Unix command line:

tar -zxvf modulename-drupalversionnumber.tar.gz

You should see a list of files extracted into a folder.

3. Upload the folder. FTP your files to the desired modules folder in your Drupal installation.
Since the /modules/ folder is typically reserved for Drupal core modules, as of version 5.x you
should create a sites/all/modules/ directory and put uploaded modules there. This will also
make it easier to update your Drupal site later on. For version 4.7 and below, put contributed
modules into /sites/example.com/modules/ (multi-site setup) or /sites/default/modules/
(single site setup)
4. Read the directions. If the module has an installation file (usually INSTALL.txt and/or
README.txt), read it for specific instructions. There are modules that require special treatment,
and even modules that depend on other downloaded files to function properly. Sometimes the
readme filename has no .txt extension. When you try to double-click on it, your computer
doesn’t know what program to use. In that case, open Notepad (or your favorite text editor) first,
and then open the file using Notepad’s ’open’ command.
5. Enable the module. Version 5.x users go to administer > site building > modules while 4.7 or
prior use administer > modules. Check the ’Enabled’ box next to the module and then click
the ’Save Configuration’ button at the bottom. NOTE: If you’re upgrading an existing module
you’ll need to browse to your update page at www.example.com/update.php and click on
’run the database upgrade script’.
4.6 USERS: As of 4.7, modules have an .install file so that any database tables which the
module requires are created automatically when the module is enabled. If the new module
doesn’t have one, look for modulename.mysql and/or modulename.pgsql. If you see
those, the module isn’t using .install files yet, and you need to read step 6 of the 4.6
instructions. If there are none of those files, the module doesn’t affect the database.
6. Set file permissions. Some modules will require you change permissions or settings to get
them working. Permissions and settings info may be in the instructions that came with the
module. Usually, go to administer > users > access control. Scroll down to see if the module
appears in the list and, if it does, give the appropriate permissions to roles.
7. Adjust settings. In 5.x, settings are with the module. In 4.7 and prior, go to administer >
settings and see if the name of the module you just installed is in the list. If it is, click the
module name and configure as appropriate.
8. If you run into problems, search the forums. If your problem hasn’t already been addressed,
post a question and someonw will try to help you out.

Note: To keep up-to-date on any issues and fixes related to your newly installed module(s), you
can create a user account (if you haven’t done so all ready) and then subscribe to each module
you are using.

Note: You can have only one copy of a module with the same name in each Drupal site.

112
3 Aug 2007 Drupal Handbook

HOWTO: Install glossary module


I just finished installing the Glossary module in three Drupal 4.7x websites, so I thought I’d
write out some basic steps here:

Where is the Glossary?


One of the first things to try to understand is that, although we will install a "Glossary Module",
all the glossary content is actually entered and created in "Administer>Categories*" as entries in
a Vocabulary. Although Taxonomy Vocabularies are quite powerful, and contain many other
uses (many of which I don’t yet understand or I’m not yet aware of), this article only explains
Vocabularies as they relate to the Glossary Module. The Glossary Module takes the Vocabulary
entries and turns them into one or more Glossaries. Each time you create a new "Vocabulary",
you are creating (the potential for) a new Glossary. (The Vocabulary terms are only turned into
Glossaries when chosen in the "Administer>Input Formats" section.) (More about this later below.)
*Note: Although the Glossary content is entered through "Administer>Categories>Vocabularies" , don’t
get this confused with the optional, but different, Category Module, which adds it’s own
"Administer>Categories" menu listing.

What is the purpose of the Glossary Module, and what does it do?
Creates Glossary Page(s), the Glossary Module creates a glossary page of all your terms, with
the definitions. You may create one or multiple glossaries.

Terms Identified:, on any page on your website, whenever you use any of the words in the
glossary, those words will be identified on each page. You can choose whether the words will be
identified by being underlined (with a broken line), or using a superscript letter (or word), such
as the superscript letter "i", like this i (You can actually type in any letter or word that you want), or
by using a small icon by the word. (You can also chose whatever icon you like)(see instructions
below)

Definitions Available on "Hover", whenever the visitor "hovers" the mouse pointer over any
one of the identified terms, the definition will "pop up" in a small box for about 6 seconds. This
way the definitions of all the words in your glossary will be readily available every time you use
any of those words.

Instantly Go to Glossary. If you click on the underlined word, or one of the identifiers (the
superscript "i" or the small icon), you will immediately be taken to the full glossary page.

Full Page Definitions, you can attach full page (or multiple pages) of descriptions to any, or all,
of the glossary terms. (see instructions for this at the bottom). If you have attached any full pages
to any glossary term, the pop up definition will still work, but when you click on the word, you
will be taken to the full page descriptions instead of to the glossary page. If you have multiple
pages attached to the glossary term, then you will be shown the teasers of all the definition
pages. You can then choose to look at any of those pages.

113
Drupal Handbook 3 Aug 2007

Installing the Glossary Module


More detailed instructions (for some of the following steps) can be found in the Glossary
Readme file.

1. First download the Glossary Module from http://drupal.org/project/glossary onto your


computer.(Some website control panels allow you to upload an archived file; zip, tar, etc. and then
unarchive it after the file is on your website in a folder. If this is the case, then just upload the
Glossary Module tar or zip file to your website. Otherwise, unzip the file on your computer, then ftp
the whole folder to you website folder.)

Using either a ftp program, such as FileZilla, or from your website control panel: file
manager, upload the folder/files to (mywebsite.com/drupal/modules)

Configuring the Glossary


1. On your Drupal website, go to "Administer>Modules" and enable the glossary module
and save the new configuration.
Go to Administer>Categories: Add one or more Vocabularies. You might give the
vocabularies names that will encompass all your terms. For example, since I do upholstery, I
might name one of my Vocabularies "Upholstery Terms" , then add some terms.
Go to Administer>Input Formats: Choose one of the input formats, for example chose
âFiltered HTMLâ, At the right side, under "Operations", click on âconfigureâ. This will take
you to the "’Full HTML’ input format" page.
Under the âViewâ tab (which is the default), under âFilters,â enable the "Glossary filter", At
the bottom of the page, click âSave Configurationâ. After it is saved, you will be on the same
page.
Now, at the top of the page, click on the âconfigureâ tab.
Click on âGlossary Filterâ which will open up some choices. In the âSelect Vocabularyâ
box, click on the vocabulary term(s) that you created in Administer>Categories.
Next, do you want all the terms of your glossary to show on one page? (This would be
suitable for small glossaries) If not, click in the box by "Show glossary across many
smaller pages"
The next choice is "Match Type". I haven’t figured that one out yet, so I leave it alone on
"Word".
Chose whether you want your glossary terms to be case sensitive or insensitive. I usually
chose case insensitive, since I want all the tems to show up, whether capitalized or not.
Next, do you want all the terms on any given webpage to be identified as being in the
glossary, or do you only want the first term on any page identified? Chose Replace
Matches: "Only The First Match" or "All Matches".
Under "Indicator Settings", you now make choise about how you want your terms
identified on the website pages.
Under "Term Indicator" Choose "superscript", "icon", or "replace with acronym link":
Superscript:If you want a superscript letter (or word) by each word, like this i or this term
Icon: A default icon is installed with Drupal. the icon will follow the term in place of the

114
3 Aug 2007 Drupal Handbook

superscript. If you want to choose a different icon, upload it somewhere on your website,
such as your picture gallery, or a file, copy the URL to your chosen icon, and enter that URL into
the Glossary Icon URL: text box.
Underline: If you’d rather have all you terms underlined (only with a broken line), then
choose "replace with acronym link" in the Term Indicator box.
When you are finished with all of your choices, click on âsave configurationâ

Glossary Administration: Finally, Choose which type of user(s) that you want to be able to
administer the glossary, such as all "authenticated users" or only members in a "specific user
role", or just the "administrator(s)". To make this choice, go to "Administer>Access
Control>Permissions. Scroll down to "glossary module" and enable your chosen user role(s).

Your Glossary Module should be working now. Go back to


"Administer>Categories>Vocabularies" to enter your glossary/vocabulary terms. I would
suggest that you keep your terms down to one brief paragraph. This paragraph will display all
through the website whenever a user’s mouse pointer "hovers" over the indicated word; it will
only display for about 6 seconds. Keep your paragraph down to about 6 seconds of comfortable
reading. (Yes, a user can go back to the indicated word and get the definition to pop up again, but
why should they have to? You can put more detailed definitions or explanations on other page(s), which
can be connected to any glossary/vocabulary term(s).)

Adding Full Page Definitions


Do you want to allow any registered user to add full page definitions to the glossary, or do
you want only specific persons to have this ability? This is controlled through the
"Administration>Input Formats". If you want every authenticated user to be able to add full
pages to the glossary, then you would enable the glossary with each of the input formats
available to those users. However, if you only want specific users to have that abililty, Use or
create an input format that only those users, or type of users, will be using.
.............>>> More to be added here later <<< .................

Adding Glossary To Menus


This part (below) needs to be written better, more later.

1. To create additional glossary entries, go to Administer>Categories (as you did above)


and enter more.
(when your create Vocabulary (in Administer>Categories above), menu items and blocks
are created for them, but not enabled.)
If you want your Vocabulary to be on the website menu, go to Administer>Menus and
enable them.
If you want your Vocabulary to have its own menu block, go to Administer>Blocks and
enable them.

Stephen Winters
Winters Sewing
Winters Sewing: Upholstery Information Website

115
Drupal Handbook 3 Aug 2007

Kingwood Bible: Community Website

Leech - automating content addition


The Leech module is an amazing module that automagically adds content to your site. Once its
set up it will read RSS feeds and "leech" the articles from the originating site and each article as a
node on your drupal site.

This is how you set up leech (4.7.x-1.6 as of 3/3/2007).:

Enable the following 2 modules:

1. leech

node_template (which comes with leech)

next, according to modules/leech/README.txt you have to do the following:

1. create a story called "template story" and in the body of the story, put any place holder
like "template node". Under publishing options disabled "Published"
2. After creating the story, you will find the node now has a new tab called "template".
Click on that and then on the button named "create"
3. Next go to admin/settings/content-types and enable leech using the template created
above. and save
4. The final and most important part of the leech puzzle is from
http://drupal.org/node/116859. which says you have to create a PAGE for each RSS
feed. When you create content/page you will now find there is a new option called
leech. put in your rss feed’s url and wait for like 10 to 30 seconds. the advanced options
will fill up with the data for your feed. Give your new leech feed a name and save. I
don’t believe any body would want this new leech feed posted to their front page so
uncheck that option from under publish.
5. once saved, there is still no data, depending on how often you set your leech module to
check for updates (dependent on cron) you will either have to wait for the next cronjob
or click on leech data now and VOILA! NEW STORIES!

NB. its supposedly possible to use other node types and even CCK but i havent tried and
the above is exactly what i need

Relationships between modules


This is a start to explain how similar or related modules are related and why you would use one
vs another.

Internationalization
- Locale (core), i18n also known as Internationalization, and Translation

116
3 Aug 2007 Drupal Handbook

http://drupal.org/project/locale
- provides multiple translations of strings generated by drupal
- now part of the core code of drupal, critical if you want the site in something other than english

http://drupal.org/project/i18n
- provides a mechnanism to define multiple a single piece of content in multiple languages.
- requires locale module
- only use this if you want your site in English AND french

http://drupal.org/node/12875
- translation module which allows for people to switch between node content in other languages
- must require locale and i18n module
- designed to make it easier to produce sites in both english AND french

Module Comparisons

- http://drupal.org/project/scheduler vs http://drupal.org/project/event (applied to nodes)

- http://drupal.org/node/19813 vs taxonomy

Installing new modules (Drupal 4.6 or older)


After installing Drupal, you have the option of installing extra modules to extend or alter
Drupal’s behavior.

In brief. Download the module, extract, upload the folder into your Drupal modules folder, run
the mysql file if necessary, and enable the module in administer » modules.

1. Download the new module. Make sure the version of the module is compatible with your
version of Drupal. Also note that modules labeled CVS are considered unstable and should
be handled with care. Often, CVS modules work only with the CVS version of Drupal. They
may be in draft form, or be in the midst of active development.
2. Extract the module. When you first get the module, it will probably come in a compressed
file format such as tar.gz. On Windows, use a program like WinZip to extract it. On the
Mac, you can use Stuffit Expander. To extract the file using the Unix command line:

tar -zxvf modulename-4.5.tar.gz

You should see a list of files extracted in to a folder.

3. When you’ve extracted the file, upload the files via FTP to a folder inside the modules/
folder of your Drupal installation.
4. Read the installation file (usually INSTALL.txt and/or README.txt). Sometimes the
installation file has no extension, so when you try to click on it, your computer doesn’t
know what program to use. In that case, open Notepad (or your favorite text editor) first,
and then open the file into it.
5. There are modules that modify the database. You can generally tell if there is a
modulename.mysql and/or modulename.pgsql file included with the module. If you

117
Drupal Handbook 3 Aug 2007

do have to modify the database, see the next few steps. If you do not, please skip to step 7.
6. If you have to modify the database to get your module running, you will need to add tables
to the database you made when you installed Drupal. Instructions given here are for MySQL.
Using phpMyAdmin:
If you have phpmyadmin, log in and go to your drupal database. If you have it, but do
not know how to access it, please contact your host.
Click on the tab that says ’SQL’
You should see a text area labeled ’Run SQL query/queries on database
yourdrupaldatabase’. Underneath, it says ’Or Location of the textfile:’ Click browse,
and find the modulename.mysql that came with the module. Click go. Unless your
instructions for the module says anything else, that should be all you have to do to the
database.
Using the Unix command line:
Run the following command.
mysql -u username -ppassword database_name < modulename.mysql
Replace ’username’ with your MySQL username, ’password’ (but keep the -p before it)
with your MySQL password, ’database_name’ with the database Drupal uses, and
’modulename.mysql’ with the SQL file that the module comes with. You can generally
find this out from settings.php in either the sites/default folder or the
sites/sitedomain.com folder, replacing sitedomain.com for the domain that hosts
Drupal.)
7. For most modules, all that is left is to activate it! To activate your module, you need to click
administer » modules, check the box next to your new module name, and click on ’Save
configuration’ at the end.
8. Some modules will require you change permissions or settings to get them working as you
like them. Permissions and settings info may be in the instructions that came with the
module. If not:
9.
1. Click administer » access control. Scroll down to see if the module appears in the list
and, if it does, give the appropriate permissions to roles.
2. Click administer » settings and see if the name of the module you just installed is in the
list. If it is, click the module name and configure as appropriate.
10. If you still run into the problems, search the forums. If your problem hasn’t already been
addressed, post a new post.

Note: To keep up to date on any issues and fixes you can create a user account (if you haven’t
done so all ready) and subscribe to each module you are using.

Note: You can have only one copy of a module with the same name in an Drupal installation.

Multi-site installation and set-up


Instructions on multi-site configuration (also known as "multisite" and "single code base"
installations) can be found within the installation instructions.

118
3 Aug 2007 Drupal Handbook

Here are some useful links:

Search results
4.6 Multi-Site from single code base
Multi-Site .htaccess configuration
multi-site, single installation, shared db, single sign on. is this possible?
Automatic Multi-site registration
Using Multi-Site
Multihosting Off Single Codebase
Multisite and symlinks doesn’t work
Sharing tables between installations

10 Minute Multisite Install & Configuration


Multisite 10 minute Install:

Server: LAMP
SSH/Telenet Client: PuTTY
Must have root access to your server.

If website in question is an addon domain, i.e., addon.mydomain.tld, then substitute "www" for
"addon" in steps below.

For list of Linux commands visit: http://www.oreillynet.com/linux/cmd/ or


http://www.ss64.com/bash/

Here we go:

[login via PuTTY]

Get to location where Drupal core will be located:

[/]# cd /var/www

Upload Drupal core:

"x.x" should be replaced with the version of Drupal you’re installing, e.g. "5.1"

[/var/www]# wget
http://ftp.osuosl.org/pub/drupal/files/projects/drupal-x.x.tar.gz

Unpack Drupal core:

[/var/www]# tar -zxvf drupal-5.1.tar.gz

Move contents of Drupal core (including .htaccess) to html:

119
Drupal Handbook 3 Aug 2007

[/var/www]# mv drupal-x.x/* drupal-x.x/.htaccess /var/www/html

Clean-up:

[/var/www]# rm drupal-x.x.tar.gz
[/var/www]# rm drupal-5.1

Create the files directory per Drupal instructions and change permissions (will change
permission again after install):

[/var/www]# cd html
[/var/www/html]# mkdir files
[/var/www/html]# chmod 777 files

Make directories that will hold custom and contributes modules and themes:

[/var/www/html]# cd sites/all
[/var/www/html/sites/all]# mkdir modules
[/var/www/html/sites/all]# mkdir themes
[/var/www/html/sites/all]# cd modules
[/var/www/html/sites/all/modules]# mkdir custom
[/var/www/html/sites/all/modules]# mkdir contrib
[/var/www/html/sites/all/modules]# cd ../
[/var/www/html/sites/all]# cd themes
[/var/www/html/sites/all/themes]# mkdir custom
[/var/www/html/sites/all/themes]# mkdir contrib

Create directory "www.mydomain.tld":

[/var/www/html/sites/all/themes]# cd ../
[/var/www/html/sites/all]# cd ../
[/var/www/html/sites]# mkdir www.mydomain.com

Change permission of "settings.php" per Drupal instructions and copy "settings.php" in default
to www.mydomain.tld:

[/var/www/html/sites]# cd default
[/var/www/html/sites/default]# chmod 777 settings.php
[/var/www/html/sites/default]# cd ../
[/var/www/html/sites]# cp -rp sites/default sites/www.mydomain.tld

Create database and user with permissions:

[/var/www/html/sites]# mysql
mysql> CREATE DATABASE wwwmydomaintld_drupal;
mysql> GRANT ALL PRIVILEGES ON wwwmydomaintld_drupal.* TO
’wwwmydomaintld_myusername’@’localhost’ IDENTIFIED BY ’mypassword’;

120
3 Aug 2007 Drupal Handbook

mysql> \q

Go back to PuTTY to chmod on settings.php in www.mydomain.tld:

[/var/www/html/sites]# cd www.mydomain.tld
[/var/www/html/sites/www.mydomain.tld]# chmod 755 settings.php
[/var/www/html/sites/www.mydomain.tld]# logout

What next?:

Make changes to "settings.php" in www.mydomain.tld? I’ve read that it’s not necessary to
make changes to setting.php.
Make changes to "httpd.conf" in /usr/local/apache/conf?

I’ve been using WHM to create accounts, putting Drupal in public_html and having no
problems. But when it comes to parting from the WHM abstraction and getting multisite set-up
correctly this is the end of the proverbial road for me.

Could use help...:

1. Help making improvements to steps articulated above


2. Help with next steps so that I/we can get on to grander things, like creating modules,
custom themes, profiles, (and maybe - just maybe - spend some time working on business
strategy :-)

Access all multisites with www. only [.htaccess]


The default .htaccess RewriteRule to redirect every multisite.com to www.multisite.com does
not work properly.

If you have problems with that too, just leave the two lines uncommented, and ADD THE
FOLLOWING 3 LINES FOR EVERY MULTISITE you set up:

RewriteCond %{HTTP_HOST} mysite\.com$ [NC]


RewriteCond %{HTTP_HOST} !^www\. mysite\.com$ [NC]
RewriteRule ^(.*)$ http://www.mysite.com/$1 [L,R=301]

(Thanks to Florian!)

Drupal as a library
Short introduction on how to share drupal with all users on a shared server (without having
troubles with file-permissions).

Note: it is still possible to use the Multisite option of drupal.

121
Drupal Handbook 3 Aug 2007

example server’s file-structure:

/path/to/phplibraries/drupal (chmod 644)


/home/
user1/ (example.com)
lib (symbolic link => /path/to/phplibraries/)
public_html/
main/
files/
includes (symbolic link =>
/home/user1/lib/drupal/includes)
misc (symbolic link => /home/user1/lib/drupal/misc)
modules (symbolic link =>
/home/user1/lib/drupal/modules)
profiles (symbolic link =>
/home/user1/lib/drupal/profiles)
sites/
all (symbolic link =>
/home/user1/lib/drupal/sites/all)
default (symbolic link =>
/home/user1/lib/drupal/sites/default)
example.com/
settings.php
themes (symbolic link =>
/home/user1/lib/drupal/themes)
.htaccess (copy from drupal/.htaccess)
cron.php (copy from drupal/cron.php)
index.php (copy from drupal/index.php)
install.php (copy from drupal/install.php)
robots.txt (copy from drupal/robots.txt)
update.php (copy from drupal/update.php)
xmlrpc.php (copy from drupal/xmlrpc.php)
.htaccess (1)
user2/ (example2.com)
(same as user1)
user3/ (example3.com)
(same as user1)
etc...

.htaccess (1)
this isn’t neccessary but it keeps public_hml/ clean when several sites are maintained by one user. When
only one site is maintained the contents of the main/ directory could be moved to public_html/ itself

Options +FollowSymLinks
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine on

122
3 Aug 2007 Drupal Handbook

RewriteCond %{REQUEST_FILENAME} !-f


RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*) main/$1 [L,QSA]
</IfModule>

Multi-site setup in 5.x using CPanel


After some searching around, I found out how to do multi-site setup using CPanel.

1. Create your initial Drupal site at www.yourdomain.com. Drupal 5.x makes this very easy to
do, as it will automatically install the database for you -- all you have to do is input the database
information.

2. Create a folder in the sites/ folder that matches the subdomain you want to create (so for
site1.yourdomain.com, the folder name would be site1.yourdomain.com).

3. Duplicate the settings.php file from the default folder and place it in your newly created
folder from step 2.

4. Edit the settings.php file you just placed in the site1.yourdomain.com folder so that it points to
the correct database.

5. In CPanel, set up the subdomain. For the above example of site1.yourdomain.com, a folder
named site1 will be automatically created by CPanel.

6. Delete the folder that was created.

7. Use the following example to create and upload a php file onto your site. An easy way to do
this is to use Notepad, pasting in the text below, editing as necessary, and then saving as
multisite.php. Afterwards, upload via FTP or CPanel’s File Manager.

<?php
symlink( ’/home/username/public_html/’, ’site1’ );
?>

8. Go to the location of the php file in your browser (such as


www.yourdomain.com/multisite.php)

This will create a symlink, allowing your subdomain to work properly.

9. Go to your subdomain. Drupal will install the tables necessary to run the new site.

10. You’re all set to use the new site.

If you run into any problems, or have questions, use the contact form attached to my user
account here to contact me.

123
Drupal Handbook 3 Aug 2007

Multi-Site, Single Codebase, Shared Database, Shared


Sign-on 4.6
I used this option, having a network of interrelated sites. While each site has its own domain,
offers its own theme and own primary (homepage) content, the sites are essentially related and
needed to share user registration accounts and forums. With a shared database, they also share
information, e.g. the site which offers reviews can also display news headlines in a sidebar; the
site which offers classified ads can offer reviews in a sidebar; etc.

An unintended consequence of this approach is that savvy users can effectively navigate any
and all content from any and all sites (once they understand breadcrumbs and drupal-specific
navigation), so they get, essentially, whatever content they want in whatever theme they want.

Apache (http) Configuration


All domains will point to one document root. That cannot be emphasized enough. When using
virtual hosting, do not create a separate virtual domain for each site -- only for the first site.
When using a control panel such as cPanel or Ensim, create only the first domain. In the first
domain’s alias area, list all the additional domains and subdomains to be used. Your virtual
hosting entries should end up like this:

ServerName www.firsthost.com
ServerAlias firsthost.com
ServerAlias secondhost.com www.secondhost.com
ServerAlias thirdhost.com www.thirdhost.com forums.thirdhost.com
etc...

DocumentRoot /home/virtual/whatever/var/www/html
etc...

Any request for any of the domains will all run to /home/virtual/whatever/var/www/html
for response. This is the desired result.

Download and Placement


The code base should sit in the DocumentRoot defined above. Download the tar ball for the
latest stable version (4.6 as of this writing) and open it in the doc root. Note: all remaining
commands assume you are sitting in your doc root, so go there.

wget http://drupal.org/files/projects/drupal-x.x.x.tar.gz
tar -zxvf drupal-x.x.x.tar.gz
mv drupal-x.x.x/* .
mv drupal-x.x.x/.htaccess .

Check ownership and permissions - if you’ve downloaded directly, they’re likely to be very
wrong. Security note of caution: I typically go through and change permissions to 444
(read-only) for all .php, .gif, .jpg and .css files. In drupal, that’ll also mean .module files. You’ll

124
3 Aug 2007 Drupal Handbook

have trouble editing these files, but that’s the point. It’s easier to change permissions temporarily
on a file you want to hack than it is to fix a break-in.

chown -R siteX:siteX .
chmod -R 444 *.php *.gif *.jpg *.css *.tar *.module

SQL Setup
There are two ways to do this: on the command line and via a control panel. Some control panels
(Ensim, for example) require that you create new databases through their interface (so they can
limit a site to a set number of databases).

If you can create new databases through the command line, do it like in the install file -

mysqladmin -u user -p create Name


mysql -u user -p
GRANT ALL PRIVILEGES ON Name.* TO user@localhost IDENTIFIED BY
’password’;
flush privileges;

I substituted Name for ’drupal’ in the instructions -- really, name your database something other
than ’drupal.’ Helps to prevent hacking if the attacker isn’t intimately familiar with the site
configuration. Even if you call it mysite_drupal, that’s something.

I also have no idea why the installation instructions suggest permissions for ’nobody,’ so I
changed that to the database user. If you don’t have a database user setup for this site, setup an
SQL user with its own unique password. phpMyAdmin makes it easy to do this.

If you have to create databases via your control panel, open it and go to the SQL page. Create a
new, empty database associated with the correct host and call it what you will (see notes above
about calling it ’drupal.’ Most systems create a database user for each site; if yours doesn’t,
create that user and give it permissions for the database you just created.

Just because you have to create the database via the control panel doesn’t mean you have to fill it
that way. You can now return to the command line and setup the database structure.

mysql -u user -p Name < database/database.mysql


chmod 000 database/database.*

Technically, you’re done after the first line, but I like to lock up all setup files once I’m finished
with them. This prevents someone else from trying to reset my system to hack in and prevents
me from erasing my database in a fat-fingered typing accident.

125
Drupal Handbook 3 Aug 2007

Individual Site Configuration & Theming


Now, to the individual site information. Drupal will parse the http request and provide the
correct content based on the domain name and settings files. You’ll need one directory for each
domain name and one settings file for each. You can link aliases together. In the example below,
Drupal will load this settings.php file for calls to http://firsthost.com and
http://www.firsthost.com.

mkdir sites/firsthost.com
cp sites/default/settings.php sites/firsthost.com
ln -s sites/firsthost.com sites/www.firsthost.com

Now, edit sites/firsthost.com/settings.php and enter the following values (using the SQL values
above for user, password and database Name). This allows the site to connect up to the database
created above, and to create links to itself correctly.

$db_url = ’mysql://user:password@localhost/Name;
$base_url = ’http://firsthost.com’; (or www.firsthost.com depending on preference)

And add the following lines (using site values). This overrides any theme or database settings to
provide unique values for this site. Things you may want to override include the individual
site’s name, slogan, and theme. Also, you can use site_frontpage to set a default module. In the
case below, we’ve chosen ’node’ (generic stories) as the home page for this site.

$conf = array(
’site_name’ => ’Name of the First Site’,
’site_slogan’ => ’My Original Drupal Site’,
’site_frontpage’ => ’node’,
’theme_default’ => ’pushbutton’,
’anonymous’ => ’Visitor’
);

Now, repeat from the ’mkdir’ command for each new site. Some things will remain the same.
The configuration variables will change. In the example below, we’ve changed the homepage to
the book module and the theme to bluemarine. When Drupal parses a request for this second
site, it will present those options.

$conf = array(
’site_name’ => ’Name of the Second Site’,
’site_slogan’ => ’The We Love Drupal Fan Site’,
’site_frontpage’ => ’book’,
’theme_default’ => ’bluemarine’,
’anonymous’ => ’Dude’
);

126
3 Aug 2007 Drupal Handbook

You have working multisites. Call up the first domain, setup your administrative user and run
with it. Keep in mind that sites/default is the settings.php file which will be used if Drupal
doesn’t recognize the http call, so you might want to set that one up to run with your default site
... or set it up to notify you if someone tries it.

Some things which can be improved:


- I have yet to try to use the FOAF module ( http://drupal.org/project/foaf ) to automate logins
from one domain to the other. At the present time, users must login separately to each site, even
though they use the same account info.

- I don’t use the statistics module, so I can’t say what it does, but it can be difficult to get
individual domain info out of the Apache logs. Unless you do some fancy configuration, you get
one combined log.

- Note that to use different databases (completely different Drupal sites) with the same code
files, you can still follow the above instructions, creating a separate database and user for each
one. Then, point each settings.php file to the appropriate database instead of pointing them all to
the same one.

Keywords: multisite multi-site multi site, multihost multi-host, host, sharing code, one codebase,
site configuration, step by step

Multi-Site, Single Codebase, Shared Database, Shared


Sign-on 5.x
This document is written with assumptions that you have:

installed Drupal 5 before


access to your server via ssh / telnet
access to MySQL database / you can setup your own MySQL database

In this example, I will setup two sites using:

Drupal 5
One database on MySQL
Linux-based server

Also:

Website’s url is: www.example.com


Drupal is installed in: /var/www/drupal
Names of sites are: âsite_1’ and âsite_2’

These sites will share session and user-related tables so once users login to one of the sites, they
can view the other site without logging in. User roles and profiles are also shared among the two
sites.

127
Drupal Handbook 3 Aug 2007

1. Prepare database and database user

1.1. create a database and user


In this example, I will use:

DB name: drupal_db
DB username: druser
Password: twosites
Access right: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER,
CREATE TEMPORARY TABLES, LOCK TABLES

2. create and modify site configuration


2.1. duplicate settings folder
Duplicate a folder contains site config information under drupal/sites/

dru@/var/www/drupal/sites: cp âR default/ www.example.com.site_1


dru@/var/www/drupal/sites: cp âR default/ www.example.com.site_2

2.2. Modify config files

2.2.1. provide DB connection detail


Open settings.php in a folder under www.example.com/site_1. Go to line 93 (or somewhere
around there) and you should find a line that goes:

$db_url = ’mysql://username:password@localhost/databasename’;
change this line with your DB name, DB user and password. It will look like:
$db_url = ’mysql://druser:twosites@localhost/drupal_db’;

2.2.2. set prefixes for table names


just below the line we just changed above, there is a line that goes like:

$db_prefix=’’;
Since we want to share a database among two sites but not completely, we decide which tables
to share / not to share. This can be done by adding prefixes to table names. An example given
below is for sharing user-related tables, sequences (this table is a âcounter’ of users, nodes and
other stuff) and session information.
$db_prefix = array(
’default’ => ’site_1_’,
’users’ => ’shared_’,
’sessions’ => ’shared_’,
’role’ => ’shared_’,
’authmap’ => ’shared_’,

128
3 Aug 2007 Drupal Handbook

’sequences’ => ’shared_’,


’profile_fields’ => ’shared_’,
’profile_values’ => ’shared_’,
’users_roles’ => ’shared_’,
);

the second line that goes:

’default’ => ’site_1_’,


this means tables that are not shared with other sites will have a prefix âsite_1_’. So for example,
table name ânode’ will be âsite_1_node’.

Now, when you finish editing this file, open and edit
drupal/sites/www.example.com.site_2/settings.php. This time, you enter the exact same
information for the database connection. So the line around 93 should look like:

$db_url = ’mysql://druser:twosites@localhost/drupal_db’;
Then, you add an array of prefixes, which will look like:
$db_prefix = array(
’default’ => ’site_2_’,
’users’ => ’shared_’,
’sessions’ => ’shared_’,
’role’ => ’shared_’,
’authmap’ => ’shared_’,
’sequences’ => ’shared_’,
’profile_fields’ => ’shared_’,
’profile_values’ => ’shared_’,
’users_roles’ => ’shared_’,
);
notice a prefix in the second line is now âsite_2_’. At the installation, all tables will have this
prefix except for the ones that are specifically given a prefix âshared_’.

3. create static links


In order to access site_1 and site_2 from web browser, you have to make static links to drupal
directory. In the directory /var/www/drupal, enter the following commands:

ln -s drupal site_1
ln -s drupal site_2

now access âwww.example.com/site_1’ (and âsite_2’). If you see a drupalicon and a message
like âUnable to select database’, go back to 2.2.1 of this manual and check if you have all details
correct, including a single-quotation and semicolon.

If you see hundreds of messages like âWarning: Table ’continuu_test.access’ doesn’t exist’, you
are almost there. While this may look scary or makes you think you have done something
wrong, it is just saying that it cannot find tables Drupal needs to have access to. This is simply
because we have not yet finished installing Drupal. All the necessary tables will be created in the

129
Drupal Handbook 3 Aug 2007

next step, which is described below.

4. install drupal
Since we have entered information for database connection, we can run the install script
(install.php) straight away, instead of giving all the detail to installation wizard. From your web
browser, just access:
http://www.example.com/site_1/install.php
http://www.example.com/site_2/install.php

Installation should complete within a second (or two). If you fail to install:

read the error message and find out what is wrong (wrong DB name, username or
password, etc.)
make sure $db_url (around line 93 in settings.php) ends with a quotation mark and
semicolon. ( â; )

If you have two separate Drupal sites and are thinking about merging them with above method,
I would recommend you not to do it. Yes, it is not impossible. You can rename tables and
modify values in sequence table and so on, but i tried it and had a hell of a hard time... If you
have sites already setup, using CAS or other authentication services is more appropriate than
merging.

Multiple domains or vhosts using different databases


Apache supports both IP- and name-based virtual hosts (vhosts). While running more than one
engine (by using vhosts) can be very useful for development and testing purpose, it might even
be more interesting for hosting companies. Therefore, we tried to support vhosts in the best
possible way in order to make the life of any administrator easier. We do so by making it
possible to run an unlimited amount of vhosts on the same physical source tree, though by using
different configuration files. Moreover, you can setup multiple configuration files in your
includes-directory.

$ ls -l sites/*/*.php
-rw-rw-r-- 1 drupal drupal
sites/www.example1.com/settings.php
-rw-rw-r-- 1 drupal drupal
sites/www.example2.com/settings.php

The only thing left to be done is to setup the corresponding vhosts in your Apache configuration
file. Note that the DocumentRoot points to the same source tree twice:

NameVirtualHost 127.0.0.1
DocumentRoot /home/www/drupal
ServerName www.example1.com
DocumentRoot /home/www/drupal
ServerName www.example2.com

130
3 Aug 2007 Drupal Handbook

Remember that as of Drupal 4.6, you can have site specific modules and themes as well. Just
create a directory under the sites/www.example1.com called ’modules’ and place the site
specific modules. The same applies to themes as well.

Consult the INSTALL.txt that came with your Drupal installation for more details.

Sharing Drupal tables between databases using MySQL5 Views


Note: The more Drupalish way to achieve this is through advanced table prefixing. The docs are
in this handbook.

Problem: You’d like to share some data between two different drupal websites without changing
any Drupal code or otherwise having to lift much of a finger. But you don’t want to share
information unless it meets certain requirements (for example, only users labeled "foo" in
somedatabase.sometable) For our example, we’ll use the users table.

Solution: Use MySQL5 Views (http://dev.mysql.com/doc/refman/5.0/en/views.html)

Our "master" users table resides in a database called "master". The database of the site that will
have restricted access to our masters users table is called "banana". Assumming you’re starting
with a fresh instance of the Drupal schema in your database "banana", do this:

mysql> use banana;


mysql> drop table users;
mysql> CREATE VIEW users AS
mysql> SELECT *
mysql> FROM master.users
mysql> WHERE uid IN (
mysql> SELECT uid
mysql> FROM somedatabase.sometable
mysql> WHERE uid = 0
mysql> OR label = ’foo’
mysql> )

Drupal will use banana.users just as it would a normal users table. No other modifications are
necessary. Now only "foo" users will be included in the users table for your banana website.

Note: Drupal has a dependency that is not really documented. Every users table must have an
entry that contains uid=0. It’s a "stub" entry that Drupal needs to function properly. A
workaround for this dependency is to include "user 0" in the results set that defines your view.

See, wasn’t that easy?

131
Drupal Handbook 3 Aug 2007

Multiple domains using the same database


If you want to host multiple domains (or subdomains) on top of the same database (e.g.
http://example.com/ and http://www.example.com/), simply use symbolic links to setup the
required configuration files:

$ ln -s sites/example.com sites/www.example.com
$ ls -l sites
-rw-rw-r-- 1 drupal drupal sites/example.com
lrwxrwxrrx 1 drupal drupal sites/www.example.com ->
sites/example.com

If your installation isn’t in the root folder then you need to specify the path to the Drupal
installation. For example if the URL to your installation is http://www.example.com/drupal/
you would use sites/www.example.com.drupal with a settings.php file in it.

If you want cookies to be shared between two sites, you will need to set the value of PHP’s
session.cookie_domain correctly. In the case above, set it to ".example.com". You can do this
through Drupal’s .htaccess file.

Same codebase, completely different content and users


This document assumes the following:

You want to create more than one Drupal site using the same codebase (the same basic set
of Drupal files, uploaded into one location).

You know how to install mysql tables in your database.


You know how to set up subdomains/folders/other domains that you want to use.
You have already downloaded Drupal 4.7, and set up one MAIN site.

This document contains instructions on how to create completely separate Drupal


site, with different configurations, users and content. Nothing is shared between
the installations except the codebase.

Some definitions:

codebase: the basic set of Drupal files, included in the .tar.gz


file. the stuff that makes Drupal work.

database: a collection of tables that stores data.

Affected files:

settings.php (sites/default/...)

132
3 Aug 2007 Drupal Handbook

database.mysql

For this example, we will assume the following:

www.example.com: the MAIN site, where the codebase has already been uploaded,
and settings.php has been properly configured.

sub1.example.com; www.example.com/sub2; www.subexample.com : the other sites


we will create.

1. Create the following folders in your sites directory:

sites/sub1.example.com/

sites/www.example.com.sub2/

sites/www.sub3example.com/

Copy the settings.php file from sites/default into each of the above folders.

2. There are different database files (inside the database folder). Select
the one that is appropriate for your database version. Copy it to each of the
folders you made in step 1. This is OPTIONAL, but it will help you keep things
straight.

3. Decide on SEPARATE PREFIXES for each site. Below is what we will use for
the example:

site
database prefix

sub1.example.com
sub1_

www.example.com,sub2
sub2_

www.sub3example.com
sub3_

4. Configure your settings.php for each site.

This code MUST BE CHANGED FOR EACH SITE:

$db_url = ’mysql://username:password@localhost/databasename’;

Note; if you are using the same database as the MAIN site, the $db_url is the
same.

133
Drupal Handbook 3 Aug 2007

OPTIONAL:

# $base_url = ’http://www.example.com’; // NO trailing slash!

# $conf = array(
# ’site_name’ => ’My Drupal site’,
# ’theme_default’ => ’pushbutton’,
# ’anonymous’ => ’Visitor’
# );

For sub1.example.com, the settings would be:

$db_prefix = ’sub1_’;
$base_url = ’http://sub1.example.com’;
$conf = array(
’site_name’ => ’My SUB1 Drupal Site’,
’theme_default’ => ’pushbutton’,
’anonymous’ => ’Visitor’
);

For www.example.com/sub2, the settings would be:

$db_prefix = ’sub2_’;
$base_url = ’http://www.example.com/sub2’;
$conf = array(
’site_name’ => ’My SUB2 Drupal Site’,
’theme_default’ => ’fancy’,
’anonymous’ => ’Anonymous’
);

For www.sub3example.com, the settings would be:

$db_prefix = ’sub3_’;
$base_url = ’http://www.sub3example.com’;
$conf = array(
’site_name’ => ’My SUB3 Drupal Site’,
’theme_default’ => ’marvin’,
’anonymous’ => ’Guests’
);

6. Upload the modified settings.php files in their respective folders.

7. Open the database file you copied into each sites folder. Find the following (don’t forget
the SPACE at the end!!!):
CREATE TABLE
INSERT INTO

134
3 Aug 2007 Drupal Handbook

Replace each ’create table’ and ’insert into’ with ’create table dbprefix_’ and ’insert into
dbprefix_’

For sub1.example.com:
CREATE TABLE >> CREATE TABLE sub1_
INSERT INTO >> INSERT INTO sub1_

8. Upload the modified mysql files into the database you specified in your settings.php.

9. Voila!

Setup of /sites directory for multi-site


Drupal’s multi-site hosting capability is built in with any installation. This is great news for
users who run numerous web sites from a single hosting account. A single Drupal installation
can be used to run multiple domains, which makes it much easier to manage and maintain the
code base. Even if you are dealing with only one domain, the multi-site capability may be
valuable by providing the ability to run a separate domain or sub-domain for a development
version.

This page describes the set-up of the /sites directory for multi-sites. The single-site basics are
discussed at Basic /sites directory setup.

With version 5.x, the intended location for all non-core elements of a Drupal installation is in a
separate /sites directory inside the Drupal installation.

Directory Contents
/drupal/sites/all /modules
(used by all sites) /themes
/drupal/sites/default /files
(used when there is no /sites/example.com directory) settings.php
/files
/module
/drupal/sites/example1.com /themes
/tmp
settings.php
/files
/module
/drupal/sites/example2.com /themes
/tmp
settings.php

135
Drupal Handbook 3 Aug 2007

The intended best practice configuration is to create a /sites/example.com directory for each
domain. It should contain a site-specific settings.php file and /files directory. Configure Drupal
site settings to specify ’File System Directory’ of ’sites/example.com/files’ instead of the default
’files’. It’s possible to do this with an existing web site, but moving file uploads around can cause
a lot of confusion if there are already URLs pointing to the old locations.

Domain specific modules and themes should also be placed in /sites/example.com/modules


and /sites/example.com/themes respectively.

Contributed modules and additional themes which are for use by all domains in a multi-site
installation should be placed in /sites/all/modules and /sites/all/themes. Note that there
shouldn’t be a /sites/all/files or /sites/all/settings.php.

The /sites/default directory should contain /files and settings.php, for use if the
/sites/example.com directory doesn’t exist for a domain.

In addition to multiple sites, such as www.example1.com and www.example2.com, sub


domains are also easily set up. Adding sub3.example2.com and sub3.example2.com/site4, the
directory structure for these four sites would be:

/drupal/sites/all/modules
/drupal/sites/all/themes
/drupal/sites/default/files
/drupal/sites/default/settings.php
/drupal/sites/example1.com/files
/drupal/sites/example1.com/modules
/drupal/sites/example1.com/settings.php
/drupal/sites/example1.com/themes
/drupal/sites/example1.com/tmp
/drupal/sites/example2.com/files
/drupal/sites/example2.com/modules
/drupal/sites/example2.com/themes
/drupal/sites/example2.com/tmp
/drupal/sites/example2.com/settings.php
/drupal/sites/sub3.example2.com/files
/drupal/sites/sub3.example2.com/modules
/drupal/sites/sub3.example2.com/settings.php
/drupal/sites/sub3.example2.com/themes
/drupal/sites/sub3.example2.com/tmp
/drupal/sites/sub3.example2.com.site4/files
/drupal/sites/sub3.example2.com.site4/modules
/drupal/sites/sub3.example2.com.site4/settings.php
/drupal/sites/sub3.example2.com.site4/themes
/drupal/sites/sub3.example2.com.site4/tmp

136
3 Aug 2007 Drupal Handbook

Once you’ve done this, the file structure of your site will be cleanly organized:

The main Drupal directory will contain only the standard ’core’ files.
All of your custom themes, add-ons, settings, and so on will be in /sites/example.com,
/sites/all, or /sites/default.
/sites/default/settings.php and /files will be used if there is no /sites/example.com
directory.
/sites/all/modules and /themes will be available to all sites.
Backing up the /sites directory and your Drupal database will give you everything you
need to restore the site in the event of a crash, or to move to a new server.
Adding a domain is easy: just copy the /sites/default directory to /sites/example5.com

Symbolic links can be used for several purposes:

Even if using default settings, a good option is to use links from /sites/example.com
directory to point to the /sites/default directory. That way, if the settings and /files are
ever changed from the default and actually placed in /sites/example.com, their location
does not ’move’ and no links are broken.
Links could also be used to point the /sites/default directory to your primary site.
A /files directory could easily be shared across two domains without being shared across
the remaining domains.
A non-domain-name path for /files can be setup. If it is possible that the domain name
might change (say, from a development name), then you can set up a link from
/drupal/sites/moniker to /drupal/sites/example.com, where ’moniker’ is a short version
of the site name that will remain constant even if /example.com changes.

Although the /sites/default directory could contain a /modules and /themes directory, these
elements should usually be placed in /sites/all or /sites/example.com. Similarly, although
contributed modules could be placed in /drupal/modules as was the practice in version 4.7, this
is not recommended.

Multi-site directory setup for sub-domains, including non-standard ports, is described in the
installation instructions (INSTALL.txt).

See multidomain for a contributed module that allows spanning one site across multiple
domains, so that specific content types appear on specific domains or sub-domains.

Version 4.6 and 4.7: Best practice for multi-site set-up under version 4.6 and 4.7 is similar to 5.x.
The primary difference is that there is no /sites/all directory. Instead, /modules and /themes
that are available for all domains are kept in /drupal/modules and /drupal/themes.

Installing new themes


Once you get Drupal installed and you start to come to terms with it you will probably want to
customize the way it looks.

137
Drupal Handbook 3 Aug 2007

There are several themes which you can download from the Drupal web site which should get
you started.

Installing a new theme is very straightforward:

1. Download a new theme package. Note that themes for different Drupal versions are not
compatible, version 4.4 themes do not work with Drupal 4.5 and reverse.
2. Read any README or INSTALL files in the package to find out if there are any special
steps needed for this theme.
3. Check to see if you have the required theme engine to be able to display your theme. Theme
engine files go in a folder in themes/engines in your Drupal directory.
4. Upload the contents of the theme package to a new directory in the themes directory in
your Drupal site. For example;
in 4.7 you place your theme in themes/box_grey.
in 5.0 you place your themes in /sites/all/themes/box_grey
5. Click administer » themes and enable the new theme (Drupal will auto-detect its presence).
6. Edit your user preferences and select the new theme. If you want it to be the default theme
for all users, check the default box in the themes administration page.

Note: You can see a variety of themes on themes.drupal.org. Some of these themes shown there
are available for download from Drupal.org and others are merely samples.

138
3 Aug 2007 Drupal Handbook

Basic site configuration


Drupal is an extremely flexible platform that provides you with many options for changing how
your site looks, how users interact with it, and the kinds of information you wish to display.
Although there are many configuration options, Drupal works well "out of the box" and there is
very little initial configuration to perform. As your site evolves and your demands grow, Drupal
makes it easy for you to dramatically alter its look and add to its functionality. Best of all,
because it is released under the GNU General Public License, Drupal is infinitely customizable
and lets you tailor it to your specific needs.

You will want to start your configuration with your drupal site’s basic settings can be found on
the settings page, which you can reach by clicking administer » settings in the navigation
block. You must be logged in and have permission to access this page. After you change the
settings, don’t forget to click "Save configuration" at the bottom of the page.

The information you enter here is stored in Drupal’s database to help Drupal decide how to
prepare and serve your pages. Keep in mind that the settings on this page are only basic
configuration settings. There are many other places to configure Drupal. These are discussed in
the appropriate sections of this handbook. Much of the configuration information can be found
in the modules help file or in the modules section of the handbook. For more advanced
configuration then an out of the box modules provide, see the Customization and theming
handbook.

A lot of the information you are asked to supply on the settings page is self-explanatory and
there are brief help messages below each setting to guide you. Note that the "Slogan," "Mission,"
and "Footer message" may or may not be immediately visible, depending on the theme you are
using. If you are new to Drupal, we recommend supplying all the information for these boxes. If
you decide that you don’t need or like how Drupal uses them, you can change it later (see the
handbook section on configuring themes for more on this).

Settings
Below are links to provide you with explanations and tips for some of the more technical
settings on the "settings" page. If you just want to get Drupal up and running, you can safely
ignore these settings. You’ll always be able to come back and experiment with them later. The
one possible exception to this is the "file system settings" which you may wish to set now. For
more information on the "File system settings," click its link below. This link can also help you
resolve issues with errors that often appear at the top of the "settings" page after Drupal is
freshly installed.

You can

configure your sites basic settings at administer >> settings.

139
Drupal Handbook 3 Aug 2007

General settings
The General settings area is where you configure some basic information for your site.

Name: this is where you set the name displayed for your site.

E-mail address: A valid e-mail address for this website, used by the auto-mailer during
registration, new password requests, notifications, etc. You can set this to a real email address
that people can reply to or to something generic no-reply@example.com that is outbound only.
The email server that your site uses is set in the php.ini file and not by Drupal.

Slogan: The slogan of this website. Some themes display a slogan when available. It will also by
displayed in the title bar of your sites visitor web browser.

Mission: Your site’s mission statement or focus. Your mission statement is enabled in your
theme settings and requires that the theme support it’s display.

Footer: This text will be displayed at the bottom of each page. Useful for adding a copyright
notice to your pages.

HTML formating can be used in the mission and the footer areas.

Anonymous user: Users who interact with your site without being logged in are labeled as
"Anonymous" by default. Drupal gives you the option to change this to something different (e.g.
"Anonymous coward"). The name you give anonymous users is used by Drupal when creating
bylines for posts which typically reads something like, "Posted by Anonymous on January 1,
2006".

Default front page


This setting gives you control over what Drupal-generated content a user sees when they visit
your Drupal installation’s root directory. For example, you might have created a node with a
large collection of links to act as a table of contents to the different sections of your site and you
want this directory to be what users see first.

This setting tells Drupal which URL users should be redirected to. It’s important to note that the
URL is relative to the directory your Drupal installation is in. So, instead of

"http://www.example.com/node/83"

or

"http://www.example.com/drupal_installation_directory/node/83,"

you need only type "node/83". For those not using clean URLs, note that there is no need to type
in "?q=" before typing the URL.

140
3 Aug 2007 Drupal Handbook

By default, the "Default front page" is set to "node," which simply displays articles that have
been "Promoted to front page." Note that when you change the "Default front page" to
something other than "node", nodes that are "Promoted to front page" will no longer appear on
the front page. They can however, still be viewed by visiting the relative URL path "node".

If you enter a value in here that is not a valid Drupal path, the user will be confronted with a
"Page not found" error. You cannot redirect users to any web documents (e.g. a static HTML
page) not created by your Drupal site.

Examples
Problem 1:
You want a particular node to be the first page user’s see when they visit
http://www.example.com (we are assuming Drupal is installed in the site’s root directory).
Solution:
Determine the id number of the node you wish to have Drupal redirect users to. One way to
determine the node’s id number is to visit the node and look at the number after the last
slash in your browser’s address bar. This is your node’s id number. Now set the "Default
front page" to "node/id#". So, assuming your node’s id is "83," you would type "node/83".
Problem 2:
You want user blogs to be the front page.
Solution:
Set the "Default front page" to "blog".
Problem 3:
You want content from a single category to appear on the front page
Solution:
Determine the category’s id number. You can determine the id number by going to
administer » categories. Roll the mouse on top of the "edit term" link next to the category to
reveal the URL in your browser’s status bar (usually located at the bottom of your browser’s
window). The number after the last slash in the URL is the category’s id number. Now set
the "Default front page" to "taxonomy/term/id#". If your category’s id number is "5" for
example, you’d write "taxonomy/term/5".

Clean URLs
By default, Drupal passes path arguments to itself via its internally generated URLs. This results
in URLs that look like the following: "http://www.example.com/?q=node/83." This can make
URLs hard to read and it also stops many search engines, like Google, from indexing the pages
with these URLs.

You can tell Drupal to use "clean URLs", eliminating the "?q=" in internal URLs. Note that this
works only for Apache servers which have the LoadModule rewrite_module configured and
mod_rewrite enabled in httpd.conf configuration file.

141
Drupal Handbook 3 Aug 2007

There are two ways to enable URL rewrites in Apache. If there is complete control of the Apache
webserver clean URLs should be enabled in the httpd.conf as this has better performance and
security.

Warning. Enabling "Clean URLs" if your server is not properly configured can make it difficult
to navigate back to administration pages to undo your mistake. If you find yourself in this
situation, you can return to the administrative settings page by typing in the URL in the
’non-clean’ form: http://www.example.com/?q=admin/settings.

Enabling clean URLs involves three steps:

1. Enable mod_rewrite for Apache. Please talk to your web host or consult the Apache
documentation for mod_rewrite to get more information on how to do this. At a minimum,
this will involve making sure that mod_rewrite is enabled for your installation of Apache. It
will have to be either compiled-in or made available as a loadable module. Generally
speaking, you can tell Apache to load the module by including
LoadModule rewrite_module modules/mod_rewrite.so
AddModule mod_rewrite.c

in your Apache configuration file. Be sure to uncomment AddModule mod_rewrite.c. Note


that this may not be the case for all distributions of *nix operating systems. Consult your
distribution’s documentation that came packaged with your Apache software. We also
recommend disabling multiviews in Apache as they conflict with clean URLs.

2. Edit your Apache configuration files for your site: the configuration information may be
found in httpd.conf, a virtual-host-specific file, or in an .htaccess file in your Drupal
installation directory. You can find this file usually in /etc/httpd/conf/httpd.conf. You
may use
find /etc -name httpd
to find the file if it is located else where in your Unix system. The main configuration option
which may need to be changed for your site is the RewriteBase. For example, if your
Apache DocumentRoot is /var/www/ (i.e., /var/www/index.html is what is displayed
when you point your browser at http://www.example.com/) and your Drupal installation
is installed in the subdirectory /var/www/mysite/, then the RewriteBase should be set to
/mysite. In some configurations setting
RewriteBase /
will allow mod rewrite to work.

If you don’t use the .htaccess that comes with Drupal you’ll need to add some rewrite rules
into your apache directory directive. Consult the .htaccess file in Drupal for examples of
rules.

142
3 Aug 2007 Drupal Handbook

<Directory /var/www/example.com>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</Directory>

You will also need to set the Allow Override settings in httpd.conf so that local .htaccess
commands will be run for you site. If you are changing the .htaccess file in the Drupal
distribution you want to set it to

AllowOverride All
to ensure rewrites are enabled. Read "Behind the scenes with Apache’s .htacces for a
thorough review of .htaccess.Here are samples of Apache 2 directives.
3. You should ensure your Drupal site has the path module enabled and the correct
permissions set in order to create custom URLs. You can enable the path module in
administer >> modules. You can then set permissions to administer URL aliases and create
URL aliases. Enable clean URLs on your administration >> settings page. First, see if you
can go to the settings page on your site using clean URLs: type in the URL
http://www.example.com/admin/settings (where www.example.com is replaced by your
hostname). If you get no errors and get to the same page you would have gotten to by clicking
on "administer" then "settings" , then you know that you have setup the ReWriteRule rules
successfully and can then click the Yes checkbox for "Clean URLs:" . If you have problem you
can read the instructions to unset clean URLs. If you If you still have problems with clean
URLs you can set the Drupal Settings.php $conf[’clean_url’]=1;.

Note: The standard Drupal installation contains a sample .htaccess file which supports clean
URLs. It is easy to miss copying this file, because of the leading "dot".

Note Regarding MultiViews: The Apache webserver supports a feature called "MultiViews"
(more generally: "Content Negotiation"), which allows navigation to your pages without the
need for file extensions. For instance, if you had a file called "evaluation.txt", a
MultiViews-enabled site could access this file with the URL "example.com/evaluation". While
MultiViews can be a handy feature when used knowingly, they can cause problems when
Drupal’s Clean URLs are enabled. Unless you know what you’re doing, you should consider
disabling MultiViews if you plan to use the clean URLs feature of Drupal. Be aware that there’s a
good chance that MultiViews is already disabled, however; it’s not enabled in a default Apache
installation. Consult the Apache documentation for further information about MultiViews.

.htaccess for clean urls on specific shared hosts


zorroposada posted this .htaccess file, the use of which then allowed clean urls to be enabled
when using several hosts like 1and1.com, mediatemple.net, ehostpros.com, ehosting.ca

143
Drupal Handbook 3 Aug 2007

bobdonohue reported that this .htaccess file worked on dotster.

This code was taken from the boost.module and modified just a little bit.

There is no guarantee this will work for you though.

Instructions:

Create a text file, copy and paste the code below and save it as .htaccess

Upload the file and put it in the public_html directory of your site.

Modify "RewriteBase /" in line 68 to "RewriteBase /example" if your site is in


subdirectory "example."

#
# Apache/PHP/Drupal settings:
#
# Protect files and directories from prying eyes.
<FilesMatch
"(\.(engine|inc|install|module|sh|.*sql|theme|tpl(\.php)?|xtmpl)|code-style\.pl|Entries.*|Repository|Root)$">
Order deny,allow
Deny from all
</FilesMatch>
# Set some options.
Options -Indexes
Options +FollowSymLinks
# Customized error messages.
ErrorDocument 404 /index.php
# Set the default handler.
DirectoryIndex index.php
# Override PHP settings. More in sites/default/settings.php
# but the following cannot be changed at runtime.
# PHP 4, Apache 1
<IfModule mod_php4.c>
php_value magic_quotes_gpc 0
php_value register_globals 0
php_value session.auto_start 0
</IfModule>
# PHP 4, Apache 2
<IfModule sapi_apache2.c>
php_value magic_quotes_gpc 0
php_value register_globals 0
php_value session.auto_start 0
</IfModule>
# PHP 5, Apache 1 and 2
<IfModule mod_php5.c>
php_value magic_quotes_gpc 0

144
3 Aug 2007 Drupal Handbook

php_value register_globals 0
php_value session.auto_start 0
</IfModule>
# Reduce the time dynamically generated pages are cache-able.
<IfModule mod_expires.c>
ExpiresByType text/html A1
</IfModule>
# Various rewrite rules.
<IfModule mod_rewrite.c>
RewriteEngine on
# If your site can be accessed both with and without the prefix www.
# you can use one of the following settings to force user to use only
one option:
#
# If you want the site to be accessed WITH the www. only, adapt and
uncomment the following:
# RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
# RewriteRule .* http://www.example.com/ [L,R=301]
#
# If you want the site to be accessed only WITHOUT the www. , adapt
and uncomment the following:
# RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
# RewriteRule .* http://example.com/ [L,R=301]
# Modify the RewriteBase if you are using Drupal in a subdirectory
and
# the rewrite rules are not working properly.
RewriteBase /
# Rewrite old-style URLs of the form ’node.php?id=x’.
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{QUERY_STRING} ^id=([^&]+)$
#RewriteRule node.php index.php?q=node/view/%1 [L]
# Rewrite old-style URLs of the form ’module.php?mod=x’.
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{QUERY_STRING} ^mod=([^&]+)$
#RewriteRule module.php index.php?q=%1 [L]
# Rewrite rules for static page caching provided by the Boost module
# BOOST START
<IfModule mod_mime.c>
AddCharset utf-8 .html
</IfModule>
RewriteCond %{REQUEST_URI} !^/cache
RewriteCond %{REQUEST_URI} !^/user/login
RewriteCond %{REQUEST_URI} !^/admin
RewriteCond %{HTTP_COOKIE} !DRUPAL_UID
RewriteCond %{REQUEST_METHOD} ^GET$

145
Drupal Handbook 3 Aug 2007

RewriteCond %{QUERY_STRING} ^$
RewriteCond %{DOCUMENT_ROOT}/cache/%{SERVER_NAME}/0/%{REQUEST_URI} -d
RewriteCond
%{DOCUMENT_ROOT}/cache/%{SERVER_NAME}/0/%{REQUEST_URI}/index.html -f
RewriteRule ^(.*)$ cache/%{SERVER_NAME}/0/$1/index.html [L]
RewriteCond %{REQUEST_URI} !^/cache
RewriteCond %{REQUEST_URI} !^/user/login
RewriteCond %{REQUEST_URI} !^/admin
RewriteCond %{HTTP_COOKIE} !DRUPAL_UID
RewriteCond %{REQUEST_METHOD} ^GET$
RewriteCond %{QUERY_STRING} ^$
RewriteCond
%{DOCUMENT_ROOT}/cache/%{SERVER_NAME}/0/%{REQUEST_URI}.html -f
RewriteRule ^(.*)$ cache/%{SERVER_NAME}/0/$1.html [L]
# BOOST END
# Rewrite current-style URLs of the form ’index.php?q=x’.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</IfModule>
# $Id: boosted.txt,v 1.4 2006/12/05 10:39:19 arto Exp $

403 Permission denied error


So you’ve tried every advice above but still get the 403, "You don’t have permission to access",
error when testing for clean urls. This is how I solved it after many tedious hours of googling....

Apparently there’s an option called Multiview in apache which enables the server to look for
files without an extension in the parent directory of the directory you specified, if it can’t find
the directory. So if you type www.mysite.com/admin/settings and it can’t find the directory it
looks for a file named settings.(some extension) in www.mysite.com/admin, however if you
also have directory browsing turned of and it can’t find a file it will report it as you trying to
find a file in www.mysite.com/admin which you don’t have a permission to view or doesn’t
exist i.e. the 403 error. To solve this you either turn of diretory browsing in your .htaccess file by
writing:

Options +Indexes

instead of

Options -Indexes

However if you don’t feel like having directory browsing on, I guess most people do, you just
turn of Multiviews like this under the other options in your .htaccess file:

146
3 Aug 2007 Drupal Handbook

Options -MultiViews

A mod_rewrite bug causing occasional corruption of the query string


It seems that using mod_rewrite to set or modify the query string can corrupt it. One case where
it certainly fails is if the URL has %2B (a urlencoded "+" character) in it.

As a demonstration, try searching for the string "alice + bob". You can see on
http://drupal.org/search/node/alice+%2B+bob that the rewrite rules change the %2B to a
space, while on http://drupal.org/?q=search/node/alice+%2B+bob it work correctly without
clean URLs.

The reason I am posting it here as a warning and not as a bug report is that it’s not a Drupal
issue, but a mod_rewrite issue. (It would be worth a bug report for mod_rewrite, but they have
such bug reporting guidelines that require a few hours’ work to follow...)

Apache 2 configuration of clean URLs on Debian


If you’re running Apache2 on Debian stable, in order to install the rewrite module you simply
need to:

# a2enmod rewrite

then restart the webserver:

# /etc/init.d/apache2 restart

then edit either /etc/apache2/sites-enabled/drupal or to your .htaccess and ensure it looks


something like this:

#
# Apache/PHP/site settings:
#
# Protect files and directories from prying eyes:
<Files ~
"(\.(conf|inc|module|pl|sh|sql|theme|engine|xtmpl)|Entries|Repositories|Root|scripts|updates)$">
order deny,allow
deny from all
</Files>
# Set some options
Options -Indexes
Options +FollowSymLinks
# Customized server error messages:
ErrorDocument 404 /index.php
# Set the default handler to index.php:
DirectoryIndex index.php
# Overload PHP variables:
<IfModule sapi_apache2.c>

147
Drupal Handbook 3 Aug 2007

# If you are using Apache 2, you have to use <IfModule


sapi_apache2.c>
# instead of <IfModule mod_php4.c>.
php_value register_globals 0
php_value track_vars 1
php_value short_open_tag 1
php_value magic_quotes_gpc 0
php_value magic_quotes_runtime 0
php_value magic_quotes_sybase 0
php_value arg_separator.output "&amp;"
php_value session.cache_expire 200000
php_value session.gc_maxlifetime 200000
php_value session.cookie_lifetime 2000000
php_value session.auto_start 0
php_value session.save_handler user
php_value session.cache_limiter none
php_value allow_call_time_pass_reference On
</IfModule>
# Various rewrite rules
<IfModule mod_rewrite.c>
RewriteEngine on
Options All
# Modify the RewriteBase if you are using Drupal in a subdirectory
and the
# rewrite rules are not working properly:
RewriteBase /drupal
# Rewrite old-style URLS of the form ’node.php?id=x’:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} ^id=([^&]+)$
RewriteRule node.php index.php?q=node/view/%1 [L]
# Rewrite old-style URLs of the form ’module.php?mod=x’:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} ^mod=([^&]+)$
RewriteRule module.php index.php?q=%1 [L]
# Rewrite URLs of the form ’index.php?q=x’:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</IfModule>
# $Id: .htaccess,v 1.58 2004/10/09 20:41:49 dries Exp $

This is because the debian package installs the drupal "sites-enabled" virtual host, result being
that drupal is accessed from http://yourhost.com/drupal, hence the need to uncomment
RewriteBase. Change it to the base that corresponds to your system.

148
3 Aug 2007 Drupal Handbook

ref: http://www.debian-administration.org/articles/136
http://drupal.org/node/14322

--
Sean K. O’Brien
CTO
Colley Graphics, LLC
http://www.colleygraphics.com

Apache 2 on Ubuntu
Two methods here:

Editing apache2.conf

First thing to do is make sure you have apache up and running:


/etc/init.d/apache2 start

Then you have to enabled the rewrite module(mod_rewrite). You no longer have to do the:
LoadModule rewrite_module modules/mod_rewrite.so
AddModule mod_rewrite.c

It’s now as easy as:


a2enmod rewrite

To disable this module it’s just:


a2dismod rewrite

with Apache version 2, the httpd.conf has been depreciated and the new file is located at:
/etc/apache2/apache2.conf

in this file you need to add your directory and the allow override to give access to your drupal
site.
so look for a section in your apache2.conf that has Directory tags and just add another section:

<Directory /var/www/drupal_website_install>
AllowOverride all
</Directory>

*keep in mind that my website is in a subdirectory (drupal_website_install) and so you may


need to edit the above to reflect this. By this I mean if i go into my webbrowser I need to go to
http://localhost/drupal_website_install/

After you edit you apache2.conf as listed above you need to restart the server by:
/etc/init.d/apache2 restart

149
Drupal Handbook 3 Aug 2007

If you are having problems with getting your rewrite to work you can always use logging. To do
that add this to the end of you apache2.conf:

RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 3

Level 0 is no logging
Level 9 is log everything
You can pick the level to determine the amount of output you need.
***Security Warning: Make sure to take the log code out, disable it, or put the log file in a
directory that can’t be read by normal users (as shown above) otherwise it can result in a
security breach.***
hopefulley this helps some people and saves them the time that I spent trying to get it working.

Editing apache2/sites-available

My configuration:
drupal 5.x
apache 2.2
mysql 5.0
debian/ubuntu server install

drupal path: /www/drupal/sites/site1...site2

I have root access to my server.

First, from the linux command line, I enabled the rewrite module for apache like this:

a2enmod rewrite

Next I restarted Apache:

sudo /etc/init.d/apache2 restart

Then I reloaded Apache config files:

sudo /etc/init.d/apache2 reload

Finally, I changed the file located at:

/etc/apache2/sites-available/default

(in the sites-available directory, you should see as many files as you have websites enabled. One
is named default and the others should reflect the names of your additional sites if you are
running virtual hosts. If you have only a single site, it will most likely be named default. You can
open these files in an editor such as nano and make changes.)

150
3 Aug 2007 Drupal Handbook

change this directive in the file(s) found in sites-available:

AllowOverride None to AllowOverride All

Save this file and then restart apache as we did above.

Now browse to your site with your browser, login, click administer, find "Clean URLs" and
browse to that page, run the test for "Clean URLs" buried in the paragraph explaining "clean
Urls".

If your setup is like mine, you should now have Clean URLs in drupal.

Clean URL Support in Abyss


This clean URL implementation has been tested on Abyss X1, one which has a properly set
Custom Error Page 404 to any arbitrary file that, for this purpose, will be referenced as
"/url_rewrite.php". Due to the generalized design of this solution, this method could
theoretically work on virtually any webserver that can redirect missing URI location onto a php
resource. The method described here works only on webservers with a singular host
configuration.

One esoteric requirement is for the webserver to pass the server variable REQUEST_URI
containing the value of the original resource requested. For more information on configuring
Abyss X1 for this purpose, please visit this Aprelium forum resource.

This solution could be rendered academic if Aprelium finally decides to implement URL rewrite
in Abyss internally. This method is useful for Abyss webservers version 2.3.2 and most other
versions prior to this specific release. Another drawback is that the URL rewrite becomes only
invisible to the machine but is always visible to the human.

The idea is to pass (or redirect) the missing URI location on the HTTP-404 handler
"/url_rewrite.php". For illustrative examples, let’s look at the following scenarios:

1. http://www.example.com/node/add => "/node/add" not found, pass to 404 handler


"/url_rewrite.php" => "/url_rewrite.php" determines "/index.php?q=node/add" exists and
serves that instead.
2. http://www.example.com/admin/settings => "/admin/settings" not found, pass to 404
handler "/url_rewrite.php" => "/url_rewrite.php" determines
"/index.php?q=admin/settings" exists and serves that instead.
3. http://www.example.com/no_exist/location => "/no_exist/location" not found, pass to
404 handler "/url_rewrite.php" => "/url_rewrite.php" determines
"/index.php?q=no_exist/location" exists and serves that instead but lets Drupal display the
proper "page not found" informational message.

Here are the steps in letting this method apply to your setup.

151
Drupal Handbook 3 Aug 2007

1. Create the following file and save it as "/url_rewrite.php".


<?php
/* Add in this array the list of (old path => new path) pairs */
$redirection = array(
’^(.*)$’ => ’index.php?q=$1’
);
if (!file_exists($_SERVER["REQUEST_URI"]))
/* Get the URI and trim leading slashes */
$uri = ltrim($_SERVER["REQUEST_URI"], "/");
{
foreach ($redirection as $key => $value)
{
if (eregi($key, $uri))
{
/* Convert the replacement string syntax - $1 -> \1 */
/* and perform the substitution */
$uri = str_replace("index.php","",substr($uri,0));
$new_uri = str_replace("?","&",$uri);
$new_uri = "/index.php?q=".$new_uri;
$new_uri = str_replace("%26","&",$new_uri);
break;
}
}
}
if (isset($new_uri))
{
header("Status: 307");
header("Location: $new_uri");
exit;
}
?>
<!-- Your 404 error page -->
<HTML>
<HEAD>
<TITLE>Not Found</TITLE>
</HEAD>
<BODY>
The object <tt><?php echo $uri; ?></tt> is not available.
</BODY>
</HTML>
2. In the Abyss web console, enter the Custom Error Pages, add a 404 Status Code entry with
the Associated URL value "/url_rewrite.php". Click OK and restart the Abyss webserver.
3. Test for functionality by querying your website directly with URI’s such as:
http://www.example.com/admin/settings
http://www.example.com/node/add

152
3 Aug 2007 Drupal Handbook

If the redirection works properly, proceed to the next steps. If the redirection would not
work, check if the steps above have been strictly followed. Modify only those things that you
have absolute knowledge of.

4. Log on to your website and log on to your "/admin/settings" page. Under General Settings
section, enable Clean URLs. If the Clean URLs option is grayed out, add the line
"$conf[’clean_url’] = 1;" in your settings.php, then repeat this step. Don’t forget to click the "Save
configuration" button.
5. If things do not work out, completely remove the line "$conf[’clean_url’] = 1;" from your
settings.php. And browse to your http://www.example.com/index.php?q=admin/settings
page to disable Clean URLs properly.

Clean URL support in XAMPP


Clean URLs do not work out of the box on XAMPP 1.5.x with PHP4 due to a problem in
Apache’s module load order; mod_rewrite will not work properly. To remedy this edit the file
[path_to_xampp]/apache/conf/httpd.conf.

Move the line

LoadModule rewrite_module modules/mod_rewrite.so


to just above or below
#LoadModule cache_module modules/mod_cache.so

You also have to set AllowOverride All for the directory Drupal is in. Do this in
httpd.conf or extra/httpd-xampp.conf

Always restart Apache or changes to its configuration files won’t have an effect.

If Drupal is not installed in the document root, the next thing you’ll have to do is to modify the
file .htaccess, that comes with Drupal. Remove the commentsign (#) in front of RewriteBase
and, if necessary, modify the path:

RewriteBase /drupal

Finally, in Drupal go to administer » settings (admin/settings) and click the "Enabled" option for
Clean URLs and save the settings.

Clean URLs in Mac OS X Server


For Mac OS X Server 10.4 (Tiger Server) and most likely previous versions as well, do not make
changes to /etc/httpd/httpd.conf expecting the AllowOverride All directive to work.
The correct file to add the AllowOverride All directive is in the directory
/etc/httpd/sites/. In that directory are the virtual host configuration files. Each virtual
server has a configuration file in that directory so it is in those files that you must enable
AllowOverride All. If you only have one web server on your server configured, then the file
you want to modify is /etc/httpd/sites/0000_any_80_.conf.

153
Drupal Handbook 3 Aug 2007

Clean URLs with different webservers


Microsoft Internet Services Server

Windows ISS MySQL PHP(WIMP)-Tips for Configuring Drupal on WIMP

Lighttpd

For those who have stepped up a notch in performance and moved from Apache to Lighttpd,
you can use the following configuration for Lighty’s mod_rewrite module:

url.rewrite-final = (
"^/system/test/(.*)$" => "/index.php?q=system/test/$1",
"^/([^.?]*)\?(.*)$" => "/index.php?q=$1&$2",
"^/([^.?]*)$" => "/index.php?q=$1"
)

The first line ensures that Drupal’s clean URL check (when saving Settings) succeeds (Drupal
makes an HTTP request for a path of the form /system/test/yLgnwqqUu5cWnvPi4Hrz.png). It’s a
special case that must be handled separately (read on for the reason).

The two following lines let Drupal handle any URL that doesn’t contain a dot. This is significant
because we can assume, fairly confidently, that addresses like /node/add are Drupal URLs, but
addresses such as /themes/bluemarine/style.css are physical files. So the above configuration will
work for all cases where this assumption holds true; if there are exceptions to the rule, they can
be manually added to the rewrite configuration.

See also the related discussion at http://drupal.org/node/20766

I just successfully set up lighttpd 1.4.8 with php4 via fastcgi using those rules above.
As per lighttpd documentation I also set up /etc/php4/cgi/php.ini to have that cgi fix. Then I
added those rewrite rules for corresponding virtual_host.

Ubuntu breezy’s php4-cgi package


bougyman’s lighttpd package (see http://www.lighttpd.net/download/ for details)

Clean URLs with Easyphp.


To get that the clear URLs works in Easyphp 1.8 you have to join the httpd.conf file and change
this two lines:

#LoadModule rewrite_module modules/mod_rewrite.so

and

#AddModule mod_rewrite.c

154
3 Aug 2007 Drupal Handbook

and leave like this in the same line.

LoadModule rewrite_module modules/mod_rewrite.so

AddModule mod_rewrite.c

and Re-start the server.

Easyphp have the mod_rewrite within.

If there is any problem tell me.

Oskar Calvo.

Example Clean URL configuration of httpd.conf for performance


This was tested and applies to FC4/php5/Apache 2.0.54.

Enabling .htaccess in Apache requires more work on the part of the server. A full explanation
can be found here:
http://www.serverwatch.com/tutorials/article.php/3436911
Suffice it to say that it is in your interest to not use .htaccess files and even disable them if you
are concerned about squeezing more performance out of apache.

I moved the rewrite rules (all of the sample .htaccess file really) to /etc/httpd/conf/drupal.conf.
Then for each virtual host, one can add the line:

Include conf/drupal.conf
The rewrite rules change slightly:
# Rewrite current-style URLs of the form ’index.php?q=x’.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

Note that I added %{DOCUMENT_ROOT} and a leading slash in front of index.php -- because I
have index.php installed in my document root. If you install it in another directory, you will
want to give the relative path to it from document root with the leading slash.

Important: If you forget the leading slash (more specifically, forget to give the relative path with
leading slash), Apache will give you a "400 Bad Request" error.

This is better. But we still have a problem where every request will check for the existence of a
file and a directory before we apply the rewrite rule. The OS may be able to cache some of that
information, but it would still be better to avoid the two file-system checks in the first place.

155
Drupal Handbook 3 Aug 2007

There are some directories that we should not rewrite. And there are certain extensions that we
should not rewrite. Using this information, we can update the rewrite rule to send everything to
index.php that does not fall into this category. The first rule excludes the directories "files",
"misc", and "uploads". The second rule excludes the extensions you see. Add more if you have
other extensions in your directory that should not get passed to index.php.

RewriteCond %{REQUEST_FILENAME} !^/$


RewriteCond %{REQUEST_FILENAME} !^/(files|misc|uploads)(/.*)?
RewriteCond %{REQUEST_FILENAME}
!\.(php|ico|png|jpg|gif|css|js|html?)(\W.*)?
RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

Existing URLs for server overwrite Drupal paths


If your server has existing paths like /admin then you can either move your Drupal instance to a
subdirectory like /home/admin or you can create a virtual link to ?=admin.

IIS CleanURLs using some of the available ISAPI filters.


There is a free version called ISAPI_Rewrite Lite that should get clean URLs working for IIS.
Install that and insert these rewrite rules.

# Accept a url with the following extensions and pass them through
unchanged.
RewriteRule (.*.gif|.*.png|.*.jpg|.*.pdf|.*.js|.*.css) $1 [I,L]
# Make URLs sane
RewriteRule /index.php.* $0 [I,L]
RewriteRule /(.*)\?(.*) /index.php\?q=$1&$2 [I,L]
RewriteRule /(.*) /index.php\?q=$1 [I,L]

Next, add the following line to the end of your settings.php file for your site:

$conf[’clean_url’] = 1;

Translating Apache’s rewrite rules

RewriteCond %{REQUEST_FILENAME} !-f


RewriteCond %{REQUEST_FILENAME} !-d

In plain English: If the REQUEST_FILENAME variable does not exist (not an existing file and
not an existing directory) then apply the rule:
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]"

After much research this exact functionalty does not appear to exist in any ISAPI module for IIS.
I think the following solution will help solve this issue. It probably works with most "ISAPI
rewrite" modules (they just need the "stop the rewriting process" option).

156
3 Aug 2007 Drupal Handbook

With this approach you basically revert the "Apache Rewrite" logic. First define rules for
known files/folders (like /themes/ ..etc..). Have those "matching rules" exit, so rules processing
stops before going to the next rule. With mod_rewrite.dll you can do that with the option [l].

Here is what my rules file looks (so far) like (using mod_rewrite.dll):
RewriteRule ^/index.php\?q\=(.*)$ /index.php?q=$1 [l]
RewriteRule ^/themes/(.*)$ /themes/$1 [l]
RewriteRule ^/misc/(.*)$ /misc/$1 [l]
RewriteRule ^/(.*)$ /index.php?q=$1 [l]

Remember, you have to add an "exiting" rule for all known folders/files before hitting the final
rule. The first rule is to avoid recursion and exit immediatly if the URL already has
index.php?q=.

To better understand the Apache rules here are the definitions of the main options:
’last|L’ (last rule)
Stop the rewriting process here and don’t apply any more rewriting rules. Use this flag to
prevent the currently rewritten URL from being rewritten further by following rules.

’qsappend|QSA’ (query string append)


This flag forces the rewriting engine to append a query string part in the substitution string to
the existing one instead of replacing it. Use this when you want to add more data to the query
string via a rewrite rule.

REQUEST_FILENAME
The full local filesystem path to the file or script matching the request.

’-d’ (is directory)


Treats the TestString as a pathname and tests if it exists and is a directory.
’-f’ (is regular file)
Treats the TestString as a pathname and tests if it exists and is a regular file.

Note: Getting Apache running on MS Windows is not that bad (I had been delaying it for years).
In reality it’s a matter of a few hours to get going. http://www.sitebuddy.com aims to save you
time in that endeavor.

Pathauto and Localizer


I was looking for a way to include node language into pathauto recognizable variables, this is
how I managed to do it, you will be able to use [locale] in your nodes path.

In your pathauto_node.inc you need to add these lines:

This one is shown in the pathauto config

<?php
function node_pathauto($op) {
switch ($op) {

157
Drupal Handbook 3 Aug 2007

case ’settings’:
$settings[’bulkdescr’] =
?>
...
<?php
// LOCAL ADDON
t(’[locale]’) => t(’The locale used for this node.’),
?>

These will be loading the data

<?php
function node_get_placeholders($node) {
?>
...
<?php
// LOCAL ADDON
$result = db_query("SELECT locale FROM {localizernode} WHERE
nid=’%d’", $node->nid);
$nodelocale = db_fetch_object($result);
$placeholders[t(’[locale]’)] =
pathauto_cleanstring($nodelocale->locale);
?>

Hope this helps someone !

Setting up clean URLs above web document root on virtual private


servers
To set up clean URLs above web document root on virtual private servers, you need to change a
setting in httpd.conf.

(default setting)
Options FollowSymLinks
AllowOverride None

Change it to
Options FollowSymLinks
AllowOverride All

None of the other changes discussed in this section of the handbook were necessary (and in fact
had to be undone).

The hosting provide said this does not provide any security issues (no guarantees).

158
3 Aug 2007 Drupal Handbook

reboot vps after making change

This is excellent advice. I installed a test site at /var/www/test. My live site is at


/var/www/html. The live site worked fine. In the test site i went to set clean url’s and got an
apache error.

This fixed it.

One minor note. I had to reset the vps before the changes took affect. With my hosting company
this is simply a menu selection in their control panel, so if you have this setup and make the
change and it does not work.

Ask your provider to reset your Virtual Private Server. This is simular to stopping and starting
Apache on a Windows install.

Using Clean URLs with IIS


Drupal can display brief, pretty URLs like those at drupal.org. For Apache sites, mod_rewrite
powers this feature. For IIS, you will use a custom error handler for this. You probably want to
disable logging in IIS, since every page view is considered an error using this technique.

make sure your Drupal is working well without clean urls enabled.
open your Internet Services Manager or MMC and browse to the root directory of the web
site where you installed Drupal. You cannot just browse to a subdirectory if you happenned
to install to a subdirectory.
right click and select properties -> custom errors tab
set the HTTP Error 404 and 405 lines to MessageType=URL, URL=/index.php. If you are
using Drupal in a subdirectory, prepend your subdir before /index.php
paste the following code into the bottom of settings.php file, which is usually located
under sites/default/. the first two lines should be edited. If you aren’t using a
subdirectory, set $sub_directory to "". then set $active=1 and enjoy!
<?php
// CONFIGURATION
$sub_dir = "/41/"; // enter a subdirectory, if any. otherwise, use
""
$active = 0; // set to 1 if using clean URLS with IIS
// CODE
if ($active && strstr($_SERVER["QUERY_STRING"], ";")) {
$qs = explode(";", $_SERVER["QUERY_STRING"]);
$url = array_pop($qs);
$parts = parse_url($url);
unset($_GET, $_SERVER[’QUERY_STRING’]); // remove cruft added by
IIS
if ($sub_dir) {
$parts["path"] = substr($parts["path"], strlen($sub_dir));
}
$_GET["q"] = trim($parts["path"], "/");

159
Drupal Handbook 3 Aug 2007

$_SERVER["REQUEST_URI"] = $parts["path"];
if ($parts["query"]) {
$_SERVER["REQUEST_URI"] .= ’?’. $parts["query"];
$_SERVER["QUERY_STRING"] = $parts["query"];
$_SERVER["ARGV"] = array($parts["query"]);
parse_str($parts[’query’], $arr);
$_GET = array_merge($_GET, $arr);
$_REQUEST = array_merge($_REQUEST, $arr);
}
}
?>
at this point, you should be able to request clean url pages and receive a proper page in
response. for example, request the page /node/1 and hopefully you will see your first node
shown. you should not use the q= syntax; use the clean url syntax. if you get an IIS error, you
have a problem. please fix redo the above and then retest.
browse to index.php?q=admin/system, enable clean URLS, and press Submit.
you may get a php error if your php error reporting in your php.ini file is set to high. Try
this setting in your php.ini file

error_reporting = E_ALL & ~E_NOTICE

Note: This method seems to work for IIS5 but not IIS6. Check this thread for some approaches
using ISAPI_Rewrite.

Alternate method

Alternatively, you can use ISAPI Rewrite by Helicon software to add mod_rewrite-like
functionality to IIS:
www.isapirewrite.com

set your sites 403 and 404 Error pages


Drupal’s page error messages are meant to be direct and to the point. If you want page error
messages that are a little more user-friendly, Drupal allows you to customize them. Just follow
these steps:

1. Create two nodes, one for each kind of page error (403 and 404).
2. Determine the id number of the node you wish to have Drupal redirect users to. One way to
determine the node’s id number is to visit the node and look at the number after the last
slash in your browser’s address bar. This is your node’s id number.
3. Now enter the paths to your nodes into the appropriate boxes. For example, if the node id
number for 403 error codes is "83," you would type "node/83" into the "Default 403 (access
denied) page" setting.

160
3 Aug 2007 Drupal Handbook

Because you are creating nodes for this, they will show up in the tracker and popular content
blocks and anywhere else real nodes would show up. If this isn’t acceptable, there is a
contributed module called Custom Error that avoids this problem.

Configure your sites error reporting


Where Drupal, PHP and SQL errors are logged. On a production server it is recommended that
errors are only written to the error log. On a test server it can be helpful to write logs to the
screen. By default, errors are displayed to the screen. You should change this to ’Write errors
only to log’ only for your production site.

You can tell Drupal to automatically discard error log entries older than the age you specify.
This requires a crontab (yoursite.com/cron.php) to be set up. See step 6 of the install.txt for
example of setup.

Cache support
Busy Drupal sites may want to consider caching their pages to lighten the load on their server
and speed up page generation times.

Normally, every time you visit a Drupal page, Drupal makes dozens of queries to the database
to pull out the data needed to generate the HTML that your web-browser renders. On a large
site with many modules installed or with lots of content on a page, the number of queries per
page could rise into the hundreds. Usually, you don’t notice all the work Drupal does because
computers are very fast and Drupal is very efficient. However, on very busy sites with many
hundreds or thousands of page views per minute, the amount of work required to serve each
page may start to slowing the server to a crawl.

Busy sites can reduce the work required to generate pages by enabling Drupal’s page cache.

With the cache turned on, Drupal stores all the HTML code for any page visited by an
anonymous user directly into the database. When another request for the same page comes
along, Drupal knows to fetch this page out of the database rather than re-generating it from
scratch. The result is that hundreds of queries are replaced with one single query, thereby
significantly lightening the load on the web server.

Primary and secondary links


General Information:
In versions 4.6 and below, primary and secondary links were handled in the theme
administration.

As of 4.7, primary and secondary links have been incorporated into the menu system. To have
primary and secondary links in your theme, you make them menu items. A fresh Drupal 4.7
install comes with an empty menu called "Primary Links" that is set to be used to display both

161
Drupal Handbook 3 Aug 2007

the primary and secondary links.

Setting Up Your Primary and Secondary Links:


There are two configuration screens that deal with these links:

On admin >> settings >> menu you choose which menu is used for the primary links and
which for the secondary links. If you have added items to the default "Primary Links" menu and
they are not showing up, check to make sure the option on this page hasn’t been changed to "No
Primary Links".

On admin >> menu you will find the default "Primary Links" menu and you should add your
links to that. You can also create a menu to hold the secondary links or create a different menu
for the primary links. Be sure to change the options on admin >> settings >> menu to use the
correct menu(s).

Theming Your Link Menus


You can display your links in two ways:

1) You can add the menu block to a region just like any other menu.
2) You can insert this code where you want the links to show up:

<?php if (isset($primary_links)) { ?><div id="primary"><?php print


theme(’links’, $primary_links) ?></div><?php } ?>
<?php if (isset($secondary_links)) { ?><div id="secondary"><?php
print theme(’links’, $secondary_links) ?></div><?php } ?>

You can then use CSS to theme your DIVs however you like.

Set length of trimmed posts and # of posts on front page


admin >> settings >> post

Here you can set the number of posts on main page and the length of trimmed posts. You also
set whether previewing posts is optional or required.

URL Alias Optimization


Drupal 6.0 implements a new feature to enhance site-performance: a whitelist/blacklist for URL
alias lookups. Database queries to find url aliases created by the path module are among the
most frequent in many Drupal installations. The performance setting allows administrators to
either define paths which will no be looked up (blacklist), or paths which will (whitelist).

Similar to the block visibility settings, you can use the * wildcard to define ranges of URLs.

162
3 Aug 2007 Drupal Handbook

The blacklist comes with a set of useful default urls. For many sites, enabling the blacklist will
reduce the number of overall queries to the database without degrading any functionality.
However, if you make extensive use of URL aliases, you should think about what settings work
best for you. If you have a small number of aliases, setting them up as a whitelist may be even
better.

File system settings


Drupal provides configuration settings to control whether, and how, users and administrators
can upload files for use by Drupal.

Note: Unconfigured or improperly configured Drupal installations may display one or more
error message at the top of the "settings" page, indicating that either the "Temporary directory"
or "File system path" directories do not exist and/or their permissions are not set properly.
Simply create these directories and set their permissions so that Drupal can write and read from
the directory.

If you are unsure about where or how to create these directories or how to change their
permissions, contact your web hosting service or software documentation for further assistance.

Download method
Download settings are configured in Administer >> Settings >> File system

There are two possible settings for download method: Public and Private.

Set to Public if you don’t care if any user, even anonymous users, can download the files
uploaded by other users.

Set to Private if you wish to restrict the ability of some users to download files uploaded by other
users.

Please note that if you set your download method as private, you should set your "files"
directory to be outside the document root for your drupal installation (i.e. not in
your_drupal_site/files or your_drupal/site/sites/all/files). The private download method also
has performance implications which you may want to consider.

If you change your settings at a later date, all download urls will change, therefore it’s best to
plan ahead when you set your drupal site up and think carefully about whether you’ll need to
restrict file downloads. If that’s the case we strongly recommend setting the file download
method to private when you first create your site to avoid broken links later on. If your
download method is set as private, all users will still be able to download files until you set
otherwise.

163
Drupal Handbook 3 Aug 2007

Path settings
File system path
By default, this is set to "files". We recommend leaving this setting alone.

Temporary directory
By default this is set to "/tmp" which is the temporary directory common in GNU/Linux
distributions. If you are using a Windows or other kind of server, we recommend setting it to
"tmp" (no slash). Drupal will automatically create the temporary directory as a subdirectoy of
the "File system path."

If it does not due to permissions or other configuration issue’s, you can create the file manually.

Date and time settings


Drupal allows you to configure how dates and times are formatted and displayed. When
making the format settings, you should probably consider the culture of your target audience.
Below are suggested configurations for the "Default time zone" and "Configurable time zones"
options.

For sites where most users live in a small geographic region:


Set the "Default time zone" to the time zone of the region and disable configurable time zones.

For sites where most users live a region that spans a few time zones:
Set the "Default time zone" to the time zone usually considered to be the "standard" time zone
and disable configurable time zones. For example, in the United States, you’d set your site’s time
to the timezone that corresponds to Eastern Standard Time.

For sites where users are likely to be scattered across the globe:
Set the "Default time zone" to the time zone to GMT (+0000) and enable configurable time zones.

Customizing the interface


When launching a new drupal site, here are some things you can do to personalize the design
and architecture of your drupal site.

Choose a Theme.

The look and feel of Drupal is primarily controlled by the theme you have applied to your
site. A site can even have multiple themes. A good first step is to go to administer > themes
and set a new theme as your default. You can find more themes on the download page after
the list of modules. Once you download a new theme you will need to install it on your
system.

Create your own Theme.

164
3 Aug 2007 Drupal Handbook

Many Drupal sites will need a more unique look than these pre-built themes can offer.
Therefore, many developers will want to write their own themes. Theme development
requires a working knowledge of HTML/CSS and possibly some rudimentary PHP depending
on the complexity of your theme.

Customize the Navigation.

The menus that are displayed on the top and bottom of the page are configured in administer
> themes. Select the configure tab and scroll down to Menu Settings. The primary and
secondary links can be defined here, using straight HTML. If the primary links are left blank
your navigation will be created based on your installed modules.

Each theme has an individual configuration page (listed at the top of the global settings
page) as well. Unfortunately, in Drupal 4.6 and previous using PHPTemplate your navigation
must be defined in that theme’s individual theme area.

In 4.7 PHPTemplate engine is incorporated into the Drupal core and the Primary and
Secondary links are now part of the menu system. Mention of this can be found here.

Customize Text Strings

You can also change the text strings throughout drupal using the locale feature, which was
designed for running drupal in different languages, you can personalize almost all of the text in
drupal.

In fact, you can replace a string like "create blog entry" with html markup such as references
to graphics.

Customizing user login


In the default setup the Drupal login block is always displayed unless a user is logged in. This
may not always be desirable. For example, if you are using Drupal to create a site that has a very
small number of people actually logging into the system to create or edit content, then you
probably don’t want a large portion of your screen real-estate taken up with a login block that
doesn’t relate to them. This also confuses the majority of your users that will not have the option
to login.

To disable the login block:

1. Goto the block configuration (administer » blocks)


2. Deselect the check box for User login in the Enabled column

Your regular content editors and administrators can still login to the site by directly accessing
the login page, http://www.example.com/?q=user. If you are using clean URLs you may also
use http://www.example.com/user, but remember that the ?q=user version will always work
whether you have clean URLs enabled or not.

165
Drupal Handbook 3 Aug 2007

You can also create more customized login blocks.

You can create name and email filter rules in admin >> access control >> account rules.

Set up username and e-mail address access rules for new accounts. If a username or email
address for a new account matches any deny rule, but not an allow rule, then the new
account will not be allowed to be created.

Beginner’s guide for Cron on a shared hosting


provider
This guide is excerpted from the original article on ThemeBot.com:
Time to talk about Cron - a beginner’s guide

If you have downloaded and installed Drupal 5, you will notice that there is an error in the
administrative log when you first sign in with your administrative account.

One or more problems were detected with your Drupal installation. Check
the status report for more information.

When you look at the status report you can go ahead and click the link "run cron manually" and
this will remove the error. However, you will eventually want to set up a Cron job to do this.
Having the Cron maintenance run regularly on an automatic schedule is important for keeping
your site indexed. If this is not done, new content that is added will not be included in search
results. Cron can also perform other tasks in Drupal, such as cleaning up log files. Also, some of
the contributed modules require that Cron maintenance is run regularly.

With the Drupal 5 installation package, there is a script included for Cron and it is called
cron.php. This file is located in the root directory of your Drupal installation. You can actually
run Cron maintenance by entering, for example, the URL
"http://www.yourwebsite.com/cron.php" into a web browser. But we want to get this done
automatically, so we need to call on the help of the Lynx browser. Lynx is a text browser that is
often installed on servers. You will need to contact your hosting provider to make sure that they
have Lynx installed (most probably do).

Once you know that Lynx is installed, you will need to find the configuration panel for setting
up a Cron job in your hosting account.

The first thing to do is enter the command. The following example is the command I use to make
Lynx run cron.php:

lynx -source http://www.yourwebsite.com/cron.php

You may need to adjust this command depending on your hosting provider.

166
3 Aug 2007 Drupal Handbook

The next step is to decide on a schedule to have this Cron job run. Running Cron does use
system resources, so you don’t want to have it running every minute if you don’t need to. It is
up to you to decide on an appropriate schedule for having each Cron job run. Understanding the
format for entering a schedule can take a little getting used to. Here is a quick rundown on
scheduling options that can be entered:

Minute â any integer from 00 to 59 (specifies the minute the job will be run on)
Hour â any integer from 0 to 23 (specifies the hour the job will be run on)
Day â any integer from 1 to 31 (must be a valid day if a month is specified)
Month â any integer from 1 to 12
Weekday â any integer from 0 to 7, where 0 or 7 represents Sunday

The asterik (*) specifies that the task should be run every time for any sub-constraint. This
statement doesn’t even make sense to me so let’s just have a look at the examples to figure it out.
You can also use the command */ to have jobs run every interval. Here the examples to help you
get the hang of it.

Run cron.php task every 30 minutes:

*/30 * * * * lynx -source http://www.yourwebsite.com/cron.php

Run cron.php task once a week at 1:00 am every saturday (you can see that saturday is
represented by 0):

00 1 * * 0 lynx -source http://www.yourwebsite.com/cron.php

Run cron.php task on the first day of every month at 12:00 am (midnight) :

00 0 01 * * lynx -source http://www.yourwebsite.com/cron.php

I hope this is helpful for beginners who have installed Drupal and are wondering how to setup
Cron.

Check your filters


Drupal input filters are a little known but powerful feature. They can give a site administrator a
lot of control over the input of their site. Some contributed modules add filters here to control
content display and link behavior.

In the Navigation menu, select administer / input formats. (?q=admin/filters)

167
Drupal Handbook 3 Aug 2007

Configure user registration


Configure the user registration options for your site (?q=admin/user/configure). The three
options for your Drupal based site are listed here.

Only site administrators can create new user accounts.


Visitors can create accounts and no administrator approval is required.
Visitors can create accounts but administrator approval is required.

If you allow user registration, take the time to customize the message to something appropriate
to your site and community. User picture support is also enabled/disabled here and relies on
the theme to have support for it.

These settings can be found in admin >> users >> configure in Drupal 4.6.

These settings can be found in admin >> settings >> users in Drupal 4.7.

Some sites may want to establish rules for user names, or block registration from certain email
domains. This can be done through the Account Rules tab in admin >> access
control(?q=admin/access/rules).

Set up username and e-mail address access rules for new accounts. If a username or email
address for a new account matches any deny rule, but not an allow rule, then the new
account will not be allowed to be created.

There is allowance for wildcards as well.

%: Matches any number of characters, even zero characters.


_: Matches exactly one character.

For example a rule of

%- :would prevent any user names ending in a dash


w_rd :would prevent any combination or w any 2nd character and rd

%: Matches any number of characters, even zero characters.


_: Matches exactly one character.

There is also a checking tool to check the effect of your rules.

Creating a menu structure


Drupal comes with a menu module that allows you to create infinitely nested menu trees. You
can activate this module at administer > modules if you can’t see the menu item labeled "menu" in
the "administer" menu.

168
3 Aug 2007 Drupal Handbook

A screencast of building a basic site navigation system using menu module is also available for
Drupal 4.7 users.

Creating a menu
1. To add a new menu, go to the menu module’s page at administer > menus. Click on "add menu"
and supply a title for your new navigation. If it is the main navigation, simply call it "Main
navigation" or "Default menu" or whatever you find appropriate.

2. Now that you have created your menu, enable it on the administer > blocks page checking the
"Enabled" checkbox after the menu name that you entered in step one. You can also change the
region and the weight of the menu. This affects where the menu is placed on the page. For a
detailed description of what are blocks and how to use them, consult the block module’s
handbook page. After having enabled the block, you should see an empty section on the side
that has the title you supplied for the menu.

3. Create menu entries. This can be done by going back to the menu module’s page and clicking
on "create menu item". Now you can enter a title for the new menu item, supply a short
description, define its path (for a detailed description on paths or url aliases, consult the
path.module’s handbook page).
Select the parent for the menu item. That means, you can select under which navigation item
your new menu item is filed. Selecting the item with the same title as your menu’s title means
that the new item is a top level item.
Select the weight. This defines at which position the menu item is. A lower weight means that
the item "floats" above items with "heavier" weight.

You can also create multiple menu items for one node. This allows you to find the node on more
than one place. But generally your visitors get only confused if they can find the same content on
multiple places, so use this feature carefully and only when it’s appropriate.

Simplifying the workflow


In Drupal version 4.6.x, always having to go to the menu module page is sometimes annoying if
you just want to quickly add a page to your site. For this purpose, the Menu-on-the-fly module
has been created. It adds a section on every create content that allows you to create a new menu
item along with the node quasi on the fly (as the module’s name indicates). This functionality is
built into the core menu module in 4.7.x

Helping search engines and robots.txt


Drupal by itself is very search engine friendly. For example it is not uncommon for Drupal based
sites to have have a Google ranking of 5 or higher (out of 10) where using the same content on
another CMS would score much lower.

169
Drupal Handbook 3 Aug 2007

Still, you can make Drupal even more search engine friendly by changing some default
parameters. There are several Drupal settings you can tweak to make Drupal even more search
engine friendly.

1. First of all you might want to enable friendly URL’s


2. Then, make sure that you get rid of the session ID in the URL by changing the .htaccess if
you are using version 4.5.x. On 4.6, session IDs in URLs are disabled by default.
3. Optionally, use URL aliasing for some or all nodes. You can use the pathauto module to
automatically create aliases for new nodes.

Controlling what gets indexed -- the robots.txt file


The robots.txt file is the mechanism almost all search engines use to allow website
administrators to tell the bots what they would like indexed.

A robots.txt is included with Drupal 5.x. Drupal 4.x does not come with a robots.txt file.

By adding this file to the root of your (virtual) webserver, you can quide the search engines’
"bots" through your site or forbid indexing parts of your site. See for an example the file for
drupal.org itself at http://drupal.org/robots.txt.

If you want to have a robots.txt file, please follow the instructions below. For more details check
http://www.robotstxt.org

Create a file with the content as shown below and call it "robots.txt"

# small robots.txt
# more information about this file can be found at
# http://www.robotstxt.org/wc/robots.html
# lines beginning with the pund ("#") sign are comments and can be
deleted.
# if case your drupal site is in a directory
# lower than your docroot (e.g. /drupal)
# please add this before the /-es below
# to stop a polite robot indexing an exampledir
# add a line like (delte the #’s)
# user-agent: polite-bot
# Disallow: /exampledir/
# a list of know bots can be found at
# http://www.robotstxt.org/wc/active/html/index.html
# see http://www.sxw.org.uk/computing/robots/check.html
# for syntax checking
User-agent: *
Crawl-Delay: 10
Disallow: /aggregator
Disallow: /tracker
Disallow: /comment/reply

170
3 Aug 2007 Drupal Handbook

Disallow: /node/add
Disallow: /user
Disallow: /files
Disallow: /search
Disallow: /book/print

This file tells indexing robots that they should avoid pages that contain content for users only,
for example the search page, or the ’Add a comment’ forms for nodes.

Many robots obey the "Crawl-delay:" parameter. Since Drupal sites seem to be popular with
search engines and lots of people have more aggresive bots than visitors at their site, it might be
wise to slow down the robots by adding a robots.txt line like this:

User-Agent: *
Crawl-Delay: 10

Here 10 is the delay in seconds between page requests.

Both "Slurp" (The robot that is indexing for yahoo and altaVista) and the Microsoft robots for the
MSN sites obey this parameter. Googlebot does not use the "crawl-delay" parameter yet but will
likely do so in an upcoming version.

Change the file as you wish and save it. Now upload it to your webserver and make sure it is in
the root of the (virtual) webserver. If you have installed Drupal in a subdirectory (for example
/drupal), then change the URL’s in the robots.txt file but place the file in the root of the
webserver, not in the root of your drupal instalation.

Now watch the robots visit your site and after some time, monitor your log files ("referrer log")
to see how many visitors came from a search engine.

Add ’Disallow: /node/’ if your setup has aliases for all nodes
If your Drupal setup has aliases for all nodes (mostly happens when you use path and pathauto
both) then add Disallow: /node/ to your robots.txt. Nodes with aliases are accessible from 2
URIs: the default URI and the aliased URI. Search engine bots will discover both over a period of
time and this might lead to penalisation for duplicate content as well as twice as much crawling
as is really required.

I learnt this the hard way. It is best to do this when the site is new.

Selective Bot Crawling


here’s a copy of my robots.txt file:

# AllTheWeb
User-agent: fast-webcrawler
Crawl-Delay: 10
Disallow: /aggregator

171
Drupal Handbook 3 Aug 2007

Disallow: /tracker
Disallow: /comment/reply
Disallow: /node/add
Disallow: /user
Disallow: /files
Disallow: /search
Disallow: /book/print
Disallow: /admin
Disallow: /cron.php
Disallow: /xmlrpc.php
Disallow: /database/
Disallow: /images/
Disallow: /includes/
Disallow: /modules/
Disallow: /scripts/
Disallow: /themes/
Disallow: /email_disclaimer
Disallow: /privacy_policy
Disallow: */add/
# AltaVista
User-agent: scooter
Crawl-Delay: 10
Disallow: /aggregator
Disallow: /tracker
Disallow: /comment/reply
Disallow: /node/add
Disallow: /user
Disallow: /files
Disallow: /search
Disallow: /book/print
Disallow: /admin
Disallow: /cron.php
Disallow: /xmlrpc.php
Disallow: /database/
Disallow: /images/
Disallow: /includes/
Disallow: /modules/
Disallow: /scripts/
Disallow: /themes/
Disallow: /email_disclaimer
Disallow: /privacy_policy
Disallow: */add/
# Googlebot
User-agent: googlebot
Crawl-Delay: 10
Disallow: /aggregator
Disallow: /tracker

172
3 Aug 2007 Drupal Handbook

Disallow: /comment/reply
Disallow: /node/add
Disallow: /user
Disallow: /files
Disallow: /search
Disallow: /book/print
Disallow: /admin
Disallow: /cron.php
Disallow: /xmlrpc.php
Disallow: /database/
Disallow: /images/
Disallow: /includes/
Disallow: /modules/
Disallow: /scripts/
Disallow: /themes/
Disallow: /email_disclaimer
Disallow: /privacy_policy
Disallow: */add/
# Looksmart
User-agent: wisenutbot
Crawl-Delay: 10
Disallow: /aggregator
Disallow: /tracker
Disallow: /comment/reply
Disallow: /node/add
Disallow: /user
Disallow: /files
Disallow: /search
Disallow: /book/print
Disallow: /admin
Disallow: /cron.php
Disallow: /xmlrpc.php
Disallow: /database/
Disallow: /images/
Disallow: /includes/
Disallow: /modules/
Disallow: /scripts/
Disallow: /themes/
Disallow: /email_disclaimer
Disallow: /privacy_policy
Disallow: */add/
User-agent: zyborg
Crawl-Delay: 10
Disallow: /aggregator
Disallow: /tracker
Disallow: /comment/reply
Disallow: /node/add

173
Drupal Handbook 3 Aug 2007

Disallow: /user
Disallow: /files
Disallow: /search
Disallow: /book/print
Disallow: /admin
Disallow: /cron.php
Disallow: /xmlrpc.php
Disallow: /database/
Disallow: /images/
Disallow: /includes/
Disallow: /modules/
Disallow: /scripts/
Disallow: /themes/
Disallow: /email_disclaimer
Disallow: /privacy_policy
Disallow: */add/
# MSN
User-agent: msnbot
Crawl-Delay: 10
Disallow: /aggregator
Disallow: /tracker
Disallow: /comment/reply
Disallow: /node/add
Disallow: /user
Disallow: /files
Disallow: /search
Disallow: /book/print
Disallow: /admin
Disallow: /cron.php
Disallow: /xmlrpc.php
Disallow: /database/
Disallow: /images/
Disallow: /includes/
Disallow: /modules/
Disallow: /scripts/
Disallow: /themes/
Disallow: /email_disclaimer
Disallow: /privacy_policy
Disallow: */add/
# Yahoo Vertical Crawler
User-agent: yahoo-verticalcrawler
Crawl-Delay: 10
Disallow: /aggregator
Disallow: /tracker
Disallow: /comment/reply
Disallow: /node/add
Disallow: /user

174
3 Aug 2007 Drupal Handbook

Disallow: /files
Disallow: /search
Disallow: /book/print
Disallow: /admin
Disallow: /cron.php
Disallow: /xmlrpc.php
Disallow: /database/
Disallow: /images/
Disallow: /includes/
Disallow: /modules/
Disallow: /scripts/
Disallow: /themes/
Disallow: /email_disclaimer
Disallow: /privacy_policy
Disallow: */add/
# Exclude every other bot (hopefully)
User-agent: *
Disallow: /

... this way, it blocks every bot, except the ones i listed.

a much more logical approach, methinks.

also, a little off-topic, but don’t forget to Disable PHP’s session use_trans_sid for cleaner search
engine listings.

Increase upload size in your php.ini


Drupal’s limits on upload file size are determined by your server’s PHP settings. The default
values for PHP will restrict you to a maximum 2 MB upload file size.

Drupal 4.7.x and above calculates and displays the maximum file size that you can set in the
settings page for the upload module based on two PHP settings, ’post_max_size’ and
’upload_max_filesize’. Since ’post_max_size’ is the limit for all the content of your post,
potentially including multiple uploaded files, the upload module limits the size of a single
attachment to be 50% of post_max_size, or 100% of upload_max_filesize, whichever is smaller.
The default PHP values are 2 MB for upload_max_filesize, and 8 MB for post_max_size.

Depending on your host, changing these two PHP variables can be done in a number of places
with the most likely being php.ini or .htaccess (depending on your hosting situation).

For example, to increase the limit on uploaded files to 10 MB:

Add the below to the relevant php.ini file (recommended, if you have access). Note that for
some hosts this is a system-wide setting. However, for hosts running PHP as a CGI script
with suexec (for example) you may be able to put these directives in a php.ini file in your
Drupal root directory.

175
Drupal Handbook 3 Aug 2007

upload_max_filesize = 10M ;
post_max_size = 20M ;
Add the below to your .htaccess file in the you Drupal root directory.
php_value upload_max_filesize 10M
php_value post_max_size 20M

The PHP documentation states that the memory_limit setting also affects file uploading.
Generally speaking, memory_limit should be larger than post_max_size. If this is an issue, see
the page on how to Increase memory in your php.ini

Need images etc? - check Filtered HTML


As you start creating content like a story or an article, it’s easy to overlook "input formats" -
where there are options for filters like Full HTML or Filtered HTML.
But these are very important; and the well-meaning Filtered HTML can trip up many a Drupal
newbie: certainly caught me out, and had me searching for solution. The Filters remove HTML
that isn’t listed as acceptable, as website code is processed for previews or actual views, to
safeguard your site from potential harm. Can set the site’s default filter, plus decide which user
groups have permission to use certain filters.

For me, as plenty of others, an apparently weird early problem was that I added an image to my
text, but couldn’t see it in Preview or web pages.

The reason: I’d left "input format" in default mode, which uses Filtered HTML. And this, by
default, is so enthusiastic in stripping out potentially dangerous HTML that it also removes
<img> tags. Result: no images!

One solution is to use Full HTML, so Drupal’s bodyguards stand down, and all HTML code
entered is allowed on actual site. This, though, is unwise if you’ll have untrusted users
contributing to the site.

It’s better, then, to permit <img> and perhaps a few other HTML tags in Filtered HTML for
untrusted users (if you’re site superuser, can use Full HTML as needed).
Or, better still, create one or more new Filters: which, you’ll find, can include other filters.

Creating a Filter (site configuration - input formats - add filters), you’ll see that you have the
option to include existing main filters, such as Filtered HTML and - depending on modules -
things like a filter for menalto Gallery, and inline images filter from Image Assist.

But, in Drupal 5 at least, you can’t see the HTML tags in your custom filter.
To see these, save your Custom Filter. Then, choose "configure" from the list of key filters, and
then configure again.

Now, you can revise the list of tags.


At least add <img>. But since the default Filtered HTML seems like some latterday Ebeneezer
Scrooge of the website world, can also add more.
As I type this, Drupal site notes: Allowed HTML tags: <h1> <h2> <h3> <h4> <h5> <h6>

176
3 Aug 2007 Drupal Handbook

<em> <strong> <code> <del> <blockquote> <q> <sub> <p> <br> <ul> <ol>
<li> <dl> <dt> <dd> <a> <b> <u> <i> <sup>
There’s a post on TINYMCE - http://drupal.org/node/59769 - suggesting that use:
<quote><a> <em> <strong> <u> <cite> <code> <ul> <ol> <li> <dl> <dt>
<dd> <img> <p> <sub> <sup> <strike> <blockquote> <hr> <br></quote>
for fckeditor, a suggested list (posted by someone helping me with Filtered HTML troubles) is:
<a> <em> <strong> <small> <sup> <sub> <cite> <blockquote> <code> <ul>
<ol> <li> <dl> <dt> <dd> <h1> <h2> <h3> <h4> <img> <br> <br/> <p> <div>
<span> <b> <i> <font> <color>

You’ll want to leave option "strip disallowed tags".

It may be useful to create extra Filters, for finer control on users and HTML they can input.
For instance, if someone will be writing and editing articles, could allow them a wide range of
tags. (If you have, say, a user group "writers n editors", might create Filtered HTML for Editors.)
But for folk who register and can just add comments, post to forum, could have tighter list. This,
perhaps, could obviate need for BBcode, albeit a few fckeditor style buttons would be more
user-friendly than listing of code tags.

Note that the input formats are stored as you save text etc. So if you change filter you want to be
used as default for your site, won’t affect saved pages.

Set default content options - Stop automatic


promotion to the front page
Configure the default content workflow suitable for your site. Out of the box, Drupal modules
are set to promote to the front page. While this is desirable in many instances, it is not something
you always want.

The administration menu has changed in 4.7, so the config screen for this has moved.

In 4.6 and older:


Go to the Administer > Content
Select the Configure tab and then the Content Types sub tab.

In 4.7:
Go to Admin > Settings > Content-types

In 5.x
Go to Administer > Content Management > Content-types

Click on the configure for the node type in question and change the default workflow options to
something suitable for your site.

If you add or enable modules such as CCK that create additional node types, you will need to
revisit these settings. Remember that.

177
Drupal Handbook 3 Aug 2007

Show/hide ’Submitted by’ on posts


Set appropriate post information for your site.

In 5.x:
In (Administer > Site building > themes), select the "configure" tab, then "Global settings." Select the
appropriate "Display post information on" that are right for your site.

Available options will be determined by the installed modules on your site. Other options can be
configured on the individual theme’s configuration page.

In 4.7 and before:


In (administer > themes) (URL: ?q=admin/themes/settings) menu, select the "configure tab" and
"Global settings" sub-tab. Select the appropriate options for your site in the "Display post
information" menu.

Blocks
Blocks are the boxes visible in the sidebar(s) of your Drupal website. Most of the blocks that you
will see (e.g., recent forum topics) are generated on-the-fly by various Drupal modules, but you
can also create your own blocks.

Whether, and where, a given block will appear on a page depends on both the theme enabled
and on administrative block settings. Block settings are controlled from the block administration
screen, which you can reach by clicking administer » blocks. From this screen, you will be able to
control whether each block is enabled where it will be placed on the page, and which pages it
should appear on.

Block configuration
Whether a block appears on a page depends on a number of factors.

First, the block must be enabled by checking its "enabled" box on the block management
page;
Second, the block’s custom visibility settings must permit the block to be displayed for a
given user. You can configure a block to appear always; to be displayed by default unless
disabled by individual user preferences, or to be disabled by default but visible if enabled
by individual users. Individual users can select or disable optional blocks from their "my
account" page;
Next, whether the block appears on pages for a given section of the site can be configured
by the administrator by setting the block’s path;
The block can be configured to appear only for certain content types;
Finally, if the throttle module has been enabled, and the block has its throttle box checked on
the block management page, then it will only appear if the site’s traffic is below a given
threshold.

178
3 Aug 2007 Drupal Handbook

Once you have configured a block to appear as required on specific pages and in the correct
column, you may wish to adjust the block’s weight to position the block vertically within its
column. A block’s weight is set via a pull-down selector on the block management page. Heavier
blocks (those with a more positive weight) "sink" to the bottom of a column, while lighter blocks
"float" towards the top.

More infomration can be found in the modules section of the handbook on block

Restricting blocks to certain pages


Below the Page Specific Visibility Options options, you will see a large text box. On each line,
you can specify which pages that block will appear on -- or not appear on, depending on what
you selected above.

The following are some annotated examples. They all assume that you choose the second option
above; if you chose the first option, blocks will appear on all pages other than what you specify
below. You’re welcome to add more than one listing, each separated by lines. (Note that you
cannot specify pages on which blocks appear as well as pages on which blocks do not appear. It
is either one or the other.)

<front> Specifies that the block appears on the front page.


Specifies that the block will appear on the item with the node
node/42
ID of 42.
aggregator Specifies that the block appears on just the aggregator.
Specifies that all URLs that start with blog/ will show the
block. Note: if you want the block(s) to also appear on the main
blog/*
blog page, you need to add blog (that is, without the
trailing slash) as well.

Some users have reported they receive the error "warning: Delimiter must not be alphanumeric
or backslash in [your drupal install] modules/block.module on line 354." if they do not surround
their paths in <> like <node/42>

Another example, if you have HTML, Javascript or PHP blocks you don’t think are necessary for
administrators to see, you can select "Show on every page except the listed pages." and use the
following
wildcard for the block:

admin/*

Administrators can select which content type blocks appear on as well. This can be found under
"Content specific visibility settings" after clicking the "configure" link for an individual block.
Choose which content type blocks appear on by checking the box next to that content type. You
can use content type-specific blocks in conjunction with the above restrictions based on URLs.

179
Drupal Handbook 3 Aug 2007

Examples of using PHP for visibility combined can be found in the PHP Snippets section of the
Handbook in the article Overview Approach to Block Visibility

Preventing a block from appearing in Drupal 4.5


I’m baffled....I have reviewed the Drupal guide on the site and read through numerous
postings from the archive of this list, and have tediously tested many alternate paths.

I currently have this path (which works)

<^(?!event)>

it used to to keep certain blocks off the month view of the calendar.

I want to add to that string something that does not display a block on a specific page (e.g.
node/635)

I tried

<^(node/635)|^(?!event)>
(did not work)
<(^node/635)|^(?!event)>
(did not work)

I’m not sure I am using the vertical bar | correctly. I had trouble finding examples of
multiple paths.

I am also not specifying the node/635 correctly, as I could not get to work even when I
removed the second part

^(?!event)

Thanks,
Andrew

Hi Andrew,

I can empathize with your situation! This is one of the most powerful, but also one of the most
difficult, aspects of the block mechanism in Drupal.

Both power and difficultly spring from the same source - regular expression syntax. There are
entire books on the subject, so please don’t feel stupid! It really is pretty heavy going.

You’ll want to place the entire regular expression in angle brackets, as in your examples.

The caret (^) anchors your regular expression to the start of a line, that is, the part of the URL
immediately following the hostname.

180
3 Aug 2007 Drupal Handbook

Hence <^node> will match http://www.example.com/node,


http://www.example.com/node/foo, and http://www.example.com/node/123, if your server
is www.example.com.

If you omit this and type <node> for example, your regular expression will match
http://www.example.com/node, but also http://www.example.com/nodessert,
http://www.example.com/blog/how_to_delete_a_node, etc.

OK so far?

As you have perceived, parentheses group sub-expressions (sort of in the same way that
parentheses group sub-expressions in arithmetic, or even in written communication, as in this
example!). The ’pipe’ operator (|) is used to separate alternatives. Read it as ’or’. So,

<^(foo)|(bar)>

can be read as ’match foo or bar at the start of the line’.

The expression (?!...) is called a negative look-ahead operator. It says to match only if the
subexpression following the ?! does not match from the point where the ?! is evaluated
(matched)

So <^foo(?!(t))> matches http://www.example.com/fool and


http://www.example.com/fooze but not http://www.example.com/foot, or
http://www.example.com/football.

One more thing - letters and numbers ’match themselves’, but obviously certain other special
characters have special meaning (e.g., we’ve already seen that ^,?, !, | and parentheses are
treated specially). These are called metacharacters. To match a metacharacter you need to ’escape’
it, by preceding it with a ’\’ (backslash).

So, to match the pattern ’foo?!’ you’d have to type <foo\?\!>.

Now, we can put all of the pieces together. Just as in arithmetic, or in writing compound
sentences, you can create long expressions by combining short ones.

Regular expressions can be combined by simply catenating them:<foo> matches ’foo’, and
<bar> matches ’bar’; catenate them to get <foobar> matching ’foobar’. You can also combine
by alternation: <(foo)|(bar)> matches foo or bar. You can specify that a subexpressions
matches zero or more times by following it with an asterisk: <(foo)*t> matches ’t’, foot,
foofoot, foofoofoot, and so on. (I’ve omitted the server part of the URL for brevity)

On to your example:

<^(?!(node\/635)|(event))>

matches (at the beginning of the line) anything that doesn’t match the subexpression following
?!, namely, node/635, or event. I’ve escaped the slash - I don’t know if this is necessary (but it
doesn’t hurt - any regular character when escaped just matches itself)

181
Drupal Handbook 3 Aug 2007

If you’re beginning to love this stuff, there’s hundreds of more pages of fun examples in various
books and on other websites (for example at http://www.php.net). Just search for ’regular
expression’ or PCRE (perl compatible regular expressions)

Hope this helps,

Djun

Custom blocks
A custom block contains content supplied by you (as opposed to being generated by a module).
Custom content may be either static (i.e., HTML) or dynamic (PHP generated content). Virtually
all of the functionality of Drupal is accessible from within a PHP content block. The flexibility of
blocks provides an extremely powerful way to customize your Drupal website.

You can create a custom block via the block management screen (click on administer » blocks).
Select the new tab and complete the form.

Each custom block has a title, a description, and a body. The content within the body can be as
long as you wish.

Note: In Drupal 4.6, the title of the block is used as its identifier in the database table. Therefore
you can only have one custom block without a title (this issue has been fixed in newer Drupal
versions).

One workaround for this is to enter a title such as this: <!--title of custom block-->. This satisfies
Drupal’s need for a block title but the comment markers (<!-- ... -->) prevent it from being
displayed.

Increase memory in your php.ini


While Drupal core will run with 8 MB of memory configured for your server, you may need to
increase this depending on how may modules you use on your site.

In Drupal 4.7.x and below, when you go into ?q=admin/modules, you may experience a blank
screen. This is caused by Drupal loading all the modules of your site into memory, whether you
have them turned on or not. If you get a blank screen here, you have two choices; increase your
allocated memory for PHP or delete unused modules.

In Drupal 5.x and above, this problem has been fixed, and the modules page no longer loads all
modules. If you are still getting out of memory problems, you should either reduce the number
of modules used or increase your allocated memory for PHP.

Depending on your host, this can be done in a number of places with the most likely being
php.ini or htaccess depending on your hosting situation.

182
3 Aug 2007 Drupal Handbook

Add for example:

memory_limit = 12M to your php.ini file (recommended, if you have access)


ini_set(’memory_limit’, ’12M’); to your sites/default/settings.php file
php_value memory_limit 12M to your .htaccess file in the Drupal root

You will need to experiment with the value that is right for you.

Database table prefix (and sharing tables across


instances)
Some web hosts limit their customers to one database. Thus, no duplicate table names are
possible. In order to assure that these admins can still use Drupal, and even use multiple
installations of Drupal, Drupal offers table prefixing.

In order to use this feature, you must currently edit the script database/database.x in order
to create tables prefixed by the string of your choice. If you are adding contributed modules you
will need to also modify INSERT and REPLACE statements to have a prefix as well. For
example, change all statements from the format of

CREATE TABLE access


INSERT INTO system VALUES
(’modules/filter.module’,’filter’,’module’,’’,1,0,0);
Becomes,
CREATE TABLE dr1_access
INSERT INTO dr1_system VALUES
(’modules/filter.module’,’filter’,’module’,’’,1,0,0);

Then use dr1_ (for example) as value of $db_prefix in your


sites/example.com/settings.php file.

You can also use the prefix.sh in the scripts subdirectory of your Drupal install to do this
automatically. You can then update several sites in one swoop with a (bash shell) command-line
like

for F in ’’ prefix1 prefix2; do \


for S in ‘find ./modules --name \*mysql‘; do \
scripts/dbprefix.sh $F < $S | grep -v DROP |\
mysql -h DBHOST -u DBUSER -pPASSWD DATABASE; \
done;
done
NOTE:that not all scripts end in mysql, but you get the idea; the ’’ prefix tells the script to run
with no prefix at all, ie a straight cat - command that just lets me process all my sites together.
Here is a PHP script that creates all of the database tables for all sites in /drupal/sites/*. It
works for DRUPAL-4-6. See the Database Table Creation script issue for more info.

183
Drupal Handbook 3 Aug 2007

If you want to share users across multiple sites, you’ll need to use a $db_prefix along these lines:

<?php
$db_prefix = array(
’default’ => ’thissite_’,
’authmap’ => ’shared_’,
’profile_fields’ => ’shared_’,
’profile_values’ => ’shared_’,
’role’ => ’shared_’,
’sequences’ => ’shared_’,
’sessions’ => ’shared_’,
’users’ => ’shared_’,
’users_roles’ => ’shared_’,
’users_uid_seq’ => ’shared_’, // for pgsql
);
?>

See the sharing tables and sharing tables across databases sections.

Share tables across instances


Table prefixing may be optionally applied to some tables and not others. This has the effect that
multiple Drupal installations can share common tables. One interesting application for this is to
share the taxonomy tables (vocabularies, term_data). Another interesting use is to share users
across Drupal installations.

In order to use this capability, create two drupal installs in same DB using different database
prefixes. In this example, one is prefixed ’master_’ and the other ’slave1_’. Then edit the
conf.php file of ’slave1_’ so that it points some tables to the ’master_’. For sharing users, add the
following:

$db_prefix = array(
"default" => "slave1_", // the prefix for tables that are not
shared.
"users" => "master_",
"sessions" => "master_",
"authmap" => "master_",
"sequences" => "master_"
"profile_fields" => "master_",
"profile_values" => "master_",
);

Note: The actual tables that you will share depends on your installation.
However, the following tables contain data that is highly site specific and therefore should not
be shared:

184
3 Aug 2007 Drupal Handbook

cache
variable

There is a limitation in that you can only explicitly specify which tables will be shared and not
the other way round. The following may fail (however a recently deleted comment on this page
by marcob suggests this has been fixed:

$db_prefix = array(
// Be careful of this setup.
’default’ = ’primary_’,
’cache’ = ’slave1_’,
’node’ = ’slave1_’,
’system’ = ’slave1_’,
// etc...
);

Setup tip for Drupal 5


For Drupal 5+, an easy way to get started with table sharing across instances is to run the
installer twice using the same database - it will create the prefixed tables and handle all the
initial INSERTS (as with the ’system’ and ’menu’ tables, etc) for all your different prefixes.

Using schema prefixes with PostgreSQL


This page discusses usage of PostgreSQL schemas for prefixes. "Normal" prefixes can be used in
the same way as in MySQL, so they won’t be discussed here.

PostgreSQL has something called ’schemas’


(http://www.postgresql.org/docs/current/static/ddl-schemas.html). They can be very handy
sometimes, but if you don’t know what they are, you probably don’t actually need them and can
stop reading here.

Schemas can be used as prefixes within Drupal. That is, with a multisite setup, each site can
reside in its own schema, and shared tables can reside in a "shared" schema (or even in the
public schema).

There is one annoyance: the upgrade will fail. This is unfortunate, but nothing can be done as the
"normal" (not schema) and schema prefixes are just incompatibile. If you are interested in the
details, please see http://drupal.org/node/40034.

But, don’t worry. This can be easily fixed by changing the update script (update.php and
updates.inc) a bit. The problem lies in the CREATE [UNIQUE] INDEX and ALTER TABLE ...
DROP/ADD CONSTRAINT statesments. When schema prefixes are used, queries like this are
executed:

CREATE INDEX prefix.search_total_word_idx ON prefix.search_total(word)


ALTER TABLE prefix.boxes DROP CONSTRAINT prefix.boxes_title_key

185
Drupal Handbook 3 Aug 2007

ALTER TABLE test.contact ADD CONSTRAINT test.contact_category_key


UNIQUE (category)

The prefix must be removed from the index and constraint name--that is they must be changed
to:

CREATE INDEX search_total_word_idx ON prefix.search_total(word)


ALTER TABLE prefix.boxes DROP CONSTRAINT boxes_title_key
ALTER TABLE test.contact ADD CONSTRAINT contact_category_key UNIQUE
(category)

You can easily search for CREATE INDEX, CREATE UNIQUE INDEX and ADD/DROP
CONSTRAINT statements and remove the {} from index/constraint names.

The best way is to run a test upgrade. You’ll see a list of failed queries and it will be easier for
you to change them.

Another remark: you can’t use prefix.sh to prefix the tables, it will produce incorrect CREATE
[UNIQUE] INDEX queries. This, also, can be easily fixed, by changing:

s/^CREATE INDEX \(.*\) ON /CREATE INDEX $PREFIX\\1 ON $PREFIX/;


s/^CREATE UNIQUE INDEX \(.*\) ON /CREATE UNIQUE INDEX $PREFIX\\1 ON
$PREFIX/;

to:

s/^CREATE INDEX \(.*\) ON /CREATE INDEX \\1 ON $PREFIX/;


s/^CREATE UNIQUE INDEX \(.*\) ON /CREATE UNIQUE INDEX \\1 ON $PREFIX/;

An alternate approach
Here’s what you need to do if you want to solve it this way:

1. Add the following at the top of your database.pgsql file:

CREATE SCHEMA schemaname;


SET search_path TO schemaname;

2. Edit drupal/includes/database.pgsql.inc, replacing the function db_connect() with:

<?php
function db_connect($url) {
$url = parse_url($url);
$db_and_schema = explode(".",substr($url[’path’], 1));
$conn_string = ’ user=’. $url[’user’] .’ dbname=’.
$db_and_schema[’0’] .’ password=’. $url[’pass’] . ’ host=’ .
strtr($url[’host’],’+’,’/’);
$conn_string .= isset($url[’port’]) ? ’ port=’ . $url[’port’] : ’’;
$connection = pg_connect($conn_string) or die(pg_last_error());
if(!empty($db_and_schema[’1’])) pg_query(’SET search_path TO

186
3 Aug 2007 Drupal Handbook

’.$db_and_schema[’1’]);
return $connection;
}
?>

3. Finally, use a db_url akin to such in your settings.php file(s):

$db_url = ’pgsql://user:password@+tmp/dbname.schemaname’;

Not thoroughly tested, but works for me (on 4.6.3).


This also fixes the inability to specify a Unix socket as the host - the +tmp gets replaced with
/tmp for pg_connect().

Define shared variables for all sites


When you create a multi-site installation, an important table to duplicate is the variable table.
However, by duplicating this table, you will also duplicate some variables that you might prefer
not to. To force a set value for these variables, for all of your websites, you can do the following.

First, you will probably have a settings.php file for each site in your installation, like
sites/example.com/settings.php. Edit each file and add the following to the end.

include_once (’./sites/default/shared_variables.php’);

Now, in the default directory, add a file called sites/default/shared_variables.php


containing the following.

<?php
/**
* These variables are fixed for all sites that have this line of
* code in their settings.php file:
*
* include_once (’./sites/default/shared_variables.php’);
*/
$conf = array(
’site_name’ => ’All these sites are belong to us.’,
’theme_default’ => ’pushbutton’,
’anonymous’ => ’Visitor’
);

The element names (eg. ’site_name’) correspond to a variable in the variable table. So no
matter how many copies of the variable table that you need, each site in your multi-site
installation will defer to the variables that you define in the $conf array in your
shared_variables.php file.

187
Drupal Handbook 3 Aug 2007

The disadvantage is that these variables cannot be edited via the Drupal admin pages.

188
3 Aug 2007 Drupal Handbook

Drupal Cookbook (for New Drupallers)


Purpose
I am one of the many Drupal "newbies" who seemed overwhelmed at first. Well, I still am. But I
have learned a lot in my first month with Drupal. I’m even answering question in the forums
(actually, I think it’s fora.)

With some encouragement from other newbies, I decided to start on writing down what I’m
doing to build my sites. (Shoot, at my age, I can’t rely on my memory, I have to write it down.)
Yes, that’s plural. As of this writing I have three sites in production, plus a test site for playing
around.

Background
The basis of this book is going to be my efforts to build new test sites on my PC, running
Windows. Hopefully by the time I get to that point in this book, I’ll have figured out how to
transfer the developed sites onto the remote production servers. Pretty much all of this is
directly appicable to building a site directly on a web server.

Myths
It is a pure myth that you have to know how to program (especially in php) to use Drupal. It
doesn’t hurt to have some basic knowledge of php, HTML, and CSS, but it is not required. Here
are some good resources for you:

W3 Schools - for virtually everything Internet-related.


The Official PHP Site - the full php implementation.
PHP Builder - some tutorials and code ready-to-use.

Now, to be honest, I have used HTML in this book, and tweaked the CSS on my site a little bit.
But I have not used one line of php code.

Another common myth is that your learning curve for Drupal is going to be steep and it will
take you months, or even years, to get a web site up and running. Hogwash! I had my first,
largely static, web site with 36 pages up in less than a week after I installed my first copy of
Drupal. Then, because my hosting provider pulled the plug, I got my group’s site up in the time
it took to get the domain name transferred (about 5 days). That was after about 16 days from
starting with Drupal. That site had a lot of static content, but also required a taxonomy-based
access control module, a fancier theme, meta tags, photo albums, and a calendar - and it all had
to work right away!

189
Drupal Handbook 3 Aug 2007

You can do it! Yes, YOU.

Using the Drupal Web Site


There are a few things you need to know before you post anything on the Drupal web site:

Search to see if the subject has already been covered. If it has, then recreating the subject will
probably get you negative comments. If you don’t understand the responses (I certainly
identify with that feeling), don’t hesitate to say "I’m a newbie, can you say this in easier to
understand terms?"
You need to get a few basic terms right or you will be flamed.

Node: This is, in simple terms, a unit your content. It may, for example, be a "page,"
"story," "book page," or "blog entry."
Theme: This is the way your site is displayed (or rendered) to the end-user.
Block: This is a "container" for pieces of content on your displayed page. For example,
your navigation menu and log-in are blocks. You may also have "Recent posts,"
"Sponsor links," or "Who’s online."
Try to completely describe the situation. For example, if a page is not showing up correctly,
it could be a browser problem, so make sure you tell the reader what browser you’re using.
Always mention which release of Drupal you’re using (4.7.x, 5.x, etc).

Typing Convention
Throughout this site, as well as the Drupal site, you will see things like Administer>>Access
control>>User management>>Roles. This means click on "Administer" in the navigation
menu, then "Access control," then "User management," and then "Roles."

I will occasionally refer to "production" or "live" sites. These terms are pretty much
interchangeable. The latter term is more modern and accepted in reference to web sites and
means the site that your end-users interact with. The former term is largely synonymous but is a
more "traditional" data processing term.

Some Preliminary Advice


This is from a post by ebrad on March 26, 2007, with some minor editing.

I don’t know if I could call my sites "great;" it’s taken about 9 months to really get a good
understanding of how to use Drupal and its modules. This doesn’t include learning the API or
writing my own modules.

These are some recommendations I would have given myself before I began with Drupal:

190
3 Aug 2007 Drupal Handbook

Never try anything for the first time on a live site. Use a test site that uses the same modules
and same data (different database). I keep 2 tests sites going at all times.
Don’t try to make the "perfect site" on your first shot. Muddle through for a while until you
understand a better way. Stressing over the perfect solution will slow you down.
Stay away from Views, Category, CCK, and Organic Groups modules until you at least
have a little experience under your belt. These modules require a good bit of understanding
to master and it might discourage you if you try to dive in too fast. However, over time you
will come to realize that these are some of the most powerful and flexible modules out
there. [Nancy’s note: also stay away from access control (security) modules until later. They can
really destroy your site if you don’t know what you’re doing.]
Customize one of the default themes before creating your own, the Theme Developer’s
Guide in the handbook is a big help.
When you run into a problem with a module, make sure to read the "readme," then do
several searches with different terms, only rarely have my problems not already been
answered in the forums or in an issues queue.
To make a site really successful, make it work for the users, not against them. Once you
have the basic site set up, get your friends, family, or anyone who will talk to you to look at
your site and give honest feedback, or do user testing for a more formal approach (I run a
company Intranet and I do user testing every couple of months).
Help out in the forums when you can. It’s surprising how explaining something to someone
else helps you understand it yourself.
Go easy on what I call "gadgets" such as useless blocks, images, and graphics that clutter the
page. I prefer simplicity and I only place something on the page if it is needed. This of
course depends on your application

Good Luck!

Drupal Is Supposed to be Easy?


Drupal is very powerful and flexible. That means it must have a significant degree of
complexity. Do you think the folks at Myspace don’t have their terminology or managed to roll
out that site in a day? I don’t know who told you Drupal was easy, but many people make it
harder than it has to be by thinking they need to understand everything at once.

Terminology is necessary in order to properly convey what one is trying to say or ask. If you talk
about "that box-like thingy on the right side of my screen" you could be referring to many
things. Contrast that with "the Author Information block in the right sidebar" - now you are
precise and everyone knows exactly what you mean. You’ve told them what it is, where it is,
and even how it got there and part of how you’ve styled it.

Start by trying to understand the basic parts of Drupal, don’t try to understand everything at
once. For example, it is imperative that you know what a node is (look in my book). Then
understand what content types are. Learn the basic parts of the rendered page (header, footer,
left and right sidebars, and the center, or content areas). Check out the administration pages so
you have some idea where things are, even if you don’t understand them all today.

191
Drupal Handbook 3 Aug 2007

It’s all fine and good to have "Myspace" as your target, but you are one person with a new tool.
The people that put that together are many and using tools that they already were familiar with.
(BTW, I find Myspace to be rather illogical.)

Just start by getting something up and visible. Then celebrate that you’ve done that. Now you’re
ready to move on to more wonderful things, but do it one step at a time. Don’t add tons of
modules right away; get comfortable with what you have. Add modules one at a time and get
familiar with them - one at a time.

As for making Drupal easier and more logical, you’re welcome to submit feature requests or
explain why something is not done in the most logical manner. But don’t demand it, or threaten
to abandon Drupal if you don’t get it your way. And certainly don’t resort to name calling or
derogatory comments.

A. Getting Started
Assuming that you want to build a site on your PC (with Windows), I suggest a visit to
DeveloperSide.net to download their package. Hey - there’s no need to re-invent the wheel!

This package has already integrated the following things:

Apache 2.2 HTTP Server


MySQL 5.0 Database
PHP 5.2 and Perl 5.8 Scripting Languages
GUI WAMP-stack Controller
Dynamic DNS Client
Tomcat Servlet/JSP Container
mod_aspdotnet ASP.NET Host Interface
OpenSSL Cryptography Toolkit
mod_security Web Application Firewall
phpMyAdmin MySQL Administration
Joomla
Drupal
WordPress
MediaWiki
phpBB

Don’t ask me what all of those mean, because I have no idea. Did I need them all? I doubt it. But
disk space is cheap, and the key thing I looked at was that it had Drupal 5.0 (the latest release)
integrated.

I followed their instructions, which built me a working system! Yay! I don’t remember if it was
automatic or not, but you will find it useful to have the "Web-Developer Controller" icon on
your desk top.

192
3 Aug 2007 Drupal Handbook

The only "fly in the ointment" was that when I went to the Drupal web site to start pulling my
modules and themes, there was a big announcement on the front page saying that 5.1 had been
released and was highly recommended.

What’s a girl to do? Do I stick with 5.0 any way, or try to update it to 5.1?

Well, in for a penny, in for a pound. I downloaded 5.1. I then unzipped it (using WinZip).

Of course, that created a directory called "Drupal-5.1," but the other software I had installed was
looking for a directory called "Drupal." Well, by getting Apache and its services shut down, I
managed to rename the two directories so that 5.1 was now called "Drupal." It worked! I now
had a running 5.1 system!

And it was all fairly painless and straight-forward. [Well, you know the plot will thicken, don’t
you?] But at least I’m not as afraid to install a new release of Drupal any more.

B. Basic Configuration
Whether you run one site or several, there are some basic things you should do right now.
Here’s what I do right off the bat; the advantage to doing it in the "root" database is that when I
make copies for my other sites this has already been done. I’d give you a link to something on
the Drupal site, but I never found anything like this.

1. Go to Administer>>User management>>Roles and create an "administrator" role.


2. Go to Administer>>User management>>Users and create a user entry for yourself.
This allows you to test the site by changing your role to meet your needs.
3. Go to Administer>>User management>>Access control and allow the
"administrator" role to do everything.
4. While you’re there, go ahead and set what the "authenticated users" (logged in) and
"anonymous user" (not logged in) can do, such as using your contact form. This is not
engraved in stone; you can change it any time you want.
5. Go to the Administer>>Site configuration>>Site information page and, near
the bottom, set the "Default front page" to "node." As long as you’re on this page, set basic
defaults for the other fields. I don’t know about everyone, but I don’t like, when I visit a site,
being called "Anonymous" so I change the designation to "Visitor."
6. If there are any modules (core or contributed) that you use on all sites, go ahead and enable
them now ((Administer>>Site building>>Modules). For example, you will probably
use "Page" on all sites, and maybe "Story." I am finding more and more uses for "Book."

7. I do recommend turning on (enabling) the "Path" core module so you can use "normal"
names for your pages.

If you want to use the contact form to email anyone from the site, be sure to enable the
"Contact" module.

193
Drupal Handbook 3 Aug 2007

8. The same goes for themes.

There are a few things I recommend that you do in all your databases, so this is a good time to
do it:

Turn on "CLEAN URLS" to make your site more user friendly. Go to Administer>>Site
configuration>>Clean URLs. At the bottom of the verbiage there is a link to run the
"Clean URLs Test." If it passes, then the "Enable" radio button will un-dim. Click on that. (If
the URLs stop working for some reason here are instructions to unset clean URLs.)
In order for me to create any kind of content, I go to Administer>>Site
configuration>>Input formats and set "Full HTML" as the default until I get the site
ready to go live. Then I still allow administrators (like my other ID) to use that format. Do
this now and you will avoid a very common problem with building your site.
I don’t like having "Promoted to front page" as a default for content, so I go to
Administer>>Content management>>Content types and turn that off - in each
format.
While you’re there, decide on your default comment mode. Go to Administer>>Content
management>>Comments>>Settings and set the comments to be entered on a "separate
page" and make sure that "Preview comment" is set to "Required."
Now, let’s turn on the Contact form so your users can send you a message. Go to
Administer>>Site building>>Menus and locate the "Contact" item. Click on the
"enable" link. Remember that later on you will want to go to Administer>>Site
building>>Contact form and finish setting that up.

C. Creating Multiple Sites On Your Local Computer


Need another test site? Here’s how to do it the "easy" way. [Hint: if you want several test sites,
make a list right now. Read these instructions all the way through. Now you can do some of the
steps in bulk to save some time.]

Why create extra sites? In addition to my having several sites running already, I had some ideas
in the back of my head, not the least of which being a site where I could document everything I
do (like this book). I also had some idea for other sites that I might put up in the future. So
before you totally pooh-pooh the idea, give it a few minute’s thought. And you can always
change your mind later; it just might be a bit messier then.

At the very least, I would create a "working" site other than my "root" site. This makes it easier to
start all over again if you get totally out of control later on.

This may look like a long process, but it’s deceiving because I spell it out in detail. It is expanded
and updated from the post "Running multiple sites on a local PC (localhost) from a single
codebase, using Windows." For more details on the "official&quot. stance on the sites directories,
read Setup of /sites directory for multi-site.

194
3 Aug 2007 Drupal Handbook

Open phpMyAdmin (using "other" in Web-Developer Controller)

start bulk loop 1

On the left, select the Drupal51 database. This is the one that was created by the package
installation.
Click on "Operations"
Scroll down to "Copy Database to:"
Enter the new database name.
Verify that the radio buttons are clicked for:

Structure and data


CREATE DATABASE before copying
Switch to copied database
Click on the Go button just below this area.
When the copy is complete, click on "SQL".
In the "Run SQL query/queries on database" box, enter:
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER,
CREATE TEMPORARY TABLES, LOCK TABLES ON databasename.* TO
’admin’@’localhost’ IDENTIFIED BY ’superpw’;
FLUSH PRIVILEGES;
admin is what I call my administrative role (this is the "super-user" name);
superpw is the password for this user (I tend to use the same one for all my databases to
make it easy).
Hint: I created and saved this in c:/www/drupal/grant.txt so I could copy and paste.
Change databasename to the new database’s name.

end bulk loop 1

Close phpMyAdmin.
Go to the www/Drupal/sites directory.

start bulk loop 2

Copy one of the site folders (e.g. default) and name it for your new site.
Open the directory, then open the settings.php file in Notepad.
Change the $base_db and $base_url lines. The $base_db line should have the name of
the database you just created. The $base_url will be how you want to access the site.
Close the file.
If you are going to have site-specific modules or themes, go ahead and create directories in
this site to hold them (named "modules" and "themes").

end bulk loop 2

Navigate to the /www/Apache22/conf folder.


Locate and open the "httpd.conf" file (Hint: I always make a copy of things I’m about to
change, just in case I mess up.)

195
Drupal Handbook 3 Aug 2007

I did notice that my version of Apache sets index.html ahead of index.php, so don’t have an index.html in your
directory.

Find the line that says "# Virtual hosts." Remove the "#" from the next line. This allows you
to make all your other changes in a separate, and less dangerous file.
Save it.
Navigate to the /www/Apache22/conf/extra folder.
Open the httpd-vhosts.conf file.
At the bottom of the existing list, comment out ("#") the examples.

start bulk loop 3

At the bottom of the existing list, enter:


<VirtualHost *:80>
DocumentRoot /www/drupal/
ServerName databasename
</VirtualHost>
Change databasename to the new database’s name.

end bulk loop 3

Close the file.


Navigate to the /windows/system32/drivers/etc folder.
Open the Hosts file with Notepad. Hint: these two steps can be done by using "other" in
Web-Developer Controller.

start bulk loop 4

Add a line that says:


127.0.0.1 databasename
Change databasename to the new database’s name.

end bulk loop 4

Close the file.


Go back to Web-Developer Controller.
Click on Apache2 (top left).
Click the Stop Service button.
Wait for it to change to "stopped."
Click the Start Service button
Wait for it to say "running."

Go for it. You can now start the browser and enter http://databasename.

196
3 Aug 2007 Drupal Handbook

For more details on directories for multiple sites, see Setup of /sites directory for multi-site.

D. Error Pages
Occasionally, a user may do something that confuses Drupal, such as typing a wrong page name
or trying to access content they shouldn’t. These will generate 404 and 403 errors, respectively.

A recent SEO newsletter, they mentioned the value of letting Drupal handle these errors:

Your unique 404 error page should look like a regular page of your site. It should include
your site’s header, footer and navigation bar so that the site visitor can easily click on
another area of your site. The content of this unique 404 error page should contain text
explaining that the page selected is no longer available along with contact information so
the site visitor has the option of emailing or calling your company.

This was one of those "Duh" moments for me. How obvious it is that you should make it easy for
the user to get "back into" your site.

The same more or less goes for the "access denied" (403) error message. Let them know they did
a no-no and try to explain why.

Just go to "Create content" and select "Page." I title them "Access Denied" and "Page Not Found"
but you can call them whatever makes sense to you and your users. When you submit them,
note the node ids. Then go to Administer >> Site Configuration >> Error
Handling and enter "node/nnn" in the appropriate boxes.

Page Not Found


Here’s the HTML for my 404 page:

<p>Sorry! The page you were looking for no longer exists. We redesigned
our site and many of the pages have changed.</p>
<p>&nbsp;</p>
<p>If you are unable to find something on our new site or have a
question about our site or services feel free to <a
href="/contact">contact us</a>.</p>
<p>&nbsp;</p>
<p>--Webmistress</p>

Access Denied
Here’s the HTML for my 403 page:

<p>We’re sorry, but you must have permission to view the page you
requested.</p>
<p>&nbsp;</p>
<p>If you are already a registered member of this site, please try <a

197
Drupal Handbook 3 Aug 2007

href="user">logging in</a>.</p>
<p>&nbsp;</p>
<p>If you are not a member, you need to <a href="/join_us">join
us</a>.</p>
<p>&nbsp;</p>
<p>If you have any questions about our site or group, please feel free
to <a href="/contact">contact us</a>.</p>
<p>&nbsp;</p>
<p>--Webmistress</p>

Don’t worry that you haven’t created the "join_us" page yet. This is an advantage to having URL
Alias support (the Path module) enabled. Just add to your to-do list to create this page when you
get to the "Creating Content" step a few chapters later in this book.

E. Accessing Your Test Site(s)


Okay, great, now we have all that software installed. But how do we use it?

First, open the "Web-Developer Controller" that you put on the desk top. Look at the top left.
You want to see, and should, if Apache and MySQL are running. If they are, you’re just about
ready. If not, select Apache, then click on the "Start Service" button. Within a few seconds it
should change to "Running." Now select "MySQL" and start it.

Fabulous, we have the software ready for us. Now let’s get us ready.

Fire up your favorite browser. In the Address field type in http://localhost/drupal/ to


access your "root" database. Since you’ve done everything right, you’re now into your Drupal
database.

Congratulations! Now the work begins.

F. Adding Modules and Themes


Let me first say that a newbie shouldn’t worry a lot about adding modules and themes at first.
Work on the basics of your site first, then worry about add-ons.

Themes are largely a matter of taste. For example, I have no idea why anyone would use a "fixed
width" theme, but lots of people do. One nice thing about themes are they are pretty much
independent of your content (later on you can look at the many submissions that are dependent
on content).

Contributed modules are ways to add or extend functionality of your site. The only module I,
personally, consider necessary is the Nodewords (a.k.a Meta Tags) module; in my opinion, it
should be promoted to "core" status. This one allows you to add the "content," "keywords," and
"robots" meta tags to your pages. This is useful if you’re interested in your search engine
rankings. You will also find that many contributed modules also require the Views module; I go
ahead and make that a standard one for my sites.

198
3 Aug 2007 Drupal Handbook

Now, if you experiment with different themes and modules, as I know you will, despite my
suggestions, you should also look at the Update Status and Site Documentation modules to
make sure you are current and to document and clean up the mess your experimentation will
make.

Installation
Installing a module or theme is pretty much the same until you get to enabling them. Now keep
in mind that I use a Windows based PC (development) and Linux servers (on my live sites).

1. Go to the Drupal site and click on the "Downloads" tab. Then select either "Modules" or
"Themes" depending on what you’re after.
2. Locate the module or theme you want.
3. I always click on "Find out more" and read the stuff again. This gives you the chance to see
if there is support for your release of Drupal. You can also look at pending bugs and feature
requests - it might change your mind.
4. Download the proper release. (I put them in a Drupal folder in "My Downloads.")
5. Unzip the downloaded file (I use WinZip). It may tell you that there is only one file in the
zipped file; click "yes" or "OK."
6. Extract the code to to your Drupal/sites/sitename/modules or themes folder. If you
are not running multiple sites, this would be Drupal/sites/all/modules or themes.
7. That’s it! Now you need to enable it.

Modules
Modules
You enable a module at Administer>>Site building>>Modules. The non-core modules
are listed farther down. With 5.x, they now show you some of the inter-module dependencies. I
turn them on and "Save configuration" in order of the dependencies. For example, "Views UI"
requires "Views", so I turn on "Views" first, save the configuration, then turn on "Views UI." and
save again.

Ah, now the real work begins. Go to Administer>>User management>>Access control


to select who can use the features of the new module.

If the module introduced new content types, go to Administer>>Content


management>>Content types and configure them. Don’t forget this may also affect your
"Input formats" (Administer>>Site configuration>>Input formats) and "Categories"
(or taxonomy, Administer>>Content management>>Categories); you’ll have to check
those too.

Okay, now you can start using the new module.

199
Drupal Handbook 3 Aug 2007

This Site
My documentation site is a relatively "vanilla" implementation of Drupal.

Core Modules
Contributed Modules in Use
Enabled
Blog Codefilter - Provides tags for automatically escaping and formatting large
Book pieces of code.
Comment Meta Tags (Nodewords) - Allows users to add meta tags, eg keywords or
description.
Contact
Site Documentation - Documents and cleans up your configuration.
Help
Menu
Path

To get some idea of what modules are available, check these links: module handbook and
contributed modules handbook.

Themes
Themes
You enable a theme at Administer>>Site building>>Themes

If it has never been enabled on this site, you will have to check the "enable" box and then click
the "Save configuration" button at the bottom.

To set up how the theme works, click on the "Configure" link (not the tab at the top).

Fill in the fields.

Save the configuration.

Don’t leave the page yet.

Logo and Favorite Icon


Now use that "Configure" tab

I prefer to do this part under the "Global Settings" but it can be done theme-by-theme if you
prefer.

The "Default Logo" is that little picture (usually) in the upper left corner of the page. For
example, on the "Bluemarine" theme, it’s the Drupal logo.

200
3 Aug 2007 Drupal Handbook

If you want to change it, here’s how:

1. First, find out what size it is because you’ll want your own logo to be about the same. (If
you are comfortable with HTML and CSS you can also edit the theme’s code to
accommodate your logo rather than resizing the image. How to edit theme code is not
covered in this beginner’s guide.)
2.

Theme Name Width Height


Bluemarine 48 55
Chameleon 49 57
Garland 64 73
Minelli 64 73
Pushbutton 144 63
Fancy 80 80

3. Under "Logo image settings" either type in the path to your logo, or upload it from your PC.
4. Note: Neither one of those options turns off the "Use default logo" radio button. You must
select the correct radio button yourself.
5. The "Shortcut icon" (a.k.a. the favorite icon, or "favicon.ico") is the same way. If you want to
change this, you must specifically say, "Hey, Drupal, I’m changing this."

Now you click the "Save configuration" button. If you did this in "Global settings" it affects all
themes (assuming they behave properly); if you did it for a single theme, then only that theme is
changed.

For a list of all available themes, check Themes.

HINT: Going to make a few (or a lot) of changes to a standard theme? Think about copying it
over to your /sites/sitename/themes/ folder and renaming it. Then you can do anything
you want and still be able to undo it easily by recopying. If the changes ae a bit bigger, think
about contributing it back to the community (with your name, of course).

G. Creating Content
"Wow, I’ve done all this and I still don’t have any content on my site!" Well, let’s fix that.

201
Drupal Handbook 3 Aug 2007

First, let me explain that the page your visitor sees first upon entering your site is usually called
the "home" page. Drupal calls this the "front" page, much like a newspaper. This page is special
to Drupal. I know you’re in a hurry, but read about both "pages" and "stories" before you decide
which to use to create your front (home) page.

Content Types

Page
Drupal says, "If you want to add a static page, like a contact page or an about page, use a page."
If you’re used to building web sites with HTML, this is what you’ve done in the past. In general
a "page" is going to stand on its own and will probably have a menu entry. You may also later
add it into a book. When I created my first two sites (based on former static HTML sites, I made
the front page a "page;" I have since changed to a "story."

Story
Drupal says, "Stories are articles in their simplest form: they have a title, a teaser and a body, but
can be extended by other modules. The teaser is part of the body too. Stories may be used as a
personal blog or for news articles." Why they say to use it for a blog, I have no idea; they supply
a blogging module as part of the core support.

Okay, you’ve seen the Drupal site and noticed that there are "pieces" all over the place. Look at
the front page; you’ll see several announcements with space between them - those are "stories."

I have now switched my sites to use stories on the front page. The "welcome" message is one
story. I have an announcement story node that any of my admins can edit. If you want to have
weather or cartoons, a story is a good idea. Another use is if you are on a net ring - put the ring
links into a story.

Book Page
Drupal says, "A book is a collaborative writing effort: users can collaborate writing the pages of
the book, positioning the pages in the right order, and reviewing or modifying pages previously
written. So when you have some information to share or when you read a page of the book and
you didn’t like it, or if you think a certain page could have been written better, you can do
something about it."

Another way to use a book is to collect related information together. A book has its own
navigation, so it can also be used to de-clutter your menu.

202
3 Aug 2007 Drupal Handbook

Blog Entry
You probably already know what a blog is, but just in case: A blog is a diary, collection of
thoughts, or other time-ordered content.

So have you decided what kind of content you want? No, okay, just start with a page; it’s easy.
As you go create your content, be thinking about the menu as well.

G1. Creating a Page


A page is probably the simplest content, other than maybe a blog.

Click on "Create content" in the menu, then select what kind.

The title and body are pretty self-explanatory. Below these are a number of collapsible fields.
"Input format" controls what you can put into the page; I’m assuming you are the "super-user"
(user/1), so give yourself the priviledge of "Full HTML."

If you have Nodewords installed, the next section is "Meta Tags." It’s pretty well documented.

I have no idea why you’d use the "Log message" but I’m sure someone has a reason.

Hopefully, you already set your default "Comment settings" but the front page rarely deserves
comments, so you can disable them.

If you turned on the "Path" core module, you’ll have URL path settings next. You can enter a
"normal" name here rather than being required to use "node/2" when you refer to it later on.
Hint: if you are converting a site that was static pages, you might want to go ahead and add
".htm" or ".html" to the name so that the search engines will continue to find the page.

"Menu settings" is the next section. "Title" is what will show in the menu normally. "Description"
will show when the user hovers the cursor over the menu item. "Parent item" allows you to
create multi-level menus that collapse and expand. "Weight" allows you to set a relative position
within the menu; unfortunately, some Drupal core items are hard-coded at 0.

Chances are you won’t need "Authoring information" unless you want to attribute the page to
someone else. The other use for this section is to control the page or story order when they are
based on the time and date it was created.

Finally, "Publishing options," which you set defaults for earlier, right? You want the page
"Published" so it will show up. If this is your "Welcome" page, you’ll want it "Promoted to front
page."

"Submit" it.

203
Drupal Handbook 3 Aug 2007

Congratulations, you now have some content on your site!

G2. Creating a Story


Most of what goes for a page is also true for a story. You can largely consider the two types to be
interchangeable, and it is goodness to have at least two content types because conflicts can arise
in the way content types are used (for example, taxonomy "collisions").

Stories have a "teaser" or opening statement intended to grab the reader’s attention. The length
of the teaser is set in one of two ways:

In Administer>>Content management>>Post settings. The default there is 600


characters. You can change that.
By specifically identifying a break point with ‘‘< !--break-->’’ in your content (before the
default limit; leave out the space).

Note: You may see some places that tell you to use ‘‘<break>’’ to set a teaser point. This was
originally changed in 5.0 and created a considerable controversy, so it was backed out.

A story probably shouldn’t have a menu entry. If you use the general "convention" that a "page"
is for static or generated content that stands alone, and "story" is for collections of related content
(e.g. RSS feeds, newsletter articles, press releases, etc.), then a story is usually going to be
displayed with other stories, so which one would be the menu item? Generally the menu for a
set of stories will be a description of how they are selected for display.

You may want to promote the story to the front page. For your ‘‘Welcome’’ message, you
probably also want to make it ‘‘Sticky at top of lists.’’ Alternatively, you can give it a lighter
‘‘weight’’ so it "floats" up the list.

What’s a Teaser?
This is from a post by zoon_unit on January 10, 2007.

A ‘‘teaser’’ is essentially a snippet of text designed to tell the user the content of a post without
reading the entire post. Since most writers have embraced the common journalistic style of
explaining the nature of an article in the first paragraph, teasers work well for most articles.

Here’s what happens:

1. A node contains an entire article.


2. Drupal’s ‘‘teaser’’ function, ‘‘node_teaser,’’ strips the first x number of characters from the
article and makes it available as content. The exact length is determined by the value set in
Drupal’s Administer » Content management >> Post settings.
3. So, you list a bunch of articles on a page. You want the articles to display only a snippet of
text from the full article, so that you can fit a bunch of articles on a page without requiring
the user to page down through tons of text. If the user likes the ‘‘teaser’’ content of the
article, they will click on the article’s title and see the full content of the article on its own

204
3 Aug 2007 Drupal Handbook

page. In a sense, teasers function like summaries of an article, except that the software
decides where to cut off the text. If you want to determine where a teaser article ends, you can
insert the comment tag to instruct Drupal exactly where to fashion the break between full text
and teaser text.

NOTE: There is a bug in the core Node module. Check the issue status. It is a simple change (can
be done manually) and must be applied in order for some modules to render teasers correctly.
By the way, you might want to add your own experience to that bug report in order to increase
its attention by the developers.

G3. Creating a Book Page


Generally, I only create one book page for each book. This is the first one, usually the
introduction. All other pages will be added as "Child pages" (to be accurate, child pages will still
have the "book page" content type set for them).

In addition to the things I said about pages, a book page has a "Parent." For the first page, this
will be "<top-level>." If you use "Add child page" the "Parent." selection should be already filled
in with the book’s name. If you create another book page, you would need to make sure you
properly select which book or page teh new one is to be made a child of.

The top page of the book probably deserves a menu entry. The rest do not, unless they are really
special. Remember, a book has its own navigation.

You are currently reading a "book."

G4. Creating a Blog entry


Blog entries are a little different. Assuming you enabled the "Blog" module, you should see a
"My blog" entry in your navigation menu. When you click on that, there will be a "Post new blog
entry" link on that page.

If the blog is a diary, you probably want to use the date for the title.

If it’s a collection of thought, give it a meaningful title.

Type in the content of the entry.

Your blog will always show the most recent entries on the beginning page when visitors view it.

205
Drupal Handbook 3 Aug 2007

H. Custom Blocks
I’m not going to say a lot about custom blocks. But I will show you some really simple ones to
give you a flavor. There’s a lot I still don’t know about custom blocks, and that fills many posts
on the Drupal web site. One good starting point is: Blocks.

Address
A business or support group should always let people know how to contact them. One easy
thing is to include your mailing address on your pages. This is about the easiest kind of block to
start with.

1. Go to Administer>>Site building>>Blocks. I should already be sitting on your


default theme, but if not, select the right one.
2. Click on the "Add block" tab.
3. Fill in the "Description" and "Body." Here’s a sample body:

4. My company name<br>123 Main St.<br>Mytown, State Zip<br>USA<br>(123) 456-7890

5. Save the block.


6. For some strange reason, you now need to "Configure" the block to add the block’s name
and placement.
7. Add the name.
8. Determine whether users can turn to block on or off. Then which roles can see it; leave this
with no selections to allow everyone to see it. Then choose which pages it will be shown on;
I show the address on all pages.
9. Save the block.
10. Now you’re back on the block list. Locate the block you just created. Select its location; I like
the address in the left sidebar. You can use the "Weight" parameter to set its position with in
the selected area; again, I like the address at the bottom, so I use a heavier weight.
11. Click on the "Save blocks" button.

That wasn’t so bad was it?

Last Updated
It is fairly common practice, especially on a group site to let the visitors know when the site was
last updated. This example requires you, the webmaster or administrator (sometimes called the
"super user") to maintain the block. There are ways to automate it, but I leave that until we are
all farther along in our Drupal education.

I followed pretty much the same process for the address block, giving this one a slightly
heavier weight to sink it to the bottom.

<address>Feb. 12, 2007 - NEW</address><br>


<small>Best viewed in a full window with Internet Explorer 5.5 or

206
3 Aug 2007 Drupal Handbook

higher. Tested with IE6, Netscape 8, and Firefox 2.</small>


The main difference is that I wanted it only on the home (front) page. So under "Page
specific visibility settings," I clicked on the "Show only on the listed pages" radio button, and
entered <front> in the pages box.

Okay, now you’re an "expert" on blocks.

I. Working with the Menu


Introduction
This will not be an exhaustive piece on the subject of menus. My main point will be to start you
on building your menu and giving you a flavor for how it works. A more complete guide to
menus can be found at Creating a menu structure.

As we all know the menu, or navigation system, can make or break a web site. It must be easy to
follow, often referred to as "intuitive." It must be complete, yet compact.

There is a lot of content on the Drupal site on menus. Most newbies have trouble understanding
it all. I’ve been using Drupal for just over a month as I write this and I still have a long way to go
on completely understanding menus.

For beginners it can be very confusing to understand the difference between menus and
categories. The menu is a navigation system and categories is a system to order content data. So
menus is to arrive at content and categories to order it. Initially to understand Drupal well, you
have to see these as two separate things.

With a menu you can point directly to a node, like a page or a story, but you can also point to a
term in a category, which would show you a summary list of stories or pages.

How To Menu
Drupal offers three primary ways, which may be combined, to provide your users with site
navigation.

1. Textual menu - this is the "standard" line-by-line type of menu, like what you see on most
sites, including mine. It can be enhanced in a few ways, such as using a CSS or separate
book navigation (as I have done here).
2. Tabbed menu - becoming more popular because it’s a little more "gee-whiz" in its
presentation. It is debatable as to whether it is any more effective for your visitors. In
Drupal, it is divided into "Primary" (the tabs you always see) and "Secondary" (the part that
drops down, or slides out). Not all themes support secondary links.
3. Books - Books are organized separately from menus, but have their own navigation, which
you can see on this site. See my section Creating a Book Page.

207
Drupal Handbook 3 Aug 2007

Textual Menu
The textual navigation is the easiest to understand. As a matter of fact, I still don’t understand
how to make the "secondary" part of tabbed navigation work the way a lot of people think it
should (drop down).

You may see the terms "primary links" and "secondary links" in many posts. This is one area
where I find the Drupal documentation confusing (at best). While they sounded great, and I am
now using them, they may not be the best thing for someone just starting out. Stick to the
standard "Navigation" menu until you have a better feel; you can always go back and change
this later.

For the most part, the "standard" menu is best built as you create content, but may require a little
tweaking as you see how it lays out.

When you create a page, story, blog, or book page, one of the fields that you may (should) fill in
before submitting, is the menu entry (if the node is to have one). You have the "title" (what is to
appear in the menu as people see it) and a "description" (what they will see if they hover the
cursor over that entry).

I rarely worry about the "weight" until I see how it shows up in the menu. At that point, you can
either go back and edit the content you created or go to Administer >> Site building >>
Menus and edit it there.

Okay, that was the easy part. Now let’s say you want this particular content listed in the menu
as a
child of some other page. No problem! Let’s say you have a subject’s introductory page already
listed in the menu, for example "Family History." The page you’re creating is "1860-1899." When
you build the menu entry, you’ll notice a selection box labeled "Parent Item." Scroll down the list
until you find "Family History." Now when you submit this page, it will be a child of "Family
History," making that item an expandable menu item. You just created a hierarchical menu!

Tabbed Menu
In those themes that support this technique, the "Primary" seems to get built automatically as
you build the "Navigation" menu, unless you specify a different menu set. I have no idea yet
how to make drop down "secondary" links part work - I think it requires a separate module. I do
know how to make the secondary links appear in a block, if they exist. I like the way that works,
but it may not be for everyone.

Books
The book "menu" is built automatically for you. The only thing you have to worry about is the
order of the entries (hint: weight).

208
3 Aug 2007 Drupal Handbook

The only "complicated" part is turning on the book navigation block, which is done at
Administer >> Site building >> Blocks. All you really need to do is to tell Drupal
which region to place it in and its relative weight. You can get fancy, if you want, with your style
sheets.

More
Later you might consider using the taxonomy_menu module. It will add to your confusion, but
it will be good when there are frequent changes in your vocabularies. It will make the difference
between menu and categories almost completely disappear, because it allows you to make
vocabularies appear as a menu. This way menus will be generated automatically.

If you want hierarchical drop down menus, the nice_menus module might come in handy.

I2. The Contact Form


For something as simple as a contact form, this is one of the most complicated things to get set
up and operating.

Set Up
First, the contact module must be enabled. Go to Administer >> Site building >>
Modules and locate it in the list of core modules. Click the check box and go to the bottom to
save the change.

Go to Administer >> Site building >> Contact form. Here you can set up the
"Categories" - or recipient name/office. [Don’t confuse this with taxonomy categories.]

For example, email for the Sales Department might be given a category of "Sales." The email
address that the form is sent to may be sales@mycompany.com. If you want a reply
automatically sent to the person sending the contact email, you can specify that here. Don’t
worry if you don’t know them all right away, you can come back and change this at any time.
Click the "Submit button."

Now click on the "Settings" tab. Here you can limit how many contact emails an individual may
send in an hour -- this helps limit spamming. You may also turn on personal contact forms here;
this allows users to contact each other. Click on the "Save configuration" button.

Make It Accessible
To me this step seems totally unnecessary, but I suppose that some people want it.

209
Drupal Handbook 3 Aug 2007

Go to Administer >> User management >> Access control, locate the "Contact
module" entry and enable it for the roles you want to be able to use Contact. Save your changes.
The menu link (next step) will not be visible to any one not having access.

Add "Contact" to the Menu


Go to Administer >> Site building >> Menus. Under "Navigation," enable "Contact" as
described in the instructions. Save your changes.

Using It In Content
To add a link to a content page use <a href="/contact">Contact Us</a>. Unfortunately,
this does not give you the capability to specify which contact to send it to. Fortunately, there is
help! Check out the Contact List module.

Need a customized contact form? Check the WebForm Module. A recent change to the
Contact_List module allows you to use these two modules together.

J. URL Aliases
"URL" is an abbreviation of "Universal Resource Locater." It is a fancy way of saying "my page’s
address (or name) on the web." It is the "name" by which a browser identifies a page to display.
We’ve all seen advertisements that say "Check us out at abcxyz.com." Well, abcxyz.com is a URL
for the home page of their web site (well, sort of - there is an implied add-on to that, such as
index.html).

By default, Drupal calls your content "nodes" and identifies them by their position in your
database. So your page on "The History of the Macadamia Nut - Part 1" might be known as
"node/167." That’s all fine and well for Drupal, because it understands that. But your visitor
really doesn’t care where the page is in the database; all they want to do is find the page again,
or know what the entry in their bookmarks list is.

So Drupal has a feature called "URL Alias" that allows you to provide a more understandable
name to the content. As far as browsers, servers, and search engines go, it is totally unnecessary.
But for humans, it is nearly mandatory. This is why I tell people to always turn on the Path core
module, which supports URL Aliasing. (I will mention another module shortly, called Pathauto.)

So, just before you submit that exhaustive treatise on macadamia history, and if you have the
Path module enabled (I told you that you’d want it), then you’ll see a section on the edit page
that says "URL path settings." So let’s say you want your visitors to see it as
http://www.mysite.com/MacadamiaHistory.htm. In the URL field, you enter
MacadamiaHistory.htm.

210
3 Aug 2007 Drupal Handbook

Now, some people will argue that putting that ".htm" on the end is not necessary. That’s
absolutely true. But then it’s not necessary to do any of this. My opinion is that if you want your
visitors to see a "normal" name, it should look like a normal WEB name. Web pages have some
kind of type, such as ".htm" so we should too. But it’s your preference.

Oops, forgot to do this before you submitted the page? Not to worry - Drupal to the rescue!

First, visit the page you created. In your browser’s address field, you’ll see its URL. On the end it
will probably say "node/xxx" where xxx is some number. Write down that number. Now go to
Administer>>Site building>>URL Aliases. There’s an "Add Alias" tab at the top. In the
top box (sorry, they seem to have dropped a label in 5.1), enter "node/xxx" from above. In the
second box, enter "MacadamiaHistory.htm".

Now go back and visit that page and look at your browser’s URL field.

If your site is going to have lots of content, particularly user-submitted content, you might want
to looks at the PathAuto module. Not only will this module automatically generate URL aliases
for new content (according to rules you can set up), but can even go back and change aliases in
bulk.

K. Moving Entire Drupal Site with Databases


Start with Moving entire Drupal site with databases

This might help too: Backing Up Your Database

I know the "official" process is to load the "tar" file to the host and unpack it. As an alternative,
one can copy the code directly from your test site on your PC. I’ve tried uploading code from my
machine twice with disastrous effects. (Okay, so I was born blonde!) So, I’ve worked out my
own process that works. [By the way, this also reduces the bandwidth usage for those who
might be running short on that.]

What has always worked for me is to install Drupal with cPanel/Fantastico (I know there are
some people out here who will speak ill of Fantastico, but it has always done me right). Now, to
be fair, one needs to understand what Fantastico can and cannot do.

Fantastico only supports core functions. It does not support custom themes, contributed
modules, or custom code (outside of content). Fantastico does not use "update.php" (as a matter
of fact, doesn’t even load it), so it is not a good idea to use it to upgrade your installation. As
long as you understand this, you’re much less likely to have problems.

Make sure that the correct versions of modules and themes are working on your test site.

211
Drupal Handbook 3 Aug 2007

Here’s my process: (by the way, this should pretty much work for changing hosts as well)

1. Keep a pencil and paper handy to write down what changes you have to make. You can use
this if you need to restart, or to think about changes to your site that slow down moving to
new releases.
2. Use phpMyAdmin (on some hosts, it’s hidden under MySql) to back up your live database.
If you have a site that is actively receiving new content, you may have to put the site into
maintenance mode to prevent losing new content.
3. It would also be a good idea to back up your test database, just in case...
4. Import the database into your test site.
5. Download any pictures you’ve uploaded and any folders that are created by the modules
you have installed.
6. If your live site and test site are not at the same version, you will need to run "update.php."
7.
Open your browser to your test site. Don’t panic if everything looks strange, or even
blank.
In the URL bar, append "update.php" and press Enter. If it says you don’t have the
access rights, don’t worry.

Using Notepad or similar text editor, open "update.php".


Near the top, you will see:
// Enforce access checking?
$access_check = TRUE;
Change it to FALSE and save it.
Try "update.php" again.
If you have any errors listed, search the Drupal site for fixes. There’s a good chance
that someone else has had the problem. If it appears to be a new error, post a
request for help. Take your site out of maintenance mode and plan to start over
when it’s fixed.
Change $access_check back to TRUE.
If you had a custom theme, you probably need to re-enable it for the site to look right.
Now check out all your module settings. They’ll probably be okay.
Look through your content, especially the front page. Make sure your menus are
correct.
Check out any content that uses custom code, especially if you are changing Drupal
versions.
Does everything check out? Good, you’ve done all the real work. Now the easy(er) part.
8. Okay, now it’s time to do the damage. For me, the rest of this takes less than 15 minutes, so
the outage to your users is minimal.
9. If your current site was installed with Fantastico, delete the current installation. If not, then
you have to manually remove all the folders.
10. Now tell Fantastico to install the current version. Leave the directory field blank to put it in
your "root" directory (probably "public_html"). The userid and password you supply will be
your "super user" (user/1).
11. When it is done, I always tell it to email me the installation summary.

212
3 Aug 2007 Drupal Handbook

12. If you have any customized themes, non-core modules, or pictures, upload them (FTP) to
the correct places on the server.
13. If there were pictures or module-related folders, upload them now.
14. When that’s done, use phpMyAdmin on your test site and create a back up.
15. Then go to your cPanel again and invoke phpMyAdmin. When you get there, select your
Drupal database and then "Import." There’s a section to locate the back up on your local
computer (Browse). Find it, and then Click on the "Go" button.
16. If you have a customized theme, go to Administer>>Site Configuration>>Themes
and enable it. [Hint: Do not panic if your site looks weird at first. Remember you can always
login with http://www.mywebsite.com/?q=user (yes, "user," not your ID.]
17. If your test and live directories are not identical, you may need to update IMG links, etc.
18. You should be in business.
19. One more little bit of business if you used Fantastico: go to the main Drupal directory on
your PC and copy (FTP) the update.php script to your server. I don’t know why they
leave it out, other than they don’t use it. You may need it later.

Backup Process with phpMyAdmin

Backup Process with phpMyAdmin


The screen shots here are from phpMyAdmin 2.9.2, which I have on my local computer. My web
hosts have 2.9.0.2 and look very similar. They certainly produce exchangeable results.

1.
2. Log into phpMyAdmin on your server.
3.

4. Select the
name of your database - or your Drupal database if you have several databases.

213
Drupal Handbook 3 Aug 2007

5.

6. The next screen will show


you all the tables inside your Drupal database. Ignore those, and click the "Export" tab on the top
set of tabs.
7.
8.

214
3 Aug 2007 Drupal Handbook

Look at the left box at the top of the Export section. All the tables in the database you selected
are in that box.
9.

If you have other programs that use the database, then choose only those tables that
correspond to your Drupal installation.

If you only have Drupal installed, in the left column, click "Select All."

10. Ensure that the SQL button is selected too.


11.
12. In the Structure section tick the following boxes: Structure, "Add DROP TABLE," "Add
AUTO_INCREMENT," and "Enclose table and field names with backquotes."
13.

215
Drupal Handbook 3 Aug 2007

14. In the DATA section leave the boxes inside this section unticked, but make sure to keep the
check box next to the "DATA" heading checked.
15.
16. Tick the "Save as file" option, and leave the template name alone.
17.
18. For now, select "None" for compression.
19.
20. Now click "Go" and you should be prompted for a file to download. Save the file to your
computer.
Depending on the database size, this may take a few moments.
21.

You have now backed up your database! (Not so bad, was it?)

Once that download is complete, you may check the "zipped" option, click "Go", and download
the next file. If you want, you can download a backup in each of the compression formats. Your
choice.

L. Moving Stuff to Your Web Site


Occasionally, you need to update something other than your content (database), like the style
sheets, or new code levels.

FTP stands for File Transfer Protocol. It is pretty much the standard way to move stuff (files,
code, style sheets, etc.) to your site. This is not how you will create content; that goes into the
Drupal database.

Now, the postings on the Drupal site will tell you to get a fancy FTP program. If you are at least
on Windows 2000, there is absolutely no need. You can do it with Windows itself and it will look
just like another older and you can drag and drop. I find this process to be easier if you use
Internet Explorer than some of the other browsers.

In your "Address" bar for your browser, enter ftp:username:password@ftp.domain.com


where username is your user name at your site (not Drupal), password is the password for that
username, domain.com is your site’s domain name (without "www").

This will take you to your site. In Linux, you’ll probably have to click into the "public_html"
folder to get to your Drupal stuff. Then just navigate to the correct folders from there.

M. Setting Up Cron
I could not get a decent answer from the Drupal site on setting up the Cron jobs that it keeps
complaining about. Nor would my hosting support people help ("That’s a user problem...").

216
3 Aug 2007 Drupal Handbook

My hosting provider does not allow me to have Shell access (probably a wise move). But they do
provide the more-or-less-standard cPanel function. On my version, the "Cron" entry is in the
lower left.

I also had WebCalendar installed on one of my sites. When I went to cPanel, I noticed that
WebCalendar had a command already set up. Modifying it a bit, this is what I came up with to
put in:
cd ’/home/username/public_html/’ ; php -q ’cron.php’;

Note that username is my host’s user ID for domain management and my Drupal installation is
in my "root" folder (actually "public_html").

This worked for getting Cron run, but did generate some error messages.

I was happy that Cron ran, but a bit concerned about those messages. So I did some searching on
the Drupal site and came up with several posts of the same messages, but no solutions. So I
posted again. This time someone saw it through.

They suggested using WGET, but I don’t have shell access. But I did, for some reason, check the
"Advanced" mode on cPanel again. I noticed that there was now a helpful hint there (of course in
a small font). It said to use GET http://nanwich.info/cron.php (obviously, use your own
URL). I did and the error messages went away and Cron is working great!

For Cron jobs another possibility is http://drupal.org/project/poormanscron

For every page view, this module checks to see if the last Cron run was more than 1 hour
ago (this period is configurable). If so, the Cron hooks are executed, and Drupal is happy.
These Cron hooks fire after all HTML is returned to the browser, so the user who kicks off
the Cron jobs should not notice any delay.

N. Categories (Taxonomy)
You will see a lot of posts on the Drupal site about creating and using a Taxonomy (or
"vocabulary" and "terms"). Most of those posts will be over your head - many are still way over
my head.

While it is true that the more content you have the more obvious the need for a taxonomy
becomes, there is certainly no reason why a smaller website that has things to classify can’t use
it.

For example, I run a web site for a group that has members submit articles for a monthly
newsletter. They wanted a way to organize it so that they could go back and review it by date or
topic. So I created two vocabularies, one for the issue date and one for the topic. Now they can,
with one click, read all the book reports, movie reviews, or humorous articles. And, every month
when they submit new articles, they automatically show up in those lists.

217
Drupal Handbook 3 Aug 2007

Another use is to categorize collections of FAQs, which I do on another site. They had, at the
time I set it up, three hard-coded HTML pages with different types of FAQs; no one wanted to
touch them. I installed the FAQ module (which is great), and set up the three terms in a single
vocabulary. That allowed them to actually grow their FAQ library to now contain six categories,
and it is trivial for them to maintain it.

But to try to help you get a slightly better idea of how to use them, I’ll use a case study here.

The Recipe module is probably a good example. On one of my sites, in order to foster a bit more
"community" feel and encourage visits to my site, I decided to add a group cookbook (a real one,
not like this book). The recipe module does that.

It didn’t take me very long to realize that entering a bunch of recipes without any organization
would get messy pretty quick. Well, recipes fall into several categories: Appetizers, Entrées,
Desserts, etc. So let’s set up those things as a "vocabulary" with which we can organize the
recipes.

1. Go to Administer>>Content management>>Categories and click on the "Add


vocabulary" tab.
2. Enter the name, for example "Recipes." Then a "Description" like "Our community
cookbook."
3. Select the type of content this applies to. The Recipe module introduces a "recipe" type.
4. I selected a "single" hierarchy. Later on, if the number of contributions gets large, I can
always add sub-categories (like "Beef," "Poultry," and "Pork") and change to multiple level
hierarchy.
5. I then selected "Required" to force the users to choose a category for any recipe they enter.

That’s it for the "vocabulary," so click on the "Submit" button. You’ll go back to the Categories
list. You should see your new vocabulary listed.

Towards the right, you’ll see a link to "add terms." Click on it.

1. Since this is a single level hierarchy, the "Parent" should say "<root>."
2. In "Term name" enter your first term, such as "Appetizers."
3. Enter a "Description" such as "Things for before the meal."
4. Don’t worry about the rest yet, just click the "Submit" button.
5. Keep adding the rest of your terms ("Salads," "Soups," "Side dishes," etc.

Now when a user goes to Create content and selects "Recipe," they will be required to
choose one of these categories for it. And if they go to the "Cookbook" menu item they’ll see a
list of categories that they can browse.

That wasn’t as complicated as all those posts sound like, was it?

For another example, I run a web site for a group that has members submit articles for a monthly
newsletter. They wanted a way to organize it so that they could go back and review it by date or
topic. So I created two vocabularies, one for the issue date and one for the topic. Now they can,
with one click, read all the book reports, movie reviews, or humorous articles. And, every month

218
3 Aug 2007 Drupal Handbook

when they submit new articles, they automatically show up in those lists. [By the way this was
done with a custom content module that is easily adapted to other uses. It is available through
me.]

Another use is to categorize collections of FAQs, which I do on another site. They had, at the
time I set it up, three hard-coded HTML pages with different types of FAQs; no one wanted to
touch them. I installed the FAQ module (which is great), and set up the three terms in a single
vocabulary. That allowed them to actually grow their FAQ library to now contain six categories,
and it is trivial for them to maintain it.

Some newbies swear by these articles: Drupal and the New Paradigm and The Power of Drupal
Categories

O. Common Problems
There are some problems we all seem to "find;" this section documents a few of them.
[Remember to always search before posting on the forums.]

Tables messed up, images not showing, other "strange" problems with HTML - I think every
Drupal user finds this problem. Drupal defaults to filtered HTML; that is, only certain tags are
allowed. Further, that input format also breaks long lines of text. The fix is real easy: switch to
the "Full HTML" input format. I make that the default for administrators (like me). Note that you
may still want the URL Filter and Code Filter modules turned on for this input format; they are
not defaults.

Help, I turned on Site Maintenance, now I can’t login! - About 3 out of 4 Drupal users have
done this to themselves (including me). You can still log in with
http://www.example.com/?q=user. Note that "user" is exactly that - do not put your
username there.

I don’t want anonymous users to see "Create content." - "Create content" is actually a child
menu item of "Content" which is usually disabled. Go to your menus administration screen and
enable the "Content" parent above "Create Content." Then you will see a "Reset" link appear.
Click on that. Once again, "Content" will be disabled, but "Create content" will not be shown to
anyone who does not have the access permissions to do so (especially anonymous users).

Also read the handbook section Troubleshooting FAQ

P. Links and IMG


Yes, you can link between pages in Drupal. It’s the same as not having Drupal, except the name
may be weird if you’re not using the Path module (URL Aliasing).

219
Drupal Handbook 3 Aug 2007

The biggest mistake people make is not knowing that there needs to be a leading slash ("/").
Omitting this will probably cause a "404:Page not found" error and, depending on which
browser you’re using, additional problems, like being logged out.

My home page on this site is node #4, so a link to it would look like this: <a
href="/node/4"&gt;Home</a>, but with URL Aliasing turned on, I can also code it like this:
<a href="/home">Home</a>

The picture on the "Accessing Your Site" page is created with this tag: <img
src="/files/pictures/Docs/WDP.jpg" align="right" hspace=1>

Q. Additional Tips and Tricks


This section gives you some ideas for improving your site or making life easier for you.

Q1. Tracking Module Status


A "site" you might want to build on your PC is a "catch-all" site for monitoring module and
theme status with the Update Status module.

This module will check with the Drupal site and let you know if newer releases of your modules
are available.

Before you pooh-pooh this idea, let me suggest this additional tip: Many people eventually find
that they need (want) to patch, tweak, or otherwise modify modules or themes. If you create a
"catch-all" site, you can place unmodified code here so that you always have a "clean" copy to
fall back on. You can then copy it to the correct site before changing it. Now, not only do you
have the fall-back plan, but you get the added advantage of knowing if it needs to be updated.

Q2. Making Multiple Site Maintenance a Bit Easier


A lot of people don’t realize that there browser home page does not have to be out on the web
somewhere. It can be right on your computer.

220
3 Aug 2007 Drupal Handbook

Here’s part of my home page. As you can see, I have links for all my maintenance tasks (cPanel,
FTP, etc.) included, so I don’t have to keep looking them up.

I also included links to my test sites, so they are easy to get to as well.

Q3. Controlling User Log In


How do I disable "Create New Account?"
It’s in Administer » User management >> User settings. Click the radio button that
says: Only site administrators can create new user accounts.

How do I disable User Log In entirely, and how would I get in if I do?
First, you can go to Administer » Site building >> Blocks and change the "Region"
setting for the "User Login" block to <none>. Now your user login block will disappear.

In order for you to login, I offer two techniques:

Enter http://www.myexample.com/user (or, if you don’t use Clean URLs,


http://www.myexample.com/?q=user). Yes, it is the word "user" -- not your user ID.
Go to your Site information settings and stick a "login" link in the footer. <a
href="/user">login</a> I do this on several sites.

221
Drupal Handbook 3 Aug 2007

R. Keeping Your Local and Remote Sites Synchronized


The point of a test site is to have a place to experiment or develop new content without
impacting your users or giving away your latest gee-whiz before its time. But it is also important
to make sure that you always have a good working version of your live site on your test site.

Let’s ignore, for the moment, that in an "ideal" world you will have a staging site which is always
identical to the live site and nothing goes live without being staged.

There are two basic techniques for keeping your sites synchronized:

Manually making sure that the content of the two sites are the same.
Frequent uploads or downloads of database back ups.

The first technique is quite time consuming and it’s difficult to keep user comments on your test
site. It also relies on your memory to know what’s been changed, unless you update both sites at
the same time. If there are things that are dependent on other things (sorry for the technical
terminology), you have to be careful that you update them in the right order so that your
random visitor doesn’t break something.

The second technique allows for user comments to be downloaded to your test site. From there
they can be incorporated into the content and deleted, or left as is. You just have to be careful
that you don’t lose new, experimental, or incomplete content that hasn’t been put onto the
production site yet.

Which is better? I can’t answer that question for you. You need to weigh the risks and benefits
and decide that for yourself. Personally, at my age and with my memory, the second technique
is probably better for me, at the risk of losing something not yet uploaded. I also have the bad
habit of updating things on the live site and not bring the change back to my test site.

More to come

S. More Reading
Now that you’re a Drupal expert, there are some additional topics you might find useful:

Adding Hidden Site Design Notes - how to put design or maintenance notes on your site
that only admins can see.
Core modules - what the many core modules do.
Contributed modules - a starter list to get you to the right modules, if you need them.
Site recipes - collection of tricks and techniques.
Multi-site Installation
Site configuration challenge: corporate brochure - many ways to get to a "Corporate
Brochure" type site.
Best practices guidelines - a guide to doing the right things.
My favorite module or theme is outdated. What next? -- it happens!

222
3 Aug 2007 Drupal Handbook

PHP and Javascript snippets -- useful code to use as is or adapt to your own needs.
SQL snippets -- database stuff.
CSS Tips, Tricks, and Techniques
Theme developer’s guide
Special cases
How to write automated tests
The Road to Drupal Hell -- this should be required reading for anyone who wants to do
something not in the core Drupal.
Using Drupal in an Academic Environment

T. Glossary
Okay, "Glossary" may not be the best description for this section. I’m trying to explain terms in a
[over-]simplified way so that the beginning Drupaller can get her/his arms around Drupal.

You might also want to look at the handbook section on Basic Terminology.

A node is a container for stuff (sorry for the technical term). Some of that stuff is the content you
create. Drupal itself creates a few nodes for its own stuff.

A module is a way to extend the functionality of Drupal. It is usually a lot of programmed code
(usually in php) and, usually, a style sheet (CSS). For example, if you want to include meta tags
to describe your content, you would add on the "Nodewords" module (also known as "Meta
Tags").

A theme is a means of manipulating and describing how you want your content displayed to
your visitors. This includes elements such as your header, icons, block layout, etc. It also
includes programming and style sheets.

A server is (generally) a computer that provides services to the Internet. These services may be
things like running the database or managing the gathering and dissemination of information.

A browser is the "program" that you use to display content from the Internet. In reality, it is
usually a set of programs, not a single one; it is also a set of tables (e.g. settings) that are used to
control its display. Examples are Internet Explorer, Netscape, and Firefox. This operates on the
client, or user, side of the presentation.

HyperText Markup Language (HTML) is the standardized language of the web. It has its own
"vocabulary," consisting of tags, elements, and descriptors. A tag is the basic component and is
used to say, "The following content is to be displayed according to these rules." An example of a
tag is a level one heading (<H1>). Most tags can have additional information to tell the browser
more specifically how you want it to render the content. This specification is called an element.

223
Drupal Handbook 3 Aug 2007

Most elements require more information to make them work, this is the descriptor, which really
should be called "value." For example, if you want that heading centered, you would use the
"align" element and give it a descriptor (value) of "center." So , completely constructed it would
look like this: <H1 ALIGN="CENTER">.

A Taxonomy is a way of characterizing stuff. It can be used for grouping, selecting, and
protecting stuff. Many people who are new to Drupal think this is a very difficult subject
(admittedly, we can make it so), however, virtually all of us had an introduction to taxonomy in
school: classifying living creatures (i.e. the Linnaean taxonomy). In that taxonomy, we classified
living things according to kingdoms (plant or animal), phylum, class, and so on, down to genus
and species. In reality there is an additional classification below species; sub-species (animals) or
varietal (plants). [Oh, yeah, I vaguely remember that! That’s a taxonomy?]

In Drupal, the highest level of taxonomy description is the "vocabulary;" it is used for defining
the terms, or tags, that actually end up on your stuff to be used for the various purposes. In the
above example, think of "Living things" as the vocabulary. Each vocabulary has one or more
"terms" that are used to tag (i.e. define, or describe) your stuff. Terms may be hierarchical; that is
they may exist in levels. Genus and species would be hierarchical terms. The vocabulary is
assigned to input types (e.g. stories, recipes); terms are assigned to a given piece of content (e.g.
"Groundbreaking Research on Macadamia Nut Yields" or "My Fabulous Macadamia Brittle").
Notice that I said "terms" - plural - because an individual node may have more than one term
associated with it; for example, the "Research" news article may be assigned to "Nuts," "Trees,"
and "Harvesting." It could then be viewed through any of those terms (or keywords).

Breadcrumbs is a term borrowed from Hansel and Gretel, who left crumbs of bread along their
path so they could find their way back out of the forest. In current computer parlance, it refers to
the section, usually near the top of the page, that shows the path you followed to locate the
current page. For example, it might show Home > Macadamia Nuts > Current Events >
News Articles, meaning that you started at the home page, clicked on "Macadamia Nuts" in
the menu, then selected "Current Events" in the sub-menu, and finally selected, "News Articles."

A database is a container for containers. It is a collection of related "tables" that are generally
used for a single application (such as Drupal). A table is a collection of data used for a specific
purpose within that application, such as identifying users. Within a table, each individual
grouping of data is referred to as a row (or in traditional terms, a "record"). Each row is
identified by one or more keys that allow easy retrieving of the row. Each row is then broken
down into columns (often called fields, although this is more appropriate for forms on which the
data is displayed). A column holds a specific piece of information for the row, such as a user
name or country.

Now, just to complicate things a bit, some times we describe the collection of item-related table
rows with a collective term. One such term is "node." For example, information about a page on
your site may exist in several tables; yet we describe all of this as a "node."

224
3 Aug 2007 Drupal Handbook

Still confused? Let’s try to relate this to an example you’re probably familiar with. Let’s relate
this to your windows computer.

Your [hard] disk (or disc) is sort of like a database; it is a collection of your data. On that disk,
you have folders; they are analogous to tables within a database. Inside those folders, you have
documents or programs; these relate to rows. Within the document (e.g. a Word document), you
have paragraphs; these are much like columns.

Okay, let’s add to the analogy a little. Word or Lotus 1-2-3 would be your theme, as they
describe and manipulate the content before it is displayed to you. It’s a bit of a stretch for several
reasons, but you can then think of Windows itself as your browser, since it is responsible for the
final rendering of the content to you.

Does that help a little?

The Structured Query Language (SQL) is a standard specification for how database engines
locate data that you want. An example might be SELECT country FROM user_profile
WHERE username = "Nancy"; this would get the value from the column "country" in the
"user_profile" table using column "username" as the key.

225
Drupal Handbook 3 Aug 2007

Taking your site live


Once you’ve got your Drupal installation set up just the way you want it, there are a few final
considerations before you unleash it on the world.

Moving from a temporary location


It’s likely that you’ve put Drupal in a subfolder on your server, so it doesn’t interfere with your
existing website while you get it set up. So you have www.example.com showing your old site,
www.example.com/drupal showing drupal, and you want www.example.com to show off your
new site to the world. There are two ways you can go about this:

Moving Drupal
As of version 5, moving the Drupal base folder shouldn’t pose any problems. For older versions,
some settings may need to be changed so Drupal can find everything. See this forum thread for
more details.

Redirecting your server


Alternatively, you can leave Drupal where it is in a subfolder, and just have your webserver fool
everyone into thinking that folder is www.example.com.

With Apache, you need to add the following to the .htaccess in the root folder (or create an
.htaccess file if there isn’t one there):

RewriteEngine on
#
# stuff to let through (ignore)
#RewriteCond %{REQUEST_URI} "/folder1/" [OR]
#RewriteCond %{REQUEST_URI} "/folder2/"
RewriteRule (.*) drupal/$1 [L]

Use the RewriteCond rules to let through URLS without modification (for example, you might
have other subfolders you still want accessible). Replace ’drupal’ with the name of the folder
Drupal is in.

You also need to modify the settings.php file for your site. By default, this is at
sites/default/settings.php. Uncomment (or change) the line that sets $base_url, and set it to the
URL you want browsers to see as the base for your site:

$base_url = ’http://www.example.com’;

226
3 Aug 2007 Drupal Handbook

In other words, ensure that this does not include the drupal subdirectory. This changes the links
that Drupal generates so they point to the correct location.

Excluding paths from Drupal


It may be that your site is made up components other than Drupal, or that you have an archive
version of your old site you want to be browsable. Drupal in a root folder takes over all URLs;
Drupal in a subfolder fooled into thinking it’s root likewise.

Either way, the .htaccess file in the root folder needs to be changed to let through the paths to
files or folders you Drupal to ignore.

In the case where Drupal is in the root folder, here’s what you need to to:

1. In the your webserver root’s .htaccess file, find the section marked with the comment ’#
Various rewrite rules.’
2. Below ’RewriteEngine on’ but before any other rules, add lines in the following form:
RewriteRule /folder - [L] # a subfolder Drupal should ignore
RewriteRule /file.html - [L] # a file in root Drupal should ignore

This page is a work in progress. Please suggest other tasks it should cover.

227
Drupal Handbook 3 Aug 2007

Core modules
The pages below give help for the modules that come with Drupal. When you install Drupal,
these modules are automatically installed. To make use of a module, first make sure it’s enabled
at administer >> site building >> modules. (Some modules automatically are.) Then set the right
permissions for it at administer >> user management >> access control.

You can further extend the features of Drupal by using "contributed modules." A list of help
pages for contributed modules is available at the contributed modules page.

If you would like to add a module help page, follow the authoring guidelines. The site
maintainers can create and update pages for you.

Aggregator: publishing syndicated content


The news aggregator is a powerful on-site RSS news reader that can gather fresh content from
news sites and weblogs around the web and make it available from your site.

Users can view the latest news chronologically in the main news aggregator display or by
source.

You can add, edit, and delete feeds and choose how often to check each individual feed for
updated news. You can also tag individual feeds with categories, offering selective grouping of
some feeds into separate displays. Listings of the latest news for individual sources or
categorized sources can be enabled as blocks for display in the sidebar through the block
administration page.

The news aggregator requires cron to check for the latest news from the sites to which you have
subscribed. Drupal also provides a machine-readable OPML file of all of your subscribed feeds.

You can

administer your list of news feeds administer >> aggregator.


add a new feed administer >> aggregator >> add feed.
add a new category administer >> aggregator >> add category.
configure global settings for the news aggregator administer >> settings >> aggregator.
control access to the aggregator module through access permissions administer >> access
control >> permissions.
set permissions to access new feeds for user roles such as anonymous users at administer
>> access control >> permissions.
view the aggregator page.
run your cron job manually at your sites cron page.
read about configuring cron jobs.

228
3 Aug 2007 Drupal Handbook

Old page
Thousands of web sites, especially news sites and weblogs, syndicate their most recent site
content for others to display. The syndicated content always includes titles, also known as
headlines, for the newest published stories. Each headline acts as a direct link to the stories on
the remote site. Along with the headline, most sites typically provide either the first few
paragraphs of the story or a short summary. Many individuals use client-based news
aggregators on their personal computer to aggregate content, such as FeedDemon (for
Windows), NetNewsWire (for Macs) and AmphetaDesk (Windows, Mac and Linux).

Drupal also has a news aggregator built in as a standard feature. With it, you can subscribe to
feeds from other sites and display their content for your site users. Simply enable the aggregator
module in administer » modules, then click administer » aggregator and enter the feeds that
you choose.

Open aggregator links in new browser window


Many people would like to keep users on their site. In order to have users open links in a new
browser window instead of leaving your site you can modify two theme functions:
aggregator_page_item and aggregator_block_item.

An alternative approach would be to modify the output directly.

Here is a sample of code that could be used: $output .= "link\"


target=\"_blank\">$feed->link\n";

User Aggregator:user submitted feeds


http://drupal.org/node/30865

User Aggregator allows users to add a syndication feed to a site’s aggregator via their user
profile.

Features:
Site administrator can set
- visible and default categories that will be assigned to user entered feeds. Default categories do
not have to be visible
- default refresh interval for user entered feeds
- option to show on account setup
- allow users to select single or multiple categories
Users can select or unselect visible categories
User entered feeds go to a pending table for administrative review

229
Drupal Handbook 3 Aug 2007

What do I need to subscribe to a feed?


The standard method of syndication is using the XML-based RSS format. RSS stands for Really
Simple Syndication, RDF Site Summary, or Rich Site Summary, depending on whom you talk to.
To syndicate a site’s content, obtain the full URL of the RSS page providing syndication.
Common file tags for RSS pages are .rss, .xml and .rdf. Example:
http://slashdot.org/slashdot.rdf.

Most weblog sites that offer syndication will have an obvious link on the main page. Often you
need only look for a red XML button, such as the one Drupal uses for site syndication.

Some sites do not make their RSS feeds as easy to find. Or maybe you want to find a number of
feeds on a given topic, without extensively searching the web. In that case, try an RSS
syndication directory such as Syndic8.

To learn much more about RSS, here are some good introductions:

Mark Pilgrim’s What is RSS


WebReference.com’s The Evolution of RSS

NOTE: Enable your site’s XML syndication button by turning on the Syndicate block in
administer » blocks.

Configuring news feeds


To subscribe to an RSS feed on another site, click administer » aggregator.

Once there, select the add feed tab at the top of the aggregator administration page. Drupal will
then ask for the following:

Title -- The text entered here will be used in your news aggregator, within the
administration configuration section, and as title for the news feed block. As a general rule,
use the web site name from which the feed originates.
URL -- Here you’ll enter the fully-qualified URL for the feed for the site you want to
subscribe to.
Update interval -- The update interval is how often Drupal will automatically access the
RSS URL for the site for fresh content. The 1 hour default is typically a good minimum to
use. Accessing another site’s RSS page more frequently can be considered impolite because
it requires the other site’s server to handle your automatic requests. To take advantage of
this feature, note that cron.php must be configured to have your feeds updated regularly.
Otherwise, you’ll have to manually update feeds one at a time within the news aggregation
administration (administer » aggregator) section.

Once you submit your new feed, check to see if it is working properly. Select update items on the
main news aggregation page. If you do not see any items listed for that feed, edit the feed and
make sure that the URL was entered correctly.

230
3 Aug 2007 Drupal Handbook

Filter feeds by keyword, time, by summary


To filter by keyword: http://drupal.org/node/13047
Filtering by time and by summary to be added.

Creating categories in the aggregator


1. Go to administer » aggregator then click on the add category tab.
2. Add a title to the category, then a description.
3. If you wish to have a block of the last x items from that category, select the number of items
in "Latest items block". To place the block on your sidebar, go to administer » blocks and
look for the category you just created.

Now every time you add a feed, you can select a category which the items will automatically
appear under. Alternatively, you can tag individual items in your aggregator to appear in a
category.

Tagging individual items in the aggregator


1. To get to the categorization screen, in your sidebar navigation, click news aggregator
2. Here you have two options:
1. click categories, then the category you wish to look at, then the categorize tab.
2. click sources, then the feed source you with to look at, then the categorize tab.
3. You will be presented with a list of items to categorize, plus to the right, the categories
which you can assign to each item. If you have the multiple-select option enabled in the
aggregator configuration, you can select more than one category for an item by holding
down CTRL (PC) or CMD (Mac) and clicking on each category.

Using the news aggregator


The news aggregator has a number of ways that it displays your subscribed content:

Latest News -- Displays all incoming content in the order received


with

The title of the original post.


The name of the source, which acts as a link to an individual feed page, listing information
about that feed and incoming content for that feed only.
A description, the first few paragraphs or summary of the originating post (if any).
The list of categories that the feed (or feed item) belongs to, with a link to each category.

News by Source: Organizes incoming content by feed, displaying titles which link to the
originating post. Also has an icon which acts as blog it link.
News by Topic: Organizes incoming content by bundles, displaying titles which link to the
originating post. Also has an icon which acts as blog it link.

231
Drupal Handbook 3 Aug 2007

News Sources: Displays an alphabetical listing of all subscribed feeds and a description.
The title acts as a link to an individual feed page, listing information about that feed and
incoming content for that feed only.

RSS feed blocks


In addition to providing subscribed content through the news aggregator, Drupal automatically
can create a block for every feed as well as every category, though the administrator can choose
whether or not a feed or category gets its own blocks by configuring the individual feeds and
categories. Enable any or all of the blocks using block management by clicking administer »
blocks.

Block: controlling content in the sidebars


Blocks are the boxes of related/grouped data that are visible in the left and/or right sidebar(s) of
your web site. They can also be placed anywhere on your page using regions. These are usually
generated automatically by modules (e.g. recent forum topics), but administrators can also
create their own defined blocks.

The sidebar each block appears in depends on both which theme you are using (some are
left-only, some right, some both), and on the settings in block management.

The block management screen lets you specify the vertical sort-order of the blocks within a
sidebar. You do this by assigning a weight to each block. Lighter blocks (smaller weight) "float
up" towards the top of the sidebar. Heavier ones "sink down" towards the bottom of it.

The block management screen also provides checkboxes and a configure link for customizing the
visibility of individual blocks. A block’s visibility depends on:

The Enabled checkbox. Disabled blocks are never shown.


The Throttle checkbox. Throttled blocks are hidden during high server loads.
Page specific visibility settings. Individual blocks can be configured to only show/hide on
certain pages. You can also show/hide blocks based on the result of a PHP snippit.
Custom visibility settings. Individual blocks can be configured so that users decide whether to
show/hide certain blocks.
Its function. Dynamic blocks (such as those defined by modules) may be empty on certain
pages and will not be shown.

Module blocks
Module blocks are available when modules are enabled. These blocks can be administered in
block administration.

232
3 Aug 2007 Drupal Handbook

Administrator defined blocks


An administrator defined block contains content supplied by the administrator. Each
admin-defined block consists of a title, a description, and a body which can be as long as you
wish. The Drupal engine will render the content of the block.

Note: Blocks are configured per theme so if you use multiple themes on a site you will need to
enable and configure blocks for each theme.

You can

enable throttle and configure blocks at administer >> block.


add a block at administer >> block >> add block.

Blog: a blog for every user


The blog module allows registered users to maintain an online weblog (commonly known as a
blog), often referred to as an online journal or diary. Blogs are made up of individual posts that
are time stamped and are typically viewed by date as you would a diary. Blogs often contain
links to webpages users have read and/or agree/disagree with.

The blog module adds a user blogs navigation link to the main navigation menu (the link must be
enabled), which takes any visitor to a page that displays the most recent blog entries from all the
users on the site. The navigation menu has a create content link (which takes you to a page with a
link to a submission form) and a my blog link (which displays your blog entries as other people
will see them). The blog module also creates a recent blog posts block that can be enabled.

You can

read your blog via your user profile at my account.


post a blog at create content >> personal blog entry.
administer blog at administer >> settings >> content types >> blog entry.
administer blog api at administer >> settings >> blogapi.
enable the "recent blog posts" block at administer >> blocks to show the 10 most recent blog
posts.

HOWTO: Configure user blogs


To implement user blogs on your Drupal site, turn on the blog module and enable permissions:

1. Go to administer » modules and check the box in the status column to the right of blog.
2. Under administer » access control, check the edit own blog box for each role you wish to
maintain blogs.

233
Drupal Handbook 3 Aug 2007

Aftewards, once logged in, each user with the permission to maintain a blog will be able to click
create content » personal blog entry and will see my blog (which displays blog entries as other
people will see them) in the user navigation block. At the top of each individual blog post, the
original blog author will find an edit tab.

To add instructions for users on creating their blogs and set workflow options such as published,
promoted to the front page, etc.:

1. Select administer » content » configure » content type, then the "configure" link next to
"personal blog entry
2. Enter your instructions in the available text field.
3. Set workflow options.
4. Use the Minimum number of words in a blog entry setting to specify a minimum length for all
blog posts.

Most recent blog post block


Note that the block displaying "recent blog posts" cannot be easily customized to display fewer
than 10 items. You have to modify the source code, the number is hard wired. There is a forum
discussion on this limitation. See:
http://drupal.org/node/15635

Navigate throught categories inside a blog


It’s very useful knowing how to make the general taxonomy system fits with the needings of a
multiblog site. If in our web there are many blogs independent, but the share the same
vocabulary, there would be a problem when navigate using taxonomy links in a post.

There a interesting post titled "Blogs categories" very useful: http://drupal.org/node/20260 .

I’ll write here the code to make a term link go to a view with two arguments (the user id, and the
term id).

Soon.

What is a blog or weblog?


Drupal’s blog module allows all registered users to maintain a personal weblog on site. Blogs are
easily- and frequently-updated websites usually written in an informal and conversational style.
They are ordered reverse-chronologically (that is, the most recent entry is at the top) and have
archives of past entries. Each individual entry has a permanentâthat is to say, stableâURL
linking directly to that item. Blogs typically have comments for each entry so that readers can
participate in the discussion, and they usually have RSS feed to be syndicated elsewhere or read
in an desktop aggregator. Each entry usually contains one idea, with a link to the source of the
original item being discussed. Blogs can be (and are) written about any subject, from daily
personal life to technology to politics to knitting to sports to a company’s products.

234
3 Aug 2007 Drupal Handbook

From a more practical standpoint, blogs can be seen as a means of personal knowledge
publishing, a place for researchers or enthusiasts to build and share knowledge about their
interests. Or in project oriented sites, as a workspace for project members to post ideas for
commenting by others in a group.

For a more complete definition of blogging with links to resources and examples, see George
Siemens’ The Art of Blogging - Part 1 and The Art of Blogging - Part 2.

Making user blogs more accessible


Drupal provides a number of ways to make user blog posts accessible. You’ll need to decide
which ones work best for how your Drupal site is configured:

A link in the navigation bar: After activating the blog module, most Drupal themes will
include a Blogs link in the header navigation bar. The user blog listing contains the most
recent blog posts by all site users. If the site is using xtemplate, you’ll need to create the link
yourself. Go to site configuration » themes » xtemplate and add in the HTML to create the
URL (to find the URL, switch your site theme momentarily to Marvin and the link will be
present in the navigation header).
Making user blog listings the default home page: Click administer » settings and type in
the word "blog" (without quotes) for Default front page.
Promoting individual blog posts: If "node" is the Default front page setting, administrators
can elect to promote any user blog posts to the front page. Click onto the blog post you want
to promote, then the edit tab and then check Promoted to Front Page.
Promoting individual blog posts automatically: Click administer » content » configure »
content type, then the "configure" link next to "personal blog entry, and check the Promoted
front page box in the "Default options" group. (This will work if "node" is the Default front
page in administer » settings.
Links to recently-updated blogs on the sidebar: Drupal also makes available a Most recent
blogs block under administer » blocks.

Additional features
Blog it: Users with blogs will see a "blog it" link in the form of a linked image i.e. when
viewing posts in the news aggregator. Other news listings, such as RSS blocks, will have an
icon in place of the textual blog it link. When the blog it option is selected, the user will be
taken to the blog entry form, with the title, a link to the item, and a link to the source
already entered in the text input field, ready for the user to add explanation.
User Blog RSS syndication: each individual user blog has their own RSS feed, allowing
other sites to syndicate their content or allowing readers to read the individual blog in an
aggregator. To find the RSS feed for a user, view their personal blog (in their personal
information, which you can get to by clicking on their username, select view recent blog
entries). Then look for the XML icon at the bottom of their blog page.

235
Drupal Handbook 3 Aug 2007

BlogApi: post from blog tools


The blog API module enables a post to be posted to a site via external GUI applications. Many
users perfer to use external tools to improve their ability to read and post responses in a
customized way. The blog api provides users the freedom to use the blogging tools they want
but still have the blogging server of choice.

When this module is enabled and configured you can use a variety of programs to create and
publish posts from your desktop. Blog API module supports several XML-RPC based blogging
APIs such as the Blogger API, MetaWeblog API, and most of the Movable Type API.

For more information on using software with the BlogAPI, see the Creating New Content section
of the End User Guide.

This module also allows site administrators to configure which content types can be posted via
the external applications. So, for instance, users can post forum topics as well as blog posts.
Where supported, the external applications will display each content type as a separate "blog".

You can

view the XML-RPC page.


administer >> settings >> blogapi.

Book: structured document publishing


A book is a set of pages tied together in sequence, perhaps with chapters, sections, subsections,
and so on. You can use books for manuals, site resource guides, Frequently Asked Questions
(FAQs), or whatever you’d like.

Users who have permission can create a book and write, review, modify, or rearrange the pages.
Many users can work together on a book. You can allow or disallow collaboration, to whatever
extent you want.

At the bottom of book pages, Drupal automatically provides links for moving to the previous
page and the next, and a link labeled up that leads to the level above in the structure. A contents
page is also automatically created.

You can provide your users a menu that helps them find their way around inside your books.
You do this by enabling the book navigation block on the blocks page (administer >> blocks). (Users
will see the menu only when viewing the book.)

Apart from this, you can also add a books link to any of your menus. This link will take users to a
list of your books. You add the link by enabling the books menu item on the menus page
(administer >> menus). You’ll find this item there under "Navigation." You can also add this link
to any menu you want. (Click "add menu item," and when you fill in the "path" field on the
dialogue page just enter "book.")

236
3 Aug 2007 Drupal Handbook

The "books" link takes users to your books. The "book navigation" block helps users move around
inside your books.

You can also let users generate a printer-friendly display of a book page and all its subsections.
They do this by selecting the link for printer-friendly version at the bottom of any book page.

On the books administration page (administer >> content >> books), administrators can view a
list of all the books on your site. For each book there’s a link to an outline, from which to edit or
delete pages or sections, change their titles, or change their weight (thus putting them in a
different order).

When you edit a page or section, you can also move it to a different level in the hierarchy by
changing the "parent" to which it belongs. So you can move things around however you like.
You can also check for orphan pages (pages that have become disconnected from the rest of the
book).

On the access control page (administer >> access control) you can assign to users with various
roles the permission to create book pages, to create new books, and to edit their own book pages
or the pages of others.

When users you allow create a post of the type Book page, Drupal automatically prompts them to
add their page at the level of their choice in a book, or to start a new book (by defining its
"parent" as "top-level").

You can also give permission to outline posts in books. Users with this permission can take any
other type of existing content on your site and add it to a book. When viewing a post they’ll see
an outline tab, and by clicking it they’ll come to an interface that lets them move the post into a
book.

You can:

create new book pages: create content >> book page.


administer individual books (choose a book from list): administer >> content >> books.
set workflow and other global book settings at administer >> settings >> content types >>
book page.
enable the book navigation block: administer >> block.
control who can create, edit, and maintain book pages at administer >> access control.

Customising the book navigation menu


By default, the navigation menu block for a book appears only on pages that are part of the book
hierarchy- that is, the top-level book page (www.example.com/books/book-name) and its child
pages (www.example.com/books/book-name/child-page). This is because the code in the block
is not an actual menu- it just simulates a menu, and so will never appear on the menu page at
..admin/menu.

237
Drupal Handbook 3 Aug 2007

This means that you can’t make the book navigation block appear permanently on the front page
(if you are using the book module to create a static hierarchical structure for example), or in any
other place on the site except the book pages.

This seems like a major limitation, but fortunately a snippet is available that will create a book
navigation menu that can be placed anywhere on your site and not just when navigating a book.

Maintaining a FAQ using a collaborative book


Collaborative books let you easily set up a Frequently Asked Questions (FAQ) section on your
web site. The main benefit is that you don’t have to write all the questions/answers by yourself -
let the community do it for you!

In order to set up the FAQ, you have to create a new book which will hold all your content. To
do so,

1. Click on the create content » book page link.


2. Give it a thoughtful title. A title like "Estonia Travel - FAQ" is nice.
3. Set the Parent to <top-level> to make this page the beginning of a new book
4. Add in the text of the book page into the Body textarea.
5. Leave the log message blank for now.
6. Use the weight field to position this book in the list on the book module page.

After you have submitted this book page, you are ready to begin filling up your book with
questions that are frequently asked.

Creating new pages for your FAQ. The process for creating new pages in your FAQ is very similar
to above. When choosing the Parent option, select the FAQ book page that you already created to
add it to the book.

Adding existing non-book pages to your FAQ. Whenever you come across a post which you want to
include in your FAQ,

1. Click on the outline tab at the top of the page.


2. Place the relevant post wherever is most appropriate in your book by selecting a Parent.

Notes:

Books are quite flexible. They can have sections like Flying to Estonia, Eating in Estonia and
so on. As you get more experienced with the book module, you can reorganize posts in your
book so that it stays organized.
Any comments attached to those relevant posts which you designate as book pages will also
be transported into your book. This is a great feature, since much wisdom is shared via
comments. Remember that all future comments and edits will automatically be reflected in
your book.
You may wish to edit the title of posts when adding them to your FAQ. Clear titles improve
navigability enormously.

238
3 Aug 2007 Drupal Handbook

Book pages may come from any content type (blog, story, page, etc.). If you are creating a
post solely for inclusion in your book, then use the create content » book page link.
If you don’t see the edit link or outline tab , then you probably have insufficient permissions.

Categories (taxonomy): A way to organize your


content
The categories module lets you classify content into categories and subcategories, thus
organizing the content on your site. For example, you could classify music by genre: classical,
jazz, rock. And you might further classify "classical" into concertos, sonatas, symphonies, and so
on. When your users create new content, you can let them classify it (or even require them to do
so) right when they create it.

When users view a post to which a category has been assigned, along with the post your theme
will generally show the name of the category (or categories) to which the post belongs. Each
category’s name appears as a link. And clicking on that link will bring users to a page showing
the other posts of the same category.

You can enable the categories module on the modules page (administer >> site building >>
modules).

The categories module is also sometimes called the taxonomy module. Taxonomy means
"division into ordered groups or categories." Taxonomy also refers to the science or principles of
classification. In the language of taxonomy, groups of categories are called "vocabularies," and
the categories themselves are called "terms."

With the categories module you can define groups ("vocabularies") of categories ("terms") by
which to classify content.

Each vocabulary consists of a set of terms.


You can have as many vocabularies as you want and for each create as many terms as you
want.
You can order your terms into hierarchies.
You can also have "free vocabularies," in which users creating new content don’t have to
classify it with terms from a "controlled vocabuary," one you’ve defined. Instead they can
freely define their own terms, or "tags." (This is sometimes called "free tagging.")
When you create a term, you can also tie it to related terms. (Think of "See also" in a
dictionary.)

You can allow users to classify each piece of content they create--each story, blog item, or
whatever--using one term or many.

For simple implementations, you might create a set of categories without subcategories (like
Slashdot’s "sections"). For more complex implementations, you might use subcategories too,
thus organizing things into a hierarchy.

239
Drupal Handbook 3 Aug 2007

To further organize your site, you can have groups of categories intersect. For example,
intersecting your musical genres you might have a set of categories indicating times: seventeenth
century, eighteenth century (perhaps with subcategories like "early eighteenth century" and "late
eighteenth century"). So, using our "genre" vocabulary we might call an item by the term
"sonata," and using our "times" vocabulary we might call it by the term "early eighteenth
century." If we add a vocabulary for "composers," we might categorize the item three ways--as
an "early-eighteenth-century" "sonata" by "Bach"--and locate it by any of these three terms.

Working with vocabularies

On the categories page (administer >> content management >> categories) you can create, view and
manage your categories. You’ll see a list of the vocabularies you’ve created, and you can edit
each one.

You can add new vocabularies, using the add vocabulary tab at the top of the page. Or you can
edit an existing vocabulary by clicking the edit vocabulary link next to its name (in the
"Operations" column).

You choose a name for your vocabulary.


You can give each one a description, which modules may use in different ways. (For
example, when users hover over a link that displays this vocabulary, they may see your
description.)
You can tie your vocabulary to particular "content types"--"story," "book page," or whatever.
Then when users create content of a particular type, they’ll see a list of your vocabulary
terms that go with it. Users can then categorize their post by choosing from the list. (You
can also give your vocabulary a help text to help your users choose.)
You can make choices about the hierarchies for your vocabularies. If you want all the terms
to be on only one level, choose "disabled." To allow your terms to have one (but only one)
level of terms below them, choose "single." And if you want to allow still further levels,
choose "multiple."
You can allow "related terms."
If you allow "free tagging," when your users create content they can make up their own
terms as they go along, instead of having to choose from a list.
By choosing "multiple select," you can allow your users to put a post into more than one
category at once by tagging it with more than one vocabulary term.
Also, if you like, you can require that when your users create content of a certain "content
type" they assign at least one of this vocabulary’s terms.
You can decide the order in which your vocabulary will appear in lists by assigning to it a
"weight."
Finally, if you like you can delete the vocabulary altogether, thereby also deleting all its
terms.

Working with terms

To view or manage the terms of each vocabulary, click on its list terms link. On the list terms page
you can edit each term by clicking the edit link. Now, on the edit term page you have several
kinds of choices.

240
3 Aug 2007 Drupal Handbook

If you’ve allowed this vocabulary to have a hierarchy, you can put the term in its place in
the hierarchy by choosing the term’s "parent."
You can select from this vocabulary one or more terms with which you’d like your term to
be related. (You can select multiple terms by using the standard conventions of your
operating system, like shift-click and control-click.)
You assign your term a name. (You have to do it. There’s no such thing as a "nameless
term.")
You can list synonyms for your term. (In taxonomy lingo, you’re creating for your
vocabulary a "thesaurus.")
You can decide the order in which your term will appear in lists by assigning it a "weight."
Or, finally, if you like you can delete a term altogether.

To add new terms to your vocabulary, click its add terms link. (The list terms page also has an add
terms link that does the same thing.) When you add new terms you have the same options as
when you edit them.

Using categories in menus

The menus on your site can call for items that match specific taxonomy terms--that is, terms
you’ve named your categories. Here’s how.

When you create a new term, Drupal assigns it a number. And you can call up all the items
categorized under that term by calling for its number.
To see your term’s number, go to the categories page, choose list terms for the category to
which your term belongs, and now hover over your term’s name in the list. You’ll see the
number.
Now, on the menus page (administer >> site building >> menus) you can create a menu item
for your term. Select add item, and when you fill in the path field you add your category like
this:

taxonomy/term/1

If your category "sonatas" is term 1, this would call for all the nodes of that category.

If your category "Bach" is term 2, you could call for only those sonatas written by Bach:

taxonomy/term/1,2

Or if Brahms is term 3 and you want to call for everything that has to do with either Bach or
Brahms, you’d do it this way:

taxonomy/term/2+3

Several contributed modules make powerful use of the categories (taxonomy) module,
exploiting and extending what it can do.

241
Drupal Handbook 3 Aug 2007

You can

enable the categories module at administer >> site building >> modules.
administer categories at administer >> content management >> categories.
decide who else can administer categories at administer >> user management >> access
control.
add a vocabulary at administer >> content management >> categories >> add vocabulary.

Modules that do more with categories


Categorization is useful for three main purposes on a website.

Manage categories: Challenges include user’s ability to suggest new categories, sharing
common categories across sites, and re-organizing categories.
Taxonomy_otf
Taxonomy_xml
Organizing content by category: Challenges include understanding hierarchies, getting
users to apply categories, automatic default categorization by node type or other, automatic
defaults, pulling or subscribing to content that is automatically categorized.
Action_feed
Taxonomy_defaults
Taxonomy_image
Taxonomy_multi_edit
Taxonomy_redirect
Taxonomy_similar-not stable
Taxonomy_theme
Inserting Taxonomy Images into nodes
Seperating free tagging from categories
Use categories for navigation: Challenges include menus, blocks, layouts, lists of titles and
teasers.
Taxonomy_association
Taxonomy_block
Taxonomy_browser
Taxonomy_context
Taxonomy_dhtml
Taxonomy_hide
Taxonomy_html
Taxonomy_links
Taxonomy_menu
Taxonomy_ticker
Related_nodes

242
3 Aug 2007 Drupal Handbook

Action_feed-you to receive and classify incoming e-mails from many organizations


taxonomy_assoc The taxonomy_assoc module lets you display a node - along with the usual
node listing for that term - when you view a taxonomy term. The node can be used instead of (or
as well as) the description that taxonomy_context outputs. Unlike raw descriptions, however,
nodes can be commented on, can have filters applied to them, and can be used in a number of
other ways.
taxonomy_block This is a simple module to create blocks based on taxonomy. It displays listings
of recently posted nodes based on taxonomy definitions. You can create as many blocks as you
like.
taxonomy_browser Think of this as a ’build your own category view’ page. Users select the
terms they want to see, and are redirected to the right URL (e.g. taxonomy/term/3,4,5), which
displays the matching content.
taxonomy_context The taxonomy_context module enables you to display several useful types of
information drawn from taxonomy terms. By default in Drupal, when you bring up a taxonomy
term you get a list of "node" (stories, static pages, books, etc.) associated with that term--but
nothing to describe the term itself. But for organizational websites one often wants to display
information like a title and description of the current section. So this module includes several
methods for displaying information about taxonomy terms:
* breadcrumbs
* the current term
* listings of sub-terms of the current term
taxonomy_defaults This module provides the ability to set default taxonomy terms per node
type.
taxonomy_dhtml A page listing recent nodes on your site, organized by taxonomy term. Also
provides a block for each vocabulary, listing terms and their node counts. Finally, a box is
exported to the syndication.module main page.
taxonomy_hide This module enables to setup list of vacabularies which terms will not be listed
in reference term list during node view. It enables also grouping terms by vocabulary as well.

taxonomy_html This module adds an HTML representations of site’s taxonomy. This is useful
for enabling users to browse your site according to topics of their own interest ... Specifically,
this module an Overview page listing all terms and vocabularies. Node counts for each term are
also shown beside each term link or in a help tip (aka title attribute).
taxonomy_image The taxonomy_image module allows site administrators to associate images
with taxonomy terms. With the association created, an admin can then make a call to
’taxonomy_image_display()’ from their theme or other PHP code
to display the appropriate image.

The module allows the admin to create a one-to-one term-to-image relationship. With image
display recursion, it is also possible to create a many-to-one relationship. This is useful if
creating taxonomy hierarchies in which an entire tree of terms will use the same image. With
recursion enabled, you only need to associate an image with the tree parent, and all children will
automatically inherit the same image.

taxonomy_menu The taxonomy menu module adds links to the navigation menu for taxonomy
terms. This is useful when the community is focused on creating content that is organized in a
taxonomy. The taxonomy menu administration interface allows taxonomy terms to be enabled

243
Drupal Handbook 3 Aug 2007

to show in the navigation menu. You can also select whether a term’s descendents subterms are
displayed.
taxonomy_multi_edit A mass category editor. quickly manage the taxonomy terms associated
with your nodes.
taxonomy_otf This module provides a mechanism for adding taxonomy terms on-the-fly. Users
who are granted permission can specify new categories while creating or editing their post.
taxonomy_redirect This module allows the administrator to change the destination of Taxonomy
Term links. Ordinarily these links go to taxonomy/term/TERMID but that is not
always desirable. Using this module, you could redirect these links to custom content, or content
generated by the Views module.

Due to the way the taxonomy module handles these redirects, they are available only on a
by-vocabulary basis; you cannot redirect them for individual terms.
taxonomy_similar taxonomy_similar will display a "similar tags" screen anytime content has
been created or updated with tags from a "Free tagging" vocabulary.
taxonomy_theme The taxonomy_theme module allows you to change the theme on a given node
based on the value of a taxonomy term for that node.
taxonomy_ticker Provides a block displaying titles of nodes in a scrolling news ticker.
taxonomy_xml This module makes it possible to import and export vocabularies and taxonomy
terms via XML. It requires taxonomy.module.
Taxonomy_links It looks up the taxonomies associated with the node, and then picks up all the
link entries associated with nodes belonging to those taxonomies.
Inserting Taxonomy Images into nodes These snippets allow you to insert Taxonomy images
into your nodes, when using the taxonomy_image.module.
Separate ’free tagging’ terms from normal taxonomy termsseparates Free tagging terms from
normal ones for separate theming.
Related_nodesuses taxonomy terms to find lists of nodes similar to the currently displayed one.

Content Management System comparison focused on


Taxonomy
This paper that compares Drupal with other CMS and why the taxonomy module sets it apart.

Taxonomy - some guidelines for effective design of


taxonomies
(I wrote this as a comment and was told to make it a page, so I have).

In most small sites taxonomy is obvious, but in larger sites, especially those where the expertise
of the readership may not be that of the authors, taxonomy design can make the difference
between a site being good or bad.

VIEWS Module - with it’s powerful taxonomy based Filters - makes taxonomy design even more
important than before.

244
3 Aug 2007 Drupal Handbook

General Rules

1) Unless a Vocab is well known to all anticipated users, and alphabetical (e.g. Countries of the
World), try and keep them below 30-40 Terms.

2) If your Vocab has Parent-Child structures, think about dividing it up because it’s likely to be
going to get too big, and is probably badly designed.

Example (sort from an online arts shop) - Traditional Arts Single Select

Europe
-Lapp
-Sami
-Celtic
Australia
-Aboriginal

This represented the way the shop classified their items.

But as such it prevents some clients saying "show me European Art".

Multiple Select is an option but much better to have two Vocabs - one for Region and one for
Culture, make them both multi and a collector could say "What have you got which is Lapp, or
Celtic or Chinese?"

3) Too Many Terms

"Perfect" taxonomies are always too complex and you need to fight to make them more
manageable. (Esp if you have just cut up a few Parent Child vocabs into several smaller ones
each...)

The advantage of VIEWS is that the multiple taxonomy terms start to build context, and that can
be captured by views.

There are not many sites that ever need to show more than 3-4 filters to users, even if there are
5-6 more hidden ones .

Plus building them into structure adds even more granularity.

Eg a site for ALL the small towns of America, where people are interested in their little towns
stuff, using Book for basic structure:-

Top level - States - 50 items


Off each State - Counties
Off each County - settlements

Click the named settlement and a get a VIEWS screen with filters for News, Culture,
Announcements.

245
Drupal Handbook 3 Aug 2007

(Hidden filters in the Views filter by State/County/Settlement)

Highly non scary - any users can use that to get what they need.

4) Clients are not experts on taxonomy, not even their own

Taxonomy is a communications issue and if there is a budget for the site it’s always worth
running it past an outsider - but note that they will need to get to understand the purpose of the
site and also to an extent the jargon of the subject.

This normally requires a least one decent face to face meeting to force the client to decide what is
important, and what can be cut out. (Trust me, these decisions will have to be made, and if they
are not, then people are probably not thinking carefully enough.)

5) Taxonomy creates Legacy issues - SO GET IT RIGHT

Once you have a load of tagged data, it’s hard to make changes to taxonomy structures (apart
from adding terms) without rendering existing nodes much harder to find. Trust me, NO ONE
will go back and edit existing data, not in real life, unless there is massive funding for that
purpose.

6) Taxonomy is trial and error.

It should be the first thing you do on a site, but by adding test data you’ll find flaws, and refine
and eventually go live with something that works. In between times you solved the CSS and
templating...

I once spent 3 days testing different ways to classify cars for one site - the makes/models
complexity of past 20 years is a nightmare, and which there are several ways ot do it, all of
which work, some are more userfriendly than others!

Hope this helps.

Ian Dickson - community specialist with a sideline in taxonomy because its the buidling block
for EFFECTIVE social software... .

Taxonomy Garden: Managing Categories


Manage categories: Challenges include user’s ability to suggest new categories, sharing common
categories across sites, and re-organizing categories.

Taxonomy_otf
Taxonomy_xml

Taxonomy On The Fly

246
3 Aug 2007 Drupal Handbook

This module provides a mechanism for adding taxonomy terms on-the-fly. Users who are
granted permission can specify new categories while creating or editing their post.

Taxonomy XML

This module makes it possible to import and export vocabularies and taxonomy terms via XML.

Taxonomy Garden: Navigation by category


Challenges include menu’s, blocks, layouts, lists of titles and teasers.

Taxonomy_association
Taxonomy_block
Taxonomy_browser
Taxonomy_context
Taxonomy_dhtml
Taxonomy_hide
Taxonomy_html
Taxonomy_links
Taxonomy_menu
Taxonomy_ticker
Related_nodes

247
Drupal Handbook 3 Aug 2007

Taxonomy Association

The taxonomy_assoc module lets you display a node - along with the usual node listing for that
term - when you view a taxonomy term.

The node can be used instead of (or as well as) the description that taxonomy_context outputs.
Unlike raw descriptions, however, nodes can be commented on, can have filters applied to them,
and can be used in a number of other ways. Taxonomy association allows you to assign terms to
nodes as seen in the picture below.

248
3 Aug 2007 Drupal Handbook

Taxonomy block

This is a simple module to create blocks based on taxonomy. It displays listings of recently
posted nodes based on taxonomy definitions. You can create as many blocks as you like.

249
Drupal Handbook 3 Aug 2007

Taxonomy browser

Think of this as a ’build your own category view’ page. Users select the terms they want to see,
and are redirected to the right URL (e.g. taxonomy/term/3,4,5), which displays the matching
content.

250
3 Aug 2007 Drupal Handbook

Taxonomy context

The taxonomy_context module enables you to display several useful types of information drawn
from taxonomy terms. By default in Drupal, when you bring up a taxonomy term you get a list
of "node" (stories, static pages, books, etc.) associated with that term--but nothing to describe the
term itself. But for organizational websites one often wants to display information like a title and
description of the current section. So this module includes several methods for displaying
information about taxonomy terms:

breadcrumbs
the current term
listings of sub-terms of the current term

251
Drupal Handbook 3 Aug 2007

Taxonomy dhtml

A page listing recent nodes on your site, organized by taxonomy term. Also provides a block for
each vocabulary, listing terms and their node counts. Finally, a box is exported to the
syndication.module main page.

252
3 Aug 2007 Drupal Handbook

Taxonomy hide
This module enables to setup list of vacabularies which terms will not be listed in reference term
list during node view. It enables also grouping terms by vocabulary as well.

Taxonomy menu

The taxonomy menu module adds links to the navigation menu for taxonomy terms. This is
useful when the community is focused on creating content that is organized in a taxonomy. The
taxonomy menu administration interface allows taxonomy terms to be enabled to show in the
navigation menu. You can also select whether a term’s descendents subterms are displayed.

253
Drupal Handbook 3 Aug 2007

Taxonomy ticker

Provides a block displaying titles of nodes in a scrolling news ticker.

Taxonomy Garden: Organize content by category


Challenges include understanding hierarchies, getting users to apply categories, automatic
default categorization by node type or other, automatic defaults, pulling or subscribing to
content that is automatically categorized.

Action_feed
Taxonomy_defaults
Taxonomy_image
Taxonomy_multi_edit
Taxonomy_redirect
Taxonomy_similar-not stable

254
3 Aug 2007 Drupal Handbook

Taxonomy_theme
Inserting Taxonomy Images into nodes
Seperating free tagging from categories

Taxonomy multi-edit

Edit the taxonomy designations of multiple nodes at once, without having to select each node
individually. Simplifies changing a large number of nodes from one taxonomy classification. In
admin/categories, a tab is added to "assign categories." Every node with at least one taxonomy
designation is displayed in a table, with the first column being and the remaining columns being
the available categories.

255
Drupal Handbook 3 Aug 2007

Taxonomy_image

Attach an image to each node in specified taxonomies based on terms. Child terms can have
parent images if no images are designed for child terms.

In admin/settings/taxonomy_image, admins can set the basic settings for the module. In
admin/categories an additional tab is added to allow users to upload one image per taxonomy
term. After inserting appropriate function calls to display_taxonomy_image() in the theme,
images will be displayed with nodes.

256
3 Aug 2007 Drupal Handbook

Taxonomy_theme

In one taxonomy, each term can be mapped to a theme that will display when the node is
display on its own. In an admin/settings submenu, the module can be enabled or disabled. One
taxonomy can be selected. Each term can be mapped to a theme. If it is not mapped, it gets the
site default theme.

257
Drupal Handbook 3 Aug 2007

Views

The views module is a query building module that can display a listing or table of results. Views
can include filters to limit results by a variety of criteria. This module does not specifically
organize nodes, but allows retrieval of pre-categorized nodes.

In admin/views, users can create a view entering appropriate values into a form. The form has
the following subsections: display, block, table, URL, arguments, filters, and sorting. If a URL is
specified, a menu item can be added for later retrieval. The view can be stored for later use, or
use by other modules. Views can be displayed directly as well.

258
3 Aug 2007 Drupal Handbook

Taxonomy_default

This module automatically tags posts for which the taxonomy is not activated (in the categories
admin section). For posts where the taxonomy is active, the tags are simply preselected.

In admin/settings/taxonomy_defaults, a section is created for each content type. Each content


type can set preselected tags in any vocabulary. For enabled vocabularies, the word "active" is
not italicized. For non-enabled vocabularies, the word active is italicized. When entering a node,
in-active vocabularies are not shown, but the term(s) are automatically added to nodes. For
active vocabularies, the terms are pre-selected. In either case, the terms are visible when the
node is rendered.

259
Drupal Handbook 3 Aug 2007

The taxonomy module for Drupal 4.x


The taxonomy module is one of the most popular features because users often want to create
categories to organize content by type. Users also use categories to help in site navigation. The
taxonomy module can automatically classify new content, which is very useful for organizing
content on-the-fly. A simple example would be organizing a list of music reviews by musical
genre.

Taxonomy is also the study of classification. The taxonomy module allows you to define
vocabularies (sets of categories) which are used to classify content. The module supports
hierarchical classification and association between terms, allowing for truly flexible information
retrieval and classification. The taxonomy module allows multiple lists of categories for
classification (controlled vocabularies) and offers the possibility of creating thesauri (controlled
vocabularies that indicate the relationship of terms) and taxonomies (controlled vocabularies
where relationships are indicated hierarchically). To delete a term choose edit term. To delete a
vocabulary, and all its terms, choose edit vocabulary.

260
3 Aug 2007 Drupal Handbook

A controlled vocabulary is a set of terms to use for describing content (known as descriptors in
indexing lingo). Drupal allows you to tag each piece of content (blog, story, etc.) using one or
many of these terms. For simple implementations, you might create a set of categories without
subcategories, similar to Slashdot’s sections. For more complex implementations, you might
create a hierarchical list of categories.

Sites can also use folksonomies. By checking the "Free tagging" option when creating a
vocabularly, users can create and enter their own tags for their content.

You can

add a vocabulary at administer >> categories >> add vocabulary.


administer categories at administer >> categories.

Understanding categories for new users


Drupal’s Category, also known as ’Taxonomy’, system can sound daunting, but it doesn’t have
to be. When all the fancy language is stripped away, Taxonomy is about one thing: organizing
your site by attaching descriptive terms to each piece of content.

Those terms might describe what section of your site a particular page belongs to. They might
describe what topics are discussed in a given blog post, or what region of the country a
photograph was taken in. These terms are organized in separate ’Vocabularies’ so that recipe
ingredients don’t get mixed up with cities in Texas when you’re trying to find out what
travel-logs were written in Houston, or what soups use potatos.

Setting up these Vocabularies, and the descriptive terms that belong to them, is the first step in
organizing your Drupal site. There are different kinds of vocabularies, and understanding how
they differ can help you decide the best way to categorize your content.

1. Lists of pre-defined terms -- a ’flat’ vocabulary


2. Hierarchies of pre-defined terms -- a ’tree’ vocabulary
3. Buckets full of terms -- a ’free-tagging’ vocabulary

For example, let’s say you’re setting up a photo portfolio, and using Taxonomy to keep things
organized. First, you might create a ’flat’ vocabulary for basic organization called ’Photo Type.’
To that vocabulary, you would add the terms ’Portrait,’ ’Stop-Action,’ ’Landscape,’ and so on.
Next, to keep track of where the photographs were taken, you might create a hierarchial
vocabulary called ’Location.’ To it, you could add terms like ’Europe’ and ’United States.’ In a
hierarchial vocabulary, each of those terms can also have sub-terms like ’France’ and ’Illinois.’
This makes it possible to tag a photo once with the term ’London’ and retrieve it later with a
broader request like ’Show me all the photos taken in Great Britain.’ Finally, to capture notes
about each photograph that would be hard to plan in advance, you could add a ’free tagging’
vocabulary called ’Keywords.’ Rather than defining the terms in advance, a free tagging
vocabulary lets you enter in new terms each time you post a piece of content. If two pieces of
content share a term, they’yer automatically connected to each other.

261
Drupal Handbook 3 Aug 2007

With those three vocabularies in place, any new photograph you post to your site can be quickly
categorized. Whenever you post a new image, Drupal offers you a list of the available terms in
the ’Photo Type’ and ’Location vocabularies AND a place to type in terms for your ’Keywords’
vocabulary. When posting a photo of your brother’s wedding, you might select a Photo Type of
’Portrait,’ a Location of ’Paris’ (if that’s where he was married, naturally!) and type in ’wedding’
and ’brother’ as keywords.

If you’re used to other CMS or blogging systems, these different vocabulary types might be
familiar as ’categories’ or ’sections’ or ’keywords.’ It’s important to note that nothing requires
you to use these different Drupal vocabularies, and different kinds of content can use different
vocabularies when it makes sense. News articles and Images might share ’Keywords’, but ’Photo
Type’ obviously only makes sense for one.

Mixing and matching these techniques in Drupal allows you to create the organizational system
that best suits your needs. Getting used to it can be tricky at first, but if you take the time to
think through your site’s organization, the results are worth it.

Using taxonomy to organize content


http://drupal.org/node/73694

-->

http://digitalsolutions.ph/couchkamotereviews/power_drupal_categories

-->
http://drupal.org/node/118525 -->

Drupal Taxonomy: the power to organize and reorganize

Adapted from benc’s


http://digitalsolutions.ph/couchkamotereviews/power_drupal_categories

The Drupal Taxonomy module (and the contributed module Categories) is one of its most
powerful features. Combined with its hooks, Drupal allows administrators to organize and
reorganize content easily, giving more flexibility for knowledge sharing in an organization that
continuously discovers better ways to share knowledge.

This tutorial has two purposes:

In particular: To show content managers and web developers how web content can be
organized and reorganized by using Drupal’s taxonomy module.
In general: To show the power of Drupal for rapid organization and reorganization and
dynamic taxonomy management; these are qualities that make Drupal a good tool to
facilitate knowledge sharing.

262
3 Aug 2007 Drupal Handbook

System requirements: You need an installation of Drupal 4.7 with admin permissions.

Basic terminology:

Taxonomy: The name of Drupal’s core (included) module for classification.


Category: The label used in the Administer area for configuring taxonomy. Also, the name
of a contributed (add-on) module for classification.
Vocabulary: A group of taxonomy terms.
Term: A label (of a taxonomy vocabulary) that can be applied to an item.
Labels, Tags: other words that are sometimes loosely applied to mean the same thing as
"Term."

Scenario: Starting a news web site

You have been asked to create a web site for a news company. They want to organize web
content according to the topic of the story. The topics are Politics, Technology, Business, and
Lifestyle. Stories may be about just one topic, or they may be about more than one. For instance,
a story may be about both technology and business.

Step 1: Plan your content structure.

How will you organize content in the web site? In our scenario, our client wants to categorize
stories as Politics, Technology, Business, and Lifestyle.

Step 2: Create a vocabulary.

After logging in to Drupal, go to (administer > categories) and click the "add vocabulary" tab. In
the add vocabulary screen, type "Topic" as the Vocabulary name.

Next, you need to tell Drupal that the vocabulary "Topic" will be used by the Story content type.
To do this, check the story checkbox under Type. This step is called binding a vocabulary to a
content type.

Next, click the checkbox called Multiple select. This allows selecting more than one taxonomy
term for each story.

At this point, you will see many other options. Ignore them for now and play around with them
later.

Step 3: Add terms under your vocabulary.

We now need to tell Drupal what labels are available under the Topic vocabulary. To the right of
the categories screen, click add terms. In the screen that follows, type a Term name (e.g.: Politics)
and click submit. Repeat this for each of the terms under Topic.

You can now review your vocabulary. To the right of your Topic, click list terms. You will see
something like this:

263
Drupal Handbook 3 Aug 2007

Topic
--Business
--Lifestyle
--Politics
--Technology

This gives you an idea of the content structure so far.

Step 4: Now try it out by creating a story.

In the administer menu, click create content > story. Now you see the newly created Topic tags
near the top of the form. Type a Title, choose Technology as the Topic, and write some text in the
Body field. Click Submit.

You have just uploaded content (a story) and tagged it as Technology.

Upload three other stories and multi-tag them according to the plan below. (To multi-tag, just
Ctrl-Click one item after another.)
1 story - Business, Technology
1 story - Lifestyle, Technology, Politics
1 story - Business, Politics

Now you’re seeing a bit of the power of Drupal.

Step 5: Exploit Drupal’s linking system.

Now you’ll get more glimpses of Drupal’s power. Go back to the categories screen (administer >
categories) and click list terms for Topic. Each of your terms is still listed and are actually links,
too. Mouse over "Business" and look at the status bar of your browser; it’ll show something like
www.example.com/taxonomy/term/555. (Note that the number 555 will be different in your
case.)

The link above tells you that "Business" is term number 555. And, get this, you can show all
stories that have been tagged as Business by just invoking the link
www.example.com/taxonomy/term/555 (using "taxonomy/term/555" will give the same
results). Go ahead, try it on your browser. Type that link or just click on "Business" to see the
stories that were tagged under Business.

What does this mean? First, without having to reprogram, you can create different ways of
displaying content by invoking the taxonomy term numbers. You can create a directory page for
your website, similar to Yahoo, simply by creating a story, typing the topics and linking them to
the term number. You can even create custom menus using this technique.

You have seen how organizing content is easy in Drupal through its taxonomy module. You also
saw that multi-tagging is easy to do in Drupal. Finally, you got a taste of Drupal’s power by
exploiting term numbers. That’s the end of this scenario of our tutorial.

264
3 Aug 2007 Drupal Handbook

Meanwhile, you can play around with the taxonomy module further. Try out the other options
and test the results by creating different stories. When you are ready, go to Scenario 2 (coming
soon), which will teach you to harness more power from vocabularies.

References to other beginning-level taxonomy pages (in order):

Understanding categories for new users


Advanced taxonomies: using hierarchies
More about Taxonomy

Using vocabularies for navigation


When displaying nodes, both in teaser listings on the Drupal home pages and in full,
single-node view, many Drupal themes display the categories applied to the node. If the user
selects any category term, Drupal will then display a browsable listing for all nodes tagged with
that term.

Examine the Taxonomy URL for one such category listing. The end of the URL should look
something like this:

taxonomy/term/1

And another Taxonomy URL, for a different term, something like this

taxonomy/term/2

Note that Taxonomy URLs always contain one or more Term IDs at the end of the URL. These
numbers, 1 and 2 above, tell Drupal which categories to display.

Now combine the Term ID’s above in one URL using a comma as a delimter

taxonomy/term/1,2

The resulting listing represents the boolean AND operation. It includes all nodes tagged with
both terms. To get a listing of nodes using either taxonomy term 1 OR 2, use a plus sign as the
operator

taxonomy/term/1+2

Want to combine more categories? Just add more delimeters and numbers. Know that you can
use the taxonomy section in Drupal site administration to find out any Term ID. Just place the
cursor over any edit term and look to the status bar at the bottom of the browser. Then substitute
the new Term ID’s found there to create a different category listing.

In addition to displaying Drupal nodes by category on site, Drupal has category specific RSS
feeds for other sites to access your site content. See how the URL format for the RSS feed is very
similar to the Taxonomy URL:

265
Drupal Handbook 3 Aug 2007

taxonomy/term/1+2/0/feed

Building individual Taxonomy URL’s is not the most user friendly way to provide site users
access to browseable listings. Nor do administrators necessarily want to build custom blocks for
users with links to each category listing. To extend the means of accessing nodes by category,
download and install the optional taxonomy_dhtml and syndication modules from the Drupal
downloads page.

Vocabularies and terms


Each category group, or vocabulary, can contain multiple category entries, or terms, for tagging
content.

For example, a web-based discussion community might have a vocabulary Topics with terms
such as

Technology
Politics
Education
Religion
Sports

An administrator might also choose to create multiple vocabularies for use with the same node
type. Consider another vocabulary for use alongside of Topics, one which classifies nodes in
another way:

Content with terms

News
Reviews
Announcements
Opinions

New vocabularies can also be created or added to at any time, with as few or as many terms as
the administrator may need. And do not worry. Long before reaching Drupal’s limits at
handling very large classification schemes, users would find large vocabularies and terms
unwieldy to use and maintain.

NOTE: When creating terms for a new vocabulary, administrators might want to provide users
with a catchall term, such as Miscellaneous. Administrators can then review nodes tagged with
Miscellaneous to see if a need exists for new terms. Once new terms are created, ambitious
administrators can also update nodes with the new tag and remove the catchall category tag.

266
3 Aug 2007 Drupal Handbook

Creating a vocabulary
When setting up a vocabulary, Drupal will prompt for:

Vocabulary name (Required) -- A name for this vocabulary; for example, Topics.
Description (Optional) -- A description of the vocabulary (this item may be used by some
modules and feeds).
Types (Required) -- A vocabulary may be associated with or more node types. So, an
administrator might declare that a particular vocabulary is to be associated with stories and
blogs, but not book pages. If an expected node type is unavailable, check and make sure that
the module for the specific node type has been activated.
Hierarchy (Optional) -- Allows a tree-like taxonomy (see Using Hierarchies below).
Related terms (Optional) -- Allows relationships between terms within this vocabulary.
Think of these as "see also" references (this item is not used by many Drupal modules).
Freetagging (Optional) -- Users create terms as they go by typing comma-separated lists of
the terms they want to apply to content instead of selecting from a pre-existing list of terms.
Freetagging vocabularies will present users with a text input that will autocomplete with
matching terms if they exist.
Multiple select (Optional) -- Allows users to categorize nodes by more than one term.
Useful for cross-indexing content. Nodes may then appear on multiple taxonomy pages.
Required (Optional) -- Requires a user to select a term in this vocabularly in order to submit
the node. Otherwise, when creating a node, users will be offered a none option as the default
for each vocabulary.
Weight (Optional) -- Allows the administrator to set the priority of this vocabularly when
listed with other vocabularies. When vocabularies are left with the default weight of zero,
Drupal displays multiple vocabularies in alphabetical order. Increasing a vocabularies
weight with respect to other vocabularies will cause it to appear after them in lists.
Conversely, lighter vocabularies will float nearer the top of lists. Useful for specifying which
vocabulary a user sees first when creating a node.

Creating terms
Once you have finished defining the vocabulary, you may populate it with terms. When creating
a term, note that the available options may depend on what was selected for related terms,
hierarchy and multiple select when creating the vocabulary:

Term name (Required) -- The name for this term. Example: Technology.
Description (Optional) -- Description of the term (this item may be used by some modules
and feeds).
Parent (Required) -- Select the term under which this term is a subset -- the branch of the
hierarchy that this term belongs under (only required when heirarchy is enabled for the
vocabulary).
Synonyms (Optional) -- Enter synonyms for this term, one synonym per line. Synonyms can
be used for variant spellings, acronyms, and other terms that have the same meaning as the
added term, but which are not explicitly listed in this thesaurus, i.e. unauthorized terms
(this item not used by many Drupal modules).

267
Drupal Handbook 3 Aug 2007

Weight (Optional) -- The weight is used to sort the terms of this vocabulary (see explanation
of weight above).

Advanced taxonomies: using hierarchies


For many users needing simple classification schemes, the examples above may be the only
structure necessary for tagging site content. For more elaborate classification needs, consider the
hierarchy option when creating vocabularies. Hierarchies allow the creation of sophisticated
taxonomies with categories and subcategories in a tree structure, much like Yahoo categories or
subject classifications used by libraries.

For example, the vocabulary Food could include the following categories and subcategories:

Dairy
Milk
Drink
Alchohol
Beer
Wine
Pop
Milk
Meat
Beef
Chicken
Lamb
Spices
Sugar

Note that the term Milk appears within both Dairy and Drink. This is an example of multiple
parents for a term. Just select both parents when creating the term Milk.

Don’t forget that that the order of term siblings (e.g. Beef, Chicken, Lamb) can be controlled with
the weight option.

More about Taxonomy


Taxonomy is more than just a module in Drupal. It is also the study of classification and a
research area of information science in the digital age. Drupal admnistrators who want to push
the limits of the Drupal taxonomy system might want to read how it applies to Drupal
taxonomy module development.

The taxonomy module is one of Drupal’s strongest and most popular features because it makes
our lives easier and brings goodwill to all. This is because the taxonomy module allows
authorized users to (1) tag content using custom labels (aka terms), and (2) automatically classify
new content based on this taxonomy. This makes for truly flexible information classification and
retrieval.

268
3 Aug 2007 Drupal Handbook

How is it done? There’s a technical and a storytelling explanation. Let’s begin with the technical
explanation:

The taxonomy module allows you to define vocabularies which are simply a collection of terms
(similar to Gmail "labels" or Flickr "tags"). You can define 2 kinds of relationships between terms:

* Hierarchical: indicates a parent-child (vertical) relationship like cat and dog are children of
mammals)

*Assocation: indicates a "similar to" (horizontal) relationship like mammals is similar to


animals.

Using these relationships, the taxonomy module allows multiple lists of categories for
classification (or controlled vocabularies) and offers the possibility of creating thesauri (terms
with horizontal relationships) and taxonomies (terms with hierarchical relationships). To delete a
term choose edit term. To delete a vocabulary, and all its terms, choose edit vocabulary. {comment: The
emphasized sentence actually sounds out of place here. Please suggest how it can be
reorganized.}

{factor next para into the main text}A controlled vocabulary is a set of terms to use for describing
content (known as descriptors in indexing lingo). Drupal allows you to describe each piece of
content (blog, story, etc.) using one or many of these terms. For simple implementations, you
might create a set of categories without subcategories, similar to Slashdot’s sections. For more
complex implementations, you might create a hierarchical list of categories. {/factor}

Still confused? The story below will show some examples of what the taxonomy module can
help you do:

Case 1 (simple example). Abel sets up a website that contains his music reviews (posted as
stories). Abel uses the taxonomy module to create two terms called Reviews and New
Releases. Under Reviews, he creates the following child terms: Jazz, Folk, Classical. He then
binds these terms to the story node. Now, when Abel posts each of his reviews, he gets a
taxonomy dropdown box that prompts him to classify his review. If Abel classifies a review
as Jazz, the story automatically gets displayed in the website’s "Jazz" category.

Case 2 (intermediate example): Yoyo Ma, a classical cellist, releases an album where he
combines Jazz with Classical styles. Abel now cannot decide whether to classify his album
review as Jazz or Classical. Abel fires up the taxonomy module and modifies the taxonomy
-- now, instead of allowing only one-to-one tagging, he allows multi-tagging. Abel now tags
his review as both Jazz and Classical and everyone, including Yoyo Ma, is happy.

Case 3 (complex): Abel’s music website grows and it now contains stories, blogs and forum
discussions. Beth and Ching are both contributors to Abel’s site. As they post content, they
are also asked to tag their contributions. {to be continued}

It’s Case 3 that I am most interested in.

269
Drupal Handbook 3 Aug 2007

I’m developing a site using Drupal which will rely heavily on stories, essays, and articles
submitted by a number of different users. These folks will want to just write their stuff and post
it. They can use the menu navigation feature of the submission/posting process to determine to
which menu (custom ones previously created by me and/or authorized moderators) the piece
should be associated. [The default behavior is to list unsorted menu items in alpha order, a
perfectly acceptable practice. Myself and moderators can further modify the order of menu items
by assigning them weights.]

So why should our contributors be further required to "classify" their material using terms I have
created? Why put them (and me, who would have to spend time creating vocabularies and
terms) through an unnecessary workload hassle?

So far all I have read are excuses like "well, you can and it’s cool", "it will help people search for
things later" (assumes an otherwise poor search facility is all that is available ), or "you either get
it or you don’t". This last one being the worst response. A typical refuge of
communication-impaired people who like to think themselves more powerful and wise through
possession of secret knowledge. Are we expected to embrace a system simply because a system
can be constructed?

I picked Drupal after trying other CMS approaches because it puts forward clean, nice-looking
pages fairly easily and contains a nice set of optional features (unlike Mambo and Nuke systems
which seem to assume everybody screamingly wants to know what’s hot, what’s not, who’s
popular, and the latest gossip). But I am not convinced Drupal developers must also buy into the
theology or dialectic of the supremacy of taxonomies. Could it be something as simple as
because a Drupal-type CMS is based on a database application (like MySQL), a taxonomy-based
approach is the easiest way of making the system rational and more humanly understandable?

Cheerily Yours,
Tim O’Laguna

Creating a Block with links belonging to certain taxonomy


terms
Question

war_boar wrote:

how to have a block of links to all terms which match taxonomy like Reviews: Anime Or
Reviews: Movies without doing it manually

it should be titled, Reviews and underneath all blogs or stories which matched.

Answer

You might want to use the Taxonomy dhtml module.

270
3 Aug 2007 Drupal Handbook

You will need to create a new Block of type=php. You will then want to paste in the code
below, and customize the ’Physicians’ subject and the $tax array. $tax the list of tids that you are
inetrested in. The third element, named ’operator’, can be and or or. So in your case, assuming
the term ID for movies is ’3’ and the term ID admin/taxonomy/edit/term/3 for Anime is ’6’
admin/taxonomy/edit/term/6, you want:

<?php
// paste this code into a custom block of type=php
// customize the $tax array and the $subject as needed
$tax = array(3, 6);
$operator = "or";
$result = taxonomy_select_nodes($tax, $operator);
while ($obj = db_fetch_object($result)) {
$node = node_load(array(’nid’ => $obj->nid));
$items[] = l($node->title, "node/". $node->nid);
}
return theme(’item_list’, $items);
?>

A Block that returns the first 5 terms for a taxonomy

<?php
$taxo_id = 3;
$sql = "SELECT node.title, node.nid FROM node INNER JOIN term_node ON
node.nid = term_node.nid WHERE term_node.tid = $taxo_id LIMIT 5";
$output .= "<ul>";
$result = db_query($sql);
while ($anode = db_fetch_object($result)) {
$output .= "<li>".l($anode->title, "node/$anode->nid")."</li>";
}
$output .= "</ul>";
return $output;
?>

Taxonomy terms on a page


I have a page with a table where each cell should list nodes that are at the intersection of two
keywords. In order to accomplish this I have modified Moshe’s code slightly. Here it is:

$content = "Some text";


$content .= getnodes (1,2);
$content .= "Some text";
$content .= getnodes (3,4);
print $content;
function getnodes($id1, $id2) {
$tax = array ("str_tids" => "$id1, $id2", "tids" => array ($id1, $id2),
"operator" => "and");

271
Drupal Handbook 3 Aug 2007

$result = taxonomy_select_nodes(array2object($tax), 0);


while ($node = db_fetch_object($result)) {
$output[] = l($node->title, "node/". $node->nid);
}
return (theme_item_list($output));
}

Comment: allow comments on content


The comment module creates a discussion board for each post. Users can post comments to
discuss a forum topic, weblog post, story, collaborative book page, etc. The ability to comment is
an important part of involving members in a communtiy dialogue.

An administrator can give comment permissions to user groups, and users can (optionally) edit
their last comment, assuming no others have been posted since.

Attached to each comment board is a control panel for customizing the way that comments are
displayed. Users can control the chronological ordering of posts (newest or oldest first) and the
number of posts to display on each page.

Comments behave like other user submissions. Filters, smileys and HTML that work in nodes
will also work with comments. The comment module provides specific features to inform site
members when new comments have been posted. On sites with active commenting from users,
the administrator can turn over comment moderation to the community.

You can

control access for various comment module functions through access permissions
administer >> access control.
administer comments administer >> comments >> configure.
enable the recent comments block: administer >> block

Detailed comment documentation


When enabled, the Drupal comment module creates a discussion board for each Drupal node.
Users can post comments to discuss a forum topic, weblog post, story, collaborative book page,
etc. An administrator can give comment permissions to user groups, and users can (optionally)
edit their last comment, assuming no others have been posted since.

User control of comment display


Attached to each comment board is a control panel for customizing the way that comments are
displayed. Users can control the chronological ordering of posts (newest or oldest first) and the
number of posts to display on each page. Additional settings include:

272
3 Aug 2007 Drupal Handbook

Threaded â Displays the posts grouped according to conversations and subconversations.


Flat â Displays the posts in chronological order, with no threading whatsoever.
Expanded â Displays the title and text for each post.
Collapsed â Displays only the title for each post.

When a user chooses save settings, the comments are then redisplayed using the user’s new
choices. Administrators can set the default settings for the comment control panel, along with
other comment defaults, in administer » comments » configure. NOTE: When comment
moderation is enabled, users will have another control panel option to control thresholds (see
below).

Additional comment configurations


Comments behave like other user submissions in Drupal. Filters, smileys and HTML that work
in nodes will also work with comments. Administrators can control access to various comment
module functions through administer » access control » permissions. Know that in a new
Drupal installation, all comment permissions are disabled by default. The choice of which
permissions to grant to which roles (groups of users) is left up to the site administrator. The
following permissions:

Access comments â Allows users to view comments.


Administrate comments â Allows users complete control over configuring, editing and
deleting all comments.
Moderate comments â Allows users to rate comment postings (see more on moderation
below).
Post comments â Allows users to post comments into an administrator moderation queue.
Post comments without approval â Allows users to directly post comments, bypassing the
moderation queue.

Notification of new comments


Drupal provides specific features to inform site members when new comments have been
posted.

Drupal displays the total number of comments attached to each node, and tracks comments read
by individual site members. Members which have logged in will see a notice accompanying
nodes which contain comments they have not read. Some administrators may want to
download, install and configure the notify module. Users can then request that Drupal send
them an e-mail when new comments are posted (the notify module requires that cron.php be
configured properly).

The tracker module, disabled by default, displays all the site’s recent posts. There is a link to the
recent posts page in the navigation block. This page is a useful way to browse new or updated
nodes and comments. Content which the user has not yet read is tagged with a red star (this
graphic depends on the current theme). Visit the comment board for any node, and Drupal will
display a red "new" label beside the text of unread comments.

273
Drupal Handbook 3 Aug 2007

Comment moderation
On sites with active commenting from users, the administrator can turn over comment
moderation to the community.

With comment moderation, each comment is automatically assigned an initial rating. As users
read comments, they can apply a vote which affects the comment rating. At the same time, users
have an additional option in the control panel which allows them to set a threshold for the
comments they wish to view. Those comments with ratings lower than the set threshold will not
be shown. To enable moderation, the administrator must grant moderate comments
permissions. Then, a number of options in administer » comments » configure must be
configured.

Moderation votes
The first step is to create moderation labels which allow users to rate a comment. Go to
administer » comments » configure » moderation votes. In the vote field, enter the textual
labels which users will see when casting their votes. Some examples are

Excellent +3
Insightful +2
Useful +1
Redundant -1
Flame -3

So that users know how their votes affect the comment, these examples include the vote value as
part of the label, although that is optional. Using the weight option, you can control the order in
which the votes appear to users. Setting the weight heavier (positive numbers) will make the
vote label appear at the bottom of the list. Lighter (a negative number) will push it to the top. To
encourage positive voting, a useful order might be higher values, positive votes, at the top, with
negative votes at the bottom.

Moderator vote/values matrix


Next go to administer » comments » configure » moderation matrix. Enter the values for
the vote labels for each permission role in the vote matrix. The values entered here will be used
to create the rating for each comment. NOTE: Comment ratings are calculated by averaging user
votes with the initial rating.

Creating comment thresholds


In administer » comments » configure » moderation thresholds, you’ll have to create some
comment thresholds to make the comment rating system useful. When comment moderation is
enabled and the thresholds are created, users will find another comment control panel option for
selecting their thresholds. They’ll use the thresholds you enter here to filter out comments with
low ratings. Consequently, you’ll probably want to create more than one threshold to give users
some flexibility in filtering comments.

274
3 Aug 2007 Drupal Handbook

When creating the thresholds, note that the Minimum score is asking you for the lowest rating
that a comment can have in order to be displayed. To see a common example of how thresholds
work, you might visit Slashdot and view one of their comment boards associated with a story.
You can reset the thresholds in their comment control panel.

Initial comment scores


Finally, you may want to enter some initial comment scores. In administer » comments »
configure » moderation roles you can assign a beginning rating for all comments posted by a
particular permission role. If you do not assign any initial scores, Drupal will assign a rating of 0
as the default.

Aggregator comments
Comments for aggregator items has been added to aggregator2 module.

Contact: a way for users to get in touch


The contact module helps people get in touch with one another and with you or the people
running your site.

Through personal contact forms users can send one another e-mail. And through site-wide contact
forms users can send e-mail to the people in charge of your site.

With either form, users can specify a subject, write their message, and also have a copy of their
e-mail sent to their own address.

Through contact forms, users allow themselves to be contacted yet keep their own e-mail
addresses private.

You can enable the contact module on the menus page (administer >> menus).

Users (in their account settings) can turn their personal contact forms on or off. When their form
is turned on, a contact tab appears in their user profile, for everyone to see. (Privileged users such
as site administrators can contact even users who have turned their forms off.)

When users view their own profiles they won’t see their contact tab. Only other users will see it,
if it’s turned on.

Your navigation menu can show a link to your site-wide contact form. Just enable the "contact"
link on your menus page (administer >> menus). You can add that link to any other menu as
well. (Click "add menu item," and when you fill in the "path" field on the dialogue page just
enter "contact.")

On the contact administration page (administer >> contact form) you can set up "categories" of
site-wide contact you’d like to receive. For example, one category might be "website feedback,"
and another might be "product information."

275
Drupal Handbook 3 Aug 2007

For each category, you can specify whom you’d like to have receive your user’s e-mail. The mail
could go to one person or many. You can also specify whether or not the user will receive an
automatic reply.

The settings portion of the contact administration page offers you other options. You can specify
what message you’d like to show on your site-wide contact page. And you can limit how many
times a user can contact you in an hour.

You can

view user profiles.


let each user enable a personal contact form in my account.
administer contact at administer >>contact.

Make your site wide contact form look prettier


Drupal ships with a sitewide contact form since version 4.7 that you can use to allow site visitors
to send feedaback. As mentioned in the help text on the contact form settings page, you can also
use the body area just above the form to give site visitors your postal address or share any other
information.

However, because you can’t specify an input format for the contact form page, the additional
information you add will display without linebreaks or paragraph breaks and look pretty ugly.

There is a simple workaround for this. Just put <br> and <p> tags where you want the
linebreaks and paragraphs to appear and you will have a nice looking contact page. Experiment
with the line break and paragraph break tags until you are satisfied with the appearance of your
contact page.

Drupal: Drupal sites directory server


The Drupal module uses the XML-RPC network communication protocol to connect your site
with a directory server.

Enabling the Drupal module will:

allow members on all sites using the Drupal module to login to your site without registering
using their distributed identification and vice versa.
allow members to login to any other site which uses the Drupal module, using a login name
which looks much like an email address for your site: username@example.com

The Drupal module administration page allows you to set the xml-rpc server page. The listing of
your site in a site directory will occur shortly after your sites next cron run.

You can

276
3 Aug 2007 Drupal Handbook

run your cron job manually at your sites cron page.


view the XML-RPC page.
administer Drupal administer >> settings >> drupal.

Old page
The "Drupal" module features a capability whereby other drupal sites may call home to report
their existence. In turn, this enables a pod of Drupal sites to find, cooperate and advertise each
other.

Currently, the main application of this feature is the Drupal sites page. By default, fresh Drupal
installations can use drupal.org as their directory server and report their existence. This reporting
occurs via scheduled XML-RPC pings.

Drupal administrators should simply enable this feature to get listed on the Drupal sites page.
Just set your site’s name, e-mail address, slogan and mission statement on the administer »
settings page. Then make sure that the field called Drupal XML-RPC server on the administer »
settings » drupal page is set to http://www.drupal.org/xmlrpc.php, and enable this feature
using the dropdown directly below.

The listing of your site will occur shortly after your site’s next cron run. Note that cron.php
should be called using the domain name which you want to have listed at drupal.org. For
example, don’t kick off cron by requesting http://127.0.0.1/cron.php. Instead, use a publicly
accessible domain name such as http://www.example.com/cron.php.

Also note that your installation need not use drupal.org as its directory server. For example, this
feature is perfectly capable of aggregating pings from all of your departmental drupal
installations sites within an enterprise.

Filter: Input formats for user content


The filter module allows you to configure formats for text input for your site. For example, you
may want a filter to strip out malicious HTML from users’ comments.

Despite the name "filter," the module not only lets you keep out text you don’t want but also lets
you enhance the text you let in. So, for example, you can use a filter to turn ordinary line breaks
into HTML paragraph tags.

When users create or edit content, they can choose between the input formats you make
available. You can configure which formats are available to which user roles, as well as choose a
default input format. You can also create new input formats. And you can configure each input
format to use your choice of filters.

You can

277
Drupal Handbook 3 Aug 2007

administer input format permissions and settings at administer >> input formats.
add a new input format at administer >> input formats >> add input format.

Forum: create threaded discussions


The forum module lets you create threaded discussion boards, called forums, on your site. This is
similar to a message board system such as phpBB. Forums are very useful because they allow
community members to discuss topics with one another, and the discussions are archived for
future reference.

Topics, or threaded discussions, are posted to a forum. Each topic is comprised of an initial post
and replies, or comments. Forum topics can have their own URLs.

Multiple forums are often set up for different areas of discussion. Forums can also be placed
inside other forums for a discussion area that is a subset of the parent forum, in which case they
are often called child boards or forums.

Containers can also be created to hold a group of forums. However, topics cannot be posted to
containers, unlike a parent forums. Both containers and forums can be placed inside other
containers and forums. By planning the structure of your containers and forums well, you make
it easier for users to find a discussion area of interest to them.

Forums module requires Taxonomy and Comments modules to be enabled.

You can

administer forums at administer >> forums.


set workflow and other global forum settings on the forum configuration page: administer
>> settings >> content types >> forum .
control who can create, edit, and administer forum posts with administer >> access control
or taxonomy access control.
move forum topics to a different forum board using the edit tab; a copy can be left in the
existing forum by selecting leave a shadow copy.
enable the required comment and taxonomy modules at administer >> modules.
style with flatform theme and add features with the quote, subscription, bbcode, and
comment mover modules. Add private message with privatemsg module and extend user
profile information with the profile module.
read about the comment module at administer >> help >> comment.
read about the taxonomy module at administer >> help >> taxonomy.
The forum module, like Drupal itself, can be extended with different modules depending on
the needs or your site. What features you choose to implement are in your control.

278
3 Aug 2007 Drupal Handbook

HOWTO: Create a forum


Users can post topics to forums. Forums can appear below other forums in a hierarchy, or can
appear in containers.

1. Click administer » forums.


2. Click the add forum tab.
3. Type in a forum name.
4. Type in a forum description. This will show up below the forum name when users visit the
forum section.
5. Select a parent.
You can choose either a forum or a container to be a ’parent’ for a forum. If there are no
containers or existing forums to choose from, you will only see <root> as the option,
meaning it will be at the top of the forum hierarchy.
6. Select a weight. Higher numbers means the container will sink down in the list, lower
numbers mean the container will rise up.
7. Click the "Submit" button.

HOWTO: Create forum containers


Containers are ’parents’ for forums (discussion boards); they are used to group forums. Users
cannot post topics to containers; users post to the forums in the container(s). A site with only a
few forum discussion boards may not need any containers.

1. Click administer » forums.


2. Click the add container tab.
3. Type in a container name.
4. Type in a container description. This will show up below the container name when users
visit the forum section.
5. Select a parent. If there are no containers or existing forums to choose from, you will only
see <root> as the option, meaning it will be at the top of the forum hierarchy.
6. Select a weight. Higher numbers means the container will sink down in the list, lower
numbers mean the container will rise up.
7. Click the "Submit" button.

Help: context-sensitive guidance


The help module displays context-sensitive help.

Administrators cannot alter the help system. But module authors can make informative use of it.
And modules can make help texts available to other modules.

279
Drupal Handbook 3 Aug 2007

More about the help module


All user help should be presented using the help module. Some examples of help:

The name of a module (unused, but there).


The description found on the admin/system/modules page.
The module’s help text, displayed on the admin/help page and through the module’s
individual help link.
The help for a distributed-authorization module (if applicable).
The description of a post type (if applicable).

The text of the help topics listed on administer >> help are maintained on drupal.org in the
Drupal modules section. Additional help is often available in sub pages of that section.

Legacy: remapping of old-style URLs


The legacy module provides legacy handlers for upgrades from older installations. These
handlers help automatically redirect references to pages from old installations and prevent page
not found errors for your site.

The legacy module handles legacy style taxonomy page, taxonomy feed, and blog feed paths. It
also handles URL upgrades from Drupal 4.1. It rewrites old-style URLs to new-style URLs (clean
URLs).

Example Mappings:

taxonomy/page/or/52,97 to taxonomy/term/52+97.
taxonomy/feed/or/52,97 to taxonomy/term/52+97/0/feed.
blog/feed/52 to blog/52/feed.
node/view/52 to node/52.
book/view/52 to node/52.
user/view/52 to user/52.

Legacy module has no configurable options and does not need to be enabled for new Drupal
sites.

Locale: multi-language support


The locale module allows you to present your Drupal site in a language other than the default
English. You can use it to set up a multi-lingual web site or replace given built-in text with text
which has been customized for your site. Whenever the locale module encounters text which
needs to be displayed, it tries to translate it into the currently selected language. If a translation
is not available, then the string is remembered, so you can look up untranslated strings easily.

280
3 Aug 2007 Drupal Handbook

The locale module provides two options for providing translations. The first is the integrated
web interface, via which you can search for untranslated strings, and specify their translations.
An easier and less time-consuming method is to import existing translations for your language.
These translations are available as GNU gettext Portable Object files (.po files for short).
Translations for many languages are available for download from the translation page.

If an existing translation does not meet your needs, the .po files are easily edited with special
editing tools. The locale module’s import feature allows you to add strings from such files into
your site’s database. The export functionality enables you to share your translations with others,
generating Portable Object files from your site strings.

You can

administer localization at administer >> localization.


manage strings for the localization: administer >> localization >> manage strings.
add a locale language: administer >> localization >> add language.
download translation files from the Drupal translations page.

Adjusting your php.ini settings for importing .po files


Gettext portable object files sometimes are big enough to require you to adjust the settings of
you php.ini at least to be able to import the translated strings into your Drupal installation.

For example, the es.po (Spanish localization) for Drupal 4.6.4 is a 400K+ text file containing
1800+ translated strings. You might very well need to adjust the relevant php.ini settings for this
file to get imported.

PHP defaults to this values:

; Maximum execution time of each script, in seconds


max_execution_time = 30

; Maximum amount of time each script may spend parsing request data
max_input_time = 60

; Maximum amount of memory a script may consume (8MB)


memory_limit = 8M

You’ll more likely have to adjust the memory_limit to 16M (your mileage may vary) to have the
import process complete.

If you’re getting a blank page with no indication that the import process has been completed (or
has failed) you’re most probably having trouble with PHP’s defaults. Make sure by checking the
messages in your webserver’s error log.

If it’s the upload what is taking too much time go adjust max_input_time to a higher value. If it’s
the time the script is taking to complete the process what’s taking too much time you’ll have to
adjust max_execution_time.

281
Drupal Handbook 3 Aug 2007

There should be no need to leave this values that way once you’ve imported a big .po file. If
you’re confident the new settings won’t hurt your webserver’s performance or security just
leave them that way. Otherwise return them to the previous settings (even when it’s highly
iikely that you’ll need to readjust them whenever you perform an upgrade or reinstall)

Editing text for translation


Translating text via the Drupal interface can be pretty tedious to say the least. This is not so
much because of Drupal, but because of page reloads every time a string is updated. There is a
much better way to translate strings into a different language, namely editing PO files with a PO
editor, and then importing them into Drupal.

A full guide on how to translate Drupal Core or modules, using the above-mentioned technique,
can be found here.

How to create Drupal site in Marathi (Devnagari)


I read a few posts asking guidelines on creating a Drupal site in Marathi (Devnagari) - a
language spoken in western part of India. As there is neither standard Marathi translation nor
any Marathi language specifc help is available, I thought of writing a small set of steps /
guidelines for creating a Drupal based website in Marathi language ( rather any Indian
Language for which Unicode fonts are available)

Although I have created Marathi websites using Drupal 4.7 & 5.1, this article applies to Drupal
5.1 only.

To create a Drupal site in Marathi, you may follow these steps:

- Install Drupal!
- Create first (Admin) user account
- Login as administrator to the newly created site
- Go to Administer > Site Building > Modules (/admin/build/modules)
- Enable Locale module
- Go to Administer > Site Configuration > Localization (/admin/settings/locale)
- Click on add language tab
- From the drop down of languages, select Marathi & click on Add language button
- On the Languages list page, you will now see mr (Marathi) as a language, enable it & make it
default

Now you might expect that suddenly the entire site will appear in Marathi, but nothing like
this will happen! Now you will need to ’translate’ default English ’Strings’ to Marathi one by
one.

- To do so, go to Manage Strings Tab on the localization page


(admin/settings/locale/strings/search)
- Enter the string / text you wish to translate to Marathi (e.g. Log in)
- If the string is found, a list of all the places where this string is used in Drupal site is displayed.

282
3 Aug 2007 Drupal Handbook

- In that list, go to the row which you want to translate to Marathi, click on edit
- In the next page enter your own Marathi translation of the string using unicode marathi font &
save the string (e.g. Log In = यà¥à¤£à¥à¤¯à¤¾à¤à¥ नà¥à¤à¤¦ )

Follow these steps for all the labels / strings which are appearing on your site’s interface and
you are done!!

To avoid this painful process, there is an option of Importing a translation scheme (so we can
actually import entire Marathi translation of Drupal interface in a single click). However,
unfortunately, there is no standard Marathi Translation of Drupal interface available yet! So we
have to wait for someone to write it or follow this string by string translation process!

If you need a Marathi Transliteration Typing interface for your site (so that your users can type
in Marathi using normal English keyboards), you may try a module called as UniSaraswati
(http://drupal.org/project/unisaraswati) specifically written for this purpose

If you need generic help about computing in Marathi, you may get it on Marathi Wikipedia -
http://mr.wikipedia.org

You may find the examples of marathi sites created using Drupal at:

www.sadha-sopa.com (Drupal 4.7)


www.marathigazal.com (Drupal 5.1)
www.miloonsaryajani.com (Drupal 5.1)

Prasad Shirgaonkar

How to install a different language


To install a locale, simply enable the locale module. Then, go to admin/localization and import a
.po file that you downloaded from http://drupal.org/project/Translations. You should select
the right language code in the popup menu. That’s it !

You can now let user switch languages, or not, by activating more than one. Also, you could
look in the tab "translate srtings" in the localization module.

See Locale or internationalization support for more.

HOWTO: Creating a customized language set to replace


Drupal terminology
1. Enable the locale module on the administer » modules page
2.
administer > access control
give yourself (and any other roles that should have it) permission to access locale
3. Go to the administer » localization page.
4. Select the add language tab .

283
Drupal Handbook 3 Aug 2007

5. Assuming English, create a custom language by adding en-US in the Language code text
field.
6. Give your language a name, such as custom-English (be sure not to use spaces in your
language name), and add the language.
7. This will return you to the main localization page. Set your new language as enabled and as
the default.
8. Save the configuration.
9. Then disable the original English language set (that is, unless you would like users to be
given the option to choose between the two in their account area).

Now, any time you visit a page with Drupal hard-coded content, it will be added into your
language set database.

Once you have visited a page that you wish to change the content:

1. Go to the manage strings page (admin/locale/string/search) of the localization section.


2. Enter in the string you wish to search for.
3. Edit the result and enter your replacement text.

HOWTO: Use a customized language set to change Drupal


text and terminology
Depending on your particular application, you may find that the default text or terminology
used in the Drupal core or a contributed module doesn’t suit your style or need. Customizing
this text with the locale module is fairly simple and is portable if you create an additional site up
upgrade your version of Drupal or a contributed module.

As simple examples, you might wish to change the "Search" button to say "Find", or you might
wish that comments were shown as being "Posted by" rather than "Submitted by" a particular
user. As a more advanced possibility, you might wish that the things described by Drupal as
"forums" were instead called "bulletin boards", and that you could change this in every context
where the word "forum" is used.

The locale module is a well-developed system for handling this situation. While described as a
system for making translations, it will also efficiently substitute your prefered terminology for
the default Drupal terminology. You should first read the instructions for Creating a customized
language set to replace Drupal terminology. After following the steps outlined there to create
your custom language, this page is intended to provide additional step-by-step and detailed
instructions for those new to Drupal.

Again, before proceeding, follow the instructions in the first section at


http://drupal.org/node/24593 to enable the locale module, create a customized language, and
make it the default language. If you are not user #1, a user with appropriate access will need to
go to the access control page at administer >> access control and enable "administer locales" for
your user role.

284
3 Aug 2007 Drupal Handbook

Next, rather than searching for individual strings through the interface at administer >>
localization, you’ll probably find it easier to use a template file and then import the "translated"
strings. So, download the translation templates from the appropriate version of Drupal. Some
contributed modules will also include a translation template in a "po" directory.

In the downloaded directory of templates, you will see numerous template files ending in ".pot".
The file "general.pot" contains strings that are reused in several modules. Open this in a text
editor and look it over. Following through on the simple examples above, we can find these
strings in the file in the following form:

#: includes/locale.inc:327;346 modules/search.module:142;996
modules/system.module:1198 modules/user.module:1958
msgid "Search"
msgstr ""

Edit the file so as to specify a replacement text, such as:

#: includes/locale.inc:327;346 modules/search.module:142;996
modules/system.module:1198 modules/user.module:1958
msgid "Search"
msgstr "Find"

Similarly, we can change the text shown by each comment by making a change to this entry:

#: themes/engines/phptemplate/phptemplate.engine:250;273
msgid "Submitted by %a on %b."
msgstr "Posted by %a on %b."

Note that the text following the "#:" is for information only and does not affect the outcome of
this process.

From here, save your edited file somewhere handy (you might keep it together with your local
copy of your customized theme). Now go back to administer->localization and choose "import"
from the top tabs. Browse and choose your edited translation file, and then import it into your
customized language. Voila, you should see that the name of the Search box it changed to "Find",
etc.

For a more sweeping change, you could open the "forum-module.pot file", and provide an
alternate term every place the word "forum" is used. For example, you could edit the following
entry as shown:

#: modules/forum.module:51;110;216
msgid "forum topic"
msgstr "bulletin board subject"

Additional help and techniques for using the locale module and generating substitute text can be
found in the Translator’s guide.

285
Drupal Handbook 3 Aug 2007

Note for the curious


If you look in the PHP code for a module, you’ll find (for example) in the search.module:

<?php
$form[’basic’][’inline’][’submit’] = array(’#type’ => ’submit’,
’#value’ => t(’Search’));
?>

’Search’ is a t-ified string, which means it can be replaced by using the locale module.

Menu: customize site navigation


The menu module lets you customize your menus. Menus appear in blocks on your site and
help visitors and users find their way around. The main menu for navigation is by default called
"Navigation."

On the administer menu page administrators can ’’’edit’’’ to change the title, description,
parent or weight of a menu item. Under the ’’’operations’’’ column, click on
’’’enable/disable’’’ to toggle a menu item on or off. Disabled menu items are not deleted but
merely made no longer visible on your site. The default menu items generated by the menu
module cannot be deleted, only disabled.
Use the ’’’add menu’’’ tab to submit a title for a new custom menu. Once submitted, the new
menu will appear in a list toward the bottom of the administer menu page underneath the
main navigation menu.
Use the ’’’add menu item’’’ tab to create new links in either the navigation menu or a
custom menu. Select the parent item to place the new link within an existing menu
structure. For top-level menu items, choose the name of the menu in which the link is to be
added.
To turn off the navigation menu block, administer the block page.

You can

administer menus at administer >> menus.


turn menus blocks on and off in the administration >> block.
add a menu at administer >> menus >> add menu.
add a menu item at administer >> menus >> add menu item.
reset all menu customizations back to the Drupal default at administer >> menus >> reset
menus.

Using named anchors with menus


Users who have tried using ânamed anchors,â also known as âjump links,â in the menu system
can run into problems with them not to working. For clarification, a named anchor looks like
this:
<a name="anchor"></a>

286
3 Aug 2007 Drupal Handbook

The expected behavior is that when a link that points to this named anchor is clicked, the user’s
browswer should jump to a to the anchor tag on the html page, making it appear at the top of
the user’s browser window.

This desired behavior can be accomplished by adding the following function to your theme’s
template.php file:

function phptemplate_menu_item_link($item, $link_item) {


// Convert anchors in path to proper fragment
$path = explode(’#’, $link_item[’path’], 2);
$fragment = !empty($path[1]) ? $path[1] : NULL;
$path = $path[0];
return l(
$item[’title’],
$path,
!empty($item[’description’]) ? array(’title’ =>
$item[’description’]) : array(),
!empty($item[’query’]) ? $item[’query’] : NULL,
$fragment,
FALSE,
FALSE
);
}

Node: the content


All content on a Drupal website is stored and treated as "nodes." A node is any posting, such as
a page, poll, story, forum text, or blog entry. Comments are not stored as nodes but are always
tied to one.

Treating all content as nodes allows the flexibility of creating new types of content. It also allows
you to painlessly apply new features or changes to all content.

Behind the scenes, the nodes module manages these nodes. This module is what lets you

list, sort through, and manage all the content on your site
set norms for how all posts are displayed
list and configure the "content types" for your site, and create new ones

Offering "content types" is a way Drupal allows you to have different kinds of nodes for
different purposes. For example, a "story" is one kind of node, a "book page" another, and a
"blog entry" yet another. You can also create new content types of your own.

You can

287
Drupal Handbook 3 Aug 2007

search for content at search.


administer all nodes at administer >> content management >> content.
administer workflow and other default settings for individual node types at administer >>
content management >> content types.
configure the number of nodes to display on the main page and the length of trimmed posts
at administer >> content management
>>post settings.
set access permissions for various node types at administer >> user management >> access
control.

Page: post static pages


The page module allows users to create static pages, which are the most basic type of content.
Pages can be collected in books via the book module. Users should create a page if the
information on the page is static. An example would be an "about" page.

When a page is created, a user can set authoring information, configure publishing options,
whether readers will be able to post comments. They can also select the content type of the page
(e.g., full HTML, filtered HTML, php).

As an administrator, you can set the publishing default for a page (in its workflow): you can
specify whether a page is by default published, sent to moderation, promoted to the front page,
sticky at the top of lists, and whether revisions are enabled by default. You can set the
permissions that different user roles have to view, create, and edit pages.

You can

read the node administration help at administer >> help >> node.
read the page administration help at administer >> help >> page.
read the story administration help at administer >> help >> story.
create a page at create content >> page.
set workflow and other global page settings at administer >> settings >> content types >>
page.

Difference between page and story


Many people ask what the difference is between the "page" node type and the "story" node type.
In terms of basic functionality, there is no difference. However, as they are processed within
Drupal as two different node types, one can theme them differently, so that page nodes and
story nodes have differing looks. You can also make a distinction when using various node
access modules.

Note that as of Drupal 5.x a few default differences have been introduced:

288
3 Aug 2007 Drupal Handbook

A page doesn’t post author information, timestamps or comments by default.


A story does post author information, timestamps or comments by default.

It is still possible to configure a story and a page to be exactly the same. Drupal core now also
allows administrators to edit the names of page and story to anything you want and create your
own different types of content that suit the needs of a specific site.

Specify page by title


You can specify a page by using the URL format node.php?title=text

Path: readable URLs


The path module lets you create aliases for Drupal URLs. That is, instead of a technical-looking
web address like www.example.com/?q=node/67, your users will see, for instance,
www.example.com/?q=news.

This makes more sense for your users and may help make your site show up better in internet
searches. (And with Drupal’s "clean URLs" feature you can get rid of the "?q=":
www.example.com/news.)

Some examples of URL aliases:

user/login => login


image/tid/16 => store
taxonomy/term/7+19+20+21 => store/products/whirlygigs
node/3 => contact
node/10 => products/merchandise/cups
node/10 => cups
node/11 => products/merchandise/coffeemakers

You can use slashes however you like. So, for example, suppose a page is called
www.example.com/taxonomy/term/7+19+20+21. You could also give it both of these new addresses:

www.example.com/store/products/whirlygigs
www.example.com/timesavers/whirlygigs

You can enable the path module on the modules page (administer >> modules). Then when users
with the right permissions create or edit posts, they’ll see a field for "URL path settings." That’s
where they can enter an alias of their choice.

On the URL aliases page (administer >> url aliases) you’ll see a list of all the URL aliases on your
site. There you can edit them, and add new ones. You can assign more than one alias to a page
(just use the add alias tab again for each new alias).

289
Drupal Handbook 3 Aug 2007

On the access control page (administer >> access control) you can decide who can create aliases
and who can administer the list of them.

The path module also lets you define many URL aliases at once. This is useful if you wish to use
URLs uniformly different from those assigned by default. For example, you may want to show
your URLs in a different language. To do this sort of thing, you need to dig a bit into Drupal’s
source code.

You can

set the path for a post with the path module.


add a URL alias: administer >> url aliases >> add alias.
administer the list of URL aliases: administer >> url aliases.
read how to configure clean URLs for your webserver.
enable Clean URLS to remove the =? at administer >> settings in the General settings area.
automate URL alias creation by installing and using the pathauto module.

Mass URL aliasing


Drupal also comes with user defined mass URL aliasing capabilities. You might like to see
completely different URLs used by Drupal, or even URLs translated to the visitors’ native
language, in which case this feature is handy. Only an administrator with access to the website
source code can set up this kind of aliases. You can define a function somewhere in your code
(even in settings.php), following this example:

<?php
// Example for Drupal 4.6.x
function conf_url_rewrite($path, $mode = ’incoming’) {
if ($mode == ’incoming’) { // URL coming from a client
return preg_replace(’!^display/(\d+)$!’, ’node/\1’, $path);
}
elseif ($mode == ’outgoing’) { // URL going out to a client
return preg_replace(’!^node/(\d+)$!’, ’display/\1’, $path);
}
}
?>
<?php
// Example for Drupal 4.7.x and up
function custom_url_rewrite($type, $path, $original) {
// This path was already aliased, skip rewriting it
if ($path != $original) {
return $path;
}
if ($type == ’source’) { // URL coming from a client
return preg_replace(’!^display/(\d+)$!’, ’node/\1’, $path);
}
elseif ($type == ’alias’) { // URL going out to a client

290
3 Aug 2007 Drupal Handbook

return preg_replace(’!^node/(\d+)$!’, ’display/\1’, $path);


}
}
?>

This function will shorten every node/$node_id type of URL to display/$node_id.


Individual URL aliases defined on the browser interface of Drupal take precedence, so if you
have a ’contact’ page alias for example, then the display/3 alias will not be effective when
outgoing links are created. Incoming URLs however always work with the mass URL aliased
variant. Only two modes are supposed to be supported by your custom function.

You cannot only use this feature to shorten the URLs, or to translate them to you own language,
but also to add completely new subURLs to an already existing module’s URL space, or to
compose a bunch of existing stuff together to a common URL space. You can create a news
section for example aliasing nodes and taxonomy overview pages falling under a ’news’
vocabulary, thus having news/15 and news/sections/3 instead of node/15 and
taxonomy/term/3. You need extensive knowledge of Drupal’s inner workings and regular
expressions though to make such advanced aliases.

Ping: notify services of changes


The ping module is useful for notifying interested sites that your site has changed. It
automatically sends notifications (called "pings") to the pingomatic service to tell it that your site
has changed. In turn pingomatic will ping other services such as weblogs.com, Technorati,
blo.gs, BlogRolling, Feedster.com, Moreover, etc.

The ping module requires cron or a similar periodic job scheduler to be enabled.

You can:

enable or disable the ping module at administer >> modules.


run your cron job at your sites cron page.
read about configuring cron jobs.

Write a custom module to ping a set of sites


If the sites that you want to notify don’t use ping-o-matic you can use the following update.

Copied from here: http://drupal.org/node/29704

Replace ping.module:ping_ping with the following. Compatible with drupal 4.6.3

/**
* Implementation of hook_ping().
*
* Notifies pingomatic.com, blo.gs, and technorati.com of changes at
this site.

291
Drupal Handbook 3 Aug 2007

*/
function ping_ping($name = ’’, $url = ’’) {
$result = xmlrpc(’http://rpc.pingomatic.com’, ’weblogUpdates.ping’,
$name, $url);
if ($result === FALSE) {
watchdog(’directory ping’, t(’Failed to notify pingomatic.com
(site).’), WATCHDOG_WARNING);
} else {
watchdog("directory ping", t(’successfully notified pingomatic.com
(site).’), WATCHDOG_NOTICE);
}
unset($result);
$result = xmlrpc(’http://rpc.technorati.com/rpc/ping’,
’weblogUpdates.ping’, $name, $url);
if ($result === FALSE) {
watchdog(’directory ping’, t(’Failed to notify technorati.com
(site).’), WATCHDOG_WARNING);
} else {
watchdog("directory ping",t(’successfully notified technorati.com
(site).’), WATCHDOG_NOTICE);
}
unset($result);
$result = xmlrpc(’http://ping.blo.gs’, ’weblogUpdates.ping’, $name,
$url);
if ($result === FALSE) {
watchdog(’directory ping’, t(’Failed to notify blo.gs (site).’),
WATCHDOG_WARNING);
} else {
watchdog("directory ping", t(’successfully notified blo.gs
(site).’), WATCHDOG_NOTICE);
}
unset($result);
}

- David Herron - http://7gen.com/

Poll: community voting


The poll module lets you create simple polls. You ask a question, provide possible answers, and
let your users vote. Drupal then keeps a running tally of the results.

When you create a poll, you can also specify the "base" vote counts (how many votes an item has
at the start) and decide how long the vote will run.

292
3 Aug 2007 Drupal Handbook

You can enable the polls module on the modules page (administer >> modules).

The poll item in the navigation menu will take you to a page where you can see all the current
polls, vote on them (if you haven’t already) and view the results.

On the access control page (administer >> access control) you can decide which users have
permission to vote, to see the voting results, and to create polls of their own.

You can see some sample polls on Drupal.org.

You can

view the polls page.


administer >> settings >> content types >> poll.

Profile: extending user account information


The profile module lets your users share information about themselves. You set up forms for
them to fill in. Users tell about themselves by filling in your forms on the edit tab of their "My
Account" page. And what each user tells will be visible to the rest of the users on your site, to the
extent you choose when you design the forms.

You can enable the profile module on the modules page (administer >> modules).

When you set up the forms for user profiles (at administer >> settings >> profiles), you can define
custom fields (for example, for name, age, and country). To do this, you can make use of fields of
the following types:

single-line textfield
Example: You want to ask your user’s name
multi-line textfield
Example: You want to ask an open-ended question: "What would you most like to do to
make this a better community?"
checkbox
Example: You want to say, "Please tick this box if you’ve ever been to Brazil."
list selection
Example: You want to ask, "Which of these colors do you most prefer--red, blue or green?"
freeform list
Example: You want to ask your user for a list--"What languages do you speak?"
URL
Example: You want to ask, "What is the address of your personal website?"
date
Example: You want to ask, "When were you born?"

You can have as many fields as you want, using any of these types as many times as you want.
And you can put each field into the order you want by specifying its "weight."

293
Drupal Handbook 3 Aug 2007

Each time you add a field, you are asked to specify its "category." This allows you to divide each
user’s profile into more than one section. For example, you might divide the profile into two
sections, one on "Community interests," the other on "Professional skills." So as you define each
field, you assign it to one of these two categories. Drupal will then typically display each user’s
profile page with two separate sections--one for "Community interests," another for
"Professional skills"--each with its own set of information, derived from the fields you have
defined and your user has filled in.

You can mark a field as being required ("The user must enter a value"). And you can specify that
when new users register, a field be shown for them to fill in.

If both the profile module and the menu module are enabled, from the Menus page (administer
>> menus) you can enable on the Navigation Menu the item User list. This will take people to a
page where they can see a list of your users. A person who has permission can click on the name
of any user in the list to view that user’s profile.

The option to show this menu item may be disabled by default, but you can enable it. (And you
can rename "User list" to whatever you wish.) You can also place a link to the User list among
your site’s primary and secondary links, or on any other menu as well. (Click "add menu item,"
and when you fill in the "path" field on the dialogue page just enter "profile.")

On the permissions page (administer >> access control) you can decide who is normally allowed to
view the user profiles. (You’ll find the permissions for profiles under "user module.") In any
case, the profiles are always accessible to your site administrators.

Contributed modules can also deploy the fields in user profiles to do much more with them. Such
modules, for example, can help community-based sites identify and organize users through their
profile fields.

You can

view user profiles.


administer profile settings: administer >> settings >> profiles.

Enabling user pictures (avatars)


Note that user pictures (or avatars) or pictures are part of the user.module, not the profile
module.

1. Navigate to the administration area for user module configuration page under administer »
users » configure
2. In the Pictures

settings, for Picture support, select Enabled (Enable picture support.)

Note: you must write in your directory name. Make sure the directory is created and make
sure you have that directory has write permissions (that is, chmod to 755).
Click ’save configuration’

294
3 Aug 2007 Drupal Handbook

Drupal 4.7 allows you to enable avatars at administer » settings » users


(admin/settings/user).

HOWTO: Create new profile fields


1. Enable the profile module:
2.
In administer » modules select in the ’Enable’ column where you see:
profile | Support for configurable user profiles.
3. Create new fields or edit existing ones:
4.
Navigate to the administration area: administer » settings » profiles
Select a form field type under ’Add new field’
Follow onscreen instructions for configuring this field, and ’save field’.

HOWTO: Make a field part of the registration process


This information is pertaining to Drupal 4.6.3.

To make a field part of the registration, perform the following steps:

1. Go to: administer >> settings >> profiles.


2. Create the profile field if it doesn’t exist yet, and as follows:
3.
Under the ’add new field’ section, choose the type of field you want to create by
clicking its link.
Provide the particulars for the field, namely category, title, form name, explanation,
weight, visibility and page title.
Now check whether the field may or may not be left empty.
To make it appear on the registration page, make a checkmark in the ’Visible in user
registration’ checkbox.
4. Click on the ’Save field’ button.

Your new field will now appear on the registration page.

Form Validation in plugin


check for $type="validate" in plugin
set errors via form_set_errors() to validate the required fields in registration form

HOWTO: Create a ’country’ profile field


This page describes how to create a ’country’ field in your users’ profiles, similar to the one on
Drupal.org, that lets you easily find users in any country.

295
Drupal Handbook 3 Aug 2007

1. Create a new profile field.


2. Go to the profile settings page (administer > settings > profiles ?q=admin/settings/profile)
3. Select the ’list selection’ type of form field.
4.
Category (required): It can be a category you already have or a new one. (Suggested:
Personal Information)
Title (required): Anything is OK. (Suggested: Country)
Form name (required): Anything is ok, as long as it is unique. (Suggested:
profile_country)
Explanation (optional): Usually, country is self explanatory, but you may want to write
a note here to your users about this field.
Selection options: Copy the list from the attached file here. This file is from Wikipedia
(http://en.wikipedia.org/wiki/List_of_countries May 2006)
Weight: Select whatever you like (this is the weight in the category selected above).
Visibility: Select one of the ’Public Field’ options.
Page title (required): You must put something here. (Suggested: People who live in)
Check boxes: Check ’the user must enter a value’ to make this field required. Check
’visible in user registration form’ to make it part of user registration.
5. Click on ’Save field.’

CiviCRM: Tags, Profiles, Groups, advanced community


member management
CiviCRM’s Profile functionality allows you to integrate and extend Drupal User screens with
your contact management requirements. It also gives you tools for collecting and sharing contact
information with community members and visitors.

You can:

configure user registration forms to include standard and custom CiviCRM fields
allow users to maintain some or all of their own contact data and find other contacts with
shared characteristics
make a subset of CiviCRM data available for searchable listings
create custom ’sign-up’ forms to collect contact information from site visitors

More information:

CiviCRM Quickstart - Website Integration


Configuring CiviCRM Profiles

296
3 Aug 2007 Drupal Handbook

Search: an internal site search system


The search module lets users search for specific content on your site. You can search both for
users and for particular words.

With a regular search, if you enter more than one search term the search module will look for
content that has all the terms you’ve entered. If instead you want either one term or another, join
your terms with "or." If you’re looking for an exact phrase, enclose it in quotation marks.

With Advanced Search you can also look for "any of these words" or "this phrase," or both, you
can rule out words you don’t want, and you can choose content types within which to confine
your search.

You can enable the search module on the modules page (administer >> modules).

Drupal’s search engine indexes the text of your site and the names of your users. You can tweak
the way it does this.

The search engine does its indexing at intervals you choose by setting "cron runs." Cron (which
stands for chronograph) is not a part of Drupal. It’s a scheduler that resides on your server and
runs tasks (called "cron jobs") at intervals, which you specify. The jobs can run weekly, daily,
hourly, or whatever you like.

What you want to do is schedule a "cron job" that has a browser on your server regularly visit
your "cron page." For instance, if your site were www.example.com your cron page would be
http://www.example.com/cron.php. (This page is automatically set up for you when you install
Drupal.)

Whenever such a visit occurs, the search engine will take up the work of indexing. You need to
set up those cron runs before your search engine will work.

For a modest personal site to which you post now and then, you might set up such a cron job to
run once a day. For a more active site you’d likely want to run that job more often--perhaps
every few hours or every hour.

With Linux or Unix you can schedule your cron jobs by setting up what’s called a "crontab."
(You might rely on helper programs like C-Panel to make setting up your cron jobs easier.)

For further guidance on cron you can see Drupal’s handbook page configuring cron jobs (or, if
your server is running Windows, configuring Windows cron jobs). Your hosting company may
also help guide you.

On your settings page for Search (administer >> settings >> search) you can limit how many items
should be indexed in a single cron run. This can help keep your system from getting overloaded
with work. (If you get a message that cron is timing out or PHP is running out of memory, lower
the number of items to index per run.) You also have a few more search settings you can choose.

297
Drupal Handbook 3 Aug 2007

If both the search module and the menu module are enabled, from the menus page (administer >>
menus) you can enable on the Navigation Menu the item Search. The option to show this menu
item may be disabled by default, but you can enable it. (And you can rename "Search" to
whatever you wish.)

You can also place a link to Search among your site’s primary and secondary links, or on any
other menu as well. (Click "add menu item," and when you fill in the "path" field on the dialogue
page just enter "search.")

On your blocks page (administer >> blocks) for most themes there’s also a Search form you can
enable, and you can choose where you want it to display.

On your access control page (administer >> access control) you can decide who can do searches and
who can administer the search settings.

A technical note: To use the search module the database user needs the create temporary table
permission. If you seem not to have it, ask your systems administrator to make sure it’s granted
to you.

You can

read about how your site uses cron in the administer >> help >> system.
run your cron job manually at your sites cron page.
read about configuring cron jobs.
configure search at administer >> settings >> search.

Add searching to your custom module


In order to have a custom module be searched the module must support the search hook. Read
the Drupal API for the hook_search.

Statistics: tracking referrers, page hits, etc.


The statistics module keeps track of numerous statistics of site usage. It counts how many times,
and from where each of your posts is viewed. The statistics module can be used to learn many
useful things about how users are interacting with each other and with your site.

Statistics module features

Logs show statistics for how many times the site and specific content on the site has been
accessed.
Referrers tells you from where visitors came from (referrer URL).
Top pages shows you what’s hot, what is the most popular content on your site.
Top visitors shows you the most active visitors for your site and allows you to ban abusive
visitors.
Recent hits displays information about the latest activity on the site.

298
3 Aug 2007 Drupal Handbook

Node count displays the number of times a node has been accessed in the node’s link
section next to # comments.

Configuring the statistics module

Enable access log allows you to turn the access log on and off. This log is used to store data
about every page accessed, such as the remote host’s IP address, where they came from
(referrer), what node they’ve viewed, and their user name. Enabling the log adds one
database call per page displayed by Drupal.
Discard access logs older than allows you to configure how long an access log entry is
saved, after which time it is deleted from the database table. To use this you need to run
cron.php
Enable node view counter allows you to turn on and off the node-counting functionality of
this module. If it is turned on, an extra database query is added for each node displayed,
which increments a counter.
Display node view counters allows you to globally disable the displaying of node view
counters.

You can

administer statistics administer >> setttings >> statistics.


access statistics logs administer >> logs.
view recent hits administer >> logs >> recent hits.

Story: post static pages


The story module is used to create a content post type called stories. Stories are articles in their
simplest form: they have a title, a teaser and a body. Stories are typically used to post news
articles or as a group blog.

The story administration interface allows for complex configuration. It provides a submission
form, workflow, default view permission, default edit permission, permissions for permission,
and attachments.

You can

post a story at create content >> story.


set workflow and other global story settings at administer >> settings >> content types >>
story.
control who can create and edit stories at administer >> access control.

System: cron and caching


The system module provides system-wide defaults for running jobs at particular times, storing
(caching) web pages to improve efficiency, and performing other essential tasks. The module
also keeps track of various preferences you give for how you want your system to behave.

299
Drupal Handbook 3 Aug 2007

Some of Drupal’s modules require regularly scheduled actions. The statistics module
periodically cleans up logfiles. The aggregator module periodically updates feeds. Ping
periodically notifies services of new content on your site. Search periodically indexes your site’s
content. All of these services rely on cron.

Cron (which stands for chronograph) is not a part of Drupal. It’s a scheduler that resides on your
server and performs tasks (called "cron jobs") at intervals, which you specify. The jobs can run
weekly, daily, hourly, or whatever you like.

What you want to do is schedule a "cron job" that has a browser on your server regularly visit
your "cron page." For instance, if your site were www.example.com your cron page would be
http://www.example.com/cron.php. (This page is automatically set up for you when you install
Drupal.) This regular visit to your cron page will help keep your system running smoothly.

For a modest personal site to which you post now and then, you might set up such a cron job to
run once a day. For a more active site you’d likely want to run that job more often--perhaps
every few hours or every hour.

With Linux or Unix you can schedule your cron jobs by setting up what’s called a "crontab."
(You might rely on helper programs like C-Panel to make setting up your cron jobs easier.)

For further guidance you can see Drupal’s handbook page configuring cron jobs (or, if your
server is running Windows, configuring Windows cron jobs). Your hosting company may also
help guide you.

The system module’s caching mechanism stores dynamically generated web pages in a cache--a
stockpile--and reuses them. The pages on your site, rather than being never-changing sets of text
and images, are all (or nearly all) likely to use elements pulled together "on the fly" from various
parts of your database. Such pages are said to be "dynamically generated."

By caching such pages, the system module keeps them ready to use again, instead of having to
create them again each time someone wants to view them. This way, displaying a page takes
only one database query instead of several. Queries take time and system power, so caching
lightens the load on your system and lets it respond more quickly.

Only pages requested by anonymous users are cached. To reduce server load and save
bandwidth, the system module stores and sends cached pages compressed.

You can

run your cron job manually at your site’s cron page.


read about configuring cron jobs.
administer cache settings in administer >> settings in the Cache settings area.

300
3 Aug 2007 Drupal Handbook

Configuring cron jobs


Some modules require regularly scheduled actions, such as cleaning up log files. You can make
these happen automatically by using cron.

Cron, which stands for chronograph, is not a part of Drupal. It’s a command scheduler that
resides on your server and executes commands at intervals, specified in seconds. You can use it
to control the execution of daily, weekly or monthly jobs (or anything with a period measured in
seconds). These tasks are called "cron jobs."

What you want to do is schedule a "cron job" that tells a web browser on your server, such as
lynx or wget, to regularly visit your "cron page." For instance, if your site were www.example.com,
your cron page would be http://www.example.com/cron.php. (This page is automatically set up for
you when you install Drupal.) This regular visit will automatically tell Drupal to perform its
periodic tasks, and this will help keep your system running smoothly.

For a modest personal site to which you post now and then, you might set up such a cron job to
run once a day. For a more active site you’d likely want to run that job more often--perhaps
every few hours or every hour.

With Linux or Unix you schedule your cron jobs by setting up what’s called a "crontab." (You
might rely on helper programs like C-Panel to make setting up your cron jobs easier.)

Your crontab might look like this:

45 * * * * /usr/bin/lynx -source http://example.com/cron.php

or

45 * * * * /usr/bin/wget -O - -q http://example.com/cron.php

This would have a browser (lynx or wget) visit your cron page 45 minutes after every hour. (At
the start of the hour your site may receive a lot of traffic from other sites aggregating your
content via RSS. So running your cron job earlier helps the job avoid that traffic.)

To set up a cron job on Windows read configuring Windows cron jobs.

Suppose your hosting company doesn’t allow you to set up crontab entries.

You can ask the company to let you. Sometimes that’s all you need to do.
You can ask someone else with access to the internet to set up an entry for you. After all,
virtually any Unix/Linux machine with access to the internet can set up a crontab entry to
regularly visit http://example.com/cron.php.
You can use a webcron service (for example, http://www.webcron.org) to set up cron jobs
through a web interface.
If you can’t run cron yourself or find someone to do it for you, consider the poormanscron
module.

301
Drupal Handbook 3 Aug 2007

Cron doesn’t guarantee your commands will run at the specified interval. But Drupal will try its
best to come as close as possible. The more you visit cron.php, the more accurate cron will be.

Some guidelines of a more technical nature:

Take a look at the example scripts in the scripts directory. Make sure to adjust them to fit
your needs. For example, the cron-lynx.sh file contains the line:

/usr/bin/lynx -source http://example.com/cron.php > /dev/null 2>&1

Enter:

whereis lynx

from your shell to make sure lynx is located at /usr/bin/lynx (if not, adjust the path as needed).
Also change http://example.com/cron.php to the location of your Drupal installation (for
instance, http://www.example.com/drupal/cron.php).

A good crontab line to run this cron script once every hour would be:

00 * * * * /home/www/drupal/scripts/cron-lynx.sh

Note that it is essential to access cron.php using a browser on the web site’s domain; do not
run it using command line PHP directly and avoid using localhost or 127.0.0.1 or some of
the environment variables will not be set correctly and features may not work as expected (for
example, the Drupal module).

If your host doesn’t give you permission to use a browser such as wget or lynx, there is also a
script in Drupal’s /scripts/ directory called cron-curl.php which uses curl instead. It’s also
possible to write a simple PHP script which simulates a browser accessing your website’s
cron.php (using curl, fopen, or similar), and write a cron configuration which calls that instead.

Configuring cron jobs on DreamHost


I culled this info from the Dreamhost knowledgebase:

How do I set up a cron job?

Via the "crontab" command from the shell.

crontab -l will show you your currently set up cron jobs on the server.
crontab -r will delete your current cron jobs.
crontab -e will allow you to add or edit your current cron jobs by using your default text
editor to edit your "crontab file".

Your crontab includes all the cron jobs you’d like, with one cron entry per line. A cron entry
looks like this:

302
3 Aug 2007 Drupal Handbook

45 2 * * * /home/user/script.pl

The first number is the minute of the hour for the command to run on.
The second number is the hour of the day for the command to run on.
The third number is the day of the month for the command to run on.
The fourth number is the month of the year for the command to run on.
The fifth number is the day of the week for the command to run on.

Here are some examples to help you learn the syntax for the numbers:

32 * * * * : will be run every hour on the 32nd minute.


12,42 * * * * : will be run twice an hour on the 12th and 42nd minutes.
*/15 */2 * * *: will be run at 0:00, 0:15, 0:30, 0:45, 2:00, 2:15, 2:30, ...
43 18 * * 7: will be run at 6:43pm every Sunday.

You can also edit crontab on a local file. Upload it to a directory and run:

crontab YourFileName

It’ll replace your crontab with what’s on the text file, without having to edit it online. This is
useful if you’re using a telnet client which doesn’t support ANSI control codes (such as the
Windows’ one) and can’t understand what the heck is going on on the editors.

In my own experience, I found that only by entering one cron command per line worked (one
line each for :10, :20, :30, etc.). I could not get crontab to take the "*/15" argument, so I worked
around it. Also, if you have ANY character after the last command (space, CR, whatever) the file
will not take.

I like this file-load approach because I have a basic command file to edit or call up again if
needed. Afterwards, running crontab -l will confirm that the job did take.

I hope this helps people making new installations.

--

Cron Job configuration line by line


1. start your shell.

2. type crontab -l to see current jobs for site.

3. verify if lynx was set up on your server under /usr/bin

4. edit scripts/cron-lynx.sh putting in the direct address of your cron.php file.

5. create and edit a new text file cron.txt with your settings:

303
Drupal Handbook 3 Aug 2007

e.g.,

55 23,5,11,17 * * * /home/accountname/public_html/drupal/scripts/cron-lynx.sh

(a cron run every 11:55pm, 5:55am, 11:55am, 5:55pm)

6. import this script into crontab by typing crontab cron.txt

7. type crontab -l to see your new jobs for site.

Voila, much easier than I thought!

Cronjobs without wget/lynx or curl


Some of you might have trouble getting lynx or wget to work. This may be the case if "localhost"
is not permitted.
Then wget, lynx or curl won’t work on the local machine. If you are not willing to depend on
others to perform cronjobs and you dislike poormans cron, try this script.
touch ~/scripts/cron-php.sh
chmod 700 ~/scripts/cron-php.sh
vi ~/scripts/cron-php.sh

#!/bin/bash
#
# Simple cron script for those who cannot
# use wget, lynx or curl because the host
# closed the localhost loop.
#
# Usage:
# - put this file in the ~/scripts dir
# - add a cronjob pointing to this script
#
# Copyright OCS - 2006
# This script is provided under the GPL.
#
# v 0.1 original release
#
#############################
# CONFIGURATION OPTIONS
#############################
# Complete local path
#
# Set the complete local path
# to where the cron.php file
# is (ie the root path)
# Default is /var/www/html/
root_path=/var/www/html/
# Complete php path

304
3 Aug 2007 Drupal Handbook

#
# Set the complete path
# to the php parser if
# different from standard
parse=/usr/bin/php
##############################
# END OF CONFIGURATION OPTIONS
##############################
cd $root_path
if [ -e "cron.php" ]
then
$parse cron.php
if [ "$?" -ne "0" ]
then
echo "cron.php not parsed."
else
echo "cron.php has succesfully been parsed."
fi
else
echo "cron.php not found."
exit
fi
exit
and then the crontab itself:
crontab -e
* * * * * ~/scripts/cron-php.sh > /dev/null 2>&1

where ~ is the directory where your drupal install is (the script defaults to /var/www/html/
but your professional hosting company will probably use /home/your.domain.tld/www

Configuring cron jobs on Windows


To setup a Windows machine to run cron.php at a specific time follow the specific instructions
below. This can be useful if you are not familiar with Linux/Unix, or if your web host does not
offer the ability to run cron jobs; you can run them remotely from your own computer.

Note: These instructions were written for Windows XP but should be similar in other versions of
Windows.

Creating a Scheduled Task

1. Open Scheduler
2. Go to Start > Programs > Accessories > System Tools > Scheduled Tasks
3. Double-click Add Scheduled Task
4. The Scheduled Task Wizard will appear. Click Next.
5. Select the program to run. Choose your browser from the list (for example, Internet Explorer
or Mozilla Firefox). Click Next.

305
Drupal Handbook 3 Aug 2007

6. Give the task a Name, such as Drupal Cron Job, and choose the Frequency with which to
perform the task (for example, Daily)). Click Next.
7. Choose specific date and time options (this step will vary, depending on the option selected
in the previous step). When finished, click Next.
8. Enter your password if prompted. Change the username if required (for example, you’d
like the task to run under a user with fewer privileges security reasons). Click Next.
9. On the final page, select the checkbox Open advanced properties for this task when I click
Finish and click Finish.

Configuring the task

1. Go to the task’s setting page either by checking the checkbox at the end of the last step, or
by double-clicking on the task.
2. In the Run box, after the text that is there now (for example,
C:\PROGRA~1\MOZILL~1\firefox.exe), enter a space and then type the address to your
website’s cron.php page in double quotations (for example,
C:\PROGRA~1\MOZILL~1\firefox.exe http://www.example.com/cron.php
3. To set a frequency more often than Daily (for example, hourly), click the Schedule tab, then
click Advanced. Here you can set options such as Repeat task, every 1 hour for 23 hours.
Click Ok when finished.
4. Change the start time on the task to one minute from the current time. This will allow you
to test the task and make sure that it is working.
5. When all settings have been configured to your liking, click Apply and OK (note: you may
be prompted for your password)

Command-line version

Another way to perform the above commands is by using the schtasks (or at in Windows 2000)
command from the command line. To duplicate the example above, which runs Firefox hourly
to execute http://www.example.com/cron.php, open a command prompt (Start > Programs >
Accessories > Command Prompt) and enter:

schtasks /create /tn "Drupal Cron Job" /tr


"C:\PROGRA~1\MOZILL~1\firefox.exe http://www.example.com/cron.php" /sc
hourly

Enter your password if prompted.

Throttle: congestion control


The throttle module provides a congestion control throttling mechanism for automatically
detecting a surge in incoming traffic. If the site gets linked to by a popular website, or otherwise
comes under a "Denial of Service" (DoS) attack, your webserver might become overwhelmed.
This mechanism is utilized by other modules to automatically optimize their performance by
temporarily disabling CPU-intensive functionality. For example, in the site theme, you might
choose to disable pictures when the site is too busy (reducing bandwidth), or in modules, you

306
3 Aug 2007 Drupal Handbook

might choose to disable some complicated logic (reducing CPU utilization).

The congestion control throttle can be automatically enabled when the number of anonymous
users currently visiting the site exceeds the specified threshold. The congestion control throttle
can be automatically enabled when the number of authenticated users currently visiting the site
exceeds the specified threshold.

You can

enable throttle for modules at administer >> module.


enable throttle for blocks at administer >> block.
administer throttle at administer >> settings >> throttle.

When to use the throttle module?


The throttle is useful to sites that have limited resources and usually are not that busy. It is
actually less useful to consistently high-traffic sites, as by necessity they will already have the
required infrastructure to survive high loads.

The throttle works well for a website that’s on a shared host with limited CPU and bandwidth,
that usually only gets a handful of visitors, and then is suddenly Slashdotted. Of course, it will
only help in that case if it has been enabled and properly configured.

Tracker: viewing new and updated content


The tracker module displays the most recently added or updated content to the website allowing
users to see the most recent contributions. The tracker module provides user level tracking for
those who like to follow the contributions of particular authors.

The "recent posts" page is available via a link in the navigation menu block and contains a
reverse chronological list of new and recently-updated content. The table displays the content
type, the title, the author’s name, how many comments that item has received, and when it was
last updated. Updates include any changes to the text, either by the original author or someone
else, as well as any new comments added to an item. To use the tracker module to watch for a
user’s updated content, click on that user’s profile, then the track tab.

You cannot administer this module. There are no configuration options.

You can

view the most recent posts.


view user profiles and select the track tab.

307
Drupal Handbook 3 Aug 2007

Upload: collaborate with files


The upload module allows users to upload files to the site. The ability to upload files to a site is
important for members of a community who want to share work. It is also useful to
administrators who want to keep uploaded files connected to a node or page.

Users with the upload files permission can upload attachments. You can choose which post
types can take attachments on the content types settings page. Each user role can be customized
for the file size of uploads, and the dimension of image files. Note: you must first give a user role
upload permissions before you can customize some of these settings.

You can

enable/disable uploads for individual content types at administer >> settings >> content
types.
administer storage location of uploaded files at administer >> settings in the File system
settings area.
configure file size, number of files, and other user role defaults at administer >> settings >>
upload.
control who can upload and view attached files at administer >> access control.

The maximum upload size is controlled by your PHP environment. The standard PHP default is
2 MB. If you need to alter this, see the handbook page on how to Increase upload size in your
php.ini.

User: access and management settings


The user module allows users to register, log in, and log out. Users benefit from being able to
sign on because this associates content they create with their account and allows various
permissions to be set for their roles.

The user module supports user roles, which can be set up with fine-grained permissions
allowing each role to do only what the administrator permits. Each user is assigned one or more
roles. By default there are two roles: anonymous (a user who has not logged in) and authenticated
(a user who has signed up and been authorized).

Users can use their own name or handle and can fine tune some personal configuration settings
through their individual my account page. Registered users need to authenticate by supplying
either a local username and password or a remote username and password, such as a
DelphiForums ID or an ID from a Drupal-powered website.

A visitor accessing your website is assigned a unique ID, the so-called session ID, which is
stored in a cookie. For security’s sake, the cookie does not contain personal information but acts
as a key to retrieving the information stored on your server.

308
3 Aug 2007 Drupal Handbook

You can

view your user page.


administer users at administer >> user.
create new users at administer >> user >> add user.
configure user registration, user email, and user picture settings at administer >> settings
>> user.
allow users to select themes from their user account by enabling themes in administer >>
themes.
read user profile help at administer >> help >> profile.
configure access permissions at administer >> access control.

Access Permissions reference


(This page is a work in progress. If you know what some of these do, please add a comment and
I’ll fold it in.)

block module
administer blocks
use PHP for block visibility

filter module
administer filters

menu module
administer menu

node module
access content
Allows the user to view content. This should be enabled for all users, unless you want a
private site.
administer content types
Allows the user to edit and add content types at /admin/content/types.
administer nodes
Allows the user to create, edit, and delete nodes of all types. This overrides all the
create/edit own/edit options for specific content types below. This also exposes the
’Publishing options’ section when editing nodes, allowing users to promote content to the
front page, publish and unpublish, make sticky, and create new revisions.
create [TYPE] content
Allows the user to create content of this type. This permission exists for page and story and
each additional content type defined on the site. Overridden by the ’administer nodes’
permission.

309
Drupal Handbook 3 Aug 2007

edit own [TYPE] content


Allows the user to edit content of this type that they have created. This permission exists for
page and story and each additional content type defined on the site. Overridden by the
’administer nodes’ permission.
edit [TYPE] content
Allows the user to edit all content of this type. This permission exists for page and story and
each additional content type defined on the site. Overridden by the ’administer nodes’
permission.
revert revisions
view revisions

path module
administer url aliases
allows users the ability to administer the url aliases (modify, add, remove)
create url aliases
allows users to create url aliases

user module
access user profiles
Can see user profiles; users without this set don’t see links on user names.
administer access control
Get the admin menu items Access control, Access rules, Roles added to navigation and able
to make changes there.
administer users
Get the admin menu item Users -- can list all users, activate accounts, but NOT set roles.
change own username
what it says on the tin

system module
access administration pages
allows users access to the admin path
administer site configuration
allows users to access the site configuration area of the admin panel
select different theme
allows users to change the theme from their profile.

Access rules (email filters)


Some of us know about a few CMS’s where the administrator can filter the incoming email
registrations. For instance, you could register with your@institution.edu, but not with
your@gmail.comor your@yahoo.com.Here’s how you do it:

310
3 Aug 2007 Drupal Handbook

Add an ACCESS RULE by going to ADMINISTER -> ACCESS CONTROL-> ACCESS RULES
[for Drupal 4.7.4].

Then add 2 email address rules:

Deny %@% (which should block everyone) and Allow %@allowed.com(which will allow people
with anyone@allowed.com). That’s pretty much all there is to it. Have fun with Drupal!

Managing access control with permissions and user roles


Roles, a way of assigning specific permissions to a group, allow you to fine tune the security, use
and administration of Drupal. Users assigned to the role, or group, are granted those
permissions assigned to the role. Common examples of roles used with which you may be
familiar include: anonymous user, authenticated user, moderator, and administrator.

By default, Drupal automatically defines two roles as a part of site installation:

anonymous user -- readers of the site who are either do not have an account or are not
logged in.
authenticated user -- the role assigned to new accounts on a Drupal site.

The anonymous user role should typically have the least access to the site of all roles.
Authenticated users, because they took the time to register, might be given more permissions,
such as the ability to create some types of content. If administrator approval is required for new
users, or if they match certain criteria (such as having a company email address), you may be
able to grant more permissions that way.

The first Drupal account created on a new installation, sometimes referred to as the "root user",
always has full permissions for all Drupal activities, including administration and content
creation, editing and removal.

More trusted users might be granted special privileges through an administrator-created role,
and must be manually added to that role through the user administration interface. To create
new roles:

1. Click administer >> access control >> roles tab.


2. Enter a label for the new role in the available text field at the bottom of the current list of
roles.
3. Once you’ve added the role, select the permissions tab.
4. Your new role will be listed as a new column in the permission matrix. Grant permissions to
the new role.
5. To add users to this role you will need to edit individual user accounts. Click administer >>
users and the edit link for the user you wish to add to the role. Then you can add this user to
your new role under the Roles section of the user edit page.

311
Drupal Handbook 3 Aug 2007

Note: Although all roles you create yourself receive any permissions you give to authenticated
users automatically, neither roles you create yourself nor the authenticated user role receives
permissions given to anonymous users. If you check any of the permissions boxes for
anonymous users in the access control page, you should almost always also check the equivalent
box for authenticated users to avoid odd site behavior.

Assigning permissions and users to roles


Access to almost all Drupal modules can be controlled by either enabling or disabling
permissions for a given role. As a security precaution, the anonymous and authenticated users
are configured with very minimal permissions during a site install. You’ll have to consider
which permissions to enable.

Go to the permissions administration page (administer >> access control >> permissions tab to
begin enabling or disabling permissions. Consider the following descriptions of permissions:

Administer -- Administer permissions, such as administer content and administer users, are
usually reserved for the most trusted site users. These administration privileges grant users
extensive control of the specific module(s) described by the permission title. For example,
when administer permissions are granted on modules associated with specific node types,
the user will be able to edit and delete all content for that node type on the entire site.
Reminder: you’ll have to assign access administration pages rights to any role which also
needs to configure site options in the administration menu.
Access -- Permissions which grant access allow users read-only rights or general use of
specific site modules, without any significant configuration privileges. Typically, these roles
do not permit the creation of content. Most access permissions are safe to assign to any user
role, although giving access administration should generally be reserved for the most trusted
users.
Create -- Allows users to create, but not necessarily edit later, the specified type of content.
Generally applies to node types.
Maintain -- These permissions generally enable a user to create content, as well as allowing
the author of the submitted content to edit their own content. If you want to allow new site
members to keep a weblog or work on the collaborative book, you’ll need to enable
maintain permissions for the authenticated user.

Taxonomy_access: Restrict user roles to access specific categories


only
Access to content can be restricted by category using the Taxononmy Access:
http://drupal.org/project/Modules/taxonomy_access

Adjusting permissions after adding modules


Whenever a module is enabled, even if it is merely turned off and on, permissions for that
module are unassigned to all roles. As a security precaution, an administrator always needs to
assign permissions to roles any time a module is enabled.

312
3 Aug 2007 Drupal Handbook

User authentication
Registered users need to authenticate by supplying either a local username and password, or a
remote username and password such as a jabber, Delphi, or one from another Drupal website.
See distributed authentication for more information on this innovative feature.

The local username and password, hashed with Message Digest 5 (MD5), are stored in your
database. When you enter a password it is also hashed with MD5 and compared with what is in
the database. If the hashes match, the username and password are correct.

Once a user authenticated session is started, and until that session is over, the user won’t have to
re-authenticate. To keep track of the individual sessions, Drupal relies on PHP’s session support.
A visitor accessing your website is assigned an unique ID, the so-called session ID, which is
stored in a cookie. For security’s sake, the cookie does not contain personal information but acts
as a key to retrieve the information stored on your server’s side. When a visitor accesses your
site, Drupal will check whether a specific session ID has been sent with the request. If this is the
case, the prior saved environment is recreated.

Make a Drupal site use Basic Auth/ldap instead of the normal login
block
This is a module I wrote for Drupal 5.0 to take care of authenticating, where the webserver has
already done the user authentication via Basic Auth. In my case the user logged in via Basic
Auth is also available as a user in Ldap so I can pull the ’cn’ name and user thier real name as
thier Drupal name. Also auto populate the email address and keep the id the same as my
corporate assigned user id.

Enabling this module without first creating a user with admin priv with the same uid number
as assigned via ldap will result in you locking yourself out of your site as the normal login
block is totally bypassed by this module and becomes unavailable.

To speed things up, I also added a row into the users table that directly maps to my user id
obtained from basic auth. Also prevents users in large orgs with multiple John Smiths from
being assigned the same account.

Once again, this module totally bypasses the normal login block within Drupal substituting
existing webserver based basic authentication. For those interested in doing ldap authentication
WITHIN the Drupal login block, this module is not for you. Instead consider:
http://drupal.org/project/ldap_integration for this.

If you need to support Basic Auth, but don’t have hooks for ldap, considrer using this:
http://drupal.org/project/securesite or this http://drupal.org/project/httpauth

Some wierdness present. Users on first visit to site get the basic auth prompt twice, and the user
shows up as logging in twice in the logs.

313
Drupal Handbook 3 Aug 2007

I also commented out the "Log out" button in my application in user.module as it doesn’t do
anything other than adding extra lines into the logs after turning on this module.

This module works as is for me, and perhaps it will save someone attempting to do the same
thing as me some time. A good familarity with basic auth, ldap, and directly modifying the
’users’ table is probably a must.

<?php
/*
ldap_auth module
hook_init is run EVERY page load. We need to handle our own
consumption of resources or spiral to death.
*/
function ldap_auth_init() {
# if global $user has a uid already, bail as we are already logged
in.
global $user;
if ($user->uid > 0) { return; }
$user_tid=strtolower(trim($_SERVER[’LDAP_USER’]));
require_once ’./includes/common.inc’;
require_once ’./includes/theme.inc’;
$result = db_fetch_object(db_query(’SELECT u.uid,u.name FROM {users}
u WHERE u.tid = \’%s\’’,$user_tid));
# User doesn’t exist in database. Retrieve user info and add user.
if (! $result->uid) {
$ldap_server = ’directory.appl.yourcompany.com’;
$ds=ldap_connect($ldap_server);
if ($ds) {
$r=ldap_bind($ds);
$sr=ldap_search($ds, "o=yourcompany.com", "(uid=$user_tid)");
$info = ldap_get_entries($ds, $sr);
$user_mail = $info[0][’mail’][0];
$user_name = $info[0][’cn’][0];
$user_number = trim($info[0][’personalnumber’][0]);
# Use replace instead of insert to avoid errors in the event the
uid has been added ahead of time, such as in the case of the
administrators...
db_query("REPLACE INTO {users} (uid,tid,name,mail,status,created)
VALUES (%d,’%s’,’%s’,’%s’,1,%d)",
$user_number,$user_tid,$user_name,$user_mail,time());
ldap_close($ds);
} else {
drupal_set_message(t(’Unable to contact Ldap server %name.’,
array(’%name’ => check_plain($ldap_server))));
return;
}
} else {

314
3 Aug 2007 Drupal Handbook

# User exists in database. Set user info from there.


$user_name = $result->name;
$user_number = $result->uid;
}
# Log in, updating logs and redirecting to where the user requested,
or home. Good stuff stolen from persistent login module.
drupal_set_message(t(’Authenticated via Ldap. Welcome %name.’,
array(’%name’ => check_plain($user_name))));
$l = array(’ldap_auth_login’ => 1,’name’ => $user_name,’uid’ =>
$user_number);
drupal_load(’module’, ’user’);
$user = user_load(array(’uid’ => $l[’uid’]));
user_login_submit(’ldap_auth_login’,$l);
drupal_goto(substr(drupal_get_destination(), 12));
}
?>

NTLM Authentication
NTLM is a proprietary (and not so good) protocol for deploying Single Sign On in
predominantly Windows oriented networks (our company network also). NTLM sits on top of
HTTP, so users who are logged on to the Windows Active Directory network can transparently
log-on to web services using their Microsoft Windows credentials (and thereby having Single
Sign On). Getting IIS servers working with NTLM is easy (it should be), but traditionaly Apache
servers have had problems in doing this.

This document explains how to get NTLM authentication working in Drupal in Linux + Apache
boxes.

There are various methods for getting NTLM authentication working in Apache.

mod_ntlm - This is an Apache module which will add NTLM support to Apache. However,
this module is not very actively maintained, and getting it compiled and running in various
Apache versions ( and various distributions ) is a herculean task. To top it, the compilation
throws out a lot of warnings, and one tends to feel uncomfortable with it.
mod_ntlm_winbind - for boxes that have Winbind ( 1, 2 ) configured, this module can be
configured to provide NTLM authentication for Apache. However, this module is still
under development and is not well tested.

However, for the help of people working in such unfriendly conditions, there is an excellent perl
module that provides good support for NTLM authentication.

Follow the steps given below for getting NTLM authentication working.

1. Install/Configure mod_perl under Apache - (and get it working of-course)


2. Download the following files for doing NTLM authentication (the following files worked
for us)

315
Drupal Handbook 3 Aug 2007

For Fedora Core systems download the module from


http://search.cpan.org/~speeves/Apache2-AuthenNTLM-0.02/AuthenNTLM.pm
For Debian Linux systems, download the module from
http://search.cpan.org/~speeves/Apache-AuthenNTLM-2.10

Install the module


tar xvfz Apache*AuthenNTLM*.tgz
cd Apache*AuthenNTLM*
perl Makefile.PL
make
make test
make install
Edit the Apache configuration and enable KeepAlive
KeepAlive On
Restart your Apache server.
Configure apache to do the authentication. For eg in .htaccess add.
# Enable the Authentication module
PerlAuthenHandler Apache2::AuthenNTLM
# Do NTLM and basic authentication
AuthType ntlm,basic
# The name that should be displayed in the Auth box, if NTLM fails
AuthName OurCompany
# Ask for a valid user.
require valid-user
# domain pdc bdc
# Domain : Your windows domain
# pdc : Primary Domain Controller
# bdc : Backup Domain controller.
#
# Note : Multiple domains can be specified.
PerlAddVar ntdomain "OURDOMAIN domainpdc domainsdc"
# What should be the default domain
PerlSetVar defaultdomain OURDOMAIN
# The user names are in the form "OURDOMAIN\user_name". Let us split
it.
PerlSetVar splitdomainprefix 1
# Set the debug variables
PerlSetVar ntlmdebug 0
PerlSetVar ntlmauthoritative off

More documentation is available in the accompanying README file in the tarball or the
following link

Once this is done, the domain user is populated as REMOTE_USER in the http server
variables, which can be picked up by any application for doing authentication.

316
3 Aug 2007 Drupal Handbook

Now we need to enable Drupal to pick up this user id and automatically create a user. Once
we have NTLM authentication working, the user id is available as REMOTE_USER. The
WebServer Auth module can use this variable to automatically log the user in.

Download, install, enable and configure the Webserver auth module and you should have a
Drupal setup which can seamlessly integrate into Windows AD based networks.

User preferences and profiles


Each Drupal user has a profile, and a set of preferences which may be edited by clicking on the
my account link. Of course, a user must be logged into reach those pages. There, users will find a
page for changing their preferred time zone, language, username, e-mail address, password,
theme, signature, homepage, and distributed authentication names. Changes made here take
effect immediately. Also, administrators may make profile and preferences changes administer
» users on behalf of their users.

Module developers are provided several hooks for adding custom fields to the user view/edit
pages. These hooks are described in the Developer section of the Drupal Handbook. For an
example, see the jabber_user() function in /modules/jabber.module.

Using distributed authentication


Distributed authentication
One of the more tedious moments in visiting a new website is filling out the registration form.
Here at drupal.org, you do not have to fill out a registration form if you are already a member of
Drupal. This capability is called distributed authentication, and Drupal, the software which
powers drupal.org, fully supports it.

Distributed authentication enables a new user to input a username and password into the login
box, and immediately be recognized, even if that user never registered at drupal.org. This works
because Drupal knows how to communicate with external registration databases. For example,
lets say that new user ’Joe’ is already a registered member of Delphi Forums. Drupal informs Joe
on registration and login screens that he may login with his Delphi ID instead of registering with
drupal.org. Joe likes that idea, and logs in with a username of joe@remote.delphiforums.com
and his usual Delphi password. Drupal then contacts the remote.delphiforums.com server behind
the scenes (usually using XML-RPC, HTTP POST, or SOAP) and asks: "Is the password for user
Joe correct?". If Delphi replies yes, then we create a new drupal.org account for Joe and log him
into it. Joe may keep on logging into drupal.org in the same manner, and he will always be
logged into the same account.

Drupal
Drupal is the name of the software that powers drupal.org. There are Drupal websites all over the
world, and many of them share their registration databases so that users may freely log in to any
Drupal site using a single Drupal ID.

317
Drupal Handbook 3 Aug 2007

So please feel free to log in to your account here at drupal.org with a username from another
Drupal site. The format of a Drupal ID is similar to an e-mail address: username@server. An
example of a valid Drupal ID is mwlily@drupal.org.

Watchdog: monitor your site


The watchdog module monitors your system and records system events in a log you can review.
This helps you get a quick overview of activity on your site. Since the log records events in
sequence, it can also be useful for debugging site errors.

The watchdog log records errors, warnings, usage data, performance data, and operational
information. You can filter the entries ("Filter by message type") to view only a particular type of
message.

You should check the watchdog report regularly to make sure your site is working properly.

You can

view watchdog logs at administer >> watchdog.


configure the length of time logs are archived at administer >> settings in the Error handling
area.

318
3 Aug 2007 Drupal Handbook

End user guide


Welcome! This guide describes how to get started using (as opposed to administrating) a
Drupal-powered web-site. This naturally includes Drupal.org, as well as most other Drupal web
sites. The guide covers basic topics such as registering for an account, logging in, changing your
account settings, and creating content.

Drupal is a content management system. Its goal is to help users compose and present web-site
content such as articles, photos, and other content types. Drupal is a "dynamic" system; rather
than forcing users to specify a fixed, pre-declared arrangement of content, Drupal takes care of
the details of how information is arranged and presentated, and lets users focus on the actual
content to be displayed.

Most of the content on a Drupal-based site (the text of this page, for example) is stored in a
database. Text and images are submitted by filling in forms via a web browser. When visitors
view a page, Drupal gets the relevant bits of content from the database and composes all of the
components of the page in a template. This makes it easy to quickly add or change content,
without requiring knowledge of HTML or other web technologies on the part of the person
providing the content.

Depending on the configuration of the Drupal site and the user-roles you play with respect to
that site, you may be allowed to contribute or edit content. Fortunately, Drupal is designed to
make this relatively easy. Very little technical knowledge is assumed. Though details may vary
with a site’s configuration, the basic process involves these steps:

register with the site


log in by typing the user name and password supplied you in the registration step, and
create content such as articles and stories

This user guide will explain these steps and familiarize you with the basic information you need
to use Drupal successfully.

This section can also serve as a foundation for a set of instructions customized to your site’s
specific needs.

Registering as a user
To add or edit content on a Drupal site, usually you have to first be registered as a user.
(Sometimes the site administrator has chosen to enable "anonymous" posts of things like
comments, in which case you can post them without registering.)

In some cases, a site administrator will add you as a user. If so, they will send you a user name
and password that you can use to log on.

319
Drupal Handbook 3 Aug 2007

Otherwise, look for a small form called âUser loginâ on the main page of the site you want to
register with (usually on the right or the left of the page). Click the link that says "Create new
account".

The next page that comes up will generally have some information on the site’s policies for
registration. After reading them, to register, enter a user name of your choice and an email
address to which you have access and hit "submit". Then check your email account. Within a few
minutes, you should get an automatically-generated email confirming your registration and
giving you an initial password to use. Now you’re ready to log in.

Logging in
Before you can add or edit content, you usually need to log in. If you haven’t already done so,
register as a user, see above (or, if applicable, request that your site administrator register you).
Then hit the main page of the site you’re wishing to use and look for a "User login" form. This
will typically be on the left or right side of the page (it is a "block" in Drupal talk). Enter your
user name and password and hit "submit".

Assuming everything’s working as planned, when the new page loads it will include a new
block with your user name at the top. This is the menu you use to start entering and editing
content.

Changing your account settings


Once you have registered with a Drupal-based site, you can change settings to control
information about yourself and also your use and experience of a Drupal site. To see what
tweaks you can make to your account, log in and then click on my account in the navigation block
(that’s the one titled with your user name). Click on the edit tab.

Account Settings. You may see a different collection of settings than is presented here,
depending on what features have been enabled on your site.

password
Enter in a new password in both fields to set it. Drupal sends you a default password that is
often hard to remember, so it is recommended that you change your password to something
you can easily remember.
block configuration
The site administrator may make some blocks (chunks of content that are usually displayed
in a left and/or right column) optional. You can enable and disable the display of these
blocks by checking and unchecking the boxes next to them.
signature
If comments are enabled, you will be able to set a default signature. This will be copied into
new comments for you automatically, but may still be edited.
time zone
Your site administrator may allow users to set their time zone. This will cause all dated
content on the site to display in local time, according to the offset you enter here.

320
3 Aug 2007 Drupal Handbook

theme
A "theme" is the basic look and feel of a Drupal site. Sometimes a particular site will have
more than one theme installed. If the site administrator has made more than one theme
available, you will be able to select what you would like the default theme to be for your
account.

As mentioned earlier, different site-settings will cause different fields to be displayed on your
user account page. See the documentation for individual modules for instructions on how to use
these additional options.

Additional Information. Aside from the account settings tab, you may also see additional tabs,
titled according to the information they contain. Some examples might include "Personal
Information", "Workplace", etc. These are controlled by the profile module, and allows you to
enter more information about yourself. Please see the profile module for more information on
this.

Creating new content


Once you have logged-in, you’re ready to start posting content.

At the top of your personal menu, you’ll find a link called "create content". Click this and you’ll
see a list of the types of content you can create. This list reflects the privileges assigned to your
user account or to the group ("role") your account is part of.

There are several contributed modules which can assist with more complex content creation
within this framework, such as spell checking, image embedding, and file attachment uploading.

A step-by-step example
We will assume that you have selected create content and chosen "story" as a content type.

You should be looking at a form with the title "Submit story". From here, it is just a matter of
filling in the form and posting it.

Administrative options

At the top of the form you may see some administrative options. For example, there is a box
with the heading User comments. Drupal supports discussion/comments on postings--but
such comments are not always appropriate. If your article is one that could be usefully
commented on, keep the default settings: "Read/write". Otherwise, choose "Disabled".

Title

The title is straightforward enough. Try to be descriptive and catchy.

321
Drupal Handbook 3 Aug 2007

Topic: (may not be visible if you do not have categories defined)

Next comes the "Topic" menu. This is the section your article will go in--or in the technical
language of Drupal, its ("taxonomy categories"). This list presents all the sections available
on the website, with their structure. So, choose the appropriate section or sections for your
story and continue down the form to supply the body of your text.

Body

The "body" field is where you put the main content of the page. If you’ve typed this into a
word processor or HTML editor, just copy and paste it into this field. Alternately you can
just type straight in. For the most basic page, just type and leave a blank line (i.e., hit "enter"
twice) at the and of each paragraph.

You can optionally format your entry in friendly old HTML. But hey, if you’re a novice,
don’t worry--it’s not as difficult as it sounds. Here’s a quick primer:

If you want something to be bold, just enclose it in <b> or <strong> tags, like this:

<b>This text is bold</b>

<strong>This text is bold</strong>

Note that there is always an opening tag (no forward slash) and a closing tag (a forward
slash before the tag name, indicating that you are "turning it off").

To make something italic, put it in <i> or <em> tags:

<i>This is in italics</i>

<em>This is emphasized</em>

There is considerable debate about the semantic nature of the <b></code and
<code><i> tags versus the <strong> and <em> tags.

To put things nicely in paragraphs, enclose them in <p> tags:

<p>This is a paragraph.</p>

To make a bulleted list, first open a list with a <ul> tag (that stands for "unordered list"),
then put each list item in <li> (yes, for "list item") tags. Don’t forget at the end to close off
your list with a closing </ul> tag. Here’s how it looks:

<ul>
<li>This is the first bulleted item</li>
<li>This is the second bulleted item</li>
</ul>

322
3 Aug 2007 Drupal Handbook

The result is displayed below:

This is the first bulleted item


This is the second bulleted item

To add a link to you need to use the <a> (anchor) tag.

<a href="http://www.example.com">Example.com</a>

To add links to other pages within your Drupal site you do not need to add the full URL,
you can simply refer to the node like so:

<a href="/?q=node/1222">My node</a>

Note the "/" at the beginning. Also the above example is using non-clean URLs. If your site
has clean URLs enabled you can remove the ?q= so that you just have <a
href="/node/1222">My node</a>.

That wasn’t too painful, was it?

Decide where you want the "teaser" (the part of the main text used in links to the article) to
end. If you do nothing, Drupal will choose a breaking point for you -- but it’s better to
decide yourself, to make sure the breaking point is appropriate. You do this by typing in a
<!--break--> where the teaser is to end. (Your default break point is controlled by Post
Settings, found in 4.7 at administer > settings > posts and in 5 at administer > content
management > post settings.)

And you’re set! You can preview the page you’ve prepared by hitting "Preview"
(recommended, and sometimes required) or you can bravely or recklessly just go ahead and
publish it by hitting "Submit".

Controlling Teaser Location


In Drupal, you can cause the teaser to end at the point of your choosing by adding the following
to your content body:
<!--break-->

Everything above this tag will appear in the teaser (unless you place it beyond the point at
which Drupal automatically breaks the content).

Notes

Make sure there are no spaces in the tag or it will be ignored.


You can place the tag in the middle of a paragraph. The full text will not notice the tag so
the paragraph will look normal, but the paragraph will be cut short in the teaser

323
Drupal Handbook 3 Aug 2007

How to add a page to the Handbook


Depending on how Drupal is configured, different users can add book pages, such as to the
Documentation handbooks at drupal.org. The ability to create book pages is normally assigned
to "roles" in the administration area. At drupal.org, all logged-in users have the role
"authenticated user" and are allowed to add book pages.

It’s very easy to add a page. When you feel like writing a piece of documentation about a topic
that hasn’t already been addressed, just click on "Create content" link in the block under your
user name. Then click the "Book page" link. Type away in the Body. Depending on
administration settings at a web site, you may have various formatting options. Here on
drupal.org, by default you will have "filtered HTML" capability.

Give your page a short, descriptive Title.

You will have to set the correct parent to page, select it from the Parent drop-down menu.

Optionally you can add a log message to explain why you wrote the documentation.

Give your page a weight. Pages with a less heavy weight will stay at the top within the parent
section while pages with heavy weights will sink deeper.

Then preview and finally submit.

Types of content
There are various types of content that you can post using Drupal. Many of these are organized
into what are called "nodes". Basically, you can think of a node as the content of a page. This
might be, for instance, an article. Content is added or updated through web page forms. So to
add an article, you bring up a form, enter text into it (like the title and content of an article), and
hit a button to submit the form.

Topics, categories and terms


Content on Drupal websites is usually organized using categories through a system called
"taxonomy". A taxonomy has different "terms" that are used as categories for articles. When
you’re adding an article, you might find a drop-down list of topics. By selecting one, you choose
where on the site to categorize your article. If this seems hard to relate to, you can think of topics
as being like folders on your hard drive--they help to organize content, so that you can find
similar things in the same place.

Permissions
What types of content you can create or edit depends on the privileges assigned to the "role" or
user group that you’re a member of. In general, to find out what you can do:

324
3 Aug 2007 Drupal Handbook

On your user menu (the collection of links that has your user name as a title), look for a link
that says "create content". Click this to get a listing of the types of content you have
permission to post.
On a particular page, look for links at the bottom of an article. These links say things like "12
comments" (if there are comments that have been made on the article) and "read more" (if
you’re looking at a short version of an article). If one of these links say "administer" or
something like "edit this page", you have permissions to edit that type of content.

Moderation and the submission queue


Some Drupal sites are set up so that when you submit content it goes into a "submission queue".
Content in this queue is read by other users who have a moderator role on the site. They will
review the content and, if it is accepted, "publish" your contribution.

Note that moderation has been removed from core as of Drupal 5 and can be accomplished with
modules such as modr8.

Creating comments
Comments allow users to interact with the content on a site, to respond to an article, offer their
own ideas, make additions, or supply a critique.

Leaving comments

When you bring up an article to read, look for comment-related links at the bottom of the
article. If you’re not logged in, this might read "login or register to post comments". When
you do log in, you should see something like "Add new comment". Click on the link and
you’re ready to comment away.

Etiquette

Comments can be a great way of enriching a community site--but they can also lead to
unfriendly, even harassing exchanges. As with any communication, it’s important to try to
ensure that your comments are respectful and constructive.

"Threaded" comments

Comments on a Drupal web-site are "threaded". This means you can comment directly on
an article--or you can reply to an existing comment. If you reply, your comment will be
indented to show that it is part of that discussion.

Alternative ways to enter content


Drupal’s built-in form-based content editing approach is fine for many applications, but if you
have a lot of text to create, or you wish to convert existing content, or if you are using a
specialized content type such as a blog, it may be more convenient to use other approaches to
enter content into your Drupal-based site.

325
Drupal Handbook 3 Aug 2007

Preparing your content offline suggests some ways to use familiar software on your computer to
create or edit content before submitting it to Drupal.

Depending on what’s available on your site, you might even be able to enter new articles
without ever logging on to the site.

Drupal includes functionality for "blogging"--creating "blogs" or web-based journals with the
BlogAPI module. If this functionality is enabled on your site, you may be able to input and edit
content using one of a number of desktop "blog" software packages. These allow you to simply
type in content, hit a "post" button, and have your content automatically loaded onto your site.

In fact, blogging software can be used for more than blogs--it can allow you to post content
easily and quickly to almost any part of a website. Some examples of software you can use are:

Examples of applications that work with Drupal from the desktop include the following:

Ecto - Windows/Mac
MarsEdit - Mac
MS Word 2007 - Windows

In addition to desktop blogging tools, other services like Flickr’s "post to blog", Firefox plugin
Scribefire and Google Docs should work with your Drupal site.

Before trying out one of the blogging programs, you might want to check with your site’s
maintainer to make sure it accepts blog posts. The key question to ask is: "Is the BlogAPI
enabled?" If the answer is yes, you’re ready to roll. If not, you could request that it be enabled to
allow you quick updates.

HOWTO: Posting and editing blog entries with TextMate


Textmate is an editor for Apple Macintosh computers. The included Blogging bundle let you
post and edit blog entries in your Drupal blog.

As of writing to use the Blogging bundle you need to have the latest "cutting edge" release of
Textmate (Version 1.5.2 (1112)). Get it by choosing "Cutting-Edge" in the TextMate menu
TextMate > Preferences > Software Update and pressing "Check now".

1. Setup the Blogging bundle for your blog: Open a blank window and select Bundles >
Blogging > Setup Blogs. Enter the URL of your blog. Insert your username and append
xmlrpc.php to the URL, for example
http://user@yourdomain/yourpath/xmlrpc.php. Save the file.
Note: You are able to insert more than one blog entry.
2. Test the blog setup: Bundles > Blogging > Fetch post. TextMate will ask you for your Drupal
password first time you connect to the blog. It will be saved in the keychain so you have to
enter it only once. Next Textmate will present you with the last 20 blog entries you may
choose from.
3. New blog entry: File > New From Template > Blogging > Weblog Post. Write your text and
select Bundles > Blogging > Post To Blog to finally post the blog entry.

326
3 Aug 2007 Drupal Handbook

4. Choose Input Filter: the "Format:" header correlates to the Drupal Input Filters. Put a 3 there
and the blog entry will use the third Input Filter.
5. Trimmed version (Teaser): Insert <!--break--> where you want to end the trimmed version
of the blog entry.

For a longer explanation have a look at the screencast at Blogging from Textmate.

Problems so far:

Image files: insert image files into your text by dropping them in the TextMate window.
They will instantly uploaded to the blog and referenced in the text. Alas they do not appear
at the blog entry, at least not at the authors blog.
Taxonomy and vocabulary terms: It seems there is no way to insert vocabulary terms in the
blog entry yet.

Posting and editing content with w.bloggar


w.bloggar is a gratis software for Windows designed for "blogs" (web-based journals).

If you’ve confirmed that blog support is enabled, here’s some steps to get going:

Download the software from http://www.wbloggar.com/ and install.


Set up a new account. This is explained in the w.bloggar help files.

When it comes time to set the "Blog Tool" selection, choose "MovableType" (and not
"Drupal"). This is because (at time of writing) the Drupal support in w.bloggar is
outdated.
For "Host" put the domain of the website you’re using, then for "Path" put the rest of
the address, if any, followed by "/xmlrpc.php". So if the address was
"http://www.gworks.ca/site/" you would put "www.gworks.ca" for host and
"site/xmlrpc.php" for Path. The "xmlrpc.php" part is the Drupal file that handles the
blogging input.

Now you’re ready to start posting. In doing so, you can take advantage of the text formatting
functionality w.bloggar offers. When correctly set up, posting a web page from w.bloggar is as
simple as opening the program, typing in some text, selecting a category (the "taxonomy term"
to use) and hitting post.

update
It has been reported using 4.00.0193 (Mozilla version)

Configuration notesâa departure from the original postingâ¦

In w.bloggar, I selected âDrupalâ as my blogging tool


in the account setup dialog.

327
Drupal Handbook 3 Aug 2007

In Drupal, you must enable the blogger.api module.


You don’t necessarily require blog module. I’m only
using âstoryâ nodes, so I didn’t enable blog module.
After enabling blogger.api, go to settings >> blogger.api and:
check off the content type you wish to
edit via the API. In my case, it’s âstoryâ.
change the XML-RPC engine to âMetaWeblogâ.

Posting content with mailhandler


If the BlogAPI doesn’t meet your needs you should consider using the contrib mailhandler
module to submit content.

Preparing content offline


Before posting directly to a site, you may want to start in a word processing program. Potential
advantages include:

Saving time online. This is a particular consideration if you’re on dial-up.


Access to spell-check and other editing features.

Depending on how much formatting you wish to do, you could also consider using an HTML
editor. These include, for instance, the "composer" that comes with Mozilla and Netscape. Here
are the steps involved:

Type or copy and paste your text into the HTML editor.
Apply formatting as desired (e.g., bold, italics).
Bring up the HTML (encoded) view of the text.

This HTML is what you’ll copy and paste into Drupal’s input form, to have formatted copy.

Editing and deleting content


To edit or delete existing content, log in and then bring up the page you wish to edit. Look on
the page for an "edit" tab. Depending on your user permissions, you might see this on all pages
or only on certain ones. For example, on Drupal.org, you should see the edit tab for those pages
that you submitted.

Clicking the edit tab will bring up a page with a form for changing the page. Here you can
change the text and settings. Once you have the text and settings in a suitable form, click on the
"Submit" button on the bottom of the form. Note that certain sites may be set up to require you
to "Preview" the page before you can submit your changes.

If you wish to delete the page (and you have appropriate permissions), click on the "delete"
button near the bottom of the form. You’ll get a second chance to confirm that you wish to delete
the page, or to change your mind!

328
3 Aug 2007 Drupal Handbook

Note: Because Drupal is very configurable, there may be additional ways of editing and
managing content. Please check the documentation for your installation, ask the Drupal
administrator, or consult with another user for details.

Search
The search facility is turned on or off by your site administrator. If it is on, you will see a box for
entering your search terms and a button labelled "Search". it will be on the header of the page, or
in one of the blocks on either side of the page.

Like most search facilities, enter a word or words you want to search for and click the button.

The wild card * performs the usual function of searching for âeverything that starts withâ

Multiple words are searched as A or B, i.e. it returns pages that have one or more of the words.
There is no search only for pages that have both A and B.

The search engine gives greater weight to words used in headings or highlighted. It does this by
assigning weights (multipliers) for scores of words inside certain HTML tags.

Header h1 => 21
Header h2 => 18
Header h3 => 15
Header h4 => 12
inside a link => 10
Header h5 => 9
Header h6 => 6
underlined, bold, italics => 5

You can only search on individual words, not phrases in quotes. There is no sorting by date or
other parameters.

When searching for numerical data such as dates, IP addresses or version numbers, it considers
a group of numerical characters separated only by punctuation characters to be one piece. This
also means that searching for e.g. ’20/03/1984’ also returns results with ’20-03-1984’ in them.

The dot, underscore and dash are simply removed. This allows meaningful search behaviour
with acronyms and URLs.

With the exception of the rules above, search considers all punctuation, marks, spacers, etc, to be
a word boundary.

You might also consider using Google. Start your query with "site:example.com", so you would
enter
site:example.com my search query
or use the "Search this site" button on the Google toolbar.

329
Drupal Handbook 3 Aug 2007

Beyond the basics


Drupal is designed to support many different types of website. Many changes to a Drupal site’s
functionality, appearance, and modes of interaction are easy to make via Drupal’s configuration
and extension mechanisms.

Drupal is highly configurable. The administrator of a site can enable different capabilities and
change many settings that affect the look and functionality of a site.
Drupal has a system of privileges that makes it possible to create different user roles - for
instance, member, staff, partner. Each type of user can see and do different things on the
site.
Drupal is designed to be easily extended through modules. A module is just a fancy term for
additional software you can activate or "plug in" to your web site to provide extra features
and functions. For example, you might activate the poll module to let users easily create
web-based polls. Some modules, called "core" modules, come pre-packaged with every
Drupal installation. Third party modules, called "contributed" modules, can be downloaded
separately from the Drupal website and installed on your server.
The look and feel of a Drupal site can be changed through different "themes". As with
modules, there are both core and contributed themes.

Hence, what you see on a particular Drupal site, and what you can do there, depends to a high
degree on what the site administrator(s) have chosen to present. If you require more in-depth
information about changing the way in which information is presented or how its appearance
may be configured, please see the Administrator’s guide at http://drupal.org/handbook and the
Drupal forums.

330
3 Aug 2007 Drupal Handbook

Sports
football
“is david beckham the greatest footballer ever in england??”

331
Drupal Handbook 3 Aug 2007

Best practices guidelines


If you are going to invest in the time to setup a CMS, then you should make sure you protect
your investment with some simple best practices guidelines. These guidelines are only
suggestions on things that need to be considered when managing a web site or CMS. It is up to
you to decide what is appropriate for you to implement for your sites.

Of all the guidelines, being able to successfully backup and restore your website is probably the
most important.

Back up your Drupal site


Backups are a mandatory part of running a content management system. They are your
responsibility to perform regularly and flawlessly. Here’s what you need to know about backing
up your Drupal site:

Inquire about your ISP or web host’s backup policies. Most good web hosts have a backup
plan that kicks in every 24 hours. If yours does not, it’s up to you to back up your site daily,
or find a host who will. It cannot be stressed enough that if a site’s data does not exist in
three places, it doesn’t exist at all.
In addition to your web host’s backups, do it yourself. Periodically run a separate backup
monthly, weekly, daily or whatever fits your site’s needs. Gauge the backup cycle by how
much of your user’s data you can afford to loose without all the users revolting and starting
a riot. Even if you tell yourself, "It’s no big deal", it is, and you do not want to lose content.
Date your backups. Save each one into a directory that’s titled with the date of the backup.
You do not want to be guessing which backup is the most recent one when you are trying to
recover your failed site. Panic is not conducive to a good recovery process. Save a copy of
each backup in a different location than your webserver. Remember, if data doesn’t exist in
three places, it doesn’t exist at all. If your webserver crashes, then all the backup files might
be gone too (see earlier reference to panic).

Backing up the database


Backing up and restoring a MySQL database using the command line is covered in the MySQL
Reference Manual, section 5.10. Note that the Reference Manual cited is based on MyISAM
tables. If you use InnoDB tables in your database, please pay particular attention to MySQL
Reference Manual, section 14.2.8

Backups can also be performed with a graphical utility such as PHPmyAdmin. There’s also a
FAQ on that site called "How can I backup my database or table."

Another alternative solution is to install the Database Administration module. It has the option
to backup the database tables from within Drupal itself. Note: Be careful with the permissions.

332
3 Aug 2007 Drupal Handbook

If you are using a database other than MySQL, that vendor’s documentation should have
backup information. For a list of even more methods, consult the Handbook pages in the
Upgrade Guide as well.

Backing up the core files


The root directory of your installation contains all the files that make Drupal do its magic. Sure,
you *could* go get these files from Drupal.org again if you ever needed them, but having your
own copies of the core files is so much faster and efficient. If you’ve edited anything in the core
files for your specific website, having a copy of the core files becomes mandatory, since the site’s
changelog is part of the root directory too.

As a suggestion, everything in the root directory should be backed up monthly, but always back
up the core files before an upgrade. It’s been said before in other sections of the Handbook, but Best
Practices means that backups of the core should be a regular habit. Do this every month as
suggested, and when disaster strikes, you won’t be wondering whether you’ve made any
changes recently that have been lost forever.

Backing up the non-core files


Contributed modules and their associated third-party files should be backed up monthly as well.
If you are adhering to the Best Practices outlined in the previous section above, your contributed
modules will be part of the core files backup by default, since they exist inside a directory of the
root Drupal installation. If you do not have the bandwidth or storage resources to back up your
entire root directory each month, you must backup the /sites/all/modules/ (version 5.x) or the
/sites/example.com/modules/ (version 4.7 and lower). Failure to do this may leave you with
no clear example of which modules you had, and what versions they were. Imagine trying to
restore your site right now without knowing which versions of modules to download from
Drupal.org. Could you do it?

There are also files that are not part of the database, the core, or the contributed modules that are
important to your site. The directory you specified in Administer > Site Configuration > File
System holds uploaded pictures, user’s icons, and other stuff that you don’t want to loose. If you
are running your site in ’private’ file transfer mode, chances are good that this /files/ directory
is not inside your root Drupal installation, and therefore won’t get backed up by the procedure
outlined in "Backing Up The Core Files" above.

The /sites/ directory is another one that you should take note of, since it holds lots of things
relating to your site such as logos and embedded images. Custom themes are also stored here.

Make sure that you back these two directories up weekly, or any changes made by your users
might get lost forever. On high traffic sites, make daily backups of these two, and save the last 8
backups for safekeeping. If something goes wrong by accident, and you can bring your site back
to the same way your users left it, you will have garnered their loyalty, increased
word-of-mouth traffic for your site, and become their newest idol. You might even make it into
their blog. Yes, backups can do this for you.

333
Drupal Handbook 3 Aug 2007

Test your backups


Document and test your backup and restore procedure before you need it. The forums and IRC
chat are full of people who want help recovering from some unforeseen fatal error, and if they
knew how to restore their site using the backups they’d created, they would be in business and
making money rather than waiting for help from a Drupal volunteer.

Backup and restore using bash shell scripts


The two Bash shell scripts presented here work together automating the Drupal backup and
restore process. They work "as is" for simple installations and can be customized for multisite or
non-standard installations.

The scripts have two uses:

1. Creating Drupal backups which can be restored to their original location


e.g., restore from a failed upgrade attempt or recover from a disk failure
2. Staging data between Drupal configurations
e.g., backup a production instance and restore to a test instance

These scripts have been used successfully on and between Linux systems and on Windows
systems using Cygwin.

Functional Overview
A full Drupal backup requires data backups from both the database and file system. These two
backups must then be tied to each other.

The backup script performs a file system backup using the tar command and a database backup
using the mysqldump utility. The two backups are then combined into a single tar file. The tar is
compressed and its file name includes the backup date.

The restore script reverses the process by unpacking the file and database backups from the
container tar file and applying them to their respective targets.

The Drupal instance backed up or restored is specified by variables defined in the backup and
restore scripts.

Usage notes and cautions


Detailed usage notes are provided for each script. The following points bear highlighting:

The restore script has no safeguards against accidental restore. If you don’t understand
how it can destroy your system you are encouraged NOT to use it.
The backup script backs up every file and directory in the Drupal root directory. If you have
a hosted site with subdomain websites contained in subdirectories a backup of the main
website directory will include the subdomain websites. For backups this will only bloat

334
3 Aug 2007 Drupal Handbook

your backup file. For restores this could be disastrous, since you would restoring the file
systems for ALL of the website. If you have this kind of configuration you must customize the
tar command to make a selective backup.
These scripts make no provision to lock out users while the backup or restore is in progress.
This script does not understand Drupal multisite configurations
The backup script requires read access to all files/directories and the restore script requires
read/write access. This is sometimes a problem in hosted configurations.
Because the backup and restore is done in stages enough temporary space must be available
for the intermediate files
Some commands used in the scripts will vary between operating systems. You may have to
tailor commands for your operating system.

Site backup script


To use the script modify the variables in the Configuration block to specify the instance being
backed up.

The script will default the backup file name to value of tarnamebase appended with the date.
The default value of tarnamebase is fullsitebackup. e.g.: fullsitebackup-2006-04-14.tgz. This name
can be overridden by specifying a filename in parameter P1.

The script is run using the normal Bash script invocation for your system. e.g.:
$ sh fullsitebackup.sh
$ bash fullsitebackup.sh

You will be prompted for the database password. The backup file is placed in the same directory
the script is run from.

If multiple sites are hosted on the same system, create a copy of the script for each instance and
rename it to reflect the backup it will perform. For example, for a site named mysite1, create a
copy of fullsitebackup.sh named mysite1fullbackup.sh. You should also modify the tarnamebase
variable to be more description of the site.

Usage notes and warnings:

This script backs up every file and directory in the Drupal root directory. If you have a
hosted site with subdomain websites contained in subdirectories a backup of the main
website directory will include the subdomain websites. For backups this will only bloat
your backup file. For restores this could be disastrous, since you would restoring the file
systems for ALL of the website. If you have this kind of configuration you must customize
the tar command to make a selective backup.
This script does not understand Drupal multisite configurations
This script does not lock out users while the backup is in progress
Read access is required on all files and directories (this is sometimes a problem in hosted
configurations)
The mysqldump utility uses the --add-drop-table option so that a restore automatically
replaces tables. You may wish to modify this to add an element of safety to your restore

335
Drupal Handbook 3 Aug 2007

process. (e.g., tables must be manually dropped, script will not replace)
Commands may need to be modified for your operating system (e.g., The default tar
command in Solaris does not support compression)
Because the backup is done in stages enough temporary space must be available to build the
backup files

fullsitebackup.sh

Copy this text to a file named fullsitebackup.sh. Please ensure that special characters, such as
backtick ("‘") and quotes, are saved correctly.

#!/bin/bash
#
# fullsitebackup.sh V1.0
#
# Full backup of website files and database content.
#
# A number of variables defining file location and database connection
# information must be set before this script will run.
# Files are tar’ed from the root directory of the website. All files
are
# saved. The MySQL database tables are dumped without a database name
and
# and with the option to drop and recreate the tables.
#
# Parameters:
# tar_file_name (optional)
#
# Configuration
#
# Database connection information
dbname={DB Name} # (e.g.: dbname=drupaldb)
dbhost=localhost
dbuser={DB Username} # (e.g.: dbuser=drupaluser)
# Website Files
webrootdir={Directory Path} # (e.g.:
webrootdir=/home/user/public_html)
#
# Variables
#
# Default TAR Output File Base Name
tarnamebase=sitebackup-
datestamp=‘date +’%Y-%m-%d’‘
# Execution directory (script start point)
startdir=‘pwd‘
# Temporary Directory
tempdir=tmpbckdir$datestamp

336
3 Aug 2007 Drupal Handbook

#
# Input Parameter Check
#
if test "$1" = ""
then
tarname=$tarnamebase$datestamp.tgz
else
tarname=$1
fi
#
# Banner
#
echo ""
echo "fullsitebackup.sh V1.0"
#
# Create temporary working directory
#
echo " .. Setup"
mkdir $tempdir
echo " done"
#
# TAR website files
#
echo " .. TARing website files in $webrootdir"
cd $webrootdir
tar cf $startdir/$tempdir/filecontent.tar .
echo " done"
#
# sqldump database information
#
echo " .. sqldump’ing database:"
echo " user: $dbuser; database: $dbname; host: $dbhost"
cd $startdir/$tempdir
mysqldump -p --user=$dbuser --host=$dbhost --add-drop-table $dbname >
dbcontent.sql
echo " done"
#
# Create final backup file
#
echo " .. Creating final compressed (tgz) TAR file: $tarname"
tar czf $startdir/$tarname filecontent.tar dbcontent.sql
echo " done"
#
# Cleanup
#
echo " .. Clean-up"
cd $startdir

337
Drupal Handbook 3 Aug 2007

rm -r $tempdir
echo " done"
#
# Exit banner
#
echo " .. Full site backup complete"
echo ""

Updated fullsitebackup.sh

#!/bin/bash
#
# fullsitebackup.sh V1.1
#
# Full backup of website files and database content.
#
# A number of variables defining file location and database connection
# information must be set before this script will run.
# Files are tar’ed from the root directory of the website. All files are
# saved. The MySQL database tables are dumped without a database name and
# and with the option to drop and recreate the tables.
#
# ----------------------
# March 2007 Updates
# - Updated script to resolve minor path bug
# - Added mysql password variable (caution - this script file is now a security risk - protect it)
# - Generates temp log file
# - Updated backup and restore scripts have been tested on Ubunutu Edgy server w/Drupal 5.1
#
# - Enjoy! BristolGuy
#-----------------------
#
## Parameters:
# tar_file_name (optional)
#
#
# Configuration
#

# Database connection information


dbname="drupal" # (e.g.: dbname=drupaldb)
dbhost="localhost"
dbuser="" # (e.g.: dbuser=drupaluser)
dbpw="" # (e.g.: dbuser password)

338
3 Aug 2007 Drupal Handbook

# Website Files
webrootdir="/var/www/drupal" # (e.g.: webrootdir=/home/user/public_html)

#
# Variables
#

# Default TAR Output File Base Name


tarnamebase=sitebackup-
datestamp=‘date +’%m-%d-%Y’‘

# Execution directory (script start point)


startdir=‘pwd‘
logfile=$startdir"/fullsite.log" # file path and name of log file to use

# Temporary Directory
tempdir=$datestamp

#
# Input Parameter Check
#

if test "$1" = ""


then
tarname=$tarnamebase$datestamp.tgz
else
tarname=$1
fi

#
# Begin logging
#
echo "Beginning drupal site backup using fullsitebackup.sh ..." > $logfile
#
# Create temporary working directory
#
echo " Creating temp working dir ..." >> $logfile
mkdir $tempdir

#
# TAR website files
#
echo " TARing website files into $webrootdir ..." >> $logfile
cd $webrootdir
tar cf $startdir/$tempdir/filecontent.tar .

339
Drupal Handbook 3 Aug 2007

#
# sqldump database information
#
echo " Dumping drupal database, using ..." >> $logfile
echo " user:$dbuser; database:$dbname host:$dbhost " >> $logfile
cd $startdir/$tempdir
mysqldump --user=$dbuser --password=$dbpw --add-drop-table $dbname > dbcontent.sql

#
# Create final backup file
#
echo " Creating final compressed (tgz) TAR file: $tarname ..." >> $logfile
tar czf $startdir/$tarname filecontent.tar dbcontent.sql

#
# Cleanup
#
echo " Removing temp dir $tempdir ..." >> $logfile
cd $startdir
rm -r $tempdir

#
# Exit banner
#
endtime=‘date‘
echo "Backup completed $endtime, TAR file at $tarname. " >> $logfile

Site restore script


Caution: This script has no safeguards against accidental restores. Since a restore, by definition,
overwrites the existing website do NOT use this script unless you understand what it is doing.

To use this script modify the variables in the Configuration block to specify the instance where
the data will be restored.

To restore a site run the script specifying the backup file in parameter P1. e.g.:
$ sh fullsiterestore.sh fullsitebackup-2006-04-14.tgz
$ bash fullsiterestore.sh fullsitebackup-2006-04-14.tgz

You will be prompted for the database password and may be prompted for permission to delete
a file if it is permitted read-only.

If multiple websites are hosted on the same system create a copy of the script and rename it to
reflect the restore it will perform. For example, for a site named mysite1, create a copy of
fullsiterestore.sh named mysite1fullrestore.sh.

340
3 Aug 2007 Drupal Handbook

Usage notes and warnings:

The backup script uses the mysqldump --add-drop-table option. On a restore this allows the
database tables to be removed and recreated. No prompt is given before this happens.
Write access is required on all files and directories (this is sometimes a problem in hosted
configurations)
Enough file space must be available to allow unpacking of the backup file
This script does not lock out users while the restore is in progress
This script does not understand Drupal multisite configurations
Commands may need to be modified for your operating system (e.g., The default tar
command in Solaris does not support compression)
If restoring over top of a Drupal instance that contains modules that are not in the backup
there will be "orphaned" module tables. Depending on the situation, you may wish to drop
and recreate the database before doing the restore.
When restoring to a different server the file permissions may require updating

No Drupal configuration is required if restoring a backup to the same location it was backed up
from.

If restoring a backup to a different location the configuration must be updated according,


specifically $db_url and $base_url in settings.php. The article Creating a Test Site workflow
contains information on automating this using a command line utility named sed.

fullsiterestore.sh

Copy this text to a file named fullsiterestore.sh. Please ensure that special characters, such as
backtick ("‘") and quotes, are saved correctly.

#!/bin/bash
#
# fullsiterestore.sh v1.0
#
# Restore of website file and database content made with full site
backup.
#
# A number of variables defining file location and database connection
# information must be set before this script will run.
# This script expects a compressed tar file (tgz) made by
fullsitebackup.sh.
# Website files should be in a tar file named filecontent.tar, and
database
# content should be in a sqldump sql file named dbcontent.sql. This
script
# expects the sql to drop the table before readdding the data. In other
words,
# it does not do any database preparation.
#

341
Drupal Handbook 3 Aug 2007

# Parameters:
# tar_file_name
#
# Configuration
#
# Database connection information
dbname={DB Name} # (e.g.: dbname=drupaldb)
dbhost=localhost
dbuser={DB Username} # (e.g.: dbuser=drupaluser)
# Website Files
webrootdir={Directory Path} # (e.g.:
webrootdir=/home/user/public_html)
#
# Variables
#
# Execution directory (script start point)
startdir=‘pwd‘
# Temporary Directory
datestamp=‘date +’%Y-%m-%d’‘
tempdir=tmpbckdir$datestamp
#
# Banner
#
echo ""
echo "fullsiterestore.sh v1.0"
#
# Input Parameter Check
#
# If no input parameter is given, echo usage and exit
if [ $# -eq 0 ]
then
echo " Usage: sh fullsiterestore.sh {backupfile.tgz}"
echo ""
exit
fi
tarfile=$1
# Check that the file exists
if [ ! -f "$tarfile" ]
then
echo " Can not find file: $tarfile"
echo ""
exit
fi
# Check that the webroot directory exists
if [ ! -d "$webrootdir" ]
then
echo " Invalid internal parameter: webrootdir"

342
3 Aug 2007 Drupal Handbook

echo " Directory: $webrootdir does not exist"


echo ""
exit
fi
#
# Create temporary working directory and expand tar file
#
echo " .. Setup"
mkdir $tempdir
cd $tempdir
tar xzf $startdir/$tarfile
echo " done"
#
# Remove old website files
#
echo " .. removing old files from $webrootdir"
rm -r $webrootdir/*
echo " done"
#
# unTAR website files
#
echo " .. unTARing website files into $webrootdir"
cd $webrootdir
tar xf $startdir/$tempdir/filecontent.tar
echo " done"
#
# Load database information
#
cd $startdir/$tempdir
echo " .. loading database:"
echo " user: $dbuser; database: $dbname; host: $dbhost"
echo "use $dbname; source dbcontent.sql;" | mysql --password
--user=$dbuser --host=$dbhost
echo " done"
#
# Cleanup
#
echo " .. Clean-up"
cd $startdir
rm -r $tempdir
echo " done"
#
# Exit banner
#
echo " .. Full site restore complete"
echo ""

343
Drupal Handbook 3 Aug 2007

Updated fullsiterestore.sh

#!/bin/bash
#
# fullsiterestore.sh v1.1
#
# Restore of website file and database content made with full site backup.
#
# A number of variables defining file location and database connection
# information must be set before this script will run.
# This script expects a compressed tar file (tgz) made by fullsitebackup.sh.
# Website files should be in a tar file named filecontent.tar, and database
# content should be in a sqldump sql file named dbcontent.sql. This script
# expects the sql to drop the table before readdding the data. In other words,
# it does not do any database preparation.
#
# ----------------------
# March 2007 Updates
# - Updated script to resolve minor path bug
# - Added mysql password variable (caution - this script file is now a security risk - protect it)
# - Generates temp log file
# - Updated backup and restore scripts have been tested on Ubunutu Edgy server w/Drupal 5.1
#
# - Enjoy! BristolGuy
#-----------------------
#
# Parameters:
# tarfile # name of backup file to restore
#
#
# Database connection information
dbname="drupal" # (e.g.: dbname=drupaldb)
dbhost="localhost" #
dbuser="" # (e.g.: dbuser=drupaluser)
dbpw="" # database user password

# Website location
webrootdir="/var/www/drupal" # (e.g.: where you keep your drupal directory structure)
#
# Variables

# Execution directory (script start point)


startdir=‘pwd‘ # return of pwd() populates statdir var
logfile=$startdir+"fullsite.log" # file path and name of log file to use

344
3 Aug 2007 Drupal Handbook

# Temporary Directory
datestamp=‘date +’%Y-%m-%d’‘ # uses US format
tempdir=$datestamp

#
# Begin logging
#
echo "Beginning drupal site restore using \’fullsiterestore.sh\’ ..." > $logfile

#
# Input Parameter Check
#

# If no input parameter is given, echo usage and exit


if [ $# -eq 0 ]
then
echo " Usage: sh fullsiterestore.sh {backupfile.tgz}"
echo ""
exit
fi

tarfile=$1

# Check that the file exists


if [ ! -f "$tarfile" ]
then
echo " Can not find file: $tarfile" >> $logfile
echo " Exiting ..." >> $logfile
exit
fi

# Check that the webroot directory exists


if [ ! -d "$webrootdir" ]
then
echo " Invalid internal parameter: webrootdir" >> $logfile
echo " Directory: $webrootdir does not exist" >> $logfile
echo " Exiting ..." >> $logfile
exit
fi

#
# Create temporary working directory and expand tar file
#
echo " Creating temp working dir ..." >> $logfile
mkdir $tempdir
cd $tempdir
echo " unTARing db and file tgz files ..." >> $logfile
tar xzf $startdir/$tarfile

345
Drupal Handbook 3 Aug 2007

#
# Remove old website files
#
echo " Removing old files from $webrootdir ..." >> $logfile
rm -r $webrootdir/*

#
# unTAR website files
#
echo " unTARing website files into $webrootdir ..." >> $logfile
cd $webrootdir
tar xf $startdir/$tempdir/filecontent.tar

#
# Load database information
#
cd $startdir/$tempdir
echo " Restoring database ..." >> $logfile
echo " user: $dbuser; database: $dbname; host: $dbhost" >> $logfile
echo "use $dbname; source dbcontent.sql;" | mysql --password=$dbpw --user=$dbuser
--host=$dbhost

#
# Cleanup
#
echo " Cleaning up ..." >> $logfile
cd $startdir
sudo rm -r $tempdir

#
# Exit banner
#
endtime=‘date‘
echo "Restoration completed $endtime for $tarfile. " >> $logfile

Accounts and roles


1. Do not use the first user account for day to day stuff on your site. This account should be
used for the site setup, major configuration changes and upgrades only. UID1 (User ID) has
special use and purpose.
2. Set up some appropriate roles (do not forget to update these roles as you add new
modules). Some role suggestions are ’site admin’, ’user admin’, ’site contributor’. What roles
you need to create will depend on the type of site you have designed. Note that anyone who
can administer users can grant themselves additional permissions.
3. Adding new modules often adds additonal permissions options. When adding new
modules revisit your access lists to check for appropiate access for your roles.

346
3 Aug 2007 Drupal Handbook

Configuring Apache and PHP for Drupal in a Shared


Environment
#### STARTING TO CLEAN UP #####
#### todo: mysql tuning section ####
#### markup layout and use &gt; &lt;

These are some simple guidlines for setting up Drupal in an Apache Virtual host that provides a
fair amout of security for the rest of your system.

Starting with php.ini:

php.ini Configuration
# increase php’s memory limit to avoid the white screen of death when
# you add a few modules.
memory_limit = 16MB

Apache Virtual Host Configuration

ServerName example.com

#wildcard server alias helps direct all traffic to your end users site
#and simplifies using drupal’s multisite configuration for subdomains.

ServerAlias *.example.com

# This path will vary depending on your system, If you are using debian
# make sure you drop the default images alias it can be very annoying
# to users on shared servers.

DocumentRoot /var/www/example.com/public_html

# Place the log where your end users can see them, and make sure they
# are at the least readable to an end user.
#
# performance option:
# You can move the apache logs to another partition or drive to
# get some small increases in disk i/o on heavily loaded servers.
# You can symlink the log files to /var/www/example.com/logs/
# to keep the persistent user interface, however it doesn’t work in
# chroot environments.

ErrorLog /srv/www/example.com/logs/error.log
CustomLog /srv/www/example.com/logs/access.log combined

347
Drupal Handbook 3 Aug 2007

#Go ahead and give users access to manipulate their vhost to their
#hearts content.

AllowOverride All

#Since mod_php doesn’t like yo respect su_exec, and safe_mode is just


# too paranoid to be usable restrict php to the proper vhost, but a level
#above the document root so users have some private file space for
#.htpasswd, drupal files, backups, etc
php_admin_value open_basedir /var/www/example.com

#move php’s temp files into the open_basedir


php_admin_value upload_tmp_dir /var/www/example.com/tmp

#session.save path isn’t really necessary for drupal since it


#stores sessions in the database, but for general php enabled
#vhosts it keeps session data tied to each vhost.
php_admin_value session.save_path /var/www/example.com/tmp

//Tweaking performance
my.cnf
#big ol mysql.querycache(128M) (be aware of your systems memory limitations)
query_cache_size = 134217728
#boost mysql max connections (min = (20*number of drupal sites))
set-variable=max_connections=512

eacclerator

Creating a Test Site workflow


Terms:

prod site: the live, production website where all your web visitors go
test site: a copy of your live site, at a different URL, where you can make experimental changes
without affecting your prod site

Drupal and its modules are in pretty constant development. So things are changing pretty fast
and sometimes not completely documented. In practice, that means making a change or
adding/removing a module on your prod site can have rather surprising results - surprises
you’d rather your visitors didn’t have to live with. That’s why I recommend making all changes
to a test site, and if they work out, promote the changes to your prod site.

Here’s how I built a completely parallel site on my hosted, shared server account.

First I need to mention some things about my site, so the rest of this article makes sense:

348
3 Aug 2007 Drupal Handbook

My site is called yoursite.com


it’s hosted on a shared server
I have shell access to my hosted files. Without shell I wouldn’t really want to attempt all this.
I am allowed to have two mysql databases on my account
all site files are at /home/user/public_html
(there’s also an alias, /home/user/www, which points to public_html)
in the above, user stands for my username, which I’m not telling you
I keep my production drupal database in mysql; that db is named mydb_prod
Apache is set up so that http://www.yoursite.com and http://yoursite.com will point to
/home/user/public_html

All of this is pretty standard stuff, but you may have to make a few changes to this process if
your site is set up differently. My test/prod workflow looks generally like this:

1. Make a new (empty) database, and name it mydb_test


2. Copy your prod db into mydb_test
3. Copy all of your prod files (from public_html) into your test directory
4. Make three settings changes to connect the test site to the test db
5. Make changes to your test site.
6. (optional) replicate test site’s files and db back into the prod site to make your changes live

So how to actually do all this? Don’t worry, it’s not that hard once you have the right commands
handy. Really, I do steps 1-4 in about 2 minutes. This document is long only because I wanted to
be verbose enough for all skill levels!

Step 0 - work with your host provider

The first thing I did was ask my hosting provider to create a new directory, /home/user/test
and then set up apache and their DNS servers so that http://test.yoursite.com and
http://www.test.yoursite.com would point to this new test directory. It was important to ask
them to make a new VirtualHost entry in the apache configurations, NOT just set up a rewrite
rule. They should know what you mean by this - and they might charge you extra for it. Mine
didn’t, but even if this costs you a couple of extra bucks, it’s worth it. Trust me when I say that
using a rewrite rule or subdirectory of your existing site will make the rest of this much harder
to do.

When this is complete your directory structure will look something like:

|-home
|-username
|
|-public_html
| |
| |-database
| |-files
| |-includes
| |-misc

349
Drupal Handbook 3 Aug 2007

| |-modules
| |-scripts
| |-sites
| |-themes
| |-(drupalfiles)
|
|-test
|
|(empty because we haven’t put anything here yet)

/home/username could in your case be /var/www/username, or something else entirely. The


point is to have a test directory which is not part of your normal html directory, and which acts
as a separate site in all ways.

You’ll also need a second mySQL database to house your test site’s data.

Step 1 - Create an Empty Database

I use the commands

mysql -uuser -ppassword -e "create database mydb_test;"


mysql -uuser -ppassword -e "grant all privileges on mydb_test.* to
user@localhost identified by ’password’;"

to create my database and set the permissions. The I broke a single mysql command into the last
two lines because drupal.org wasn’t printing it all as a single line. If you are restricted from
doing so, you may need to create the empty database via cPanel, Plesk, or whatever control
panel your provider gives.

Step 2 - Replicate the database

mkdir ~/temp
mysqldump -uuser -ppassword --add-drop-table mydb_prod > ~/temp/prod-db
mysql -uuser -ppassword mydb_test < ~/temp/prod-db
rm ~/temp/prod-db

Above you see the commands I enter. You’ll need to change things user and password to your
username and password; also mydb_prod should be replaced with the mySQL database name for
your prod site. Knowing that, I bet you’ve already figured out that you need to replace mydb_test
with the name of your newly-created test database.

The first line just creates a directory to hold our temporary dump file.

The second line, starting with mysqldump, is where we dump the entire prod database to a
textfile. We use the --add-drop-table option because this essentially creates a script we’ll run
later; this option makes sure that script will erase old data before importing new data. Note that
you need to supply the proper username and password for your production database. I specify
the database name mydb_prod - you will need to change this to the name of your prod site’s

350
3 Aug 2007 Drupal Handbook

database. The textfile created by this command is actually a full script which will create tables
and populate them with data.

The third line, starting with mysql, is where we do that. Again, be sure and replace the italicized
parts with the username, password, and database name you set up in step 1.

Finally I delete the dump file (~/temp/prod-db); it’s not needed anymore now that we have
loaded it into mySQL.

Step 3 - Copy the web files

rm -rf ~/test
cp -R ~/public_html/. ~/test

Here I remove the test directory, then recreate it, and copy everything from ~/public_html into
it. I remove the test directory and all contents because I may copy of the test site in there, and I
don’t want it to pollute my fresh new exact replica of my prod site.

Step 4 - Edit Settings

nano ~/test/sites/default/settings.php

This starts the nano editor (or use whatever you like) and loads drupal’s settings file. Here you
will need to change two lines:

$db_url = ’mysql://user:password@localhost/mydb_test’;
$base_url = ’http://test.yoursite.com’;

These lines are not together in the file. Set the database connection line, pointing to the test
database you created in step one and populated in step 2. (in other words, you need to replace
the words user, password, and mydb_test with information that’s correct for your test database.)
The base_url line sets the URL you will point your browser at to use the site. Save the changes.

Now, in your web browser, navigate to the site - it should be working fine. But I also change the
Name field at administer --> settings to TEST.yoursite.com (all caps) so its easy for me to
remember I am looking at the test site.

Step 5 - Make your changes

This is where you make you changes. Change settings, add/remove modules, muck with the
code - it’s up to you. Remember you are working in a copy of your site - one that users don’t
know about - so you don’t have to worry that you are creating problems for the users.

Killes has written a very nice and very quick way of testing your site at node/11521

And if you don’t like the changes, or if you mess up your test site
completely - no worries! Just re-do steps 2-4 to bring a new copy of your
production site and database into your test environment.

351
Drupal Handbook 3 Aug 2007

Step 6 - Promoting changes to production

Now that you have your test site the way you want it, you really have two choices.

Method 1: You can re-make all the same changes manually on your production site.
Method 2: You can basically migrate the test site into production, with a very brief outage for the
users.

I usually use method 2, but have been known to do it both ways. To use method 2, I’m
essentially doing everything mentioned above, but this time copying the test site into the
production location. So I’ll skip over it more quickly this time around:

1.
mysqldump -uuser -ppassword --add-drop-table mydb_test >
~/temp/test-db
mysql -uuser -ppassword mydb_prod < ~/temp/test-db
rm -rf ~/temp/test-db
rm -rf ~/public_html/*
cp -R ~/test/. ~/public_html
2. nano ~/public_html/sites/default/settings.php (here you’ll edit the db_url
and base_url to the prod-site settings)
3. Also be sure to open the prod site, navigate to administer // settings and change the name
back to the way it should be for the prod site.

You should probably test your site again using the Killes method linked in step 5.

There are a couple of additional cleanup steps I do, once I know my site is in good shape:

rm -rf ~/test/* (just cleaning out test dir for next time)
rm ~/bash_history(because it has my database password in it)
Remove the test database (if space is a concern)

File and directory management


These are general guidelines.

1. For Drupal 5.x only: a new feature/best practice. For a normal (single site) installation, you
should put all non-core modules or themes in the sites/all/modules or
sites/all/themes folders. For a multi-site installation, put modules or themes in
sites/all that you wish to have available for all sites.
2. For 4.7 and prior: Create a sub directory in modules for each contributed module you
install. This helps you track contributed modules vs included core modules. This is fairly
important when preparing for a Drupal version upgrade and a good idea in general.
For example: a module named foo.module would go in a sub directory of modules; modules/foo Be
sure not to include the space if the module name is multiple words.
3. Multisite setups allow you to have a modules directory specific to the site in the
sites/www.example.com/modules directory. You can still put modules in directories off

352
3 Aug 2007 Drupal Handbook

the main /modules directory if you want them available to all sites.
4. Leave the CHANGELOG.txt file in your root directory as it has the Drupal version
information in it. If you manage more then one site, consider putting a version.txt file in the root
of your drupal directory with the Drupal version, date and modules you are using. If you only
manage a few sites you will probably remember them all, but if you set them up for other
people, these reminders can help you if you are asked back to do additional work. Also, it can
help the next site admin if you move on.
5. Rename update.php if you want. There are protections for it in the update script in that you
have to be logged in with UID1. As of 4.7 update.php is now required for various module
installations and other tasks so if you move/rename it for whatever reason do not forget to put it
back to it’s original state before module installs/updates.

Other Tips
Modules that are not part of core may or may not be supported by their contributor for a
Drupal version upgrade.
Avoid spaces in any directory name.

Test Sites
Set up a test site using your live data. You do not want to have to ask in the forums how to save
your site. You have worked hard to build it, it would be a shame to lose it.

1. Never do development or testing on your live production site. Drupal is fast and easy to
install. Always test on a test site first.
2. Test that your backups work and that you know how to do a restore of your site. The test
system can be your local desktop, just edit your conf.php (4.5 or earlier) file or settings.php
(4.6) to localhost. You do not want to discover the hard way that you forgot a file or did not
know how to do this when your site is down.
3. Test your site upgrade procedure before risking your live site and document the steps you
take. Documentation aids repeating the process if necessary. Testing can be done with
Simpletest.

For more information on installing test sites, please see the Installing Drupal section. There are
some specific examples of copying a production site to a test/development environment in the
Special Cases subsection under Installation.

Version update considerations


There are several approaches to updating your site and the instructions are in the INSTALL.txt
file of the Drupal download. Unless you do this often however, you may miss a few other
considerations when updating from one release to the next.

353
Drupal Handbook 3 Aug 2007

1. Read the Best Practices on test sites and don’t do it first on your live site.
2. Make sure that all the contrib modules you are using have an update path or you are
willing to upgrade them yourself or abandon them.
3. Create a new database and restore your live site to it, files and all.
4. Disable all contrib modules.
5. Set your site to the default theme Blue Marine (for Drupal 4.7.x) or Garland (for Drupal 5.x).

Read the upgrade portion of the INSTALL.txt file

Log in with UID 1.


Run sitename/update.php.
On the update.php page, check the schema date of the database, I generally leave it where it
defaults to.
Upgrade.
Check for errors. Resolve all errors BEFORE proceeding.

Log in check it out.


Get your modules and read the install and readme files to see if there are any special
upgrade instructions.
Upgrade and activate modules one at a time.
Test, etc.
Put your own favicon.ico back.
Congratulations.

You can restore this to your live site.


- or -
Follow the steps on your live site now that you are confident it will work.

Start working on your theme updates and other and stuff.

Do not modify core Drupal


Do not modify Drupal core files.

Doing so will complicate, make difficult or near impossible site updates due to Security and
bug fixes
You will make it difficult for those that come after to maintain the site
You could possibly leave your site vulnerable to exploits

Are there exceptions to this rule? Sure, but this is generally for specific sites or implementations
by people who are extremely familiar with the Drupal code base, development practices and
security model. Those who properly document their changes and practice proper revision
control with their code. If you have to ask, chances are you shouldn’t.

354
3 Aug 2007 Drupal Handbook

Security
Security is an important consideration when running your web site. If you maintain your own
server you should be aware of any announced vulnerabilities for your operating system, php,
and web server. Be sure to follow up with the appropriate patches or updates as needed. Sign up
for the security mailing list so that you can be aware of any announced vulnerabilities and how
to correct them.

Test php before putting it in blocks


Drupal gives you a great deal of power and flexibility when using PHP code in blocks.
Unfortunately, a stray typo character or a missing semi-colon breaks PHP. Drupal then attempts
to evalate this broken code on any requested page, the PHP interpreter chokes on it and
therefore your whole site is broken.

Fortunately, there is a very simple and easy solution. Instead of writing and testing your code
inside the administer > blocks page, go to create content and create a new story or page node.
Use PHP input format, write the code, and the Preview to debug your code. When you are
happy and your code is working, copy and paste the code into the block.

Thank you to Heine for this tip in the #drupal-support IRC channel.

355
Drupal Handbook 3 Aug 2007

HowTo: The Advanced user’s guide


Ok, so you’ve installed Drupal and gotten it working. You’ve added a module or two, and
maybe you’ve even changed the theme. Now you want to do more, and adding modules or
changing the options doesn’t seem to cut it. Maybe you’ve found that things don’t look quite like
you want them to, or you want there to be more functionality in a particular module.

Specifically for Modules


If you have problems with or questions about a specific module, there are two places to start
looking:
Core Modules Handbook or Contributed Modules Handbook

Another place to look for issues or bugs in contributed modules is: Module downloads page.
Click on "Bugs and feature requests" under your specific module to see if someone has already
addressed the issue. The next place to go is to the forums.

Specifically for Themes


You might find that some Drupal 4.6 or earlier themes you’ve installed don’t seem to show up. If
they are run by the phpTemplate Engine, you’ll need to download it and install it. If you are
using Drupal 4.7 or later, you already have the phpTemplate Engine installed by default, so no
worries. If you have problems with implementing and changing with specific themes, check out
the Theme downloads page. Click on "Find Out More" under your specific module, and then
click on "Bugs and feature requests" to see if someone has already addressed the issue. Again,
the next step would be to go to the forums.

The Forums
Another great resource is the forums where you can ask your question to anyone, typically in
the "How do I..." section. Be courteous, and please search for your answers first. Don’t be
dismayed if you can’t find it right away. Chances are, someone else has already asked and
answered your question, but that doesn’t mean the search will find it right away. Some people
use Google to do a website search by typing in "site:www.drupal.org" in the search box.

Advanced customization
If your answer was not anywhere listed above, the next step may be to customize your install of
Drupal by changing the code. Now, you’ve entered the realm of developing Drupal, or
customizing the code to suit your needs. Look at the Contributer’s Guide to start, and you may
end up with something we all can benefit from. There is a Module developer’s guide and a
Theme developer’s guide. Also very helpful is the: API, or application program interface. The
API is an interactive repository of information on all the functions, modules, constants,
variables, etc that are used in the core Drupal code, and it’s very useful if you want to
understand the relationships and purpose of different parts of Drupal. You may eventual find
that your new function, module, phpcode snippet, etc. can benefit the Drupal community at
large. There are several ways to do that - post it in the forums, add it to PHP page snippets, or
apply for CVS (concurrent version system) access and add it there.

356
3 Aug 2007 Drupal Handbook

HowTo: enable Imagemagick for the Image module


Imagemagick is a powerful image manipulation toolkit that, unlike PHP’s default GD library,
supports gif, png, and other raw file formats too. A lot of users have Imagemagick installed on
their server already, and don’t even know it. If you’re using the contributed image.module in
your Drupal site, and you want to access the Imagemagick already installed on your server,
here’s how to do it:

1. Locate the directory where you installed the Image module. It’s most likely in
/sites/default/modules/image or /sites/all/modules/image. Open the image folder and
look for a file called ’image.imagemagick.inc’. Copy (don’t move) that file to /includes/.
That’s a Drupal core directory, BTW.
2. After the file has been copied to your /includes/ folder on the server, surf your way to
Administer > Site Configuration > Image Toolkit. There, you will find a second entry under
"Select an image processing toolkit". Enable the Imagemagick library there, and click ’Save
Configuration’.
3. Set the proper path to Imagemagick’s Convert binary. This is usually /usr/bin/convert, but
it can be in other places too. If you installed Imagemagick on your own server, you’ll know
where to look. If you’re using a hosting company who provides it as a package, ask them
*after* you try and see if the default /usr/bin/convert works or not.

You’re done! If there are any questions or problems relating to this HowTo, post a comment
here. If you found a bug, or something doesn’t work right and you know it should, file a bug
report for image.module. Full documentation on the Image module can be found in Contributed
Modules > Image handbook.

Tips and Tricks


A collection of tips and tricks from the Drupal Newsletters, "How to make Drupal do things you
didn’t think it could."

August 2005: Upgrade, Play B-I-N-G-O!, & E-commerce


UPGRADE
Upgrading is especially important this time because of the major security fix. Failing to upgrade
can result in someone cracking into your website and abusing it. Even if it is not a security issue,
it is a good idea to upgrade every time a stable version of Drupal is released. This way, you have
the latest bug fixes and new features. However, before you upgrade, be sure to backup your
database and files so that you can roll back in case of any unforeseen issues.

357
Drupal Handbook 3 Aug 2007

PLAY B-I-N-G-O!
Want to help Drupal? Like random games of chance? Why not combine both of these interests in
one fell swoop and participate in: Patch Bingo: http://drupal.org/patch-bingo and Bug Bingo:
http://drupal.org/bug-bingo. These links will take you to a random issue in the Drupal queue.
Test out bugs to see if they’re still an issue, try out patches to see if they work and comment on
whether or not they’d be useful. You’ll both add some wacky adventures to your life, and help
Drupal at the same time!

E-COMMERCE
Check out this nice ecommerce module for Drupal: http://drupal.org/project/ecommerce.
While I wouldn’t recommend it to start an entire store, it has everything you need to make your
own little gift shop and sell t-shirts, coffee mugs and more. Plus, it integrates nicely, so your
store looks just like the rest of your website.

You can get more tips from Bryght’s "Best Practices" section at
http://support.bryght.com/taxonomy/term/8.

Commentator array
Lately on my website, which runs Drupal 4.7.4, I have been getting serious performance
problems. In one hand I have a lot of modules installed. In the other hand I have a lot of
personal code I have wrote to make my site more attractive.

One of these things was to show user’s profile data on every comment, just below user’s image.
Data like location, country and a nice country flag.

Well, the only way I could imagine to do this was either loading user’s profile or querying DB on
comment.tpl.php. That means I had to repeat this operations on every comment. Of course this
was totally redundant if the same user was commenting more than once in the same thread,
having nodes were I was loading some user’s profiles even more than 20 times. This of course is
a bad practice and makes your site pretty slow.

So today I was thinking it would be cool to load all commentators information before displaying
the comments. And here is how I made it.

1. On node.tpl.php file, after node has been closed, add this php code:

if ($node->comment) {
global $commentators;
$commentators = mystuff_getcommentators($node->nid);
}

2. On template.php file, create this function:

358
3 Aug 2007 Drupal Handbook

function mystuff_getcommentators($nid) {
$result = db_query("select distinct uid from {comments} where uid > 0
and nid = $nid");
while ($u = db_fetch_object($result)) {
profile_load_profile($u);
$commentators[$u->uid] = $u;
}
return $commentators;
}
Of course, on this function you can add other stuff to the user object besides user’s profile.

3. On comment.tpl.php file, display user’s info whenever you want it:

global $commentators;
if ($picture) { print theme(’user_picture’, $comment, ’comment’);
}
if ($comment->uid) {
print $commentators[$comment->uid]->profile_location_city .
"<br/>";
print $commentators[$comment->uid]->profile_location_state .
"<br/>";
print $commentators[$comment->uid]->profile_location_country .
"<br/>";
}
(Profile fields must be set on profile settings page)

And that’s it! I love to do stuff without touching a line of Drupal’s or modules code.

PS: I have been looking for some kind of solution for this on the forum, but haven’t found
anything so I did it myself.

PS2: Should this be on PHP snippets section?

June 2005: Custom Content Types, WYSIWIG Editors,


Organize Your Content & Quick Support
CUSTOM CONTENT TYPES

Need more flexibility in creating content? Are the simple page and story content types not
enough for your site’s needs? Do you wish you could create content types on the fly by just
filling in a few fields? Try the Flexinode http://drupal.org/project/flexinode module. Once
installed, you can go to administer->content->content types and create custom content types. For
each content type, you can specify a set of fields that can be filled out by the content
contributors. Once you set up all the fields, you can easily add content by selecting the new
content type from the create content menu.

359
Drupal Handbook 3 Aug 2007

WYSIWIG EDITORS

Writing rich content in Drupal is sometimes a hassle. You either write the page in a separate
WYSIWIG editor and copy it into Drupal or code HTML in the tiny textarea. However, it is
possible to easily integrate one of the many inline
WYSIWIG editors into Drupal. You can choose from TinyMCE
http://drupal.org/project/tinymce, FCKEditor http://drupal.org/node/16118 and HTMLArea
http://drupal.org/project/htmlarea. Install one of these modules and within minutes, you can
create diverse content right from your browser.

ORGANIZE YOUR CONTENT

Is your content rampaging all over the place? Organize it and make it easy to locate. Drupal
ships with a power organization module called Taxonomy
http://drupal.org/handbook/modules/taxonomy. Taxonomy allows you to define sets of
categories called
"vocabularies". This makes it extremely easy to organize and group content and make your
website more navigable.

QUICK SUPPORT

Feeling a little lost? Need some quick support with Drupal? Get an IRC client and pop into
#drupal-support on irc.freenode.net. Someone could be there to help you out.

September 2005: Newest modules, Change any string,


Remote authentication, and tracking project issues
Get the newest modules -- fast!
This tip comes from kbahey: To view a list of newly released modules, use the URL:
http://drupal.org/taxonomy/term/14. This will show you the newest modules at the top of the
list!

Change any string


All strings in Drupal can be changed. Just switch on locale module, then under
admin/locale/language/add create a language, with a custom code and name. Now you can
manage strings under locale/string/search. "Untranslated" (in this case: unchanged) strings fall
back to English. Read the handbook page at http://drupal.org/node/24593 for more
information.

Remote authentication
If you want to use remote authentication against your site, then create a role with no
permissions and put a user under this role. So it’s nopermissionuser@my.drupal.site.

360
3 Aug 2007 Drupal Handbook

Keep tabs on project issues


This tip comes courtesy of sepeck: Want to keep up with changes to your favorite module?
Interested in chipping in your two cents about Drupal core development? Want to be pinged
back when someone responds to your specific issue? Check out the project subscribe options at:
http://drupal.org/project/issues/subscribe . Here you can choose selected projects (or all of
them, if you have lots of hard disk space to burn!) and receive e-mail about all issues, or only
your own issues.

Winter 2005/2006: Tracking projects with RSS and Module


Linking
Track activity and changes on your favorite projects with RSS
Contributed by Bèr Kessels

The CVS log is often underrated as a means of tracking what happens to


your favorite project.

Let us take as an example the project named "shazamgallery": Visit the link
http://drupal.org/cvs?file=/modules/shazamgallery/ to see the latest commits to that project.
The /modules/shazamgallery/ in the url can be replaced by anything of your interest. You can even
track changes to one file. For example,
http://drupal.org/cvs?file=/modules/shazamgallery/shazamgallery.mysql lets you track
changes to the database file only.

The most interesting part, however, is the RSS feed that comes with that
at http://drupal.org/cvs?rss=true&file=/modules/shazamgallery/

Use this to track your own contribs (to see if some other contributor
slips in features, or bugs, by accident). Or to track changes of the
projects you use on your drupal site.

Module Linking
Contributed by Heine Deelstra

When linking to a module-specific image or CSS file, do not use a hardcoded


modules/name.module/ path, because this will break in multisite installations, where modules can
be at site/sitename/modules/.

Use drupal_get_path(’module’, ’name’) instead.

Planning a web site


http://drupal.org/node/88594/

361
Drupal Handbook 3 Aug 2007

-->

Overview

While implementing a website planning is very important. I have learned this the hard way. I
wrote this document while planning my family website. This will be my second complete site
redesign for this site that has been up for about five years. Although this is a fairly simple site
the same planning process would apply to any site. The most important thing I have learned
was that the lack of planning in the first two attempts significantly limited the end site. Many of
the limitations, or headaches, could have easily been solved during the planning phase. I am not
a programmer although I manage eight production web sites from e-commerce to purely
informational to just for fun. Some of this may seem obvious to those with programming
experience but for the do it yourselfers I hope this will help get you started.

Requirements

Gathering requirements is key and really needs to be the first step in the Website
implementation process. If you are like me it is also the hardest to force myself to do. On my last
attempts once I had some idea about what I wanted I tried out a couple of CMSes and then
loaded one and started adding content. This time is different. One thing about the requirements
below to keep in mind is this is not a totally serial process. During each step I am continually
adding to each proceeding step. As I go through the process more and more things come to
mind.

The first thing I considered is: What will the website publish or do? For a store this might be
selling products, handling RMAs, selling advertising space, or hosting forums about your
products. You also need to think about things like: What languages will you site need to
support? Will it need to be able to handle transaction processing? Will it need to talk to other
sites? If it talks to other sites, what standards are out there that you will need to comply with?
Do you need to secure access? Basically anything else you can think of that is important to how
you want your site to function.

For my family site I came up with the following requirements: I need various people to be able
to publish content. We need to be able to publish pictures, videos, audio clips, wish lists, blogs,
and stories. We need a way to secure some of our content yet other content will be open to the
Internet. We need a shared calendar that allows for event scheduling. We would like a place to
document our genealogy. The site needs to be easy enough for my grandmother to use. None of
the users are programmers so it needs to be easily deployed with a minimum of coding. We
would like to easily change the look and the feel of the site during different seasons or whenever
we feel like it. There is no income so I need to keep the costs down. The content needs to be easy
to search. I need to be able to get the majority of the content out if I decide to restart again some
day. We would like the ability to be able to comment on content. We would like the ability to
have polls. We publish a bunch of pictures to it should be easy to publish pictures especially and
keep them very organized.

362
3 Aug 2007 Drupal Handbook

The second thing I consider is: Who will be using the website? It is best to break your users into
groups, even if a group will only have one person in it for now. This is especially important if
there is any possibility for growth. The user groupings should be broken into functional groups
that will change based on the site. For a store site you might have customers, site administrators,
vendors, and your accountant.

For my family site I am able to break the users into the following
groups:

Administrators â This group will have full control over


the site. They will be able to change site layout. They will have
control over user access controls.
Family members â This group will contribute content.
They will need to be able to update and upload content. Many of the
users are not technical.
Friends â This group will view all of the content but
will not contribute content.
Anonymous users â This group will be able to view some
of the content but not all. They will not need to be able to update
the content or provide comments.

The next thing I consider is: How will the content be accessed? What are some possible work
flows? For a store I might want to make sure that I can link to vendors. I would want to make
sure that vendors could update content but that I would have approval of any changes. I would
want to make sure that putting an item on sale is access controlled. I would want my highest
profit, best selling items right up front. I want to make sure a search works well enough to
return just a handful of items.

For my family site I want easy and simple entry of content and simple viewing of content. The
users inserting content are trusted so I would like for them to have options about where their
content is published. I would like the users to handle the content so that I don’t have to get
involved every time someone adds or changes something. Users should have a way to pull up
specific content easily. They should be able to sort by date, subject, category, and content type.
Our current site ended up with a huge amount of unorganized content. It was a great site for
current news or pictures but finding an old audio clip was next to impossible. It would be best if
all the content could be organized using the same organizational structure. Our current site we
ended up with a totally different sorting system and access method for each type of content
since we used somewhat unrelated modules. The new one I want people to be able to pull all
content types of a certain subject when they want to.

Based on what you are trying to do you could take this further but this was enough for me to use
as a base set of requirements.

Evaluating CMSes and Modules

363
Drupal Handbook 3 Aug 2007

Now that I have an idea of what I want the system to do it was time to start looking at the
options. Based on my budget and eagerness for a system that could be tailored to my needs GPL
was obvious. I looked into all the popular CMSes and some not so popular ones. When it came
down to it, for what I wanted Drupal was hands down the best choice. I could go through the
others ones but I will skip to what I liked about Drupal. I really like the everything is a node
idea. I also like the way taxonomy was implemented. From a work flow stand point those two
parts made Drupal stand out above the rest. Not knowing the system I assumed it might take me
a little more work to get it setup but in the end it would be a seamless website with the ability to
eventually, if not immediately, meet all of my requirements.

Once I picked Drupal I spent a bunch of time looking at modules. There seems to be at least one
module for everything I wanted that was not included in the base. I wrote down all of the
possibilities and worked out in my head how it would all come together. I won’t go through all
of the modules here but basically this step was just a bunch of reading.

Testing Drupal and modules

Next I went right to setting up the site. I installed the Drupal base and just started playing. While
I really like Drupal on virtual paper for me it was not final until I saw how it worked. I was
pleasantly surprised. It took me a little while to really get the whole picture but once I did it all
clicked. It was very slick and really was the seamless base I wanted.

I tried a ton of modules. Based on my requirements it was very important to me that everything
worked with the base in a productive way. I did not want to end up having to pull up a picture
in a different way than I had to pull up a video. I can’t say I have everything i want but you can’t
always get everything you want and I did get much closer than expected. I ended up with
image, image_pub, quotes, wishlist, video, and audio. I am still looking for a few odds and ends
but for the most part I was able to get all of these installed and working.

Once I had this worked out I started working on taxonomy. For me this was the most difficult to
decide and also the most important. Producing a ton of unusable content would have made the
rest of this useless. Drupal has a bunch of articles on taxonomy which helped a bunch. I tried on
paper a whole bunch of things and then would talk to he users. They would provide feedback
and I would take another stab. Some of the items listed below may not be considered taxonomy
because it is not set up as a category in Drupal but is already part of the system. Although this
might still change some currently we have the following vocabulary:

Subject â This would be the subject of the content. It


could be one of the children, a house, my truck, or a project. Every
node should have at least one subject and the ability to have
multiple subjects.
Subject Date â This will default to the submit date but
it can be changed since many times content is added that is older
media.
Type â This is the node type (image, video, story,
blog, ....

364
3 Aug 2007 Drupal Handbook

Submitter â This is who submitted the content.


Category â This is some more descriptive category
(funny, news, woodworking, taekwondo, ...). Basically I expect this
to grow as our hobbies change and develop but every node should have
at least one category and the ability to have multiples.
Submit Date â When the content was submitted.

After this, I put up a test site, got everything working, and had the real users have a go at it.
Although I knew a little they are really the only ones that can make it break and have to use it. I
administer the family site I rarely add any content. I will tell you that on first pass the site is
much better than I expected. We have along way to go for the perfect site but the combination of
Drupal and a good plan is a fantastic starting point.

Server tuning considerations


The performance of your Drupal site is dependent on three main factors: the goals of your site,
the resource demands of your site traffic, and the system performance and configuration of
underlying technologies.

Identifying Drupal performance goals


If the goals of your site are to have a speedy user experience, such as Google, then you should
focus on simplicity and ensure you have the resources to deliver pages in 1.5 seconds. If you
goal is to have an aesthesticly pleasing site then a rich theme with lots of interactive javascript
and longer load times might be acceptable. Either way you should begin with clear goals in
mind before tuning your site for performance because there are many permutations of
performance.

Analysing your site’s traffic and resource consumption


You wouldn’t use another system administrators underwear. Neither should you use their
performance configuration. Each site is unique and must be tailored to address your sites traffic
impact on four resources: bandwidth, CPU, memory, and disk input/output.

Profile your site’s performance loading: bandwidth, anonymous page views (general reads),
concurrent number of users (unique reads), concurrent number of user posts (writes) are all
important in building your sites profile.

Understanding and configuring your stack for performance


Configuring your server for performance falls outside the scope of the Drupal handbook and
you should reference authoritative sources for each component of your server hardware and
software stack. In many cases you will not have control of your hardware or the software
components you rely on. We provide a list of configurable options that other Drupal
administrators have found useful in tuning their sites for performance. It is possible to destroy

365
Drupal Handbook 3 Aug 2007

your site by configuring incorrectly. Be careful and back up configurations before making
changes.

1. Understanding LAMP performance. This LAMP performance study revealed that Apache is
bandwidth limited, PHP is CPU limited, and MySQL is memory limited and disk I/O
bound. Be sure to compile your stack natively for maximum performance. You can also read
Optimize high traffic servers.

2. Analyze your site’s performance bottlenecks: CPU, memory, bandwidth, input/output.


Once you have identified what is causing your system performance problems you can make
configuration changes or resource upgrades. Use top and ps for analysing processes that are
using up too much RAM or CPU. Netstat, mrtg/awstats, who’s online block will help for
identifying network problems.
top
ps -aux
netstat -anp | sort -u

If there are other applications running on your server such as (mail, ssh, anti-virus, spam
checking, web services, custom applications, etc) that are consuming contrained resources
you might need to move them to a new server.

3. Bad guests consuming too many resources: Crawlers, Aggregators, Spammers. Search
engines may crawl your site and cause a performance degradation, although if they crawl as
an anonymous user then they should recieved cached pages which consume less resources.
Slow down the robots crawling your site by adding a robots.txt line like this:
User-Agent: *
Crawl-Delay: 10
Disallow: /archive
Here 10 is the delay in seconds between page requests. Disallow robots from sections of
your site that do not need indexing. See Controlling what gets indexed -- the robots.txt file.

Some RSS clients are set to check for aggregator feed updates too frequently. Check your logs for
aggressive reads of feeds from a specific IP address. Spammers have many ways of consuming
your sites resources, be sure your site has a spam blocking strategy. Drupal 4.7 includes a check
to ensure that that forms originated on the site. This is to prevent spammers from creating large
amounts of comment and trackback spam remotely.

Apache performance Apache is usually bandwidth limited so you should be aware how
much bandwidth your server has access to. You can ask your hosting provider how much
bandwidth you have or you can use a tool like lperf. The mod_rewrite module for Apache
can consume resources if the directives are included in local directories through .htaccess
files. If you have control of the Apache configuration then these directives should be moved
to httpd.conf. You can also configure Apache to handle more connections with
MaxSpareServers, ServerLimit, MaxClients. CGI is slow. mod_php is popular and fast,
FastCGI is fast and secure. Read this tutorial on configuring Apache for Configuring
Apache for maximum performance.

366
3 Aug 2007 Drupal Handbook

PHP tuning: CPU consumption and optimizers:Use a PHP optimizer such the upcoming
Alternate PHP Cache, Zend Optimizer, eAccelarator a development of mmcache PHP. You
can also read Optimizing PHP.

MySQL performance tuning


Bandwidth: Images or media are likely to be the greatest source of bandwidth consumption
which with limit Apache’s performance. In order to ensure images are delivered quickly the
theme should explictly call the images directly to reduce the PHP overhead of looking for image
files. Details will be provided in the future.
Drupal resource consumption: Measuring modules memory usage, measure DB query
times, and duplicate queries for modules or pages with devel.module.

The number of modules enabled on your site may effect performance but should be
measured using the techniques outlined above. If the module has slow query times look at
tuning the tables with schema changes and using the the MySQL optimization tools, such as
ANALYSE and EXPLAIN. Other areas for analysis are theme resource consumption if you
theme has a lot of PHP calls.

There are several known performance issues in Drupal 4.6.5 including the URL alias table is
loaded into memory frequently and the use of Path and PathAuto modules will lead to an
increase in the number of aliases in the table (fixed in 4.7 and higher). Recent improvements to
session handling for anonymous users and a proposed file cache that bypasses Drupal’s page
loading mechansims offer significant performance improvements for anonymous users.

Configuring Drupal for performance: Cron jobs such as aggregating lots of feeds can be
resource intensive. If the cron jobs are set too frequently there can be a consistent drain on server
performance. Drupal has a cache that is very effective for pages served to anonymous users. It
can be found at administer >> settings
Server architectures for scalability and performance: separate web server and database
server, MySQL replication topologies, clustering servers.

This page was authored by Kieran Lal, from CivicSpace Labs. If you would like to
contribute or edit this page please contact me. If you would like to fund performance
improvements for Drupal please contact Kieran as well.

Enable default 404 handling for some file types


On high-traffic, multi-editor Drupal sites, there can be missing files related to page design.
An image gets renamed. A bot spams the site looking for a specific .cgi exploit. And so on.

By design, Drupal is defined as the 404 handler for all instances in the .htaccess file. That
code is:

# Customized error messages.


ErrorDocument 404 /index.php

367
Drupal Handbook 3 Aug 2007

Drupal (and other php-based CMS systems) do this so that index.php handles all URI
requests and can generate the right page.

The problem is that using Drupal as the 404 handler invokes a full bootstrap load for any
missing file.

Adding the following code to .htaccess eliminates some of this, by telling Apache to handle
certain types of 404 errors:

# This overrides the Drupal 404 handler for files that should never
be handled by Drupal
<FilesMatch "\.(gif|jpe?g|png|s?html|css|js|cgi)$">
ErrorDocument 404 default
</FilesMatch>

We also need to put a new line:

RewriteCond %{REQUEST_FILENAME} !\.(gif|jpe?g|s?html|css|js|cgi)$


Just before the line:
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

This elminates the following file types from invoking Drupal if a 404 is encountered:

- gif
- jpeg
- shtml and html
- css
- js
- cgi

Doing so avoiding invoking Drupal’s bootstrap in order to look for missing files. This
procedure minimizes database load and helps boost site performance.

-- WARNING --

There is a known issue that occurs if you block .png files with this method. It affects the
system_test() function in system.module, which relies on a phantom .png call to the directory
’/system/test/’.

If you block Drupal’s 404 handling for .png files and do not allow this exception, you lose
the ability to configure the site for clean_urls.

Simple Decision Tree for Drupal Enterprise Scalability


Contributed by Benson Wong on the developer’s email list.
February 2006

368
3 Aug 2007 Drupal Handbook

Here’s my scaling tree. As you progress up the tree, you will find that time, money,
maintenance, headaches will all increase.

1. Use a PHP cache:

I found that using APC speeds up Drupal by a lot, 3 to 5 times the pages view per second.
This was _literally_ a 5 minute install (on FreeBSD) for a 300% to 500% performance
improvement. I think at that point it was my dev servers SATA HDDs were the bottle neck. It
sits beside me and when I hit it with ab, I can hear the HDDs wrrrrr like crazy.

2. Use mod_gzip (or ob_compress or whatever it is in php, I prefer mod_gzip, or


mod_deflate in Apache2)

The benefits of this are amazing, considering the minimal effort it takes to implement. If
doesn’t matter if it takes Drupal 0.002 seconds to generate a 40K of html, if it takes like 1 to 2
seconds for a client to download it (more if using a modem). mod_gzip usually gives a 10% to
80% compression depending on the size of pages. Amazing results for 10 minutes of work.

3. Get a faster DB server. I’m thinking of 3x15K SCSI (raid 5), dual way xeon mysql server
from freebsdsystems.com for my next installation. These things rip . Expensive (~$5K to $7K)
but fast. An average Drupal dev charges like $100USD these days right? A super fast db server is
still more bang for your buck than 50 to 70hrs of code performance tuning.

4. Get faster (or more) Web Servers. Maybe not the same specs as above, but fast anyways.

5. Get a load balancer, or a reverse HTTP proxy (squid) to distribute the load

6. Do MySQL replication

7. Profile / tune Drupal’s code (shudder).

Slow contributed modules determined using the


developer module
If you have tested a module with the devel.module and run the memory tests highlight
above then please post the results. If you add performance results in the comments they will
grow.

Squid Caching
Squid is a fully-featured, open-source web-content caching system. In accelerator mode,
squid can be used in between your users and your web-server to cache objects and reduce
requests against your web server(s) and database server(s).

Usually, Drupal has very dynamic content (nodes gets comments and so on, the pages look
different from one user to the other) and it has its own cache so Squid caching Drupal content is
neither really desired nor really feasible. Drupal does supply the necessary headers which tells

369
Drupal Handbook 3 Aug 2007

Squid not to cache its pages. However, images and other static content can be cached by Squid
and usually it really helps.

For more information on setting up squid, please see http://www.squid-cache.org/.

Tools, tips, and links on optimizing mysql


Here are some basic, but high impact ways to optimize MySQL for Drupal (there are much
more sophisticated and expensive ways to speed up your database of course):

Am not sure if these tips do any good for someone on a shared hosting plan or not (do
shared plans have access to a my.cnf file?). Also, I can only confirm these setting for MySQL
4.0.2 thru the latest 4.0.x version, but I think it would work for 5.x (maybe someone can confirm
this and leave a comment...). Actually, it will work for below 4.0.2 I think as long as you add
set-variable = before each line (see this page for more on set-variable)

1. Get this script, upload it, unzip it, and install it in your /etc folder (at the root of your
server, not your Drupal install, right). Then run it from the command line by entering sh
/path-to-file/tuning-primer.sh

The script will run and what you’ll be left with is an output with some info and suggestions
about your MySQL settings. Was shocked to learned that on my VPS the cache was not even
enabled - very helpful to know!

2. Next open your my.conf file in pico or some kind of proper code/text editor:

Depending on the memory resources you have available you’ll want to paste in something
like these examples (adjust up or down depending on how your system differs, of course):

For a setup with 500mb or ram paste this in your my.cnf file:

[mysqld]
max_connections = 800
max_user_connections = 800
key_buffer = 36M
myisam_sort_buffer_size = 64M
join_buffer_size = 2M
read_buffer_size = 2M
sort_buffer_size = 3M
table_cache = 1024
thread_cache_size = 286
interactive_timeout = 25
wait_timeout = 1800
connect_timeout = 10
max_allowed_packet = 1M
max_connect_errors = 999999
query_cache_limit = 1M
query_cache_size = 16M

370
3 Aug 2007 Drupal Handbook

query_cache_type = 1
tmp_table_size = 16M

For a system with 256mb of ram:

[mysqld]
max_connections=500
max_user_connections = 500
key_buffer = 16M
myisam_sort_buffer_size = 32M
join_buffer_size = 1M
read_buffer_size = 1M
sort_buffer_size = 2M
table_cache = 1024
thread_cache_size = 286
interactive_timeout = 25
wait_timeout = 1000
connect_timeout = 10
max_allowed_packet = 1M
max_connect_errors = 999999
query_cache_limit = 1M
query_cache_size = 16M
query_cache_type = 1
tmp_table_size = 16M

3. Save your my.cnf file and restart mysql. This can be done via WHM or the command line
(not sure what that command is - sorry)

Your new settings are now active and you can see run the script from above again and see
the difference in your results. After some experiementing I’ve found that it is useful to look at
the script results right after making a change just to see if your modifications were recognized by
the system and get the early returns from whether things were improved or not - but - to get a
truly accurate reading from the script you should check back in 24-48 hours after rebooting
mysql (this is actually noted at the top of the script itself, but it doesn’t really explain why). Also,
I’ve found that the way I’ve got Drupal set up it is particularly demanding in the tmp_table_size
and table_cache areas (e.g., you may want to bump up the number for both of these areas in the
settings above)

If you’d like to read up on more about mysql tuning I suggest taking a look at these
resources:

Tuning MySQL for Drupal

Tuning a MySQL server in 5 minutes

MySQL variables

371
Drupal Handbook 3 Aug 2007

Tuning MySQL for Drupal


For a general overview read MySQL performance tuning.
Start with an appropriate MySQL option file. For servers with at least 2GB RAM
dedicated to MySQL we recommend my-huge.cnf. For servers, with a lot of writes we
recommend my-innodb.cnf instead of the default MyISAM engine type.
To reduce the overhead of creating connnections we recommend using persistent DB
connections.
If a query is called at least twice with no modifications to the queried tables a
significant performance improvement can be gained by avoiding the processing of the
query and the execution of the query by reading the query from the MySQL query
cache. To learn how to set up the query cache read a practical set-up.
Be sure to have enough cached threads or you will launch too many new threads as
described in this story about a Yahoo site.
The biggest performance boosts can come from identifying and tuning the slowest
queries using the MySQL slow query logs.
You can use the DB Maintenance module or use the mysqlcheck commands below in a
cronjob.
echo "OPTIMIZE TABLE
accesslog,cache,comments,node,users,watchdog;FLUSH TABLES;"
|mysql -u user -ppasswd
If you have complete control of the datbase server you can use:
mysqlcheck -o -A -p
MySQL supports many different engine types including MyISAM, InnoDB, and
Archive(MySQL 5). Performance sites should use InnoDB for most tables particularly
tables such as node that get a lot of writes and reads. MyISAM exclusive table locks for
updates before selects versus InnoDB’s row level locking can mean MyISAM blocks
reads if there are many writes. Convert from MyISAM to InnoDB.
In MySQL 5 a new table type called the archive table type was introduced to deal with
common requirements for web applications like access logs where only INSERTS and
SELECTS were done. If tables such as the Access Log table are determined to not have
DELETE, UPDATE, and REPLACE then this MySQL engine type can often offer
significant performance improvements as they have done for sites like Slashdot, Yahoo,
and Live Journal.
Read and use the PHP Page Snippet for MySQL Tuning

Tuning PHP
1. If you have CPU cycles to spare, or if bandwidth is a more constrained resource than
CPU cycles, you can add the following to php.ini:

output_handler = ob_gzhandler

A comment in php.ini explains:

372
3 Aug 2007 Drupal Handbook

"You can redirect all of the output of your scripts to a function. For example, if you
set output_handler to ’ob_gzhandler’, output will be transparently compressed for
browsers that support gzip or deflate encoding. Setting an output handler
automatically turns on output buffering."

This functionality is further described here.

very interesting presentation from a PHP developer

Additional resources:

PHP Project Page

Persistent database connections


Drupal uses pconnect() when connecting to the database for a slight performance
improvement if PHP is configured to allow pconnect.

But there are times when PHP should be configured to disallow persistent connections
to the database.

Each apache process can potentially obtain a persistent connection to each database the
server is hosting. If there are lots of apache processes and lots of databases it is common
to see the database throwing "too many connections" errors.

If this occurs there are a couple of options:

Increase the number of available connections the database will allow. If most
connections are idle most of the time, this is a viable solution.
Disable pconnect via the XXsql.allow_persistent = Off attribute in your
php.ini. The performance hit from this setting is very slight.

PHP caches
PHP is a scripting language. Each time a PHP script is run to generate a webpage with
Drupal, your web server must compile the PHP script into an executable format. This
results in an obvious amount of overhead each time a page is generated.

A PHP cache can be installed to save and re-use compiled PHP scripts, thus greatly
reducing the amount of overhead required for Drupal to display a web page.

There are a number of PHP caches (aka accelerators) available, including:

PHP Accelerator
After Burner
Zend Accelerator

373
Drupal Handbook 3 Aug 2007

APC : Alternative PHP Cache

APC is a free and open PHP op-code cache that can significantly speed up PHP
applications in certain cases.

Here are instructions on how to install PHP APC on Ubuntu Dapper (and Debian?)

eAccelerator

From what I can tell eAccelerator is the best free php accelerator.

Here are my notes on how to set the control variables (in php.ini):

;linux 2.6 has 32meg limit. If you have the memory and lots of modules try to set even
higher e.g to 64
eaccelerator.shm_size="32"

; people have suggested that putting this directory on a fast separate disk will help
; you shouldn’t be generating that much activity on this disk anyway because of the
shared memory configured above
eaccelerator.cache_dir="/Applications/MAMP/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"

; You can set this to 0 for production sites. 1 means checks modification times so you
don’t need to restart web server
; if you are editing your php. You aren’t editing php scripts on live sites are you?
eaccelerator.check_mtime="1"

eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="3600"
eaccelerator.shm_prune_period="0"

; set this to 1 if you want to just use the memory cache: good if you have configured a
large one
eaccelerator.shm_only="0"

eaccelerator.compress="1"
eaccelerator.compress_level="9"

Turck MMCache

The Turck MMCache has been confirmed to work well with Drupal. Installation is quite
simple, resulting in a quick and noticeable performance increase.

374
3 Aug 2007 Drupal Handbook

Overview:
According to the project’s home page:

"Turck MMCache is a free open source PHP accelerator, optimizer, encoder and
dynamic content cache for PHP. It increases performance of PHP scripts by caching
them in compiled state, so that the overhead of compiling is almost completely
eliminated. Also it uses some optimizations to speed up execution of PHP scripts.
Turck MMCache typically reduces server load and increases the speed of your
PHP code by 1-10 times."

Compatibility:
The Turck MMCache runs on Linux and Windows, working with Apache 1.3 and
Apache 2.0, compatible with PHP 4.1 and later.

The following versions of MMCache have been tested successfully with Drupal 4.1+:
2.3.15, 2.3.23, 2.4.6.

Installation:
Step-by-step installation instructions can be found here. Once properly installed, you
should immediately notice an improvement.

CPU Utilization:
The sar utility from the sysstat collection gathers system activity numbers over time.
The following sar snapshot taken from a dedicated Drupal server shows how the
installation of MMCache can help reduce system load on even a heavily-optimized web
server (MMCache was installed around 12:00PM):

11:00:00 AM CPU %user %nice %system


%idle
11:10:00 AM all 3.71 0.00 1.85
94.44
11:20:00 AM all 3.86 0.00 0.50
95.64
11:30:00 AM all 4.49 0.00 0.33
95.18
11:40:00 AM all 4.05 0.00 0.36
95.58
11:50:00 AM all 3.76 0.00 0.36
95.88
12:00:00 PM all 3.38 0.00 0.52
96.11
12:10:00 PM all 0.52 0.00 0.10
99.38
12:20:00 PM all 0.79 0.00 0.20
99.01
12:30:00 PM all 0.57 0.00 0.12
99.31
12:40:00 PM all 0.59 0.00 0.12

375
Drupal Handbook 3 Aug 2007

99.29
12:50:00 PM all 0.44 0.00 0.11
99.45

Troubleshooting:
An easy way to tell if MMCache is working properly after following the installation
instructions is to see if temporary files are being created in ’/tmp/mmcache’, or wherever you
told them to be written with the ’mmcache.cache_dir’ directive. If no files are appearing,
something is wrong.

First, be sure that PHP has properly loaded mmcache. Create a short script on your web
browser called ’phpinfo.php’ as follows:

<?php
phpinfo();
?>
Load that file in your browser to find a wealth of useful information. Search for any
occurances of the word ’MMCache’. If it’s not there, then MMCache is not loaded. Double check
your ’Configuration File (php.ini) Path’ on that same page, and be sure that you modified the
correct ’php.ini’ file. Verify that you installed ’mmcache.so’ into the directory specified by the
’extension_dir’ directive. Also, try restarting your web browser to be sure the latest
configuration changes have been made. Finally, be sure to look in your web server’s error log to
see if there are any hints there. (Note that the phpinfo() function call reveals a _lot_ of
information about your system. For security reasons it is very unwise to make this information
available to the general public. If you created ’phpinfo.php’ in a public place, be sure to remove
it when you’re finished troubleshooting.)

Additional resources:

Turck MMCache Home Page

Useful article on optimizing PHP


A HOWTO on Optimizing PHP was initially pointed out in this forum topic. The article
describes how to optimize PHP in a variety of settings. It also includes a nice discussion on
caching.

For people who are setting up servers, or who are interested in learning more about how
Drupal can run more efficiently, this article is a good read.

Tuning Drupal on OS X Tiger


Using the devel module (http://drupal.org/node/31553) I discovered that the default
mysql configuration parameters were slowing drupal down.
To see where your mysql is installed type at the command line:
which mysql
The selection of configuration files are in share /mysql; or if you followed the above
instructions for installing MySQL, it should be in /usr/local/mysql/support-files.

376
3 Aug 2007 Drupal Handbook

The configuration file is in etc/mysql4; or if you followed the above instructions for
installing MySQL, it should go in /usr/local/mysql but is not there by default. You can put it
there by copying it in:
sudo cp /usr/local/mysql/support-files/my.large.cnf
/usr/local/mysql/my.cnf.
Restart MySQL for the new settings to take effect.

To view the current variable settings for MySQL, from the terminal command line client
type: mysqladmin -uroot -p variablesI opted for the "my.large.cnf" settings and
halved the sql query times.

You can monitor MySQL through a pleasant user interface using MySQL Administrator,
though it seems to expect my.cnf at /etc/my.cnf (it will still work, you just can’t view the conf
file).

I also discovered that I could roughly halve page load times by using Apache 2 instead of
the stock Apache on Tiger.httpd -v to see what version you are running. I downloaded
the php and Apache 2 from ServerLogistics: http://serverlogistics.com/downloads.php.

I am not sure I can recommend this for production sites as I do see some error diagnostics I
haven’t resolved yet. I didn’t expect such a big difference with Apache2. Measurements with a
system call profiler show that it does about half the read(2) system calls as Apache 1.3.

The overall impression I have from my benchmarking is that drupal pages require a lot of
disk I/O to synthesize. Anything you can do to speed up or miminize (e.g. caching) is going to
help. MySQL already has plenty of caching if a my.cnf files is being used. For the Apache/PHP
part busy sites will need a php accelerator.

377
Drupal Handbook 3 Aug 2007

Upgrading from previous versions


This chapter contains articles that discuss the upgrading process of your drupal installation.

Please note that comments are not meant to address problems you found during installation. For
problems with installation, please address your questions at proper places. Note that Drupal
versions prior to 4.6.3 are now known to have security vulnerabilities and therefore you should
upgrade to the latest version of Drupal. After upgrading Drupal core you might need to convert
custom modules and convert custom themes.

NOTE: One of the most IMPORTANT things to do BEFORE you upgrade, is to backup your
sites files and database. See this node for an example of an automated backup script.

Introduction to upgrading
Every few months, a new version of Drupal is released. In order to fix security issues and take
advantage of many new features, upgrading your Drupal site to the latest version is
recommended. Upgrading your Drupal site involves three basic steps:

1. Back up your existing site and database.


2. Download and unzip the new Drupal files to your server.
3. Run the update.php script, which will update your database.

However, to make your update run as smoothly as possible, there are various preparations that
experienced Drupal users do to guarantee the least frustrating upgrade and minimal
interruption to their users. These best practices are represented in this full tutorial along with the
basic steps.

NOTE: You should check to see if the contributed modules you rely on have been upgraded as
well. Old versions of modules will not run on an upgraded version of Drupal (e.g 4.7 modules
do not work on a Drupal 5.x site).

Getting started: Choosing your method and preparing the


site
Before you begin the actual upgrade, determine which interface methods are available for you to
use to update your site. The server you use to host your site may limit you to one of the
following options:

Command line. Via SSH terminal access, you can connect to the server, enter commands
directly, and complete all the steps in the upgrade.
GUI. You can use phpMyAdmin, a browser-based MySql interface, to do anything you
need on your database. And you can use any FTP client, such as SmartFTP, to transfer the
files for your Drupal site from your desktop to the server.

378
3 Aug 2007 Drupal Handbook

Once you have determined whether you will use the GUI or command-line version (or a bit of
both), you’re ready to prepare to upgrade by following the instructions given in the links below.

Preparing the site


Complete the following steps to prepare your site for upgrading:

Login as USER 1, the root user, the very first account created when Drupal was installed. If
you cannot login as the root user, you will need to modify the update.php script once you
load the new files for your site.
Turn off all modules that are not core modules:
administer >> modules
Also, switch your theme back to the default theme (’BlueMarine’ in 4.7 and lower, ’Garland’
in 5.x):
administer >> themes

Do I need to upgrade my database?


After uploading the new files, visit http://example.com/update.php, read and act upon the
instructions, then click through to "run the database upgrade script". You may expand the
"Select version" fieldset to review the updates Drupal automatically selected or simply click
update.

Drupal 5 and later will also alert you to run update.php if it is detected that your database is no
longer up to date. The alert will appear on the Administration page (admin) and the status
report (admin/logs/status).

Important! : Backing up the database and existing files


Please back up the existing files and database for your site before you begin the rest of the
upgrade process. Even if you have determined that you may not need to upgrade the database,
it doesn’t hurt to make a backup. If the upgrade process fails, you may not be able to resurrect
your site without the use of backups.

Choose either the GUI or command-line method for backing up your site.

Backing up your site (GUI)


Backup your Drupal files
Using your FTP client, download all your existing Drupal files to your hard drive and put the
files in a folder called ’backup’.

Backup your database with phpMyAdmin

Select your database from the dropdown box on the left


If you are upgrading a test site, choose your test site database.

379
Drupal Handbook 3 Aug 2007

Click the "Export" tab


Click "select all"
Make sure to check the "structure" and "data" checkboxes
Check "Save as File" desktop
Click the "Go" button and save the .sql file to your desktop. Let’s put it in the same ’backup’
folder where you backed up your Drupal files.

Back up your site (command line)


Back up your Drupal files
Copy the contents of your Drupal directory to a new directory called "backup"

cp -r . backup/.

Where the directory ’drupal_site’ is a the path to your live site. If you are upgrading a test site,
this would be your test site directory. Go ahead and back up your test site files to a new
directory.

Make sure the .htaccess file gets copied to the ’backup’ directory as well.

Back up your Drupal database with MySQL


Before you begin, it’s best to turn off all automated jobs (cron jobs).

a) Navigate to your live site directory, and download a special script to your Drupal site folder
which will backup your database to a file called ’backup.sql’. Put the backup in your ’backup’
directory.

cd drupal_site/
wget
http://cvs.drupal.org/viewcvs/*checkout*/drupal/contributions/sandbox/dr...
chmod +x drupalsqldump.sh

If you are upgrading a test site, the path ’drupal_site’ would be the path to your test site.

b) The following command will look at your Drupal settings file, automatically connect to the
database, and make a backup of it.

If you are running a version of Drupal that is 4.6 or newer, then enter the following:

./drupalsqldump.sh sites/default/settings.php > backup/backup.sql

If you are running a version of Drupal 4.5 or older, run the following:

./drupalsqldump.sh includes/conf.php > backup/backup.sql

380
3 Aug 2007 Drupal Handbook

If you are upgrading a test site, the path ’drupal_site’ would be the path to your test site.

Remember where you saved this backup.sql in case there is an error during the upgrade.

Create a test site first or upgrade your existing site?


It is recommended that you copy your existing site to a test site and upgrade that one first. Even
though you have made backups and can restore your site, you don’t want your live site (the one
people are actively visiting) to crash and burn if something bad happens during the upgrade.

Copying your Drupal installation to a test site takes a few steps:

Make a backup of your existing Drupal files and database


Copy the files to a test-site subfolder on your server
Copy your old database to a test-site database
Change some configuration settings

If you choose not to create a test site, skip forward to Downloading Drupal and installing the
files. Otherwise, choose either the GUI or command line method for Copying your live site to a
test site.

Copy your live site to a test site (GUI)


Before you begin, decide where the new installation will be located. Usually you can just install
Drupal to a subdirectory: example.com/test_site/.

Make sure you have already completed the steps for backing up your site.

I. Setup a test-site database with phpMyAdmin

Create a new database "test_site_db"


Select the database from the dropdown box on the left
Click the "SQL" tab
Upload the backed-up SQL script file you just saved by clicking the "Browse" button and
selecting it. It should have the extension .sql.
Hit the "GO" button to upload the .sql script and execute it

II. Change settings.php (or includes/conf.php) in your backed-up Drupal files.


Open and edit the file located under sites/default/settings.php (or includes/conf.php) with a
plain text editor such as jEdit. Follow the directions in the file and modify these three settings:

$db_url = mysql://user:pass@localhost/test_site_db’;

(test-site database login & password, URL location of the test-site database. "localhost" usually
works by default.)

381
Drupal Handbook 3 Aug 2007

$base_url = ’http://www.example.com/test_site’;

(This is where you want to move Drupal. You can install Drupal to a subdirectory such as
http://www.example.com/test-site. This is what we want.)

$db_prefix = ’’;

(Sometimes your database tables will have a prefix. Ask your webhosting company for help if you
think this is causing a problem. Otherwise leave it blank.

II. Upload the backed-up Drupal files to a test-site folder on your server

First, create the subfolder "test_site" first. Right-click in SmartFTP and click
"New"...."Folder". Other FTP clients may have slightly different methods.
Using an FTP client such as SmartFTP, upload all the backed-up Drupal files to the
directory:

http://www.example.com/test_site

In FTP world this is usually seen as public_html/test_site" or "www/test_site".

IV. Check if your test site works.


Navigate to http://www.example.com/test_site and you should see a working copy of your
live site.

V. Get ready for the basic steps.The basic steps will repeat some of the work you just did such
as backing up your live site and database. You can skip those steps in the basic steps
instructions.

Copying your live site to a test site (command line)


Before you begin, decide where the new installation will be located. Usually you can just install
Drupal to a subdirectory: http://www.example.com/test_site/.

Make sure you have already completed the steps for backing up your database.

I. Copy your live site files to a test site directory.


Copy the contents of your live site directory to a new directory called "test_site"

cp -R /path/to/drupal/path/to/drupal_backup

Make sure the .htaccess file gets copied to the test_site directory as well.

II. Setup a blank test-site database with MySQL


a) Create a new, blank MySQL database (login to MySQL) and give permissions for a user to
access it:

382
3 Aug 2007 Drupal Handbook

mysqladmin -u dba_user -p create test_site_database

(Where ’dba_user’ is an example MySQL user which has the CREATE and GRANT privileges.
Use the appropriate user name for your system.)

b) MySQL will prompt for the ’dba_user’ database password and then create a blank test_site
database. Next you must login and set the access database permissions:

mysql -u dba_user -p

c) Again, you will be asked for the ’dba_user’ database password. At the MySQL prompt, enter
following command:

GRANT ALL PRIVILEGES ON test_site_database.* TO nobody@localhost


IDENTIFIED BY ’password’;

where ’test_site_database’ is the name of your database ’nobody@localhost’ is the username of


your webserver MySQL account ’password’ is the password required to log in as the MySQL
user.

d) To activate the new permissions you must enter the command:

flush privileges;

and then enter ’\q’ to exit MySQL.

III. Change settings.php (or includes/conf.php) in your test_site directory


a) Open and edit the file located under sites/default/settings.php (or includes/conf.php) with
an editor. Follow the directions in the file and modify these three settings:

$db_url = ’mysql://user:pass@localhost/testsite_db’;

(test-site database login & password, URL location of the test-site database. "localhost"
usually works by default.)

$db_prefix = ’’;

(Sometimes your database tables will have a prefix. Ask your webhosting company for help if you
think this is causing a problem. Otherwise leave it blank.)

$base_url = ’http://www.example.com/test_site’;

(This is where you want to move Drupal. You can install Drupal to a subdirectory such as
http://www.example.com/test_site. This is what we want.)

IV. Insert the backup.sql file into the test_site database Now that you have a new blank
test_site database, you must take the backup.sql file created by the live site database and run it.
This will create a copy of the live site database on the new test site database.

383
Drupal Handbook 3 Aug 2007

a) Change to the test_site directory.

cd test_site

b) Get the database insertion script, and set permissions on the script. You database may a limit
on the size of file it can import. Use the --max_allowed_packet option for mysql to increase the
size of db import.

wget ’http://civicspacelabs.org/home/files/drupalsql’ -O drupalsql.sh


chmod +x drupalsql.sh

c) Now execute the script which will create all the Drupal tables needed on the test_site
database:

If you are running a version of Drupal 4.6 or newer, then enter the following:

./drupalsql.sh test_site/sites/default/settings.php <


/path/to/backup.sql

If you are running a version of Drupal 4.5 and older, run the following:

./drupalsql.sh test_site/includes/conf.php < /path/to/backup.sql

V. Check if your test site works


Navigate to http://www.example.com/test_site and you should see a working copy of your
live site.

Downloading Drupal and installing the files


Choose either the GUI or command line method for downloading and installing the files.

If you setup a test site, you are going to be updating it instead of your existing, live site.

Downloading Drupal and installing the files (GUI)


I. Download and unzip (using unzipping software such as WinZip) the latest Drupal release
to your desktop

II. Move your old Drupal files


You made a backup, right? Using your FTP client, move all your old Drupal files on your server
to backup directory. If you are upgrading a test site, move your test site files. It is considered
best practice to remove the old files completely rather than overwriting to ensure you have a
clean installation of the new files.

III. Upload the new version of Drupal


Using your FTP client, upload the new version of Drupal to the same place where your old files
were located. If you are upgrading a test site, upload the files to your test site directory.

384
3 Aug 2007 Drupal Handbook

Make sure your files directory is writable.

IV. Upload contributed modules


Again with your FTP client, upload the new version of all your contributed modules. Make sure
you have the version of the module which matches your new Drupal version.

V. Copy over necessary files from the ’backup’ copy directory


Using your FTP client, copy the following files from your ’backup’ directory to the Drupal
directory on your server:

.htaccess
sites/default/settings.php (*** see note below!)
the ’files’ directory
any other files you need from the ’backup’ directory

*** If you are upgrading from a version of Drupal that is older than Drupal 4.5, you will have to
look in your ’backup’ directory for a file called:

<strong>includes/conf.php</strong>

Then using a plain text editor such as jEdit, copy the following three lines as they appear in your
conf.php file:

<strong>$db_url = mysql://user:pass@localhost/drupal_db’;
$base_url = ’http://www.example.com’;
$db_prefix = ’’;</strong>

And paste them over the appropriate lines in your new Drupal file on your server, located here:

<strong>sites/default/settings.php</strong>

It’s simply a matter of overwriting the above three lines in settings.php with the lines in
conf.php.

These settings are responsible for connecting your Drupal to the database and to the files it
needs. The file name and location was changed from Drupal 4.5 to 4.6, hence the magical dance
involved.

Downloading Drupal and installing the files (command line)


I. Replace your Drupal files

1. Navigate to your Drupal directory and move all the old files using the standard Unix ’mv’
command. If you are upgrading a test site, this means move all the test site files. Move these
to a backup directory.
2. Download and untar the new Drupal files to your Drupal directory:
cd drupal_site/
wget

385
Drupal Handbook 3 Aug 2007

http://ftp.osuosl.org/pub/drupal/files/projects/drupal-4.7.3.tar.gz
tar -xzvpf drupal-4.7.3.tar.gz

If you are upgrading a test site, the path ’drupal_site’ would be the path to your test site.

II. Copy over necessary files from the ’backup’ directory


Copy over the following files from the ’backup’ directory to your Drupal site directory:

.htaccess
sites/default/settings.php (*** see note below!)
the ’files’ directory
any other files you need from the ’backup’ directory

*** If you are upgrading from a version of Drupal that is older than Drupal 4.5 , then you will
have to look in your ’backup’ directory for a file called:

includes/conf.php

Then using your favorite text editor, copy the following three lines as they appear in your
conf.php file:

$db_url = mysql://user:pass@localhost/drupal_db’;
$base_url = ’http://www.example.com’;
$db_prefix = ’’;

And paste them over the lines in your new Drupal file located here:

sites/default/settings.php

It’s simply a matter of overwriting the above three lines in settings.php with the lines in
conf.php.
These settings are responsible for connecting your Drapal to the database and to the files it
needs. The file name and location was changed from Drupal 4.5 to 4.6, hence the need to move
these lines to the new file.

Running update.php
If you have previously determined that you do not need to update your database, you may skip
the following step. However, it does not hurt to run the update.php script just to verify whether
or not a database update is necessary. Just make sure that you have made a backup of your
database first.

If you setup a test site, you are going to be running update.php on it instead of your existing,
live site.

I. Did you login as USER 1?


Previously, you were asked to login as USER 1, the root user, the first user created on your
Drupal site. If you were not able to do so, you will need to edit the update.php script in a text

386
3 Aug 2007 Drupal Handbook

editor. Otherwise, you will not be permitted to update the database. Change TRUE to FALSE for
the $access_check statement like so:

$access_check = FALSE;

After you complete the upgrade, be sure to CHANGE the update.php file BACK TO IT’s
ORIGINAL STATE if you have made this change. Otherwise, anyone would be able to run the
update.php file on your site.

II. Run update.php


In your web browser navigate to the directory where Drupal is installed:

http://www.example.com/update.php
or
http://www.example.com/test_site/update.php (if you are upgrading a
test site)

The update script should only be run once, it will complete all the updates at once. If prompted
for which version, choose the closest starting version that makes sense for you.

This will update the default Drupal and contributed module database tables automatically
(versions prior to 4.7 will require manual upgrade of the contributed modules). Once the script
has stopped loading, be sure to scroll to the bottom to look for errors.

Optional configuration steps


I. Review unique steps for your site
Your site is unique like you. You might have special files or a special configuration. During your
site upgrade it’s important to keep notes about any special changes you made. More often then
not when people have problems, it’s because they forgot some special steps that are unique to
their site. Keep track of these steps on a change board, which you can use in future upgrades.

II. Get additional features(modules)


Drupal comes with many features but your site may have special needs. You can get additional
modules from the Drupal modules page. You must know which Drupal modules are compatible
with your site (e.g. use the 4.7 version of a module with Drupal 4.7.x.) In Drupal 4.7 and greater
your contributed modules will upgrade automatically with the core Drupal upgrade as long as
you have the new version uploaded to the site before running update.php.

III. Convert your custom modules to the new version


You may have custom modules on your site. If you need to learn how to upgrade your modules
you can learn about in the upgrading section of the Drupal developer’s handbook.

IV. Manually configure special steps for your database


The update script is designed to automatically upgrade your database. However, from time to
time there are steps which could not be automated. These steps appear as commands at the
bottom of your update.php report. There may also be special steps which are recommended or
where found too late to be fixed by the update script.

387
Drupal Handbook 3 Aug 2007

If you are moving from Drupal 4.4 to Drupal 4.5 then you need to change the path table to
replace node/view/number and book/view/number to node/number. Users path changed
from /user/view/number to /user/number. You should also enable legacy module to do
handle URL requests of the old type.

We recommend you upgrade to the latest release which takes care of all known database issues
at this time.

Post-upgrade steps
Congratulations! You have completely upgraded your Drupal installation.

You should now go to your adminster >> modules page and enable new modules from your
upgrade. Be sure to then go to adminster >> access to get enable permissions to use that module
for different roles. Make sure anonymous users don’t have too many permissions.

The last step in an upgrade is to delete or move the following files from your site:

install.php
update.php
CHANGELOG.txt
INSTALL.txt
LICENSE.txt
MAINTAINERS.txt
UPGRADE.txt

If you have upgraded a test site and are satisfied with the results, you will now need to copy the
test site to a live site.

If you have more questions, please consult the Troubleshooting FAQ guide and please don’t
hesitate to Ask for Help in the Forums.

Testing Your Newly Upgraded Site


Once your upgrade is complete, it is important to test your site for functionality and for
potential problems visitors to your site may see.

I. Test your new version of Drupal


You should test your site to make sure it works. We recommend that you try the most common
tasks your users do on the site. A good way to to see what your users like to do on your site is to
review your site administration logs at
administer >> logs.

For a more thorough review we recommend you review the administration help in your site at
administer >> help. Each page of help documentation has links to the most important pages for
each module.

388
3 Aug 2007 Drupal Handbook

II. Prevent file not found errors


After you upgrade your site you should check your site for bad links, to prevent the file not
found errors. The http error number for these pages is 404. You can use a simple tool to check
the links on your site. You will see errors in you Drupal Administrator logs as well as your web
server error logs. Perform the following commands through the administrator menu on your
site:

Enable contributed image module


administer >> modules
Set permissions so images can be written for userid running link check.
administer >> access control
Enable the menu module
administer >> modules
Disable the logout menu
administer >> menus

From a command line on a computer connected to the Internet run wget with the following
options:

The cookie this command is referring to is the cookie downloaded from your browser when you
last logged into your Drupal site as an admin.

wget -r --delete-after --cookies=off --header=’Cookie: PHPSESSID=xxx’


http://yoursite.com

-r to recursively crawl the site. --delete-after, --cookies=off tells the crawler not to use a cookie.
--header=’Cookie: PHPSESSID=XXXX’ tells the Drupal site that session information will be
passed in the http header. This should be repeated 2 more times; once for a regular userid, and
once for an anonymous userid. After the link check is done check your Drupal admin logs and
your webserver error logs. Look in your browser preferences to see what cookies you have for
your url.

III. Invite users to test


Your users are your best source of feedback. They will tell you quickly which parts of your site
are not working like they expect them to. Send an email informing users that your test site is
available for them and instruct them how to give feedback. You may wish to install the feedback
module to assist with user feedback.

Copy your test site to a live site


For those that created a test site, there is one additional step in the process. Now that you have
successfully completed upgrading your test site, it is time to copy your test site to your live site.

Moving your Drupal Installation takes a few steps:

389
Drupal Handbook 3 Aug 2007

Make a backup of your test site files


Copy the test site files to your root directory on your server
Change some configuration settings

Choose either the GUI or command line method below.

Copying your test site to your live site (command line)


TIP: Make sure your test site is a recent copy of your live site, otherwise you will lose changes. It might be
a good idea to create a new test site if it has been a while.

I. Backup Your Drupal Files


Copy the contents of your live site directory to a ’backup’ directory, in case something goes
wrong.

cp live_site/.htaccess backup/.

Make sure the .htaccess file gets copied to the ’backup’ directory as well.

II. Copy your test site files to your live site directory

1. Delete all your live site files with the Unix ’rm’ command. You made a backup, right?
2. Copy the contents of your test site directory to your live site directory

cp test_site/.htaccess live_site/.

Make sure the .htaccess file gets copied to the test_site directory as well.

III. Change settings.php in your live site Drupal files


Open and edit the file located under live_site/sites/default/settings.php with a plain text editor
such as jEdit. Follow the directions in the file and modify this setting:

$base_url = ’http://www.example.com/’;

(This is the address of your live site directory. This tells Drupal where to look for the Drupal files to
connect with.)

There is no need to change the database settings. Just take note that your test site database is now
being used as the live site database.

IV. Check if your live site works


Navigate to http://www.example.com/ and you should see your newly upgraded live site.

Copy your test site to a live site (GUI)


TIP: Make sure your test site is a recent copy of your live site, otherwise you will lose changes. It might be
a good idea to create a new test site if it has been a while.

390
3 Aug 2007 Drupal Handbook

I. Backup Your Test Site Files


Using an FTP client such as SmartFTP, download all your existing test site files to your hard
drive. The especially important files to keep track of are settings.php, and .htaccess.

II. Change settings.php in your test site Drupal files


Open and edit the file located under sites/default/settings.php (or includes/conf.php) with a
plain text editor such as jEdit. Follow the directions in the file and modify this setting:

$base_url = ’http://www.example.com/’;

(This is the address where you will upload your live site directory. This tells Drupal where to look for the
Drupal files to connect with.)

There is no need to change the database settings. Just take note that your test site database is now
being used as the live site database.

III. Upload the test site Drupal files to your live site directory
Using an FTP client such as SmartFTP,

1. Download all your live site files to a backup folder on your desktop.
2. Delete all your live site files on your server. You made a backup, right?
3. Upload all the test site files to the directory:
http://www.example.com/

In FTP world this is usually seen as "public_html/" or "www/".

IV. Check if your test site works


Navigate to http://www.example.com/ and you should see your newly upgraded Drupal site.

Differences from 4.7 to 5.x


This section will be the central location for noting differences between 4.7 and 5.x and items to
consider when upgrading or switching versions. Please click the "add child page" link below to
add anything you consider significantly different between these versions.

Important note on upgrading from 4.7 to 5.1


As noted in this comment:

"DO NOT attempt to go from 4.7.6 to 5.1 direct. You MUST upgrade to 5.0 first, else update.php will
fail. there are database changes at 5.0 and 5.1 and they need to be done in sequence. this useful fact is not
documented anywhere but it is hinted at here http://drupal.org/drupal-5.1

391
Drupal Handbook 3 Aug 2007

Important note on upgrading from 4.7 to 5.1


As noted in this comment:

"DO NOT attempt to go from 4.7.6 to 5.1 direct. You MUST upgrade to 5.0 first, else update.php will
fail. there are database changes at 5.0 and 5.1 and they need to be done in sequence. this useful fact is not
documented anywhere but it is hinted at here http://drupal.org/drupal-5.1

Version specific upgrades


People have contributed version specifc upgrade instructions over time and you can find them
here. The general instructions and pattern of upgrade has remained fairly similier across many
Drupal versions.

See the Introduction to upgrading for more generic information.

Upgrading from Drupal 4.4 to 4.5


If you upgrade from Drupal 4.4.x, you will need to create the users_roles and
locales_meta tables manually before upgrading. To create these tables, issue the following
SQL commands:

MySQL specific example:

CREATE TABLE users_roles (


uid int(10) unsigned NOT NULL default ’0’,
rid int(10) unsigned NOT NULL default ’0’,
PRIMARY KEY (uid, rid)
);
CREATE TABLE locales_meta (
locale varchar(12) NOT NULL default ’’,
name varchar(64) NOT NULL default ’’,
enabled int(2) NOT NULL default ’0’,
isdefault int(2) NOT NULL default ’0’,
plurals int(1) NOT NULL default ’0’,
formula varchar(128) NOT NULL default ’’,
PRIMARY KEY (locale)
);

PostgreSQL specific example:

CREATE TABLE users_roles (


uid integer NOT NULL default ’0’,
rid integer NOT NULL default ’0’,
PRIMARY KEY (uid, rid)

392
3 Aug 2007 Drupal Handbook

);
CREATE TABLE locales_meta (
locale varchar(12) NOT NULL default ’’,
name varchar(64) NOT NULL default ’’,
enabled int4 NOT NULL default ’0’,
isdefault int4 NOT NULL default ’0’,
plurals int4 NOT NULL default ’0’,
formula varchar(128) NOT NULL default ’’,
PRIMARY KEY (locale)
);

Note from comments:


For upgrading from 4.4 to 4.5 you need to run extra SQL stuff.
If your phpwebdmin broken, you can use this small php script to do the update.

<?php
// Connecting, selecting database
$link = mysql_connect(’host’, ’dbuname’, ’dbpw’)
or die(’Could not connect: ’ . mysql_error());
echo ’Connected successfully’;
mysql_select_db(’dbname’) or die(’Could not select database’);
// Performing SQL query
$query = "CREATE TABLE users_roles (uid int(10) unsigned NOT NULL
default ’0’, rid int(10) unsigned NOT NULL default ’0’,PRIMARY KEY
(uid, rid))";
$result = mysql_query($query) or die(’Query failed: ’ . mysql_error());
$query = "CREATE TABLE locales_meta (locale varchar(12) NOT NULL
default ’’,name varchar(64) NOT NULL default ’’,enabled int(2) NOT NULL
default ’0’,isdefault int(2) NOT NULL default ’0’,plurals int(1) NOT
NULL default ’0’,formula varchar(128) NOT NULL default ’’,PRIMARY KEY
(locale))";
$result = mysql_query($query) or die(’Query failed: ’ . mysql_error());
// Closing connection
mysql_close($link);
?>

Upgrading from Drupal 4.5 to 4.6.3


The following is a simple step-by-step approach to upgrade a site from Drupal 4.5 to Drupal
4.6.3.

It takes about an hour and a half to complete and it is important to follow each step carefully to
avoid glitches or gremlins appearing at a later stage.

393
Drupal Handbook 3 Aug 2007

Before you Start


If you are using any of these modules in your Drupal 4.5 site that you plan to upgrade, please
read the notes at the bottom of this book page: Image.module, Forum.module, Event.module.

Make a backup of your Drupal MYSQL database and the Drupal 4.5 files & folders on your
server, so you can recover your complete site in case anything should go wrong during the
upgrade.

Step-by-step Upgrade from Drupal 4.5 to 4.6.3


1. Log into your Drupal 4.5 site as the administrator, go to ADMINISTER --> MODULES and
disable all extra add-on or contributed modules you may have installed, i.e. modules that
don’t come with the core Drupal download . I have listed below the core standard Drupal
Modules:

standard Drupal modules


--------------------------
aggregator.module
archive.module
block.module
blog.module
blogapi.module
book.module
comment.module
drupal.module
filter.module
forum.module
help.module
legacy.module
locale.module
menu.module
node.module
page.module
path.module
ping.module
poll.module
profile.module
queue.module
search.module
statistics.module
story.module
system.module
taxonomy.module
throttle.module
tracker.module
upload.module

394
3 Aug 2007 Drupal Handbook

user.module
watchdog.module
=================

2. Go to ADMINISTER --> THEMES and make BLUEMARINE the default theme.


3. Go to the root of the Drupal directory and open the file called CHANGELOG.txt. Make a
note of the version number and date (important!) in the first line at the top of the file.
4. Go to your includes directory and make a copy of the conf.php file on your local
computer.
5. Delete all the Drupal files and directories from your server using an FTP program or a
control panel filemanager provided by your web host.
IMPORTANT: before doing this, make sure you have a backup of your Drupal MYSQL
database and the Drupal 4.5 files & folders on your server. You will need your old "/files/"
folder and its contents to copy to the new site later, and backing up the other files will allow you
to recover your complete site in case anything should go wrong during the upgrade.
6. Download Drupal 4.6.0 and upload all the files to your server.
7. Go to the sites/default directory and edit the settings.php file (you can use your
old conf.php file as reference).
8. Once settings.php file has been edited, go to your site and login as the administrator.
9. Go to http://www.yoursite.com/update.php.
10. You should be presented with the instruction screen for upgrading. Click on the link to start
the upgrade script; you will be asked from which version you are upgrading from. This is very
important: revert back to the note you made earlier from the 4.5 CHANGELOG.txt file.
11. Click the "Update" button. You should see a successful green "OK" after each update
operation and finally a link to go to your main and administration pages. If you get red error
messages, it means some or all of your update has failed.
12. On a sucessful update, go to the root Drupal directory and make a note of the version
number & date from the very top of the CHANGELOG.txtfile (important).
13. Go to the sites/default directory and make a copy of the settings.php file to your
local computer.
14. Delete all the Drupal files from your install.
15. Download Drupal 4.6.2 and upload the files to your server and restore the information in
settings.php.
16. Go to your site and login as the administrator.
17. Go to http://www.yoursite.com/update.php (click on your browser’s Refresh button
a few times to make sure it’s not loading from cache and the previous update.php file).
18. Click on the link to run the update script. Select the correct version number and date from
the CHANGELOG.txt file you made a few steps back.
19. Click the "Update" button. You should see a successful green "OK" after each update
operation and finally a link to go to your main and administration pages. If you get red error
messages, it means some or all of your update has failed.
20. Repeat this process again to upgrade from Drupal 4.6.2 to version 4.6.3.
21. Once you have reached a live version of 4.6.3, you can now start downloading the 4.6
versions of the add-on contributed modules & Themes you used with your 4.5 site. All appear to
work okay apart from event.module that needs extra special attention. When you’re

395
Drupal Handbook 3 Aug 2007

downloading a 4.6 version of the modules. Some of the more complex modules will usually have
a unique module-update.php file included, to ease the process. Check the readme.txt or
install.txt in the module folder as you download them to check for upgrading instructions.

Finalising your upgrade


There are a few significant differences between Drupal 4.5 and 4.6.x that means to finalise your
upgrade you may need to apply the following:

Rebuilding your Drupal Search Index.


Because of the new improved search module, your site’s search index will need to be rebuilt.

1. Go to ADMINISTER -->> SETTINGS -->> SEARCH. It will indicate how much of your
upgraded site is being indexed.
2. If your site search index is not 100%. Type www.example.com/cron.php in your
browser.
3. Wait for a minute (longer if you have a very large site) and press the back button to bring
you back to the SETTINGS/SEARCH page.
4. If your site is still not 100% indexed and/or you received an error message when running
CRON.PHP adjust the settings accordingly and type www.example.com/cron.php again.
5. Repeat the process until your site is 100% indexed

Blocks
There are a lot of improvements in how BLOCKS are built in Drupal 4.6.x. If you had block
paths configured on the block administration page in your Drupal 4.5 site, you’ll have to
reconfigure these after the upgrade.

1. Go to ADMINISTER --> BLOCKS


2. Click on the CONFIGURE link for each BLOCK you applied special PATH conditions to on
your Drupal 4.5 site and modify accordingly

Permissions
Please note that permissions screen has moved to ADMINISTER -->> ACCESS CONTROL in
Drupal 4.6.x. To ensure your permission settings match those set on your Drupal 4.5 site, follow
these steps:

1. Go to ADMINISTER --> ACCESS CONTROL


2. Double check that the permissions are correct and click on SAVE CONFIGURATION.

396
3 Aug 2007 Drupal Handbook

Forums
After upgrading, you need to re-associate the category terms you used in Drupal 4.5.x to
FORUM TOPIC node types. The reason is that there is a change in how FORUMs are managed
between version 4.5.x and 4.6.x including the new FORUM configuration screen that makes it
easier to manage your FORUMS.

1. Go to ADMINISTER --> CATEGORIES


2. Click on EDIT VOCABULARY TERM for the FORUM category
3. Scroll down and ensure that FORUM TOPIC node types are associated with your
Vocabulary Term.

There also appears to be a bug in the update.php script dealing with forums that registers every
LAST POST in each category to Anonymous.

Worth checking the Upgrade Poblems Forum in case someone else has worked out what’s
wrong.

Images
Upgrading a site with the image.module installed also appears very problematic. I didn’t have
the image.module in the site I upgraded so I can’t help with any tips. Best to follow the forum
discussions in the Upgrade Problems Forum

Events
Upgrading a site with the event.module installed also appears very problematic. The
events.module comes with a special update-event.php script, which appears to work when
you run it, but, I have tried it on a few occasions and it doesn’t seem to upgrade properly.

I ended up spending so long trying to work out what’s wrong it was quicker for me to copy and
paste each event from the old site into the new site by hand. There maybe a better solution in the
Upgrade Problems Forum

Upgrading from Drupal 4.6.3 to 4.6.5


The following is a simple step-by-step approach to upgrade a site from Drupal 4.6.3 to Drupal
4.6.5.

It is a relatively straightforward thing to do and takes about 15 minutes to complete. It is


important to follow each step carefully to avoid glitches or gremlins appearing at a later stage.

397
Drupal Handbook 3 Aug 2007

Before you Start


There are no database changes between Drupal 4.6.3 and Drupal 4.6.5 but it’s worth making a
backup of your Drupal MYSQL database as well as the files & folders on your server before
starting your upgrade.

Tip for beginners who want to back up the database: If you are unfamilir with PHP MYADMIN or
other MYSQL database management tools it’s worth downloading and installing the Database
Administration Module (dba.module) for Drupal. It allows you to backup your site database from within
Drupal very simply and easily.

Step-by-step Upgrade from Drupal 4.6.3 to 4.6.5


For a trouble free upgrade, it’s recommended to follow each step carefully. It should take about
15 minutes to complete these steps.

1. Once you have made a backup, check to make sure you are upgrading from the correct
version of Drupal.

(Using a text editor like notepad.exe or other, open the CHANGELOG.TXT file from the root (main)
folder of your Drupal installation and check the very first few lines. That indicates the version of
Drupal you are using.)

2. Download a copy of your /SITES/ folder to your local computer


3. Download, unpack and upload the Drupal 4.6.5 files to your server.
(You are simply overwriting the existing core modules and files with the updated Drupal 4.6.5
versions so it will just take a few minutes depending on your connection speed.)
4. After all the files have been uploaded sucessfully with no errors, upload the copy of the
/SITES/ folder you created on your local computer at step 2 to your upgraded Drupal
installation.
5. Congratulations ! Your site is now upgraded to Drupal 4.6.5.

Upgrading from Drupal 4.6.4 to 4.6.5


The following is a simple step-by-step approach to upgrade a site from Drupal 4.6.4 to Drupal
4.6.5

It is a relatively straightforward thing to do and takes about 15 minutes to complete. It is


important to follow each step carefully to avoid glitches or gremlins appearing at a later stage.

Before you Start


There are no database changes between Drupal 4.6.4 and Drupal 4.6.5 but it’s worth making a
backup of your Drupal MYSQL database as well as the files & folders on your server before
starting your upgrade.

398
3 Aug 2007 Drupal Handbook

Tip for beginners who want to back up the database: If you are unfamilir with PHP MYADMIN or
other MYSQL database management tools it’s worth downloading and installing the Database
Administration Module (dba.module) for Drupal. It allows you to backup your site database from within
Drupal very simply and easily.

Step-by-step Upgrade from Drupal 4.6.4 to 4.6.5


For a trouble free upgrade, it’s recommended to follow each step carefully. It should take about
15 minutes to complete these steps.

1. Once you have made a backup, check to make sure you are upgrading from the correct
version of Drupal.

(Using a text editor like notepad.exe or other, open the CHANGELOG.TXT file from the root (main)
folder of your Drupal installation and check the very first few lines. That indicates the version of
Drupal you are using.)

2. Download a copy of your /SITES/ folder to your local computer


3. Download, unpack and upload the Drupal 4.6.5 files to your server.
(You are simply overwriting the existing core modules and files with the updated Drupal 4.6.5
versions so it will just take a few minutes depending on your connection speed.)
4. After all the files have been uploaded sucessfully with no errors, upload the copy of the
/SITES/ folder you created on your local computer at step 2 to your upgraded Drupal
installation.
5. Congratulations ! Your site is now upgraded to Drupal 4.6.5.

Differences from 4.6 to 4.7


This section will be the central location for differences between 4.6 and 4.7 and items to consider
when upgrading or switching versions. Please click the add a child page button to add anything
you find or consider significantly different between the versions.

Block visibility settings


Page specific visibility settings have changed between Drupal versions 4.6 and 4.7. In 4.7 the is a
new option to use PHP code to determine when to show the block. If the code returns TRUE, the
block is displayed.
But because that option was not in Drupal before 4.7, you first have to switch it on from
(administer -> access control).

Configure options centralized


Continuing the UI work started back back between 4.4 and 4.5, many one time configuration
options have been moved from odd locations to admin >> settings menu.

399
Drupal Handbook 3 Aug 2007

If you have previously had trouble finding such one time configuration options such as work
flow for content types or post length, check for them in admin >> settings menu.

core module help text linked to the handbook now


Core modules help text now have a link to the Drupal.org handbook.

In your local Drupal (4.7) site, if you have the help module turned on you have admin >> help
That takes you to this page ?q=admin/help
Let’s pick a common one, taxonomy ?q=admin/help/taxonomy

At the bottom of this text is a paragraph with a link

For more information please read the configuration and customization handbook
Taxonomy page.

If you click on the link, you are brought back to Drupal.org. If anyone has provided additional
information to that module since release, they will now get the updated text and and additional
material people have seen fit to contribute as child pages.

Creating context sensitive menus with primary and


secondary menus
About context sensitive menus
One popular way to navigate a web site is to have to have a simple hiearchy of navigation, with
primary pages acting as "parents" to secondary pages, or "children." When a primary page is
visited, links to its secondary pages become visible. And when a secondary page is visited, its
"sibling" secondary links are made visible. In this way, the the secondary links are "context
sensitive". That is, the links to a particular group of secondary pages are displayed only when
that group’s parent or sibling pages are visited.

Drupal 4.7 allows you to easily create context sensitive menus using primary and secondary
menus.

To enable this behavior, in admin >> settings >> menu you must set both Menu containing
primary links: and Menu containing secondary links: to the same menu.

Don’t turn off contributed modules that provide an .install file


The Basic Upgrade Steps handbook page recommends to turn off all modules that are not core
modules before starting the update. Since Drupal 4.7 provides an install and update system for
contributed modules this is not always correct.

Contributed modules that come with an .install file should be kept enabled. The .install
file is not only used to do setup tasks, it also includes instructions to perform updates. If the
module is enabled when running update.php, these instructions can be automatically executed

400
3 Aug 2007 Drupal Handbook

during the Drupal update process. This of course requires that the module’s old files are
replaced by the new ones before the update.

If such modules are disabled before the update process, database error messages are likely to
appear when they are enabled again. Also performing the module’s update afterwards is a
rather cumbersome task.

Module .install files


As of version 4.7, modules authors can use .install files to do module setup work.

A .install file is run the first time a module is enabled, and is used to do setup required by
the module. The most common task is creating database tables and fields (which prior to version
4.7 was done manually).

.install files are also used to perform updates when a new version of a module needs it.

More information for module developers can be found in the developers handbook here.

The short answer for site admins is that if a contributed module uses this new method, you will
no longer need to manually load SQL tables into the database.

Primary/secondary links now part of the menu system


In 4.7 Primary and Secondary links have been incorporated into the menu system. Your theme
will still need to have the code to display them but behavior is handled through admin >>
settings >> menu settings. Then links are added in admin >> menu.

The migration script attempts to successfully migrate your existing links but you will need to
verify if it is successful.

queue module removed from core


The queue module has been removed from Drupal core. There are a variety of reasons for this
and if you wish you can search the development archives for the relavant discussions around 10
months ago. No one has stepped forward to maintain queue module. For those needing
moderation they should look to the newly updated nmoderation module by Jeff Eaton.

The Nmoderation project has been updated to 4.7 compatability. It now uses the VotingAPI for
its storage and calculation, so in the coming months it will also benefit from the increasing
integration with actions.module and views.module that is being added to the API.

401
Drupal Handbook 3 Aug 2007

Removal of base href statement from header


Using the $base_url from settings.php, Drupal previously generated a base href statement in the
header for all HTML output. The base href statement has been removed in 4.7 in an effort to
make Drupal more W3C compliant.

This will change the way in which relative links are encoded by hand in a Drupal site.
Previously, to link to a Drupal node such as

http://example.com/drupal/node/1000

one would create a relative link in an a href statement like this

<href="node/1000">

Now, with the absence of the base href statement, the relative link is written relative to the
domain name like this

<a href="/drupal/node/1000">

When updating from 4.6 to 4.7, update.php will fix relative links in previously existing content
in

nodes
comments
custom blocks
node submission guidelines
user registration guidelines

Site administrators will want to check HTML code with relative links that they have added in
other places (such as content managed by contributed modules).

Developers creating new Drupal sites for move to a different location when production ready
should be aware. If you build a site in

http://example.com/drupal/

all of the relative URL’s that the content might include have to be expressed in terms
"/drupal/..." (see above). If you then move the site to another folder location or a root domain,
the URL’s cease to function. It is recommended that if you plan to move the site to a root
domain, then construct it in a subdomain so that the relative URL is preserved. Or developers
may choose to borrow from update.php to create a script to update their tables (perhaps
someone will share such a script).

402
3 Aug 2007 Drupal Handbook

Some HTML Tags stripped from mission statement


In phptemplate engine the $mission and $footer_message variables were changed to run
through the filter_xss_admin() function. This limits the allowed HTML code slightly. Scripts and
CSS styles are no longer allowed.

To get around this new limitation, in your page.tpl.php file you can replace print $mission
with include ’mission.tpl.php’. Create a file mission.tpl.php with your mission
statement and it will be called by your page.tpl.php.

XTemplate engine removed from core


The XTemplate theme engine has been removed from the Drupal core and replaced by the
PHPTemplate engine. A 4.7 version of the XTemplate engine is available here and will be
maintained as a contributed module.

403
Drupal Handbook 3 Aug 2007

Troubleshooting FAQ
If you are installing Drupal for the first time, or you are trying to configure some part of your
existing installation, chances are your problem has been asked and answered countless times
already. Use this list of Frequently Asked Questions as your initial problem-solving helper. If
you don’t find your answer here, search the entire Drupal site. Failing that, you can ask for help
in the Support forum.

DO NOT simply post a Support Forum request without at least making an effort to find the
answer yourself. Yes, we know its tempting, but the answer you seek has been found by
someone else before you.

How to troubleshoot (read this first)


Before panicking or posting questions to the forum, here are a few ways and places you can look
for clues to your problem.

Set a man a fire and he’s warm for a night.


Set a man afire and he’s warm for the rest of his life.

1.

Stop and think


As ever, identify what changes you’ve made recently, what new modules may have been
installed. Most of the time something seems to go wrong, it’s your fault. Remember that :-)
and avoid those "Doh" moments after posting your problem.
Are you SURE the modules you installed are the right versions?

2.

Read the errors


If pages are just not displaying, see your server logs. Find them, read the last few entries to
see what’s going wrong. Errors like

.htaccess config problems - "Internal server error" - Error 500 directive not allowed here
Memory problems Fatal error: Allowed memory size of 8388608 bytes exhausted
Misbehaving javascript - modules/troublesome/utility.js 404 file not found

can be found there.

3.

404
3 Aug 2007 Drupal Handbook

Validate your page


If it’s a layout problem - alignment, font size, overflowing blocks etc - For the love of Mike
run it through the validator. Validation is a target to aim at, but admittedly not always easy to
achieve. However, you should know what errors exist, and how important they are. Specifically,
close all tags correctly and fix structural problems. The rest of the complaints about entities
and invalid attributes are less of an issue.
If it’s a non-public dev site get the web developer toolbar and use the "Validate local HTML"
option.
Get the web developer toolbar anyway, and use the CSS inspector to find out what styles
apply to which elements.

Bring up the DOM inspector [CTRL-SHIFT-I]


Use the ’Select element by click’ pointer and click on the problem element
Navigate the DOM tree to ensure it’s the right element
Select ’CSS Style Rules’ from the right pane where it says ’Object - DOM Node’
Click through the ’Rules’ and find out all the places where the element gets its
formatting from. The rule at the bottom takes precedence. Learn about the first ’C’ in
CSS - the Cascade
Check out the same for the container and child elements - one items margin may be
another items padding. (List items especially)
If you find unwanted css coming from a core Drupal css - over-ride it in your own
style.css with the same rule pattern, don’t hack core.
4.

Read the README


No, Really.
Although many modules can ’just work’ on installation, some bits (like enabling HTMLTidy
under WYSIWYG) need an extra step or two. It’s not broken, it’s documented in the
README.
Some modules have dependancies on server PHP extensions or assume other modules are
available (eg ’forum.module’ assumes ’comment.module’ is available, and dies if you turn
them off). The README should mention this.
Some modules have potential conflicts, or may even require patches to other modules (see
img_assist+tinyMCE). Again, the answer may be hidden in plain sight.
Avoid the head-slap moments and read everything you can that came with the module.

5.

Search the right way


If the error you see (in the log or the screen) doesn’t make sense to you, try a search on it.
Use Google, and quote the error as best you can.
Google: "Argument #1 is not an array" drupal.
- A google on a phrase, plus the keyword ’drupal’ is probably better than a drupal.org

405
Drupal Handbook 3 Aug 2007

search.

Take care to leave out pathnames (but filenames are probably useful). Try different
permutations of quotes around what seem to be discreet parts of the message.
Try searching both with and without arguments. Strings input by the user won’t help much
when searching for the problem elsewhere.

6.

Identify the source of the problem


You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near ’(n.nid), n.title FROM category c INNER JOIN category_node r ON
c.cid = r.cid INN’ at line 1
query: SELECT c.*, r.DISTINCT(n.nid), n.title FROM category c INNER
JOIN category_node r ON c.cid = r.cid INNER JOIN category cn ON c.cnid
= cn.cid INNER JOIN node n ON c.cid = n.nid INNER JOIN node cnn ON
cn.cid = cnn.nid WHERE n.status = 1 AND n.moderate = 0 ORDER BY
cn.weight, cnn.title, c.weight, n.title in
/var/www/html/doadance/drupal/includes/database.mysql.inc on line 120.
Error like the above are not caused by drupal database.inc. They are simply found by it
because a module has sent some bad instructions to the internals.
We need to find where the call came from, unfortunately you won’t get a call stack by
default.
Try to identify the table being addressed in this query to see what module may be doing it.
In this case it looks like category, but it may in fact be any other module that’s trying to
directly access data about categories.
7.

Dump some diagnostics


Debugging. If you are really trying to find the causes, it may help to display some of the
code.

Try the devel.module


For one-off quick hacks, when you just want to know why you are seeing (EG):
warning: in_array() [function.in-array]:
Wrong datatype for second argument
in /home/httpd/global/drupal/modules/node.module on line 1303.
Try some lightweight code.
Go look at that file. Modify it a bit. It’s safe to do so if you remember to undo
aferwards.
On line 1303, node.module we find
in_array(’status’, $node_options)
on the line before try inserting the code:
print("Node options are : ’".print_r($node_options,1)."’");

406
3 Aug 2007 Drupal Handbook

and see if that gives any clue.


A useful data dump when debugging, even within node pages themselves is
sometimes.
print("Node is : ".print_r($node,1)");
8.

Ask the right questions


When posting questions on the Drupal forum, it’s usually better to post more info than less.
The more work you can demonstrate has gone into solving it already, the more likely folk
are to help you get the rest of the way. Do ask questions "The smart way". Do follow up in
the same thread if you resolve it - even if no-one else posted. Do consider submitting your
solution as a comment under Troubleshooting FAQ or the elsewhere in the handbook.
In Drupal, it’s usually important to know if you are on a shared hosting provider - mention
this!

9.

Identify the module that’s giving you problems


All Drupal ’pages’ are dynamically created to one extent or another. Which dynamically
created pages are published under which URL is usually defined in each modules
hook_menu() implimentation.
When installing or investigating new modules, it’s usually interesting to open up the code
and look at the ***_menu() function to see what it does. Conversely, if you want to find
which module is serving which page, you’ll have the search there also.

To answer a question like "how is my sites rss.xml created?", a troubleshooting process may
be:

Do a find-in-files for "rss.xml"


This returns, sure enough, a result in node.module : node_menu()
This tells us that the function in question - that serves that page - is node_feed(). This is
where you want to look for further details.

All dynamic pages can be debugged by starting like this. Look at the URL, identify the
module that serves that URL, trace the callback through the code.

My admin > modules page is blank


This is most likely a memory issue. On this page all modules are loaded, whether they are
enabled or not. This can cause PHP to run out of available memory.

There are two fixes:

407
Drupal Handbook 3 Aug 2007

1. Remove (unused) modules--the quickest/easiest solution.


2. Increase PHP’s memory limit, either by adding:
memory_limit = 12M to your php.ini file (recommended, if you have access)
ini_set(’memory_limit’, ’12M’); in your sites/default/settings.php file
php_value memory_limit 12M in your .htaccess file in the Drupal root

The popular distribution from CivicSpace requires 24MB of memory so you may have to
experiment with what memory value works for your needs.

All fatal errors can result in a blank modules page. If you want to be sure if the memory limit is
causing this problem, you should check your web server error logs. Hunt for a line that looks
like:

Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to


allocate 418591 bytes) in /path/to/drupal/includes/database.mysql.inc
on line 29
That indicates that Drupal needed more memory than PHP was allowed to give it.

Always keep in mind that generally, "Less is More." The less memory your installation
consumes, the faster it is, and the more people can visit your site at one time.

You may have to restart Apache for the configuration changes to take effect.

How do I get the User Login block back


The block administration page can be reached on

Drupal 4: http://www.example.com/?q=admin/block
Drupal 5: http://www.example.com/?q=admin/build/block

If you need to login, visit:


http://www.example.com/?q=user

Note: Use the literal word user, not your username or user id.

Client does not support authentication protocol


requested by server...
You are installing a new install of Drupal and during setup receive the error

Client does not support authentication protocol requested by server;


consider upgrading MySQL client.

You are probably using MySQL 4.1 or higher and need to reset the password to pre 4.1 style.

408
3 Aug 2007 Drupal Handbook

Webhosting issues for new Drupal users


A lot of new Drupal users run into issues getting Drupal to work properly on their webhost.
These problems are not Drupal problems as such, they are usually the way the webserver is
configured. Complex and functional web applications like Drupal will naturally require a lot
more from a web server than just hosting a static HTML site would.

Unfortunately there is usually a knowledge gap between the Drupal installation documents and
the exact environment a new user is confronted with when attempting to install and configure
Drupal. For more experienced users that have a little Unix and Apache (a typical webhost setup)
knowledge under their belts, bridging the gap between their webhosting environment and the
general purpose Drupal installation guide is no problem. Things are more confusing for less
experienced users though. The following info is intended to help newbies come to grips with the
documentation and their webhosts environment.

There are a wide range of web site configuration tools (eg CPanel, Plesk, webmin etc) and near
infinite number of ways a webhost could configure a webserver. What this means is that a lot of
the general Drupal docs you read will have to use the lowest common denominator (ie Unix
shell commands) to describe configuration steps.

Less experienced users will not fully understand what these commands do or why they should
do them, and definitely won’t know when to deviate from them. To make matters worse most
webhosts don’t even offer shell access, so the instructions need to be ’translated’ to whatever
control panel they offer.

The following topics will hopefully provide just enough insight into Apache and Unix that new
users will be able to better understand the installation documentation and ’tune’ their sites for
running Drupal without too much pain. As a new user you might also gain an understanding of
why most of the docs are written the way they are.

Note: There are webhosts that offer Drupal specific hosting for those without the time or
inclination to do it themselves. See http://drupal.org/services and
http://drupal.org/forum/34 for more info.

Brief intro to Unix file permissions


Unix is a multiuser operating system. That means that it was designed for multiple users to be
logged in at once and each running their own programs without getting in the way of each
other.

Every program that runs on a Unix machine runs as a specific user account. This includes the
webserver itself, any command line shell you are running, and whatever software you use to
access the servers filesystem and admin interfaces (eg FTP software, CPanel interface etc). When
you log in with a username and password through an FTP client or a control panel you are now
operating on the server using that user account.

409
Drupal Handbook 3 Aug 2007

Note: this doesn’t include any Drupal user accounts you have set up. They only exist in your
Drupal database, not as any operating system user accounts.

All files on a Unix server have an owner and a group assigned to them. Whenever a file is
created on the server it is automatically owned by the user account running the program that
created it. Each user account also has a primary group associated with it, and this group also
gets assigned to the files group.

Each file and directory also has a set of permission ’bits’ assigned to it as well. These permission
bits determine what access various users get to a file. The owner of a file is allowed to change
these permissions, but all other users can’t change them (with the exception of the root user).

The file permission bits are arranged into three sets: ’user owner’, ’group owner’, and ’other’.
These three sets can also be referred to as ’user’, ’group’ and ’world’ respectively. ’world’ or
’other’ refers to the permissions that apply for any user that isn’t the owner and isn’t in the files
group. Each of these can have its own combination of three basic permissions.

The three basic permissions are ’read’, ’write’, and ’execute’ and are abbreviated as ’rwx’. When
you see dashes replacing a letter that means that the permission is absent eg ’r--’ means that only
read access is present.

When all three sets of permission bits are combined you get a setting like ’rwxr-xr-x’ which
represents ’rwx’ for the owner, ’r-x’ for the group, and ’r-x’ for everyone else.

You will also see permissions represented as a numerical shorthand eg 755 or 644 etc. In this case
the value of ’r’ = 4, ’w’ = 2, and ’x’ = 1, and the digits are determined by adding up these
numbers for each set.

examples:

755 is shorthand for ’rwxr-xr-x’. Translation: full access for the owner, everyone else has
read and execute access
664 is shorthand for ’rw-rw-r--’. Translation: the owner and the group get read and write
access, all other users get read access.

For files these permissions settings are quite straight forward. ’read’ allows accessing the
contents of a file, ’write’ allows the file to be changed or deleted, and ’execute’ allows the file to
be run as a program from the command line shell. Note that the execute bit isn’t really required
for PHP files as they don’t generally get run from the shell.

Permissions on directories are a little different from those on files. ’read’ allows the contents of a
directory to be listed, ’write’ means that you can add or delete files in the directory, and
’execute’ allows direct access to files in the directory (if you already know their names). On most
directories read and execute bits tend to go together ie typically directories will either have both
bits set or neither set.

410
3 Aug 2007 Drupal Handbook

There is a friendly tutorial here if you need more information:


http://www.perlfect.com/articles/chmod.shtml

Host-specific error messages


Some web hosts generate inexplicable errors when you install, upgrade, or even use certain
contrib modules in Drupal. The host may not know they’re the one causing the problem, mostly
because you assume you’re the one who doesn’t understand the inner workings of Drupal. Here
are a few host-specific error messages we’ve encountered, and how you can ask your host to
solve them.

Hosting Company Error Message Solution


Ask the host to make a
While editing a View, you receive the following
mod_security entry for
error message:
Webmasters.com your
Forbidden. You don’t have permission to access
www.example.com
/admin/build/views/edit/1 on this server.
account.
While editing a Content Template (Contemplate), Ask the host to make a
you receive the following error message: mod_security entry for
Webmasters.com Forbidden. You don’t have permission to access your
/admin/content/templates/yourtemplatename on www.example.com
this server. account.

If you have something to add to this list, please post a comment, and one of the document
maintainers will add it for you, then erase your comment.

SELinux may cause mysterious permission problems


Security Enhanced Linux (SELinux) is a relatively new, powerful mechanism for fine-grained
access control on Linux systems. Properly configured and maintained, it offers much better
protection from misbehaving programs and exploitable security weaknesses of server
application stacks than conventional Unix systems can provide. Many distributions now come
with SELinux support enabled by default, or at least make it available for installation. SELinux is
installed/available on Red Hat, Fedora, Debian, Gentoo, SuSE, Slackware, and Ubuntu, among
others.

If you (or your ISP) are running Drupal under an operating system which has SELinux installed
and enabled, you may find that certain operations fail mysteriously. Symptoms include, for
example, files not being written or read though the webserver has permissions; communications
operations such as sending mail or attempting XMLRPC operations failing, although firewall
permissions are OK, etc.

411
Drupal Handbook 3 Aug 2007

You can confirm that SELinux is causing the problem by turning SELinux off temporarily (run
the command setenforce 0 as root) and try the operation. If it succeeds, likely SELinux is the
culprit. (I’m assuming that this is a development setup, not a production machine - SELinux is
designed to protect your system, so turning it off on a production machine is not to be done
lightly). You can get more information about exactly why SELinux is shutting you down by
looking in the log files that it generates, for example, in /var/log/audit/audit.log on FC4.
Look for ’avc’ (access vector cache) messages.

Once you have tracked down exactly what aspect of SELinux policy is causing your operation to
fail, you can modify the SELinux configuration to fix the problem. This may be as easy as
turning on a boolean configuration setting in a configuration file, or as complicated as writing a
new snippet of SELinux policy.

Using the avc messages, the supplied SELinux administration tools and a little bit of help from
Google, the SELinux FAQs/tutorials on the web, and folks on the various the SELinux mailing
lists, you should be able to find your way around configuring additional policy to get Drupal to
do what you need.

I highly encourage you to bite the bullet and run with SELinux enabled, though it does involve a
rather steep learning curve.

Typical webhosting setups


The typical webhost sets up their servers so that each website gets a user account to manage it
(eg your FTP login). Each user account has a home directory where they can create files. These
website files will generally be owned by the user account that uploaded them.

The default permissions on these files usually won’t allow other users to write to them for
obvious reasons.

On most servers by default, the webserver runs under a different user account. eg on a Debian
Linux server, Apache usually runs as the www-data user. Some webhosts though might have
installed Apache modules that switch the webserver to run as the owner of the files it is serving
up.

Note: To find out what user the webserver is running as, you can use the phpinfo() function.
There are various ways of doing this - you can upload your own php file to do so, or that
functionality might already be built into tools you already have available like phpmyadmin.

Most documents or people answering forums tend to assume that the webserver is running as a
different user account. The explanations get a bit too fiddly and convoluted otherwise. But if
your server does run the webserver as your own account, keep that in mind when reading other
docs or answers - they might be aimed at the case where it runs as a different user.

How the web server is set up determines which permissions get used to control access to your
files. If the webserver runs under your user account, then Unix uses the file owners permissions
to provide access to your files. If the webserver runs as a different user, then Unix uses either the
’group’ or ’other’ permissions to determine access depending on whether or not the webserver

412
3 Aug 2007 Drupal Handbook

account is in the files group or not.

Using PHP to change files on the webserver


One side effect of having files created by Drupal (eg the image module), is that your user
account might not have ownership of them any more. And you might not be able to delete the or
move them around.

There is a workaround though. You can create a small PHP script containing the commands you
want to carry out and upload it to the server. Once uploaded, you can run it from your web
browser by entering the URL for it. The script will run as the user account the webserver runs as.
Be sure to remove the script after you have used it though.

Documentation for PHP filesystem functions:


http://php.net/manual/ref.filesystem.php

And documentation for the PHP system() function:


http://php.net/manual/function.system.php

With these techniques you should be able to get the webserver to do anything the Unix shell can
do.

Take care doing this though. These are the kind of tasks where it pays to practice them on your
test instance first - you do have a test instance right?

What do all those Unix commands mean?


You will notice references to Unix commands in some documentation or forum posts and might
be a little unsure what they do. The reason a lot of the docs or forum posts just list the
underlying commands is because they are a much more universal interface and the process can
be expressed quickly without writing long winded paragraphs describing things.

You may wonder why you would want to know what these Unix commands do, but once you
have a better idea of what they do you can then translate them to the functionality provided by
your control panel or FTP client etc.

Some Unix command you’ll see mentioned:


chmod
changes the permissions on files and directories. The ’-R’ (for recursive) option switch
changes the permissions on subdirectories and files as well.
mv
moves or renames files and directories. In general to rename a file or a directory you ’move’
it to its new name.
rm
removes (ie deletes) files and/or directories. To remove a directory you need to use the r
(for recursive) switch ie ’rm -r’.

413
Drupal Handbook 3 Aug 2007

cp
copies files and directories. The ’-p’ (for preserve) option switch also copies permissions and
ownerships etc. The ’-r’ (for recursive) option switch also copies subdirectories and files as
well. The ’-a’ (for archive) option switch includes both -r and -p options.
mkdir
creates a directory.
ln
creates a filesystem link. The main kind you will see mentioned is a ’symbolic link’ (using
the ’-s’ option switch) which behaves a bit like a shortcut in windows. You can create a link
to a file or directory located somewhere else and it will behave just like a copy of that file or
directory. But because they are linked rather than just copied, changes to one are reflected in
the other.
wget
a command to download web pages or files off the net and save them to disk.
tar
a zipping and unzipping utility. eg the Drupal download is what’s called a tarball. tar is
used to ’unzip’ the tarball into a subdirectory.
mysql and mysqladmin
command line utilities for connecting to and managing a MySQL database. Just about
anything they can do can also be done by phpmyadmin.

Special characters:
/
the Unix directory separator (just like with URLs) and also represents the root directory.
When a path starts with / it is an absolute path ie it starts with the root directory. A path
ending in / is an optional way of explicitly referring to a directory rather than a file.
..
refers to the parent directory (just like in Windows). A path starting with this is relative to
the current directory. Can be chained together eg ../.. refers to the parent of the parent
directory.
.
like ’..’ but refers to the current directory.
*
wildcard that matches any number of characters (like in Windows)
?
wildcard that matches just one character (like in Windows)

What permissions does Drupal need?


Now that you know which user the webserver runs as, you’ll need to make sure your file and
directory permissions are set properly. If you set them too tight Drupal won’t run properly or
even at all. Too loose and you run a higher risk of security breaches.

414
3 Aug 2007 Drupal Handbook

Most of the time, any files you upload should end up with the correct permissions to run a basic
Drupal site. Your webhost will have set the default permissions so they will be able to be read by
the webserver.

Where things get trickier is with the infamous ’files’ directory. If you install or enable modules
that upload files or images, they get stored under this directory. To do this, the webserver will
need write access to this directory. What this also means is that any files you upload will be
owned by the webserver user account and may not be able to be moved or deleted any more by
your FTP client or control panel as you might not have enough permissions. In most cases don’t
worry about this too much, but if you really have to delete some of these files manually there are
ways around the problem by uploading your own PHP scripts for the webserver to run and
change the permissions.

Basic summary of file permissions for a Drupal installation:

All the Drupal files (eg .php, .module, .css, .theme and images etc) will need to be able to be read
by the webserver account. The ’files’ is generally the only directory will need to be writable by
the webserver account.

If you get error messages complaining about missing files, or not being able to open/read a file
etc and you know that the file really is there - chances are that the webserver doesn’t have read
permissions for it. Recheck the permissions on subdirectories etc.

Ideally your settings.php file won’t be world readable as it contains your database connection
string (with password). But sometimes you can’t avoid it if making it world readable is the only
way your webserver can read it.

Along similar lines, ideally for security reasons you won’t have to make anything world
writable. But on a lot of webhosts it is hard to avoid having to make the ’files’ directory world
writable. What ever you do don’t go making anything other than the ’files’ directory world
writable. That makes it easy for other users to overwrite your Drupal files.

If it is possible through your admin interface it can be useful to assign the group ownership of
the ’files’ directory to the group the webserver runs as, and allow group write access. This
improves security a bit by not requiring the directory to be world writable.

Quite often you will hear people talk about setting permissions to 777 which is no restrictions at
all. While that is a good way to isolate any permissions issues when troubleshooting, you should
try to tighten the permissions back again afterwards if possible. Preferably you wouldn’t need to
use 777 permissions anywhere.

Another thing to keep in mind is that a permission setting only tells part of the story about
access - when troubleshooting it is also important to know who the owner and group are, and
well as which user the webserver runs as.

415
Drupal Handbook 3 Aug 2007

Why is this uploading stuff so difficult?


The reason it is more complicated when you need to upload files and/or images is because you
are now operating the web server in a different way.

With standard HTML only Drupal configuration, Drupal is not creating any files on the web
servers filesystem. When in that mode it runs like a standard web site - all the web server needs
to do is read the files, it doesn’t need to write anything. All the content you submit to the site is
going into the database not the filesystem.

But to be able to upload files or images through the Drupal interface, now Drupal needs to be
able to write files to the filesystem on the server.

This gets tricky because most of the time you don’t want the webserver to be able to write files
into your site directory. Just think what would happen if someone exploited a vulnerability in
someone else’s website on that server - they could now overwrite any of your website files very
easily. Just think what you could get up to just by uploading PHP files if other peoples sites had
wide open write access - no don’t try this.

So generally web servers aren’t allowed to write files in peoples websites. If you do want to
Drupal to be able to write files into a subdirectory - you will have to manually weaken the
filesystem security to make it work.

This isn’t a Drupal issue - any code (eg PHP, Perl, Python etc etc) run by the web server will
need those permissions weakened if they are to be able to write files to part of your web
directory.

You may also run into upload filesize problems that require changing settings like:
memory_limit, post_max_size, upload_max_filesize etc. These settings are there to limit what
any one website can do to overload the server. If these are too high, it allows one site to
completely tie up the server causing trouble for all the other sites.

Its all just the nature of sharing a server with lots of other people. There will be security and
resource limits put in place to stop a badly behaved user causing trouble for the others.

Your webhost is trying to strike a balance between ease of use and security. Different webhosts
will draw the line in different places - that is why it is impossible to write detailed docs that
cover all situations.

"Headers already sent" error


If you get a "headers already sent" error, there are two likely causes.

If this error is not the first error message on the page, then it is most likely a ’avalanche effect’ of
previous errors and you may ignore it. Instead, focus on fixing the errors before it. When you fix
the first error message(s), the "headers already sent" error(s) will most likely disappear.

416
3 Aug 2007 Drupal Handbook

However, if you get an error "headers already sent" as the first error, especially when trying to
log in and it tells you the error is near the end of a file (check which file "output started at" points
to), that probably means that there are extra spaces or lines after the closing ?> php tag. Just
delete them, and everything should work fine.

The extra whitespace being added probably is caused by a bad unpacking program and / or a
windows editor adding it.

"LOCK TABLES sequences WRITE" error


This is in reference to the following kind of error:

user error: Access denied for user: ’user@host’ to database ’database’


query: LOCK TABLES sequences WRITE in [path]/database.mysql.inc on line
xx

When you installed Drupal, you created a database and a database user. This error is caused by
that database user not having a certain privilege over your database.

When you come across this problem, first, double check that you have granted all privileges to
your user. You can try to grant the LOCK tables privilege by executing the following query:

GRANT LOCK TABLES ON databasename.* TO username@localhost IDENTIFIED BY


’password’;

If the GRANT command does not seem to have any effect on MySQL, you may need to follow it
by "FLUSH PRIVILEGES." If you still get this problem, and you are using shared hosting, it is
very likely that your host does not usually let users have the kind of permission required. For
reference, you may want to read these forum posts. You need to contact your host (e-mail seems
better than live support for this) and ask (if you are using mySQL 4) for global LOCK TABLES
privilege for your user in that database.

Although there are fixes in the forums, these are not recommended. If your host denies your
request, they may not be an appropriate place for your Drupal site.

"Method POST is not allowed for the URL /index.htm"


error (Error 405)
Your Drupal directory contains both an index.html and index.php file. Remove the index.html
file or configure your web server to look for index.php first before index.html. The same goes for
basically any html file in your Drupal directory. If you have for example "node.html" in your
root, you get the error message for every form that is submitted to node/*.

417
Drupal Handbook 3 Aug 2007

"Page Not Found" error when trying to access a


subdirectory
When you create a subdirectory inside the main Drupal directory that requires authentication
(with a .htaccess file), you may receive a "Page Not Found" Drupal page instead of the page you
expect to receive from the subdirectory.

This is caused by the way Drupal handles unauthorised access to items. There is an easy fix to
this problem. The following line should be added to the end of the .htaccess file in the
subdirectory you are trying to access (NOT THE DRUPAL .HTACCESS FILE).

ErrorDocument 401 "Unauthorized"

Doing this rewrites the default 401 error so that it is not intercepted by Drupal.

Block referrer spam


In some Content Management Systems, you can configure a block that shows what links people
clicked to come to your site. This is called a referrer sting. Drupal doesn’t display this referrer,
which is a good thing.

Many porno and online poker sites have robots that are sending "fake" referrer strings, claiming
they entered your site via their own site. When you would have a block displaying these
referrers, they would get more hits from people clicking these displayed referrer URL’s. So it is a
good thing that Drupal doesn’t display these referrers, apart from the referrer logs admin page.

Often, the robots sending these referrers do this via a so-called zombienetwork, thousands and
thousands of misconfigured or hacked PC’s which are "open proxys". You can’t really block this
referrer spam, the robots are sending real user-agents, are using many URL’s and there are so
many zombie IP addresses that are changing fast, that you can’t block these.

There is some work underway to block bad behaving robots and users from within Drupal. This
will probably be part of Drupal 4.7. Until that time, the only way to block the referrer spam it by
looking at your referrer log and look for often used word in the fake referrer URL’s, like
"online-poker".

Now you can block these words in your .htaccess file. Say you want to block the referrers
"internet-poker" and "viagra" as well as all user-agents that contain "looksmart"

First localize your .htaccess. This file is most likely in your Drupal document root. You can use
vi, pico, notepad or another editor. Now go to the end of the file and just before the last line add:

# Block referrer spam


RewriteCond %{HTTP_REFERER} (viagra) [NC,OR
RewriteCond %{HTTP_REFERER} (internet-casino) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (Looksmart) [NC]

418
3 Aug 2007 Drupal Handbook

RewriteRule .* - [F]

You don’t have to restart your webserver, these settings take place immediately. When you look
at your logs, you will still see the spamming robots with the fake referrer URL’s. But you will see
that these clients now get a 404 error, this means that they are not allowed to access that (or any
other) page.

If the robot that is sending this referrer spam is a "smart" robot, it will know sending the fake
URL didn’t work. Now it wont stop all the bad guys, they will probably try to send another
URL. Or the will go to another site to spam there. But there is a chance you will make it a better
world. Try it.

.htaccess sample list plus domain blocking


As described you can block via the use of .htaccess. Here is a sample list to stop trackback spam
(or splogs) from occuring in the first place.

Here is a list already made available to use, which blocks several spams.

# Single word blocks


RewriteEngine On
RewriteCond %{HTTP_REFERER} poker [OR]
RewriteCond %{HTTP_REFERER} medicine [NC,OR]
RewriteCond %{HTTP_REFERER} pills [NC,OR]
RewriteCond %{HTTP_REFERER} diet [NC,OR]
RewriteCond %{HTTP_REFERER} viagra [NC,OR]
RewriteCond %{HTTP_REFERER} mortgage [NC,OR]
RewriteCond %{HTTP_REFERER} casino [NC,OR]
RewriteCond %{HTTP_REFERER} insurance [NC,OR]
RewriteCond %{HTTP_REFERER} loan [NC,OR]
RewriteCond %{HTTP_REFERER} buy [NC,OR]
RewriteCond %{HTTP_REFERER} xanax [NC,OR]
RewriteCond %{HTTP_REFERER} meridia [NC,OR]
RewriteCond %{HTTP_REFERER} incest [NC,OR]
RewriteCond %{HTTP_REFERER} lesbian [NC,OR]
RewriteCond %{HTTP_REFERER} viagra [NC,OR]
RewriteCond %{HTTP_REFERER} adult [NC,OR]
RewriteCond %{HTTP_REFERER} hentai [NC,OR]
RewriteCond %{HTTP_REFERER} tramadol [NC,OR]
RewriteCond %{HTTP_REFERER} phentermine [NC,OR]
RewriteCond %{HTTP_REFERER} gambling [NC,OR]
RewriteCond %{HTTP_REFERER} texas- [NC,OR]
RewriteCond %{HTTP_REFERER} holdem [NC,OR]
RewriteCond %{HTTP_REFERER} pharmacy [NC,OR]
RewriteCond %{HTTP_REFERER} ultram [NC,OR]
RewriteCond %{HTTP_REFERER} tramadol [NC]
RewriteRule .* - [F,L]

419
Drupal Handbook 3 Aug 2007

Remember to use [ and ] to close the arguments above.

read more on:


http://www.i-marco.nl/weblog/archive/2005/08/29/saving_some_valuable_ban...

Or another way is to block domains also in the .htaccess file:

SetEnvIfNoCase Referer ".*.baddomain.com" BadReferrer


SetEnvIfNoCase Referer ".*anotherbaddomain.com" BadReferrer

order deny,allow
deny from env=BadReferrer

read more on:


http://www.hojohnlee.com/hacks/2006/01/12/blocking-spam-domain-referrals...

Color picker doesn’t appear on theme configuration


page
Color module is not enabled
Make sure to enable color.module on Administer » Site building » Modules
(admin/build/modules).
File download settings
The color picker is incompatible with the Private download method and will only show
when the download method is set to Public - files are available using HTTP directly.

Visit Administer » Site configuration » File system (admin/settings/file-system) to check the


download method your site uses.

PHP’s image library GD is not enabled.


Check your status report at Administer » Logs » Status Report (admin/logs/status) to see
if the GD library is working on your server. This is needed to actually create the images. If it
is not, you need to install it or get your host to do so for you.
Javascript is disabled.
You still see the Color scheme fieldset with a select box and a number of textboxes, but no
longer the color wheel or the preview.

Make sure you have Javascript enabled in your browser.

Drupal 4.7 Install inserts CGI-BIN in URL


In some hosting environments it is necessary to use the optional BASE_URL setting in
settings.php. Uncomment the line by removing the # at the beginning, type in the site URL and
save.

420
3 Aug 2007 Drupal Handbook

Duplicate entry error


This page is for errors similar to the one below:

user error: Duplicate entry ’24’ for key 1


query: INSERT INTO node (status, moderate, promote, sticky, title,
body, format, uid, created, type, teaser, changed, nid) VALUES(’1’,
’0’, ’1’, ’0’, ’test’, ’this is a test’, ’1’, ’1’, ’1149692821’,
’story’, ’this is a test’, ’1149692832’, ’24’) in
.../includes/database.mysql.inc on line 66.
warning: Cannot modify header information - headers already sent by
(output started at .../includes/common.inc:384) in
.../includes/common.inc on line 192.

The likely problem (short form): At some point, the sequence table in your Drupal database
was not updated.

The solution

1. Access your database. Check the affected table. In this case, the error tells us that it is the
node table (query: INSERT INTO node). This also happens with other tables, modify these
instructions accordingly.
2. This is the node table, so the problem is the node id (nid). Each node has a unique id. Look at
your table, and find the highest node id (nid). If you have many nodes, it may help to sort
your table by nid to find the highest one.
3. Go to your sequences table. Change the node id in the sequences table to a number higher
than the id you found in step 2.

The problem (long form):

The ’key’ in a table is a column where every entry has to be unique. For example, in the users
table, every UID (user id number) must be unique. You don’t want two users with the same id!

Drupal keeps track of what is the highest ID value separately, in the sequences table. When a
new user is created, Drupal checks the sequences table to find out what the next UID should be.
Presumably this is more efficient than checking the user table itself. Drupal then creates the new
user, updates the user table with the new user information, and updates the sequences table with the
new UID. The same thing happens for the node table, comment table, really, a whole bunch of
tables.

Sometimes, for some reason, Drupal does not update the sequence table. The number there
becomes out of date. So let’s say that in the node table the highest NID is 300, but somewhere,
something went wrong, and in the sequences table, the NID is only 297. The next time Drupal
makes a node, it will check the sequences table, and try to make a node with a NID of
298...whoops! That already exists.

421
Drupal Handbook 3 Aug 2007

The solution (long form):

The error itself can tell us a lot. Let’s divide it into 3 parts:

The error:

user error: Duplicate entry ’24’ for key 1

Duplicate... meaning the ’24’ is the same as something else in the table, something where no two
things can be the same. Which table? Which column?

The query:

query: INSERT INTO node (status, moderate, promote, sticky, title,


body, format, uid, created, type, teaser, changed, nid)

INSERT INTO [tablename] tells us which table produced the error. What follows is a list of
column names.

The values:

VALUES(’1’, ’0’, ’1’, ’0’, ’test’, ’this is a test’, ’1’, ’1’,


’1149692821’, ’story’, ’this is a test’, ’1149692832’, ’24’) in
.../includes/database.mysql.inc on line 66.

The values we tried to insert into columns of the NODE table... We already know ’24’ was the
problem, we see here it is the LAST value, corresponding to the LAST column, the nid, or node
id.

So the problem is, we tried to insert 24 into the nid column of the node table, when that value
already existed (duplicate entry!).

Why? Because the sequence table was not updated, and told Drupal the wrong nid. The solution
is to enter a value for nid into the sequence table that is higher than ANY nid in the node table.

To find the highest nid in the node table, access your database, however you do it. Find the node
table, and sort it by nid. Write down the highest value. Let’s say for this example that the highest
number is 68.

Go to the sequences table, and find the row that has nid in it. Replace the number there with
ANY number higher than the highest value in the node table. For this example, the highest value
was 68. 69 would work, so would 70, 90, and 201. ANY NUMBER higher than 68 would work in
this example.

Additional point: 99% of the time, the solution is in the sequence table, but this error will come
up ANY time you try to insert duplicate data into a column where every value has to be unique.

422
3 Aug 2007 Drupal Handbook

E-Mail from Drupal is bouncing or not being sent


If you are not receiving any E-mails from Drupal, or if E-mail sent by Drupal is bouncing, then
ensure that the SMTP configuration is set properly in your php.ini.

If you continue to have problems, the use the "user_mail_wrapper" option included with
Drupal.

You can now hook up your own custom SMTP library to Drupal instead of using the default
PHP mail() function. For more people mail() will work just fine, but for others this is a major
problem and it does not work properly. If you just want to get started you will have to
download a custom wrapper function from the Drupal contrib repository. If you already
have a favorite SMTP function you want to use you will have to create your own wrapper
function.

Make an include file that defines a user_mail_wrapper function: user_mail_wrapper($mail,


$subject, $message, $header); This function should take the parameters and pass them to the
SMTP lib. You will probably have to configure the SMTP lib in some way.

Modify your configuration file (conf.php) to include: $conf["smtp_library"] =


"path/to/wrapper.inc";

Check out http://cvs.drupal.org/viewcvs/drupal/contributions/tricks/smtp/ for an


example.

Originally written by Kjartan on January 9, 2002, with modifications.

Customize smtp.inc from the repository above to ensure that the proper settings for your SMTP
server are being used.

Relay SMTP mail to external mail server using smtp.class


Note that there is now also a SMTP module that will do this for you: http://drupal.org/project/smtp

The following are steps that I used to get Drupal 4.6.x running on Apache with PHP 4.3.10-15 to
successfully relay mail to an external mail gateway without using the php_mail() function. I
have tested this on Postfix and Exchange server mail gateways successfully.

1. Download class.smtp.inc from


http://www.phpguru.org/downloads/smtp/smtp.class-1.0.5.tar.gz.
2. Untar using tar âxzvf and copy class.smtp.inc to the /includes directory.
3. Edit the file and change the following lines to coincide with your external mail gateway:

$this->host = ’localhost’; Change localhost to the IP address of your mail gateway. You may
also use the FQDN instead of the IP address if you have DNS set up correctly to something
like yourmailgateway.yourdomain.com.
$this->helo = ’localhost’; Change localhost to reflect the hostname (FQDN) of your external

423
Drupal Handbook 3 Aug 2007

mail gateway. For example: yourmailgateway.yourdomain.com.


If your gateway requires SMTP authentication to relay mail, then you will need to modify
the following lines to appropriately reflect the authentication credentials. (If you manage your
own mail gateway or it resides within local subnets behind your firewall, then you should be
able to leave authentication set to FALSE and allow relaying based upon IP address/network
ID. This will probably only affect you if you use a hosting company for email management.

$this->auth = FALSE; (change to TRUE)


$this->user = ’’; (put username here(you may need to preceed with domain; e.g.
domain\username))
$this->pass = ’’; (put password here)

4. Download smtp.inc from http://cvs.drupal.org/viewcvs/drupal/contributions/tricks/smtp/


and place it in your /includes directory. No modification to this file is needed.
5. Add the following line to the sites/default/settings.php file before the closing ?> tag:

$conf["smtp_library"] = "includes/smtp.inc";

6. Finally be sure to add the IP address of the mail gateway to the [mail function] section in your
php.ini file and restart your web server.

Good Luck! I hope this saves you the hours of researching it took me to get it running.

Error 1364 upon importing database.mysql with


MySQL 5.0+
Symptom

When you use the file database/database.mysql to create a drupal database, MySQL reports the
following error:

error 1364 (hy000) line 803: field ’page’ doesn’t have a default value.

This error is caused by the following lines in database.mysql:

REPLACE blocks SET module = ’user’, delta = ’0’, status = ’1’;


REPLACE blocks SET module = ’user’, delta = ’1’, status = ’1’;

You may have additional problems when working with Drupal. Sidebars will be absent and
posting content results in an error:

user error: Field ’revisions’ doesn’t have a default value [snip]

Cause

424
3 Aug 2007 Drupal Handbook

MySQL 5.0 and higher have a strict mode that is currenty incompatible with a number of queries
in Drupal. The Windows Installer from MySQL.com enables this strict mode by default.

Workaround

There are several workarounds

1. Replace in my.ini the current sql-mode line with sql-mode="MYSQL40"


2. Start MySQL with the option --sql-mode="MYSQL40"
3. Execute the query SET GLOBAL sql_mode=’MYSQL40’

MySQL needs to be restarted before changes in my.ini have an effect. My.ini can be found in the
MySQL installation directory or the Windows directory, depending on your configuration.

Note: After switching MySQL mode you have to recreate your Drupal database or your site will
not function properly.

Error on installation step 3: Warning: Table


’[database].access’ doesn’t exist [...]
To run the install script point your browser to the base url of your website (i.e.
http://www.example.com). You will be presented with the "Database Configuration" page.

On Step 3 of INSTALL.txt - RUN THE INSTALL SCRIPT you do not arrive at the Database
Configuration page, but are greeted with the following warning(s) instead:

Warning: Table ’[database].access’ doesn’t exist query: SELECT CASE


WHEN status=1 THEN 0 ELSE 1 END FROM access WHERE type = ’host’ AND
LOWER(’[ip-address]’) LIKE LOWER(mask) ORDER BY status DESC LIMIT 0, 1
in [path]/includes/database.mysql.inc on line 172

Followed by one or more warnings concerning headers that have already been sent:

Warning: session_start() [function.session-start]: Cannot send session


cookie - headers already sent by (output started at
[path]/includes/database.mysql.inc:172) in
[path]/includes/bootstrap.inc on line 811

This happens if you have already edited the $db_url variable in settings.php. The installer
will no longer be automatically invoked, because Drupal assumes installation has already been
completed.

To remedy, run the installer manually by visiting http://example.com/install.php.

425
Drupal Handbook 3 Aug 2007

Fatal error: Allowed memory size of X bytes


exhausted (tried to allocate Y bytes)...
That indicates that Drupal needed more memory than PHP was allowed to give it.

Increase PHP’s memory limit, either by adding:

memory_limit = 12M to your php.ini file (recommended, if you have access)


ini_set(’memory_limit’, ’12M’); in your sites/default/settings.php file
php_value memory_limit 12M in your .htaccess file in the Drupal root

The popular distribution from CivicSpace requires 24MB of memory so you may have to
experiment with what memory value works for your needs.

Fatal error: Call to undefined function


This is almost always a symptom of version problems with a contrib module (or theme)

This is most often seen in form functions -undefined function: form_*() but could result from any
missed upgrade step listed in the module developers upgrade notes which lists the deprecated
functions, but most likely means you have installed the wrong version of the module (or that a
compatable version doesn’t exist yet).

You may find that turning on legacy.module will support a few of the older (deprecated)
functions that the troublesome module is trying to call.

Fatal error: Call to undefined function: form_*() on


Drupal 4.7
After installing a module on Drupal 4.7 you get the error:

Fatal error: Call to undefined function: form_*() in [module_path]

This error usually occurs on the modules settings page, but also on other module pages
containing forms.

Most likely cause: the module is specific for Drupal version 4.6.

The way forms are created changed completely in version 4.7. This new forms API means that
all former form_* functions such as form_checkbox, form_select and form_submit, are no longer
available.

Solution: You need to download a 4.7 specific version of the module in question. If the module
isn’t available for 4.7 you might want to try the version marked as "CVS". If that one does give
the same error you should try to update it yourself. For easy forms you can use

426
3 Aug 2007 Drupal Handbook

formupdater.module. An online version of this is available here:

http://lullabot.com/formupdater

If you succeed in converting the module you should send it to the author so that he can upload it
for others to download.

You may also get this error if you use php snippets in pages or blocks that display forms.
Disable such snippets before upgrading.

Fatal error: Cannot redeclare blah_function() in


../modules/blah.module
Usually seen on the admin/modules page, the admin/themes page, or after modifying module
or theme files.

As the error say, you have duplicate function declaration.


Most common cause seems to be :

On the modules page and themes page, EVERY file in themes/*/*.module


(themes/*/*.theme) is evaluated once each.

If you (or someone) tried making their own module by copying an existing directory (which is
the correct step 1) but failed to rename every function inside the files to their new theme name
(which is the neccessary step 2) you’ll get this error.

Go in and physically remove/move the module/theme files you don’t use out of the
modules/themes directory.

Try to "find in files" for that funcname listed in the errors and see where the dupe is.
Even just having a backup called "Copy of troublesome.module" Is illegal, as the dir scan
returns it as another available theme. It gets evaluated, then conflicts with the original.
Rename it to troublesome.module.bak instead

This error can also arise if two different module installs choose to use and bundle the same third
party library. This is pretty rare. Do the find-in-files to identify the problem, and enquire with
the respective module projects.

PS - NEVER have a module the same name as a theme!

Forgotten your Drupal account password


When you forgot your Drupal account password for user 1 (the administrator) and the email
notification doesn’t work, you can still set the password via a database query.

427
Drupal Handbook 3 Aug 2007

Execute the following query on your drupal database:

UPDATE ‘users‘ SET pass = MD5(’newpwd’) WHERE uid=1;

Of course, change ’newpwd’ to the password you want.

Forum overview stopped working


Following a problem of the forum overview stopped working (missing vocab after disabling,
deleting, re-enabling the module as described here

When the forum module is first enabled, it creates a vocabulary of its own (called Forum) where
it stores half its structure.
If for any reason this vocabulary is deleted (like you decide you don’t want forums yet, or you’re
working on an unstable development site) re-enabling the module will not correctly re-create
the needed vocab again

Thus, you end up with only half a working forum. It seems you can post topics, but the indexing
and overview pages are a bit scrambled, and don’t list anything useful.

(Just remaking a new ’Forum’ vocabulary manually will not work.)

The Fix
... is to tell the forum module to forget its old invalid vocabulary id and make a new one.

Short answer is this code needs to run:

<?php
variable_del(’forum_nav_vocabulary’);
?>

I use the devel.module, which provides a console where I popped this line, and a variable
viewer which showed me what happened, but another quick way is:

Create new node (don’t save)


Set content to php code. Disable wysiwyg if needed
Paste the above in the body
Preview

the php code will execute, although you won’t see anything yet.
discard the node, don’t need to save it.

visit admin/forums

this triggers the forum code to check if its parameters are correct.
they are not so it will create the Forum vocab as needed

428
3 Aug 2007 Drupal Handbook

continue, create a new forum or container. The pages should work again as they are
supposed to.

FTP uploads and file permissions using Transmit


Transmit has the capability to change the permissions of a file as it uploads it to your server.
Make sure the check-box "Auto-set my permissions" is unchecked. Typically, Drupal (all
versions) like to have most of their files at octal 755 or 775. If you accidentally have Transmit set
to change things to 644 or something similar, your newly-uploaded Drupal site will not work.

Help! I enabled a buggy module and now I can’t


disable it!
A situation can arise where you’ve enabled a module through administer >> modules, but then
because of a fatal error of some kind cannot get back to administer >> modules to disable it
(sometimes you cannot access any pages of your site at all) -- only the error is displayed and
nothing else.

This can be resolved by executing the following query in the database:

UPDATE ‘system‘ SET ‘status‘ = ’0’ WHERE ‘name‘ = ’module_name’ LIMIT 1;

This will disable the module so that you can access your administration panel again.

How can I adminstrate my navigation on my Drupal


site? (version 4.5 or older)
A lot of questions come up about how navigation on drupal can be modified, tweaked, altered
or any other synonym.

The theme: example, Internet explorer, Netscape, Opera, Lynx has two Navigation block that
look like this (assuming you have managed to
add link ’Mypage’ there by defining a ’page’):

will show:
* Navigation
* home
* news feeds
* archives
* blogs
* books
* forums
* My Page
* polls

429
Drupal Handbook 3 Aug 2007

* search

but also:

Navigation
* create content
* recent posts
* news aggregator

Where the second one (create content etc.) changes its name to name of the user after the user
logs in.

Themes: marvin and unconed have no generic navigation block but has the same links in the
menu on the top of the page.
Other themes do not have any version of generic navigation block.

In the poast drupal used to have a , what I call "functional navigation". Each module -each
function- could add a link to a general list of links. That list could then be displayed anywhere in
drupal. The list has only one level. so sub-elements were not possible.

For most of the CMS powered sites a functional navigation is the best method of navigation:
forums, blogs etc all have their own specific content-display and content navigation, based on
their function.

But as of drupal 4.3 people started inventing all sorts of navigation modules. These modules
would use tabs, blocks, or even hardcoded (D)html to make the navigation easy.
So in drupal 4.4 there was a general, standard "navigation" block introduced. But this one was
not configurable. Only modules could add items in that block.
So as of 4.5RC JonBob together with lots of others came up with a nice menu system, fully
configurable, with permissions and of course multi-levelled (as was the previous too).

Q: I like the first, generic Navigation block but most of the themes do not display it, even after I
enable Navigation block in the configuration of blocks.

A: The links list is still present in drupal, even in 4.5. You can print a list of linkes using for
example:

<?php
$output .= theme("links", link_page(), " " :: " );
?>
the list will then be something like blogs :: forum :: mypage :: weblinks

Not all themes use this function. In fact, nowadays only very few do. So you will need to add
this manually somwhere.

For example in a custommade sideblock you can say:

430
3 Aug 2007 Drupal Handbook

<?php
return $output .= theme("links", link_page() "<br />" );
?>
Please refer to the documentation on drupal.org about printing vs returning in blocks. This is
different in some releases of drupal!

Q: What does the Navigation block in block config refer to? (which block displayed above is
THE navigation block?)
A: That is the default drupal navigation blok. It offers multi-levelled navigation. It is also a place
where some modules place their navigation too (event.module for example).
You can disable this block, but you will then not be able to get into your adminstration, other
than typing in the urls by hand. So be carefull!

Q: Where is the first (generic) Navigation block defined? What to look for if I want to add it to
my theme? I like xtemplate so far so that’s where I would like to have the generic navigation
block.

A: That is an implementaion of

<?php
print $output .= theme("links", link_page() "<br />" ); //Or something
very similar
?>

How do I get rid of the "Welcome to your new Drupal


website" on the front page?
If you are seeing this message it is because your front page is set to ’node’ and you have no
content promoted to the front page.

To fix this, you either need to (1) promote something or (2) change your front page.

(1) Edit a node (or create a new node) and click the arrow next to "Publishing Options" to
expand that section. There is a checkbox labled "Promoted to front page". If you check that and
(re)submit the node it will show up on the front page and the welcome message will disappear.

(2) By default, the front page of your site is ’node’, which is a list of all nodes that have been
promoted to the front page as explained in (1). If you don’t like this, you can change your front
page to any page you like. To do this, go to www.yourdomain.com/admin/settings and click
the arrow next to ’General settings’ to expand that section. Towards the bottom, you will see
’Default front page’. If it’s still at the default, it will be ’node’. Change this to the page you would
like to be your front page. That is, the page that loads when you go to www.yourdomain.com.
For example, if you want people to go straight to the blogs, you would put ’blog’ in that setting.

431
Drupal Handbook 3 Aug 2007

This message is hard coded into the program files so, at this time, it is not possible to have your
front page set to ’node’, have no nodes promoted, and not have this message without changing
the source code. A work-around can be found here:
http://drupal.org/node/30816#comment-53200 .

How do I get the Navigation block back


A common question in the forums, is you disable a block without realizing the implications of
what it does. For instance the main menu/navigation block.

Visit http://www.example.com/?q=admin/build/block to change block settings.

Visit http://www.example.com/?q=admin/build/menu to change menu items.

How do I unset the clean URLs?


After enabling the clean urls in configuration all content is inaccessible, because the system you
run drupal on, does not support (all) clean urls.

Clean urls are those fancy looking addresses: instead of www.example.com/?q=/foo/bar you
see www.example.com/foo/bar with clean urls.

Problem is that you cannot set it back, because you cannot browse to the specific page anymore.

There are two solutions:

The first one is very handy if you have mysql access.


Run the mysql command:
UPDATE variable SET value = ’s:1:"0";’ WHERE name = ’clean_url’;
DELETE FROM cache;
Alternatively, you can modify the appropriate settings.php file: you should add the line
$conf[’clean_url’] = 0;
somewhere in this file.

NOTE: Drupal 4.6 has added the ability to detect whether your site is capable of running with
clean url’s. If the option to turn them on is greyed out, then you will be unable to activate it until
you resolve the underlying issue.

NOTE: In some situations you can navigate to http://example.com/?q=admin/settings and


disable it there.

How to login once you have turned your site off-line


for maintenance

432
3 Aug 2007 Drupal Handbook

Once you have turned your site off-line using admin » settings » site
maintenance(admin/settings), you can log back in by visiting:

http://example.com/?q=user

Note: Use the literal word user, not your username or user id.

You need to enter the username and password of an account with permission to administer site
configuration. User 1 has this ability as a safety net, should you not have this turned on in other
administrator account(s).

If you attempted to login with a username that does not have the "administer site configuration"
permission you will be stuck in that user account until you clear the browser’s cookies. Simply
instruct your browser to delete cookies for the site and visit the referenced URL above again.
You can also use another browser to access the URL.

To return the site to online mode visit the following page:

Drupal 4: administer » settings (admin/settings)


Drupal 5: Administer » Site configuration » Site maintenance (admin/settings/site-maintenance).

On the page, set Site status to Online.

If you are truly desperate you can try the following database queries to restore access:

UPDATE variable SET value = ’s:1:"0";’ WHERE name= ’site_offline’;


DELETE FROM cache WHERE cid = ’variables’;

HOWTO: Download a fresh copy of a missing or


corrupted module/image/file
Thanks to revision control, you can download any file from any version of Drupal from 3.0
onwards by using the ViewCVS server.

1. Go to http://cvs.drupal.org/ . You should see something looking similar to a folder listing.


2. Click on the drupal folder.
3. Click the Select Branch dropdown next to Show files using tag: and select the appropriate
DRUPAL-X-Y-Z tag in the Non-branch tags section. The file index will change to a view of
the files from that release.
4. Browse to the appropriate folder. (Ignore any empty folders. Due to the way CVS stores
information, you may come across empty folders that didn’t actually exist for your release.)
5. Click the dotted number in the Rev. column for the file you need. This will show a preview
of the file.
6. Right click the download link and choose Save Target As....
7. Make sure the file type is set to All Files. Browse to the desired location on your disk and
press Save.

433
Drupal Handbook 3 Aug 2007

You should now have a fresh copy of the missing or corrupted file.

Installation/configuration
406 Error when XMLRPC is used
Some hosting providers (at least one!) may disable xmlrpc.php scripts to plug security holes in
older versions of the XMLRPC libraries. If you’ve installed Drupal and enabled the BlogAPI
module or the Drupal login module on such a provider, you’ll get "406 errors" when you try to
use the features.

One possible solution (aside from convincing your provider to turn the relatively ineffective
security measure off) is to rename the xmlrpc.php file in drupal’s main directory. While this is
bad and will make upgrading a bit of a hassle, it can get you up and running.

You’ll have to alter blogapi.module to point to the newly renamed file, as well as any other
modules that point to xmlrpc.php. In the case of blogapi.module, the reference can be found on
line 560:

560: $xmlrpc = $base_url .’/’. ’xmlrpc.php’;

Junk {head} {styles} codes as output


Symptom:

When visiting your Drupal site for the first time you see what looks like code output, instead of
the expected theme:

{head} {styles} {_BLOCK_.header.logo} {_BLOCK_.header.site_name}


{secondary_links}
{primary_links}
{_BLOCK_.header.blocks}

This chunk of code is followed by the standard welcome message.

Cause:

Changes made after 4.6.x was released in PHP 5.0.5+/5.1.1+ and the template engine XTemplate
are incompatible.

The quickest solution is to go to http://www.example.com/?q=admin/themes and change the


default theme to Chameleon or Marvin.

Before you can change the theme you’ll need to be logged in. Either create the first account or
login at http://www.example.com/?q=user.

434
3 Aug 2007 Drupal Handbook

Another solution is to switch to a PHPTemplate based theme. PHPTemplate is another theme


engine, which will become the default in Drupal 4.7 anyway. You will need to download and
install PHPTemplate before you can use themes that depend on it.

Make sure to disable all XTemplate themes to prevent visitors from using them. Drupal 4.6
comes with two XTemplate themes included: Bluemarine and Pushbutton. A PHPTemplate
version of Bluemarine is available. Primary/Secondary links configured in the theme general
settings will not carry over to PHPTemplate. You will need to re-configure any
Primary/Secondary links in the PHPTemplate configuration of the theme.

Login after disabling the User login block


If you disabled the User login block and need to login, you can visit the login page on:

http://example.com/?q=user

The alternative http://example.com/user will only work when clean URLs are enabled.

Note: Use the literal word user, not your username or user id.

Login doesn’t work or must be done twice


There are at least two possible reasons why you can experience a symptom of "Visit the site,
login, and while the username and password are correct the user does not appear to be logged
in."

Cookies
Make sure cookies are enabled in your browser.

Cache Problems
It seems that sometimes the cache doesn’t get updated when logging into a site so even after
logging in the user is still shown the cached version of the site: not logged in. The source of this
problem (browser, webserver, Drupal settings) is not completely understood.

One solution seems to be to disable the Drupal cache of the site, though that has the undesired
side effect of increasing the load on your site.

Another workaround is for the users to hit the browser refersh button which seems to work
fairly well, but has the drawback of not being easily discoverable and is a hassle for every user of
the site. On a site where only one or two users login, this is not a problem. On a community site
it is a bigger problem.

435
Drupal Handbook 3 Aug 2007

For the next version of Drupal - the problem is fixed as a result of this issue.

Logging in at www on a site with no www in the baseurl


This problem is more easily understood and fixed. If a site is set with http://example.com as the
base URL and the user types www.example.com into his URL then he will still be presented the
main page. When the user uses the login block to login then Drupal will send them a cookie with
www.example.com as the domain and will forward the user to http://example.com where the
cookie will not be valid and the user will not be logged in. One solution to this problem is to
configure your server so that the URL and the Drupal settings match perfectly. If you are using
apache and .htaccess is enabled you can achieve this with an .htaccess rewrite directive inside of
the "Various rewrite rules" section:

RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]


RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

While the example has always been to remove the www, the problem and this solution can be
reversed for adding www.

This second issue has been fixed for the "next" version of Drupal in this issue

Login problems on PHP 5.2


This problem manifests itself when visiting a new page after login; the system seemingly forgets
that the user has already logged in.

This problem occurs due to the way PHP handles objects in session handlers. It effects all Drupal
versions upto Drupal 4.7.4 and Drupal 5-beta 1.

The best method of fixing this for Drupal 4.7.4 (and below) users is to upgrade to Drupal 4.7.5
which fixes this problem.

For those wishing not to do a full upgrade yet but need in "instant fix", a patch for Drupal 4.7.4 is
available on http://drupal.org/node/93945#comment-155161. See Patches » HOWTO: Apply
patches for help on applying the patch.

For Drupal-5 beta testers; this has been resolved since the Beta-1 release.

My layout collapses - content appears below left


column (IE) or overflows over the right (FF)
This commonly happens in themes that use CSS for flexible column layouts.

First, please Validate your page and fix all the problems you can. Use the web developer toolbar
to validate local pages.
More on validation below.

436
3 Aug 2007 Drupal Handbook

The most common problem is:

The content is too wide for the space it’s been given
What’s a poor robot to do?
If you tell a robot to push 1130 pixels into a bag that only holds 1000 - something’s gonna break.
Overlap or overflow are the only things the page renderer can do. (There is currently no
supported ’shrink to fit’ option, and ’expand to fit’ isn’t available in current versions of CSS.)

This is often seen in pages that embed tables, objects (like Flash) or large images that are of
fixed-width and end up making the content column (plus sidebars) wider than the available
screen space.
With percentage-width themes, the available space will depend on browser window size, which
you cannot control.

CSS work-arounds abound, but the first solution is to shrink your content if at all possible.
This is especially easy if you’ve pasted in a fixed-with table. Just remove the width attribute.

Another approach is it apply #content{overflow:auto;} on your css.


This results in a scrollbar in the middle of your page when the content forces it, and is not always
very nice-looking, but it’s better than the alternatives.
#content{overflow:hidden;} also works, is safer on your design, and looks better (maybe)
but may hurt accessibility slightly.

You can try #content{min-width:450px;} and similar fixes, but you’ll need to
browser-test. Any suggestions on getting this right are welcome.

Last resort - if you would rather the page always expand to fit your content - and trigger
browser scroll bars at lower resolution - is switch to an old-fashioned table-based layout. If CSS
is too hard for you, you may have to give up on tableless design.

OTOH, if you are keen, alternative fixes are always being proposed over at alistapart.com and
CSS3 apparently will make this dilemma solvable.

Validation Woes
While validation is The Right Thing to do, some warnings/errors are important, some less so. In
general:

document type does not allow element "div" here; (inside a P)


- may have side effects, but is probably non-fatal. It’s because of the way some themes, or
the line-break converter place extra (block-level) markup inside paragraphs - which is not
technically right. Can ignore.
end tag for element "..." which is not open.
Possibly related to the above. Fix it if possible

437
Drupal Handbook 3 Aug 2007

there is no attribute ... or required attribute ... not specified.


OK to ignore.
or end tag for "..." omitted, but OMITTAG NO was specified
Likely to be a sign of layout problems. If the end of a DIV or a TABLE (or other block-type
tags) is missing this will probably be very bad and needs fixing. Traditionally seen in badly
cropped teasers that try to display the top half of a table.
an attribute value specification must be an attribute value literal unless SHORTTAG YES is
specified.
Fix it if possible, but probably safe to ignore.
cannot generate system identifier for general entity ... or reference to entity "..." for which no
system identifier could be generated.
OK to ignore.

For more CSS troubleshooting, try the instructions for using the CSS inspector to find the active
styles and go from there.

Mysterious 403, 404, 406 or 500 errors depending on


submitted content
When submitting certain words in content, you receive a 403, 404, 406 or 500 error message.

This behaviour is most likely caused by the Apache module mod_security. Depending on its
filter settings, phrases that trip the module include

lynx, perl, mother, select from, table, cc:, and many more.

Ask your host to tone down the mod_security settings.

Alternatively you can try to add the following to .htaccess:

# Turn off mod_security filtering.


<IfModule mod_security.c>
SecFilterEngine Off
</IfModule>

This will turn off filtering by mod_security.

Not all hosts will allow this, so you may need to contact your hosting provider.

Permission denied in includes/file.inc


This describeds an error which may occur with to Drupal 4.5.2. The details for other versions
may differ.

438
3 Aug 2007 Drupal Handbook

http://www.example.com/?q=admin/settings might yield error messages like this:

warning: mkdir(files): Permission denied in


/data/www/public/includes/file.inc on line 77.
warning: mkdir(files/tmp): No such file or directory in
/usr/data/www/public/includes/file.inc on line 77.

This means that Drupal needs write access to create (and later access) the files and files/tmp
directories. One way to solve this is to give the webserver write access in the directory. Another
common solution seems to be granting everybody write access to the "files" directory. Both
solutions has the drawback that somebody else is able to write files into that directory. [if you
know a better solution, please mention it here]

Solution 1 (recommended)
In the drupal root directory:
mkdir -p files/tmp
chown -R www files
Note: you may need to substitute www with the user id of your webserver process.
Solution 2
In the drupal root directory:
mkdir -p files/tmp
chmod -R 777 files

Persistent ’Welcome to Drupal’ for anonymous users


When anonymous users see the ’Welcome to Drupal’ message on the frontpage (?q=node) even
though you have promoted nodes to the frontpage, you may experience an access problem. This is
usually the result of uninstalling an access module* without disabling it properly.

First, you have to exclude other possible causes. Make sure:

anonymous users have ’access content’ permission


a node has been promoted to the front page OR you have set the front page path on the
settings page

If the above conditions have been met, you may use the following SQL queries to reset the
node_access table. You can run these from the command line or in phpmyadmin by clicking on
the SQL tab of your right hand pane and pasting the querries into the text area, then clicking go.

Warning: the following SQL queries will reset the entire node access table:

TRUNCATE node_access;

This query deletes all access rules. The next query grants the ’view’ permission to all nodes.

INSERT INTO node_access (nid, gid, realm, grant_view, grant_update,


grant_delete) VALUES (0, 0, ’all’, 1, 0, 0);

439
Drupal Handbook 3 Aug 2007

* For example: taxonomy access, organic groups, nodeprivacy by role, simple access

phpinfo
On occassion it is useful to see what your php settings are. You can create a php page using
phpinfo() function from within your own Drupal install if you can create php type content. This
is probably not a page you want to leave permanently but can be useful for finding specific
information.

http://us3.php.net/phpinfo

Create a page of php content type and copy and paste the following line in it.

<?php
phpinfo();
?>

It will probably mess up your sites formatting.

Plain unstyled HTML output


If your site appears as plain HTML with missing styles and/or images there are two main
reasons:

1) You are trying to use a theme that is not active. This can happen when you have set the
default theme in settings.php but that theme has not yet been added or configured. It can also
occur when did not switch back to the default theme before upgrade. To fix that issue, go to
admin > build > themes and select the default theme (Garland in 5.x and Bluemarine in 4.7 and
4.6).

2) Your $base_url setting (in your settings.php file) is misconfigured. The $base_url
setting is what gets prepended to all paths for extra resources like stylesheets, images, javascript
includes and form handlers. If the browser can’t find those resources on that path, then they will
be missing from the rendered HTML you see in your browser.

example:
When developing and testing on a local Drupal version you might use localhost in your
$base_url. This works fine when using the browser on the development computer, but
when you access Drupal from another computer all these extra resources are missing. What
is happening is that browser on the other computer is trying to access these extra resources
from localhost and failing to find them there. The solution is to change $base_url to
use a hostname that points to Drupal from both computers (ie not localhost).

440
3 Aug 2007 Drupal Handbook

Setting up Clean URLs


You put AllowOverride into the apache config for your server (ususally httpd.conf). Here is an
example:

ServerAdmin webmaster@example.com
# DocumentRoot /home/example/http
DocumentRoot /home/example/drupal
Options +FollowSymLinks +Includes
ServerName old.example.com
ServerAlias www.old.example.com
ErrorLog /var/log/apache/old.lexample.com-error.log
CustomLog /var/log/apache/old.example.com-access.log common

AllowOverride All

Next fix up the .htaccess in /home/example as follows:

RewriteEngine on

# Modify the RewriteBase if you are using Drupal in a subdirectory and


# the rewrite rules are not working properly.
#RewriteBase /
RewriteBase /home/example/drupal

# Rewrite old-style URLs of the form ’node.php?id=x’.


#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{QUERY_STRING} ^id=([^&]+)$
#RewriteRule node.php index.php?q=node/view/%1 [L]

# Rewrite old-style URLs of the form ’module.php?mod=x’.


#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{QUERY_STRING} ^mod=([^&]+)$
#RewriteRule module.php index.php?q=%1 [L]

# Rewrite current-style URLs of the form ’index.php?q=x’.


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_FILENAME} !^index.php
RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA]

NOTE: the change to the last rule above. Without it you may get odd results similar to what is
reported in http://drupal.org/node/54417. Do read the handbooks too.

441
Drupal Handbook 3 Aug 2007

Lastly reload your http server.

unblocking account through SQL


Say you accidently ’block’ your admin account and cannot log in. From with in a MySQL client
you can run this command to unblock it

update user set status = 1 where uid = 1;

Weird behaviour - module-theme name collision


When someone is building a custom site it can happen that same name module and theme are
being developed. This results in very weird behaviour from Drupal’s side: overriding hooks can
make your blocks disappear, print $content returns only ’array’, hence disappearing admin
interfaces which force us to alter the database to get back on track.

Now we have to find out how to remove the new theme and switch back to an old one. We are
lazy people, moreover our site is big, with lots of content, so reinstalling is not an option. I tested
this with mysql, so these hints are for mysql only.

Dump your database first, and save it somewhere safe so we have a backup. We are going to
edit the dumped records, and reinsert the database. I used this method because using my
favourite editor is way easier and safer than using mysql shell (anyway we shouldn’t edit a live
site database).

The theme name is registered in the following tables in your database: system, variables and block.
After many tries I realised I have to clear the cache manually, meaning to remove all the
INSERT INTO ‘cache_‘ lines in order to see results. Change the ’default_theme’ value in
‘system‘, where note that ’s’ stands for string length, so be sure you put the string length after
the ’s:’. Also make sure you change the value to an existing theme (available themes listed in
‘system‘). And remove, or rename your troublemaker theme.

The change in ‘block‘ is imperative, otherwise the blocks will not appear. Drop your old
database from the sql server and insert the edited one. Voila, we have recovered from a theme
crash.

Where is the taxonomy choice when adding content?


http://drupal.org/node/31156

-->

Q: Where is the taxonomy choice when adding content?

442
3 Aug 2007 Drupal Handbook

A: Most likely, you need to assign a taxonomy vocabulary to the content type.

You’ve just created a taxonomy and filled it with a perfect array of terms. But there’s no category
menu on the post submission page! What gives?

You’ve forgotten a critical step: Assigning your taxonomy to a content type.

Go to (administer > categories > edit vocabulary) and look under the "Types" heading. There you
can assign your taxonomy to any content types you want. Save your configuration here, and try
to submit a post. Your taxonomy should now be available to you.

Miscellaneous
How can I change Drupal’s character encoding? (UTF-8 and
Unicode)
Several people have asked how to specify the character encoding that Drupal uses. The short
answer is: you can’t, but you don’t have to.

Drupal uses UTF-8 for encoding all its data. This is a Unicode encoding, so it can contain data in
any language. You no longer need to worry about language specific encodings for your website
(such as Big5, GB2312, Windows-1251 or 1256, ...). Also, when Drupal imports external XML
data (such as RSS or XML-RPC), it is automatically converted into UTF-8 (iconv support for PHP
will be required for most encodings).

If you really want to change Drupal’s encoding, you will experience a lot of troubles, because of
the various ways Drupal can receive and send out data (web, e-mail, RSS, XML-RPC, etc).

443

Potrebbero piacerti anche