wp-configThe bottom line for this article is that I want to make WordPress as fast, secure, and easy to install, run, and manage because I am using it more and more for client production sites, I will work for days in order to solve an issue so that I never have to spend time on that issue again. Time is money in this industry and that is ultimately (time) what there is to gain by tweaking WordPress.

Basic Concepts

For a better handle on the way I like to structure web site directories, see Optimize a Website for Speed, Security, and Easy Management but note it is a bit outdated compared to what I'm doing now. I don't have the luxury of using only one type of server, or hosting provider anymore, so I have been working towards making things even more portable in order to move from host to host from server to server without issues i.e. my portable .bash_profile.

So I've been basically experimenting various ways to accomplish that and thought I would share what I am currently doing for my benefit and hopefully get some input. All of my WP installs run the development version, and one main idea with my setups is that upgrading is automated. So I really keep the WordPress install clean and use plugins and wp-config.php to do all the customization.

  • Portability - Hands-free upgrades and easy to move
  • Security - Additional security and protection
  • Speed - Less CPU and Disk I/O
  • Customization - All my favorite customizations


These are the main settings I use.. Seriously this is more like an interactive article, because to understand it you will need to do some code grepping. You may want to grab a jolt.


The ASKAPACHE_ROOT variable is just a better way for me to be able to include and access all the different files in my site tree. For instance, in my non-wp php files, I can do this:

!defined('ASKAPACHE_ROOT') && require $_SERVER['DOCUMENT_ROOT'] . '/wp-config.php';
include(ASKAPACHE_ROOT . '/includes/custom-download.inc.php');


This is one of my all-time favorite hacks, that I think is one of the most useful methods I employ as a web developer. This allows me to use far-future-expire headers for optimum caching, while still forcing browsers to re-validate every day or so automatically, or forcing them to re-validate whenever I change the suffix. This takes advantage of the mod_rewrite trick that I use on EVERY site I run, definately worth learning. Because I practice best-practice web-standards, for every web site I create a single css file and javascript file, which I then add to the template like:

<link rel="stylesheet" type="text/css" media="all" href="http://s.askapache.net/c/apache-0<?php echo ASKAPACHE_LOCK?>.css" />
<script src="http://s.askapache.net/j/apache-0<?php echo ASKAPACHE_LOCK;?>.js" type="text/javascript"></script>

 * The base configurations of the WordPress.
 * This file has the following configurations: MySQL settings, Table Prefix,
 * Secret Keys, WordPress Language, and ABSPATH. You can find more information by
 * visiting {@link http://codex.wordpress.org/Editing_wp-config.php Editing
 * wp-config.php} Codex page. You can get the MySQL settings from your web host.
 * This file is used by the wp-config.php creation script during the
 * installation. You don't have to use the web site, you can just copy this file
 * to "wp-config.php" and fill in the values.
 * @package WordPress
/* http://codex.wordpress.org/Editing_wp-config.php */

/** /web/liet/askapache.com */
!defined('ASKAPACHE_ROOT') && define('ASKAPACHE_ROOT', str_replace('/public_html','', $_SERVER['DOCUMENT_ROOT']));

/** The 008 at the end is for manual tweaking.  time() returns seconds since '00:00:00 1970-01-01 UTC'. */
// http://www.askapache.com/htaccess/mod_rewrite-fix-for-caching-updated-files/
!defined('ASKAPACHE_LOCK') && define('ASKAPACHE_LOCK', substr(time(),0,5).'008'); // 12533001

/** absolute path to the WordPress directory */
!defined('ABSPATH') && define('ABSPATH', ASKAPACHE_ROOT .'/public_html/');

 * WP_SITEURL, defined since WordPress Version 2.2, allows the WordPress address (URL) to be defined. The valued defined is the address where your WordPress core files reside.
 * It should include the http:// part too. Do not put a slash "/" at the end.
 * Setting this value in wp-config.php overrides the wp_options table value for siteurl and disables the WordPress address (URL) field in the Administration > Settings > General panel.
!defined('WP_SITEURL') && define('WP_SITEURL', 'http://'.$_SERVER['SERVER_NAME']);

 * WP_HOME is another wp-config.php option added in WordPress Version 2.2. Similar to WP_SITEURL,
 * WP_HOME overrides the wp_options table value for home but does not change it permanently.
 * home is the address you want people to type in their browser to reach your WordPress blog. It should include the http:// part. Also, do not put a slash "/" at the end.
!defined('WP_HOME') && define('WP_HOME', WP_SITEURL);

/** no trailing slash, full paths only */
!defined('WP_CONTENT_DIR') && define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );

// full url - WP_CONTENT_DIR is defined further up
!defined('WP_CONTENT_URL') && define( 'WP_CONTENT_URL', WP_SITEURL . '/wp-content');

/** Allows for the plugins directory to be moved from the default location. @since 2.6.0 */
// full path, no trailing slash
!defined('WP_PLUGIN_DIR') && define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );

/** Allows for the plugins directory to be moved from the default location. @since 2.6.0 */
// full url, no trailing slash
!defined('WP_PLUGIN_URL') && define( 'WP_PLUGIN_URL', WP_CONTENT_URL . '/plugins' );

/** Allows for the plugins directory to be moved from the default location. @since 2.1.0 */
// Relative to ABSPATH.  For back compat.
//!defined('PLUGINDIR') && define( 'PLUGINDIR', 'wp-content/plugins' );

/** Number of autosaves to save. TRUE is default and enables post revisions, FALSE disables revisions completely. */
!defined('WP_POST_REVISIONS') && define('WP_POST_REVISIONS', 150);

/* ini_set('memory_limit', WP_MEMORY_LIMIT); */
!defined('WP_MEMORY_LIMIT') && define('WP_MEMORY_LIMIT', '64M');

/** Only check at this interval for new messages. Default is 5min */
/** @since 2.9  */
!defined('WP_MAIL_INTERVAL') && define('WP_MAIL_INTERVAL', 3600); // 1 hour

/** Saves updated post values to post from edit window every x seconds. (default 60)
 * When editing a post, WordPress uses Ajax to auto-save revisions to the post as you edit. You may want to increase this setting for longer delays in between auto-saves, or decrease the setting to make sure you never lose changes.
 * @since 2.5.0 */
!defined( 'AUTOSAVE_INTERVAL' ) && define( 'AUTOSAVE_INTERVAL', 60 );

/** @since 2.9.0  */
/** Permanently deletes posts, pages, attachments, and comments which have been in the trash for EMPTY_TRASH_DAYS. */
!defined( 'EMPTY_TRASH_DAYS' ) && define( 'EMPTY_TRASH_DAYS', 300 );

Debugging WordPress

One of my secrets for getting really good at this stuff is to master debugging. There is really not ever a time when I am working on a site that I don't have color-highlighted logs scrolling automatically in an ssh window. It's really almost impossible to fix problems with wordpress or do any kind of advanced anything without being able to view debugging info. At first I relied heavily on a custom php.ini being available on the server, but after having to deal with many hosts who don't allow php.ini files I now rely completely on setting values using ini_set for ultimate portability. Detailed towards the end of this article and is also included in this wp-config.php

/** display of notices during development. if false, error_reporting is E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR otherwise E_ALL */
!defined('WP_DEBUG') && define('WP_DEBUG', false);

/** The SAVEQUERIES definition saves the database queries to a array and that array can be displayed to help analyze those queries.
 *  The information saves each query, what function called it, and how long that query took to execute.  */
!defined('SAVE_QUERIES') && define('SAVE_QUERIES', WP_DEBUG);

!defined('ACTION_DEBUG') && define('ACTION_DEBUG', WP_DEBUG);

/** This will allow you to edit the scriptname.dev.js files in the wp-includes/js and wp-admin/js directories.  */
!defined('SCRIPT_DEBUG') && define('SCRIPT_DEBUG', WP_DEBUG);

/** Add define('WP_DEBUG_LOG', true); to enable php debug logging to WP_CONTENT_DIR/debug.log */
//!defined('WP_DEBUG_LOG') && define('WP_DEBUG_LOG', true);

/** This determines whether errors should be printed to the screen as part of the output or if they should be hidden from the user.
 *  Add define('WP_DEBUG_DISPLAY', false); to wp-config.php to use the globally configured setting for display_errors and not force it to On */
!defined('WP_DEBUG_DISPLAY') && define('WP_DEBUG_DISPLAY', false);

Ultimate Security Tweaks

Well, ultimate for WP's built-in keys and password functions, this is all for wp-config.php keep in mind. This is a very neccessary and recommended step, and is one of the only things I modify for each new installation.

Security KEYS

If like me you are familiar with password-cracking software like John the ripper, rainbow hash tables, l0pht-crack, etc.. then you will like to know that you can specify your own keys and salts for the encryption used by WP. They are AUTH_KEY, AUTH_SALT, SECURE_AUTH_KEY, SECURE_AUTH_SALT, LOGGED_IN_KEY, LOGGED_IN_SALT, NONCE_KEY, NONCE_SALT, SECRET_KEY and SECRET_SALT.

A random and long key gives you better encryption, and exponentially increasing that is using a random and long salt for the encryption. Encryptions with known salts are incredibly easy to decrypt compared to encryptions with secure salts, because the salt + key individually need to be guessed in order to find a matching hash, vs. just the key if the salt is known. See: Locating weak passwords.

A secret key is a hashing salt which makes your site harder to hack and access harder to crack by adding random elements to the password.

In simple terms, a secret key is a password with elements that make it harder to generate enough options to break through your security barriers. A password like "password" or "test" is simple and easily broken. A random, unpredictable password such as "88a7da62429ba6ad3cb3c76a09641fc" takes years to come up with the right combination.

For more information on the technical background and breakdown of secret keys and secure passwords, see:

I like to use the WordPress.org secret-key service 4 times. That's because for each key and salt I like to do: (1 key from api +random keyboard input+1 key from api).

 * Authentication Unique Keys.
 * Change these to different unique phrases!
 * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/ WordPress.org secret-key service}
 * You can change these at any point in time to invalidate all existing cookies.
 * This will force all users to have to log in again.
 * @since 2.6.0
 * Get salt to add to hashes to help prevent attacks.
 * The secret key is located in two places: the database in case the secret key
 * isn't defined in the second place, which is in the wp-config.php file. If you
 * are going to set the secret key, then you must do so in the wp-config.php
 * file.
 * The secret key in the database is randomly generated and will be appended to
 * the secret key that is in wp-config.php file in some instances. It is
 * important to have the secret key defined or changed in wp-config.php.
 * If you have installed WordPress 2.5 or later, then you will have the
 * SECRET_KEY defined in the wp-config.php already. You will want to change the
 * value in it because hackers will know what it is. If you have upgraded to
 * WordPress 2.5 or later version from a version before WordPress 2.5, then you
 * should add the constant to your wp-config.php file.
 * Below is an example of how the SECRET_KEY constant is defined with a value.
 * You must not copy the below example and paste into your wp-config.php. If you
 * need an example, then you can have a
 * {@link https://api.wordpress.org/secret-key/1.1/ secret key created} for you.
 * Salting passwords helps against tools which has stored hashed values of
 * common dictionary strings. The added values makes it harder to crack if given
 * salt string is not weak.
 * @since 2.5
 * @link https://api.wordpress.org/secret-key/1.1/ Create a Secret Key for wp-config.php
 * @return string Salt value from either 'SECRET_KEY' or 'secret' option
define('AUTH_KEY',        'jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?p[B+GR{@>{Yq`c|LnG;dvq#| %OA_cbBSU6,rICC1o/c)-|');
define('SECURE_AUTH_KEY', 'jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?Vp[Bb15baar8&R-r<[T|?(xhJJABGq+Ux+U$)-Hltp/');
define('LOGGED_IN_KEY',   'jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?Vp[B<5n6DG|YWnJ9tY2!M1L)`{-$LW~~Ia%.uCbn!P. 41o2$Z$4');
define('NONCE_KEY',       'jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?Vp[Bgu<wM*zewR0.{+m:bmrB?wj!B,4]Wo+4 Avk ApR-D?E');
define('SECRET_KEY',     'jflkhaskljdfhkljasdhflkjashd;flkjhas;djfh;kajshdflkjashdlfkjhasdlkfhal?Vp[B52ugH6muE9r4._iZwoYKUybrqLPpv|d Xr+|yrqhUE');

define('AUTH_SALT',        '123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdm~Ky%+%~PPa5b YEmDI%U[W!-B');
define('SECURE_AUTH_SALT', '123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdmad/7o6.AU3%9o-|Kqm]+eUqr-n~:ag');
define('LOGGED_IN_SALT',   '123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdmsLiCv@KJ{#wd(?qe(KcH3!');
define('NONCE_SALT',       '123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdmG9>+wm 2)bS0Pd_+1rx0brX]ND8|');
define('SECRET_SALT',      '123423190847olqkfhladhfsldshafasdfasdf09a7f-90a87df98adfyapoiyaf9asd8f70a9s8d7f908a7sdf97W4qCdm2<>))U|sty)+4vpWooKls/^[vN');

Using SSL for Admin and Login

SSL is kinda required from my point of view, it is just way to easy to sniff data off the wire otherwise. At least with SSL you force them to use tools like burpsuite, paros proxy, webscarab, etc..

/** @since 2.6.0  */
!defined('FORCE_SSL_ADMIN') && define('FORCE_SSL_ADMIN', true);

/** @since 2.6.0  */
!defined('FORCE_SSL_LOGIN') && define('FORCE_SSL_LOGIN', true);

Mod_Rewrite to Force SSL

This is pretty cool, it forces non-https for all urls except for /wp-admin and wp-login.php, which both require https. It also checks for the logged_in_cookie, and if that is present in the request then it doesn't force non-https. Kinda confusing if you don't have a mod_rewrite cheatsheet.

RewriteCond %{THE_REQUEST} ^$ [OR]
RewriteCond %{REQUEST_URI} ^/(wp-admin|wp-login.php).*$ [NC,OR]
RewriteCond %{HTTP_COOKIE} ^.*wp_li_sadfsdfasdf11b361cdsdfasdfasd=.*$ [NC]
RewriteRule .* - [S=1]

RewriteCond %{HTTPS} =on [OR]
RewriteCond %{HTTP_HOST} !^www.askapache.com$ [NC]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(wp-admin/.*|wp-login.php.*) HTTP/ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

File System Permissions

chmod, umask, file permissions testYou can get a basic and solid intro on file permissions by reading: Changing File Permissions, or you can check out some of my file permission research.

/** The permissions as octal number, usually 0644 for files, 0755 for dirs.
 *  http://codex.wordpress.org/Changing_File_Permissions
 *  if ( !$wp_filesystem->mkdir($remote_destination, FS_CHMOD_DIR) )
!defined('FS_CHMOD_DIR') && define('FS_CHMOD_DIR', (0755 & ~ umask()));
!defined('FS_CHMOD_FILE') && define('FS_CHMOD_FILE', (0644 & ~ umask()));

/** Define the timeouts for the connections. Only available after the construct is called to allow for per-transport overriding of the default. */
//stream_set_timeout( $stream, FS_TIMEOUT );
//!defined('FS_TIMEOUT') && define('FS_TIMEOUT', 30);

//$this->link = @ftp_connect($this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT);
//!defined('FS_CONNECT_TIMEOUT') && define('FS_CONNECT_TIMEOUT', 30);

// function get_filesystem_method($args = array(), $context = false) {
//  $method = defined('FS_METHOD') ? FS_METHOD : false; //Please ensure that this is either 'direct', 'ssh', 'ftpext' or 'ftpsockets'
//!defined('FS_METHOD') && define('FS_METHOD', 'direct');

/** These methods for the WordPress core, plugin, and theme upgrades try to determine the WordPress path, as reported by PHP, but symlink trickery can sometimes
 * 'muck this up' so if you know the paths to the various folders on the server, as seen via your FTP user, you can manually define them in the wp-config.php file.
 * FS_METHOD forces the filesystem method. It should only be "direct", "ssh", "ftpext", or "ftpsockets".
 * FTP_BASE is the full path to the "base" folder of the WordPress installation.
 * FTP_CONTENT_DIR is the full path to the wp-content folder of the WordPress installation.
 * FTP_PLUGIN_DIR is the full path to the plugins folder of the WordPress installation.
 * FTP_PUBKEY is the full path to your SSH public key.
 * FTP_PRIKEY is the full path to your SSH private key.
 * FTP_USER is either user FTP or SSH username. Most likely these are the same, but use the appropriate one for the type of update you wish to do.
 * FTP_PASS is the password for the username entered for FTP_USER. If you are using SSH public key authentication this can be omitted.
 * FTP_HOST is the hostname:port combination for your SSH/FTP server. The standard FTP port is 21 and the standard SSH port is 22.
//define('FS_METHOD', 'ftpext');
//define('FTP_BASE', '/path/to/wordpress/');
//define('FTP_CONTENT_DIR', '/path/to/wordpress/wp-content/');
//define('FTP_PLUGIN_DIR ', '/path/to/wordpress/wp-content/plugins/');
//define('FTP_PUBKEY', '/web/username/.ssh/id_rsa.pub');
//define('FTP_PRIKEY', '/web/username/.ssh/id_rsa');
//define('FTP_USER', 'username');
//define('FTP_PASS', 'password');
//define('FTP_HOST', 'ftp.example.org:21');

 * Block requests through the proxy.
 * Those who are behind a proxy and want to prevent access to certain hosts may do so. This will
 * prevent plugins from working and core functionality, if you don't include api.wordpress.org.
 * You block external URL requests by defining WP_HTTP_BLOCK_EXTERNAL in your wp-config.php file
 * and this will only allow localhost and your blog to make requests.
 * The constant WP_ACCESSIBLE_HOSTS will allow additional hosts to go through for requests. The format of the
 * WP_ACCESSIBLE_HOSTS constant is a comma separated list of hostnames to allow.
 * @since 2.8.0
 * @link http://core.trac.wordpress.org/ticket/8927 Allow preventing external requests.
/** @since 2.9  */
//!defined('WP_HTTP_BLOCK_EXTERNAL') && define( 'WP_HTTP_BLOCK_EXTERNAL', false );

 * The constant WP_ACCESSIBLE_HOSTS will allow additional hosts to go through for requests. The format of the
 * WP_ACCESSIBLE_HOSTS constant is a comma separated list of hostnames to allow.
 * @since 2.8.0
 * @link http://core.trac.wordpress.org/ticket/8927 Allow preventing external requests.
 * $accessible_hosts = preg_split('|,s*|', WP_ACCESSIBLE_HOSTS);
 * return !in_array( $check['host'], $accessible_hosts ); //Inverse logic, If its in the array, then we can't access it.
//!defined('WP_ACCESSIBLE_HOSTS') && define( 'WP_ACCESSIBLE_HOSTS', 'askapache.com,askapache.org' );


There's always a little comfort in having non-default cookies for security (against auto-bots), and using shorter names also means smaller HTTP Packets.

The $cookie_hash is my hack to get around the fact that COOKIEHASH isn't definable in wp-config.

 * Used to guarantee unique hash cookies @since 1.5 */

/** Set a cookie now to see if they are supported by the browser.
 * setcookie(TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN);
 * @since 2.3.0 */
!defined('TEST_COOKIE') && define('TEST_COOKIE', 'wp_tc');

/* @since 2.6.0 */
!defined('LOGGED_IN_COOKIE') && define('LOGGED_IN_COOKIE', 'wp_li_' . $cookie_hash);

/* @since 2.6.0 */
!defined('SECURE_AUTH_COOKIE') && define('SECURE_AUTH_COOKIE', 'wp_sa_' . $cookie_hash);

/* @since 2.5.0 */
!defined('AUTH_COOKIE') && define('AUTH_COOKIE', 'wp_a_' . $cookie_hash);

/* @since 2.0.0 */
!defined('PASS_COOKIE') && define('PASS_COOKIE', 'wp_p_' . $cookie_hash);

/* @since 2.0.0 */
!defined('USER_COOKIE') && define('USER_COOKIE', 'wp_u_' . $cookie_hash);

/* ok unset this var, its not needed as COOKIEHASH will have this value, but is not definable in wp-config.php */

/** @since 1.2.0 */
!defined('COOKIEPATH') && define('COOKIEPATH', preg_replace('|https?://[^/]+|i', '', WP_HOME . '/' ) );

/** @since 1.5.0 */
!defined('SITECOOKIEPATH') && define('SITECOOKIEPATH', preg_replace('|https?://[^/]+|i', '', WP_SITEURL . '/' ) );

/** @since 2.6.0 */
!defined('ADMIN_COOKIE_PATH') && define( 'ADMIN_COOKIE_PATH', SITECOOKIEPATH . 'wp-admin' );

/** @since 2.6.0 */
!defined('PLUGINS_COOKIE_PATH') && define( 'PLUGINS_COOKIE_PATH', preg_replace('|https?://[^/]+|i', '', WP_PLUGIN_URL)  );

/** @since 2.0.0 */

  * The WP_CACHE setting, if true, includes the wp-content/advanced-cache.php script, when executing wp-settings.php.
  * For an advanced caching plugin to use, static because you would only want one
  * if ( defined('WP_CACHE') )@include WP_CONTENT_DIR . '/advanced-cache.php';
!defined('WP_CACHE') && define('WP_CACHE', true);

/** WordPress Localized Language, defaults to en_US.
 * Change this to localize WordPress.  A corresponding MO file for the chosen
 * language must be installed to wp-content/languages. For example, install
 * de.mo to wp-content/languages and set WPLANG to 'de' to enable German
 * language support. */
!defined('WPLANG') && define ('WPLANG', 'en_US');

/** Stores the location of the language directory. First looks for language folder in WP_CONTENT_DIR
 *   and uses that folder if it exists. Or it uses the "languages" folder in WPINC. @since 2.1.0 */
//!defined('WP_LANG_DIR') && define('WP_LANG_DIR', ABSPATH . WPINC . '/languages');

/** LANGDIR defines what directory the WPLANG .mo file resides. If LANGDIR is not defined WordPress looks first to wp-content/languages and then wp-includes/languages for the .mo defined by WPLANG file.  Old static relative path maintained for limited backwards compatibility - won't work in some cases*/
//!defined('LANGDIR') && define('LANGDIR', 'wp-content/languages');

/** Stores the location of the WordPress directory of functions, classes, and core content. @since 1.0.0 */
//!defined('WPINC') && define('WPINC', 'wp-includes');

WPMU Stuff

I personally don't use.

/** Allows for the mu-plugins directory to be moved from the default location. @since 2.8.0 */
//!defined('WPMU_PLUGIN_DIR') && define( 'WPMU_PLUGIN_DIR', WP_CONTENT_DIR . '/mu-plugins' ); // full path, no trailing slash

/** Allows for the mu-plugins directory to be moved from the default location. @since 2.8.0 */
//!defined('WPMU_PLUGIN_URL') && define( 'WPMU_PLUGIN_URL', WP_CONTENT_URL . '/mu-plugins' ); // full url, no trailing slash

/** Allows for the mu-plugins directory to be moved from the default location. @since 2.8.0 */
//!defined( 'MUPLUGINDIR' ) && define( 'MUPLUGINDIR', 'wp-content/mu-plugins' ); // Relative to ABSPATH.  For back compat.

WordPress Database

This is usually the only thing I have to manually edit when creating a new site, unless I just use the same DB and modify the $table_prefix, (farther down). I run everything I possibly can in UTF-8, but if you don't already know alot about character sets, wow it is one of the most confusing things so you may want to save learning about that topic for another day. Otherwise the following are helpful (and show how confusing character sets are!)

If you ever setup WP to use the builtin membership features, make sure you learn about the CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE constants, I've found them very helpful.

 * MySQL settings
/** The name of the database for WordPress */
define('DB_NAME', 'askapachewpblog75');

/** The username to access the database */
define('DB_USER', 'askapache245d');

/** The password for the username to access the database */
define('DB_PASSWORD', 'asdfklj2340');

/** The hostname to connect to the database at */
define('DB_HOST', 'mysql.askapache.com');

/** The charset of the database */
define('DB_CHARSET', 'utf8');

/** The collation of the database */
define('DB_COLLATE', 'utf8_general_ci');


The $table_prefix is the value placed in the front of your database tables. Change the value if you want to use something other than wp_ for your database prefix. Typically this is changed if you are installing multiple WordPress blogs in the same database, and also for enhanced security.

Its a safe and good idea to change this value pre-installation to add more security to your WordPress blog. Exploits attempted against your WordPress blog by malicious crackers often are built with the premise that your blog uses the prefix wp_, by changing the value you mitigate some attack vectors.

 * WordPress Database Table prefix.
 * You can have multiple installations in one database if you give each a unique
 * prefix. Only numbers, letters, and underscores please!
$table_prefix  = 'ar15_';

/** CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE are used to designated that the user and usermeta tables normally utilized by WordPress are not used, instead these values/tables are used to store your user information. */
//!defined('CUSTOM_USER_TABLE') && define('CUSTOM_USER_TABLE', $table_prefix . 'my_users');
//!defined('CUSTOM_USER_META_TABLE') && define('CUSTOM_USER_META_TABLE', $table_prefix . 'my_usermeta');

Setup PHP Ini Settings

/** Turns the output of errors on or off, you really never want this on, you should only view errors by reading the log file. */
ini_set('display_errors', WP_DEBUG_DISPLAY);

/** Tells whether script error messages should be logged to the server's error log or error_log. */
ini_set('log_errors', 'On');

/** http://us.php.net/manual/en/timezones.php */
ini_set('date.timezone', 'America/Indianapolis');

/** Where to log php errors */
ini_set('error_log', ASKAPACHE_ROOT . '/logs/php_error.log');

/** Set the memory limit, otherwise defaults to '32M' */
ini_set('memory_limit', WP_MEMORY_LIMIT);

Sessions are slow

So I only use sessions when I have a specific use... In this case I need sessions only when one of the tools in the /online-tools/ directory is being used. And that is for the captcha image. In the future I won't ever use sessions.

if(preg_match( '#^/online-tools/#',$_SERVER['REQUEST_URI'])) session_start();

Include Custom Files

Sure you could use the my-hacks.php that WP allows, or you can just stick your functions in your TEMPLATEPATH/functions.php file, but they are executed only after the wp-settings.php file, which may be too late for your file.

In the past I've also used the auto_prepend_file settings to run my script before anything (index.php) but I ran into some issues on different hosts, and it wasn't as portable.

This is useful because you can have a file with globally available functions that you can use in non-WP areas as well as WP areas. I am moving away from this more and more as I learn more about classes and build plugins instead for portability.

include_once ASKAPACHE_ROOT . '/includes/myfunctions.inc';

/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

Some Useful PHP

I am constantly trying to make my sites and code more portable, so I am using plugins alot more to accomplish things that I use to do with separate php. Here are some examples of minimal php.

add_filter("the_generator", create_function('$a','return "";'));
add_filter('the_content', create_function('$a', 'return ((is_feed())? $a."<p><a href="".get_permalink()."">".get_the_title()."</a> originally appeared on ".get_bloginfo("name").".</p>" : $a);'), 99999);
add_filter('excerpt_length', create_function('$a', 'return 300;'),99);
add_filter('excerpt_more', create_function('$a', 'return "&hellip;";'),99);
add_action( 'wp_head', create_function('$a','echo "<link rel="pingback" href="'.get_bloginfo('pingback_url').'" />n";'), 95 );
add_action( 'wp_head', create_function('$a','echo "<link rel="schema.rss" href="http://purl.org/rss/1.0/" />n";'), 96 );
add_action( 'wp_head', create_function('$a','echo "<link rel="schema.rel" href="http://purl.org/vocab/relationship/" />n";'), 97 );
add_action( 'wp_head', create_function('$a','echo "<link rel="meta" type="application/rdf+xml" href="/foaf.rdf" />n";'), 98 );
add_action( 'wp_head', create_function('$a','echo "<link href="/favicon.ico" rel="shortcut icon" type="image/x-icon" />n";'), 99 );

Debugging Note

AskApache Advanced Debugging OutputIf you read this far than you probably know how important debugging is, but I sometimes like to stick the best tips deep in my articles to make sure only YOU find it. GRTFM isn't used on this site, it's mostly a requirement because my writing can get pretty bad.. The point, debugging is more than a crucial requirement if you want to do anything cool. Don't worry I got you.. check my AskApache Debug Viewer Plugin from the official WP site. It's pretty close to providing as verbose amount of information that I could possibly figure out how to get out of php, probably more than you have ever seen at least, I focused on quantity. I use it all the time on new installs as there is no setup required and it tells me advanced information about the setup of the server, hacker code for sure.

Here's a quick function to see set global vars, I just think this is interesting code.

function askapache_global_debug(){
  $gv=create_function('$n','global $$n; ob_start(); if ( is_array($$n) && sizeof($$n)>0 && print("[{$n}]n") ) print_r($$n);return ob_get_clean();');

Also check the WordPress Codex page: Editing wp-config.php and Perishable Press's: Stupid WordPress Tricks