• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » How to build custom Sage Roots modern environments extensions utilizing modern Filesystem API schemas

How to build custom Sage Roots modern environments extensions utilizing modern Filesystem API schemas

Leveraging the Filesystem API for Custom Sage Roots Environments

Sage Roots, a popular WordPress starter theme, provides a robust foundation for modern theme development. While its core functionality is extensive, developers often encounter scenarios requiring custom environment configurations beyond the default `development`, `staging`, and `production` setups. This typically involves managing distinct sets of configurations for plugins, theme options, or even specific API keys based on the deployment environment. Traditionally, this might involve complex conditional logic within theme files or separate configuration files managed manually. However, by leveraging Sage’s built-in filesystem utilities and a structured approach, we can create highly maintainable and extensible custom environment configurations.

Defining Custom Environment Schemas

Sage Roots utilizes the `wp-config.php` file to define its environments. The `WP_ENV` constant is the primary driver. We can extend this by introducing custom constants or by creating a more structured configuration system. A common pattern is to use a dedicated configuration file that maps environment names to specific settings. For this example, we’ll assume a JSON structure stored within the theme’s `config` directory.

First, let’s define a custom environment, say `local-dev`, which might have different database credentials or API endpoints than the standard `development` environment. We’ll create a file named `config/environments/local-dev.json` within your Sage theme’s root directory.

Example `config/environments/local-dev.json`

{
  "wp_config": {
    "DB_HOST": "localhost",
    "DB_NAME": "my_local_db",
    "DB_USER": "root",
    "DB_PASSWORD": "password",
    "WP_HOME": "http://my-local-dev.test",
    "WP_SITEURL": "http://my-local-dev.test"
  },
  "theme_options": {
    "api_endpoint": "https://api.dev.example.com",
    "debug_mode": true
  },
  "plugins": {
    "advanced-custom-fields-pro/acf.php": {
      "enabled": true,
      "settings": {
        "google_api_key": "DEV_GOOGLE_API_KEY_12345"
      }
    },
    "woocommerce/woocommerce.php": {
      "enabled": false
    }
  }
}

Integrating Custom Environments with Sage Roots

Sage Roots’ build process, managed by Bedrock, typically handles environment configuration. We need to hook into this process to load our custom environment’s settings. The `config/application.php` file is the central point for this integration.

Modifying `config/application.php`

We’ll extend the existing logic to detect our custom `WP_ENV` and load the corresponding JSON configuration. Sage’s `Config` class provides a convenient way to load and merge configurations.

<?php
/**
 * Sage configuration file.
 *
 * @package Sage
 */

use Roots\Sage\Config;
use Illuminate\Support\Arr;

/**
 * @param string $file
 * @return string
 */
function config_path($file = '') {
    $path = WP_CONTENT_DIR . '/themes/' . basename(get_template_directory()) . '/config';
    return $path . ($file ? DIRECTORY_SEPARATOR . $file : '');
}

// Determine the current environment
$env = env('WP_ENV') ?: 'production';

// Base configuration
$config = Config::read('config.php'); // Loads config/config.php

// Load environment-specific configuration
$env_config_path = config_path("environments/{$env}.json");

if (file_exists($env_config_path)) {
    $env_settings = json_decode(file_get_contents($env_config_path), true);
    if (json_last_error() === JSON_ERROR_NONE) {
        // Merge environment settings into the main config
        // This is a simplified merge; for deep merging, consider a library
        $config = array_replace_recursive($config, $env_settings);
    } else {
        // Handle JSON parsing error if necessary
        error_log("JSON parsing error in {$env_config_path}: " . json_last_error_msg());
    }
}

// Apply configurations
Config::apply($config);

// Define constants from wp_config section if present
if (isset($config['wp_config']) && is_array($config['wp_config'])) {
    foreach ($config['wp_config'] as $key => $value) {
        if (!defined($key)) {
            define($key, $value);
        }
    }
}

// Example of using theme_options
if (isset($config['theme_options']) && is_array($config['theme_options'])) {
    // You might store these in theme options or use them directly
    // For demonstration, let's assume they are accessible via Config::get()
    // Example: Config::get('theme_options.api_endpoint')
}

// Example of managing plugin enablement/settings
if (isset($config['plugins']) && is_array($config['plugins'])) {
    add_action('plugins_loaded', function() use ($config) {
        foreach ($config['plugins'] as $plugin_file => $plugin_config) {
            if (isset($plugin_config['enabled']) && $plugin_config['enabled']) {
                // Ensure plugin is active
                if (!is_plugin_active($plugin_file)) {
                    activate_plugin($plugin_file);
                }
                // Further logic to apply plugin-specific settings if needed
                // e.g., if ($plugin_file === 'advanced-custom-fields-pro/acf.php' && isset($plugin_config['settings']['google_api_key'])) {
                //     // Logic to set ACF Google API Key, potentially via ACF's API or options
                // }
            } else {
                // Ensure plugin is inactive
                if (is_plugin_active($plugin_file)) {
                    deactivate_plugin($plugin_file);
                }
            }
        }
    });
}

return $config;
?>

Setting the `WP_ENV` Constant

To activate our custom environment, we need to set the `WP_ENV` constant. This is typically done in `wp-config.php`. For local development, you might set this directly or use environment variables managed by tools like Docker or Vagrant.

Modifying `wp-config.php`

<?php

/**
 * Sage configuration.
 *
 * @package Sage
 */

define('WP_ENV', getenv('WP_ENV') ?: 'development'); // Default to 'development' if not set

// ... other wp-config.php settings ...

// Load Sage configuration
require_once(get_template_directory() . '/config/application.php');

// ... rest of wp-config.php ...
?>

If you are using a local development environment manager (like Local by Flywheel, DevKinsta, or a custom Docker setup), you’ll configure the `WP_ENV` variable within that manager’s settings or via environment files (e.g., `.env`). For instance, if you’re using a `.env` file with a tool that loads it (like WP-CLI’s `wp-env` or a custom script), you would add:

WP_ENV=local-dev

Advanced Considerations and Best Practices

Deep Merging Configuration

The `array_replace_recursive` function is a basic way to merge configurations. For more complex nested arrays, especially where you might want to append rather than replace, consider using a dedicated array merging library or implementing a more sophisticated recursive merge function. This is crucial if your environment configurations have deeply nested structures that need to be combined intelligently.

Plugin Management Logic

The example shows basic activation/deactivation. For more granular control, you might need to interact with plugin APIs directly. For instance, setting ACF field group visibility or modifying WooCommerce settings based on the environment. This often involves checking the environment within plugin-specific hooks or functions and applying settings accordingly.

Security and Sensitive Data

Never commit sensitive data (API keys, database passwords) directly into your version control system, even in JSON files. Use environment variables for secrets. Your `config/environments/*.json` files should reference environment variables, and your `wp-config.php` or `config/application.php` should load these variables using `getenv()` or a library like `vlucas/phpdotenv`.

// Example in config/environments/local-dev.json
{
  "wp_config": {
    "DB_PASSWORD": "${DB_PASSWORD_LOCAL}" // Expects DB_PASSWORD_LOCAL env var
  },
  "theme_options": {
    "api_endpoint": "${API_ENDPOINT_DEV}",
    "google_api_key": "${GOOGLE_API_KEY_DEV}"
  }
}
// Example in config/application.php to load env vars
// ... inside the loop for wp_config ...
if (!defined($key)) {
    $value_to_define = $value;
    if (is_string($value) && strpos($value, '${') === 0 && strpos($value, '}') === strlen($value) - 1) {
        $env_var_name = substr($value, 2, -1); // Extract variable name
        $env_value = getenv($env_var_name);
        if ($env_value !== false) {
            $value_to_define = $env_value;
        } else {
            // Handle missing environment variable, e.g., throw an error or use a default
            error_log("Environment variable {$env_var_name} not set for {$key}.");
            // Optionally: $value_to_define = 'default_fallback_value';
        }
    }
    define($key, $value_to_define);
}
// ...

Extending Beyond `wp_config`

The `theme_options` and `plugins` sections in the JSON are illustrative. You can define any structure needed for your project. This could include settings for specific plugins, custom post type configurations, or even feature flags that are toggled per environment. The key is to parse this data within `config/application.php` and apply it appropriately, either by directly using `Config::get()` or by hooking into WordPress actions and filters.

Conclusion

By defining custom environment schemas using JSON files and integrating them into Sage Roots’ `config/application.php`, developers gain a powerful and organized way to manage environment-specific configurations. This approach enhances maintainability, reduces the risk of configuration errors, and allows for more sophisticated deployment strategies. Always prioritize security by using environment variables for sensitive data, ensuring your custom environment setup is both robust and secure.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • How to securely integrate Mailchimp Newsletter endpoints into WordPress custom plugins using WordPress Database Class ($wpdb)
  • Implementing automated compliance reporting for custom member profile directories ledgers using mpdf engine
  • Step-by-Step Guide: Refactoring legacy hooks to use Factory Method design structures pattern in theme layers
  • Building secure B2B pricing grids with custom Rewrite API custom endpoints endpoints and role overrides
  • WordPress Development Recipe: Staggered database writes for high-volume custom form fields using WordPress Options API

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (637)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (842)
  • PHP (5)
  • PHP Development (37)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (617)
  • SEO & Growth (492)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (251)
  • WordPress Theme Development (357)

Recent Posts

  • How to securely integrate Mailchimp Newsletter endpoints into WordPress custom plugins using WordPress Database Class ($wpdb)
  • Implementing automated compliance reporting for custom member profile directories ledgers using mpdf engine
  • Step-by-Step Guide: Refactoring legacy hooks to use Factory Method design structures pattern in theme layers

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (842)
  • Debugging & Troubleshooting (637)
  • Security & Compliance (617)
  • SEO & Growth (492)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala