Setting Up a WordPress Child Theme Development Environment
In today’s post, we’ll walk through a real-world example of setting up a WordPress child theme development environment using modern development tools. This setup process demonstrates how to properly configure coding standards and development dependencies for professional WordPress theme development.
Initial Environment Check
The session begins with verifying the WordPress High-Performance Order Storage (HPOS) data, showing 37,339 orders were successfully verified in 51 seconds. This indicates we’re working with a substantial e-commerce site running WooCommerce.
Theme Setup Process
The developer then navigates to the WordPress theme directory and focuses on an Understrap child theme. Understrap is a popular WordPress theme framework that combines Underscores and Bootstrap, making it an excellent choice for custom theme development.
Composer Dependencies Management
The interesting part begins with Composer dependency management. Here’s what happened step by step:
- The first
composer install
attempt encounters an error related to PHP Parallel Lint, showing the importance of proper error handling in development environments. - The developer then takes a clean approach by removing the vendor directory and composer.lock file to start fresh.
- A new
composer install
process begins, installing 34 packages including:- Code quality tools (PHPStan, PHPMD)
- Coding standards (PHP_CodeSniffer)
- WordPress-specific tools (wordpress-stubs)
- Various utility libraries (Guzzle, Symfony components)
Production vs Development Dependencies
An important step shows the difference between production and development environments:
bashCopycomposer install --no-dev --prefer-dist --optimize-autoloader --no-interaction
This command removes 24 development packages, demonstrating proper separation between production and development dependencies.
Installing Coding Standards
The final part focuses on setting up WordPress coding standards, which is crucial for maintaining code quality. The developer installs:
- PHP_CodeSniffer
- WordPress Coding Standards
- PHP Compatibility checking tools
- WordPress Theme Review standards
Final Configuration
The process concludes with configuring PHP_CodeSniffer’s installed standards paths and verifying the installation. The final check shows an impressive list of available coding standards:
- WordPress Core, Docs, and Extra standards
- PHP Compatibility standards
- PSR standards
- And more
Key Takeaways
This setup process demonstrates several best practices:
- Proper dependency management using Composer
- Separation of development and production dependencies
- Implementation of coding standards
- Use of modern PHP development tools
- Integration of WordPress-specific development tools
For WordPress theme developers, this setup provides a robust foundation for professional development, ensuring code quality and maintainability.
To check if the Composer installation and coding standards setup was done correctly on your live site, here are the steps you can follow:
- First, SSH into your live server and navigate to your theme directory:
bashCopycd /path/to/wp-content/themes/understrap-child
- Check if Composer packages are installed correctly:
bashCopycomposer show
This should list all installed packages. If you get an error, it means Composer isn’t installed properly.
- Verify PHP_CodeSniffer installation:
bashCopyvendor/bin/phpcs -i
You should see output similar to:
CopyThe installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, PHPCompatibility, PHPCompatibilityWP, WordPress, WordPress-Core, WordPress-Docs, WordPress-Extra and WPThemeReview
- Test PHP_CodeSniffer with WordPress standards:
bashCopyvendor/bin/phpcs --standard=WordPress path/to/your/php/file.php
- Check if the paths are configured correctly:
bashCopyvendor/bin/phpcs -i
vendor/bin/phpcs --config-show
If you run into any issues, you can reset and reconfigure by running:
bashCopyvendor/bin/phpcs --config-set installed_paths vendor/phpcompatibility/php-compatibility,vendor/phpcompatibility/phpcompatibility-paragonie,vendor/phpcompatibility/phpcompatibility-wp,vendor/wp-coding-standards/wpcs,vendor/wptrt/wpthemereview
what is PHP_CodeSnifferEdit
PHP_CodeSniffer (PHPCS) is a development tool that helps enforce coding standards in your PHP code. Let me explain its key aspects:
- Core Purpose:
- Detects violations of coding standards/style
- Ensures consistent code formatting across a project
- Identifies potential PHP compatibility issues
- Can automatically fix many coding standard violations
- Main Features:
- Checks spacing, indentation, and naming conventions
- Verifies proper documentation (DocBlocks)
- Ensures proper file and class structure
- Supports multiple coding standards (PSR-12, WordPress, Drupal, etc.)
- Can be customized with your own coding standards
- Includes a fixer tool (phpcbf) to automatically correct issues
- Common Use Cases:
bashCopy# Check a single file
vendor/bin/phpcs file.php
# Check entire directory
vendor/bin/phpcs src/
# Use specific coding standard
vendor/bin/phpcs --standard=WordPress file.php
# Auto-fix issues
vendor/bin/phpcbf file.php
- WordPress-Specific Benefits:
- Ensures code follows WordPress Coding Standards
- Checks PHP compatibility for WordPress environments
- Validates theme coding standards
- Helps maintain code quality for WordPress plugins/themes
- Integration Options:
- Command line tool
- IDE plugins (VS Code, PHPStorm)
- Git pre-commit hooks
- Continuous Integration pipelines
Think of PHP_CodeSniffer as a strict English teacher for your code – it ensures your code follows all the proper “grammar rules” of PHP coding standards, making your code more maintainable and consistent with the rest of your team’s code.
Would you like me to demonstrate any specific aspects of PHP_CodeSniffer or show examples of common coding standard violations it can detect? CopyRetry
E
sureEdit
I’ll show you some common coding standard violations that PHP_CodeSniffer catches and how to fix them.
Let’s create a typical PHP file with several common issues:
phpCopy<?php
// Bad code example
class userProfile{
private $Name='John';
function GetAge(){
return 25;}
public function set_status($STATUS) {
if($STATUS=='active'){
return TRUE;
}}
}
$obj=new userProfile();
When we run PHPCS with WordPress standards on this file:
bashCopyvendor/bin/phpcs --standard=WordPress example.php
It would flag several issues:
- Class Name Convention:
phpCopy// Bad
class userProfile
// Good
class User_Profile
- Property Naming:
phpCopy// Bad
private $Name
// Good
private $name
- Method Naming:
phpCopy// Bad
function GetAge()
// Good
function get_age()
- Spacing Issues:
phpCopy// Bad
if($STATUS=='active')
// Good
if ( $STATUS === 'active' )
- Boolean Constants:
phpCopy// Bad
return TRUE;
// Good
return true;
Here’s the corrected version that would pass PHPCS:
phpCopy<?php
/**
* User profile class
*
* @package YourTheme
*/
class User_Profile {
/**
* User name
*
* @var string
*/
private $name = 'John';
/**
* Get user age
*
* @return int
*/
public function get_age() {
return 25;
}
/**
* Set user status
*
* @param string $status User status.
* @return bool
*/
public function set_status( $status ) {
if ( $status === 'active' ) {
return true;
}
}
}
$obj = new User_Profile();
You can automatically fix many of these issues using PHPCBF (PHP Code Beautifier and Fixer):
bashCopyvendor/bin/phpcbf --standard=WordPress example.php
Common real-world scenarios where PHPCS helps:
- Inconsistent Array Syntax:
phpCopy// PHPCS will flag this
$array = array(
'key' => 'value'
);
// WordPress preferred
$array = [
'key' => 'value',
];
- Hook Callbacks:
phpCopy// PHPCS will flag this
add_action('init', function() {
// code
});
// WordPress preferred
add_action( 'init', 'your_prefix_init_callback' );
function your_prefix_init_callback() {
// code
}
- Nonce Verification:
phpCopy// PHPCS will warn about missing nonce verification
if ( isset( $_POST['data'] ) ) {
update_option( 'my_option', $_POST['data'] );
}
// Proper security check
if (
isset( $_POST['data'] ) &&
isset( $_POST['nonce'] ) &&
wp_verify_nonce( $_POST['nonce'], 'my_action' )
) {
update_option( 'my_option', sanitize_text_field( $_POST['data'] ) );
}
Would you like me to show you how to set up custom rules or explain any specific WordPress coding standards in more detail? CopyRetry
E
what are best practices?Edit
Let me outline the best practices for using PHP_CodeSniffer in WordPress development:
- Project Setup Best Practices:
bashCopy# Install as dev dependency
composer require --dev squizlabs/php_codesniffer wp-coding-standards/wpcs
# Set WordPress as default standard
vendor/bin/phpcs --config-set default_standard WordPress
# Configure paths correctly
vendor/bin/phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs
- Code Quality Standards:
- Always use proper DocBlocks for classes, methods, and hooks
- Follow WordPress naming conventions: phpCopy
// Functions and variables: lowercase with underscores function my_custom_function() {} $my_variable = ''; // Class names: capitalized with underscores class My_Custom_Class {}
- Proper indentation (use tabs in WordPress)
- Meaningful variable and function names
- Security Best Practices:
phpCopy// ALWAYS sanitize inputs
$title = sanitize_text_field( $_POST['title'] );
// ALWAYS escape outputs
echo esc_html( $title );
// ALWAYS verify nonces
if ( ! wp_verify_nonce( $_POST['nonce'], 'my_action' ) ) {
wp_die( 'Invalid request' );
}
- Git Integration:
- Set up pre-commit hooks to run PHPCS
- Create a
.phpcs.xml.dist
file:
xmlCopy<?xml version="1.0"?>
<ruleset name="WordPress Theme Coding Standards">
<description>WordPress Theme Coding Standards</description>
<!-- Files to check -->
<file>.</file>
<exclude-pattern>/vendor/*</exclude-pattern>
<exclude-pattern>/node_modules/*</exclude-pattern>
<!-- Rules -->
<rule ref="WordPress"/>
<rule ref="WordPress-Extra"/>
<rule ref="WordPress-Docs"/>
</ruleset>
- IDE Integration:
- Configure your editor to show PHPCS warnings in real-time
- Set up auto-formatting on save
- Use EditorConfig for consistent styling
- Performance Best Practices:
phpCopy// Cache expensive operations
$cache_key = 'my_expensive_query';
$results = wp_cache_get( $cache_key );
if ( false === $results ) {
$results = expensive_function();
wp_cache_set( $cache_key, $results, '', HOUR_IN_SECONDS );
}
- Hook Documentation:
phpCopy/**
* Modify post title.
*
* @param string $title The post title.
* @param int $post_id The post ID.
* @return string
*/
function my_modify_title( $title, $post_id ) {
// Code here
return $title;
}
add_filter( 'the_title', 'my_modify_title', 10, 2 );
- Error Handling:
phpCopy// Proper error handling
try {
$result = some_function();
if ( is_wp_error( $result ) ) {
error_log( 'Error: ' . $result->get_error_message() );
return false;
}
} catch ( Exception $e ) {
error_log( 'Exception: ' . $e->getMessage() );
return false;
}
- Regular Maintenance:
bashCopy# Regular updates
composer update --dev
# Run checks periodically
vendor/bin/phpcs
vendor/bin/phpcbf
# Check PHP compatibility
phpcs --standard=PHPCompatibilityWP
- Team Standards:
- Document custom standards
- Use consistent commit messages
- Regular code reviews
- Share common snippets and patterns
Would you like me to elaborate on any of these practices or show more specific examples for your use case? CopyRetry
E
how would i use this with a theme built with a rollup config as an understrap child?Edit
Let me show you how to integrate PHP_CodeSniffer with an Understrap child theme that uses Rollup:
- First, let’s set up the directory structure properly:
bashCopyunderstrap-child/
├── rollup.config.js
├── composer.json
├── package.json
├── src/
│ ├── js/
│ └── sass/
├── css/
├── js/
└── .phpcs.xml.dist
- Create/update your
composer.json
:
jsonCopy{
"require-dev": {
"squizlabs/php_codesniffer": "^3.7",
"wp-coding-standards/wpcs": "^2.3",
"phpcompatibility/phpcompatibility-wp": "^2.1",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0"
},
"scripts": {
"phpcs": "phpcs",
"phpcbf": "phpcbf",
"lint": [
"@phpcs"
],
"fix": [
"@phpcbf"
]
}
}
- Create
.phpcs.xml.dist
:
xmlCopy<?xml version="1.0"?>
<ruleset name="Understrap Child Theme Standards">
<description>PHPCS configuration for Understrap child theme</description>
<!-- What to scan -->
<file>.</file>
<exclude-pattern>/vendor/*</exclude-pattern>
<exclude-pattern>/node_modules/*</exclude-pattern>
<exclude-pattern>/src/*</exclude-pattern>
<exclude-pattern>/css/*</exclude-pattern>
<exclude-pattern>/js/*</exclude-pattern>
<exclude-pattern>/dist/*</exclude-pattern>
<!-- Rules -->
<rule ref="WordPress"/>
<rule ref="WordPress-Extra"/>
<rule ref="WordPress-Docs"/>
<!-- Allow theme-specific exceptions if needed -->
<rule ref="WordPress.Files.FileName">
<properties>
<property name="is_theme" value="true"/>
</properties>
</rule>
</ruleset>
- Update your
package.json
to integrate PHP checks with your build process:
jsonCopy{
"scripts": {
"build": "rollup -c",
"watch": "rollup -c -w",
"lint:php": "composer run-script phpcs",
"fix:php": "composer run-script phpcbf",
"lint": "npm run lint:php && eslint src/js",
"dev": "npm run build && npm run lint",
"production": "npm run build && npm run lint"
}
}
- Update your
rollup.config.js
to exclude PHP files:
javascriptCopyexport default {
input: 'src/js/app.js',
output: {
file: 'js/app.min.js',
format: 'iife'
},
// ... other config
watch: {
exclude: ['**/*.php']
}
}
- Set up VS Code integration (create
.vscode/settings.json
):
jsonCopy{
"phpcs.enable": true,
"phpcs.standard": ".phpcs.xml.dist",
"phpcs.executablePath": "./vendor/bin/phpcs",
"phpcbf.enable": true,
"phpcbf.executablePath": "./vendor/bin/phpcbf",
"phpcbf.standard": ".phpcs.xml.dist"
}
- Example usage in your theme files:
phpCopy<?php
/**
* Template part for displaying page content
*
* @package Understrap_Child
*/
// This will be checked by PHPCS
function understrap_child_custom_function() {
// Your code here
return true;
}
// Any custom PHP you write will be checked against WordPress standards
add_action( 'init', 'understrap_child_custom_function' );
To use this setup:
bashCopy# Install dependencies
composer install
npm install
# Run PHP checks
npm run lint:php
# Fix PHP issues automatically
npm run fix:php
# Run full build with linting
npm run dev
# Build for production
npm run production
Some tips for this setup:
- Keep PHP files in the root theme directory, not in
src/
- Use
src/
only for JS and SASS files that need compilation - Run PHPCS before committing changes:
bashCopy# Create .git/hooks/pre-commit
#!/bin/sh
npm run lint
Would you like me to explain any part of this setup in more detail or show how to handle specific use cases?