My custom WAMP configuration for local development of WordPress plugins and themes.
Currently
- Windows 11
- Apache server 2.4.37 (Win64)
- MySQL Community Server (GPL) 8.0.13 for Win64 (x86_64)
- PHP 8.0.2
Also, phpMyAdmin 5.1.1
Configuration
Domains and subdomains
Most of my local development sites are accessed as installations in a host called s.b. I prefer this to using localhost or the IP address 127.0.0.1
Some other domains and subdomains are defined in my hosts file ( c:\windows\system32\drivers\etc\hosts )
127.0.0.1 s.b # Note: for COMPUTERNAME=SB
127.0.0.1 www.s.b
127.0.0.1 wp.a2z # local wp-a2z.org - WordPress bundled plugins and themes
127.0.0.1 www.wp.a2z
127.0.0.1 core.wp.a2z # local core.wp-a2z.org - WordPress core only
127.0.0.1 blocks.wp.a2z # local blocks.wp-a2z.org - Blocks & FSE themes reference
Apache setup
- Apache 2.4 is actually installed in
C:/apache24 - Document root:
C:/apache/htdocs - Document root contents:
- Subdirectories: are one per project, each with its own WordPress installation and MySQL database.
- The primary development folder is the imaginatively named
wordpress - Some folders don’t contain WordPress eg
bw
- PHP 8 is configured to load from
C:/php, thephp_modulebeing"C:/php/php8apache2_4.dll"
Virtual hosts – extras/httpd-vhosts.conf
I have more than one virtual host. The main one is for s.b with port 80 for http: and 443 configured for https: Secure Socket Layer (SSL).
<VirtualHost *:443>
DocumentRoot "C:/apache/htdocs"
ServerName s.b
ServerAlias www.s.b
SSLEngine on
SSLCertificateFile "c:/Apache24/conf/s.b.crt"
SSLCertificateKeyFile "c:/Apache24/conf/s.b.key"
</VirtualHost>
s.b.crt is the certificate and s.b.key is the RSA private key.
My SSL certificates were created by following Deliciousbrain’s instruction video to Create Your Own SSL Certificate Authority for Local HTTPS Development for Windows.
WordPress installations
Some of the WordPress installations are standard WordPress installs. Others are clones of WP-a2z ( bobbingwide/wp-a2z) which is WordPress core without wp-content, ie It’s a git repository containing all versions of WordPress since version 4.5, but without plugins or themes. This makes it easy to revert to earlier versions of WordPress, if required for debugging.
WordPress configuration file wp-config.php
In each WordPress installation the wp-config.php file is different from the live site:
Database settings. Some of the environments have different settings.
/** MySQL hostname */
define('DB_HOST', 'localhost');I want to see all PHP messages
# Zero tolerance for PHP Notify messages
define('WP_DEBUG', true );
define( 'SCRIPT_DEBUG', true );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', true );
}Constants used by WordPress or plugins
# I don't want WordPress to update itself.
define( 'WP_AUTO_UPDATE_CORE', false );
define('WP_MEMORY_LIMIT', '1024M');
I don’t try to force the site’s URL. Instead I update the entries in the wp_options table, usually using phpMyAdmin.
// Not set in my local installations
// define( 'WP_HOME', 'https://s.b/wordpress' );
// define( 'WP_SITEURL', 'https://s.b/wordpress' );For more information about the wp-config.php file see WordPress Developer Resources wp-config.php and Developer’s Advanced Guide to wp-config
WordPress.htaccess file
Another file that’s different from the live site is the .htaccess file in each installation’s main folder. It’s this file that enables the magic of permalinks.
# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /wordpress/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wordpress/index.php [L]
</IfModule>
# END WordPress
This basically tells Apache that if the request URL is for /wordpress/ and it’s not /wordpress/index.php or a file or directory that already exists that it should change it to a request to load wordpress/index.php.
wordpress/index.phpis the file that loads WordPress- there are other PHP files in the installation’s root directory that can be invoked directly eg
wordpress/wp-login.php
- Since my installs are all in sub-directories I need to edit this file for each installation.
- I have to indicate the installation’s directory in the
RewriteBaseandRewriteRuledirectives. - Note: For Multi Site installs the file’s a little different.
This file may also contain directives added by performance optimization, caching and other plugins.
# compress text, html, javascript, css, xml:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
</IfModule>
Enable compression for text output.
## EXPIRES CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
</IfModule>
## EXPIRES CACHING ##
# BEGIN Far Future Expiration Plugin
<IfModule mod_expires.c>
ExpiresActive on
<FilesMatch "\.(gif|jpeg|jpg|png|ico|js|css|swf)$">
ExpiresDefault "access 1 year"
</FilesMatch>
</IfModule>
# END Far Future Expiration Plugin
Set expiration dates for static files.
This example shows two methods to achieve the same result
Note: These should be updated to include WebP files!
For more information about the main .htaccess file for WordPress see WordPress Support .htaccess
Plugins and themes
In the wordpress subdirectory each of my own plugins and themes is a separate Git repository.
c:\
apache\
htdocs\
wordpress\
wp-content\
plugins\
... a lot of plugin folders ( over 200, not all active )
themes\
... not as many themes The bundled plugins and themes, and the plugins catalogued in WP-a2z are also Git repositories. Other plugins and themes have been downloaded from wordpress.org or other sites.
In the other environments many of the plugins and themes are symlinked to the wordpress environment.
cd \apache\htdocs\wp-a2z\wp-content\plugins mklink /J oik-privacy-policy C:\apache\htdocs\wordpress\wp-content\plugins\oik-privacy-policy
PHP configuration php.ini
date.timezone = 'UTC'
max_execution_time = 121

