• 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 Timber Twig templating engines extensions utilizing modern WP HTTP API schemas

How to build custom Timber Twig templating engines extensions utilizing modern WP HTTP API schemas

Leveraging the WP_HTTP API for Advanced Timber Twig Extensions

For enterprise-grade WordPress applications, extending the Timber Twig templating engine with custom functionalities is a common requirement. Often, these extensions need to interact with external services or fetch data dynamically. The WordPress HTTP API (`WP_HTTP`) provides a robust, standardized, and secure mechanism for making these outbound requests. This post details how to build custom Twig extensions that harness the `WP_HTTP` API, focusing on practical implementation patterns and considerations for production environments.

Registering Custom Twig Functions with Timber

Timber allows for the registration of custom Twig functions, filters, and global variables. To integrate `WP_HTTP` calls, we’ll define a custom Twig function that acts as a wrapper. This function will accept parameters for the URL, request method, headers, and body, and return the fetched data, typically in JSON format.

The registration process typically occurs within your theme’s `functions.php` file or, more appropriately for plugin development, within a plugin’s main file or an included service provider.

Example: Registering a `remote_get_json` Twig Function

This example demonstrates registering a function named `remote_get_json` that utilizes `wp_remote_get` to fetch JSON data from a specified URL.

<?php
/**
 * Plugin Name: Custom Timber HTTP Extensions
 * Description: Adds custom Twig functions for making HTTP requests.
 * Version: 1.0
 * Author: Antigravity
 */

use Timber\Twig_Function;

add_filter( 'timber/twig/functions', function( array $functions ) {
    $functions[] = new Twig_Function( 'remote_get_json', 'custom_timber_http_remote_get_json' );
    return $functions;
} );

/**
 * Fetches JSON data from a remote URL using WP_HTTP API.
 *
 * @param string $url The URL to fetch data from.
 * @param array  $args Optional. Arguments to pass to wp_remote_get.
 *                     See https://developer.wordpress.org/reference/functions/wp_remote_get/
 * @return array|WP_Error Decoded JSON data or a WP_Error object on failure.
 */
function custom_timber_http_remote_get_json( string $url, array $args = [] ): array | \WP_Error {
    $response = wp_remote_get( $url, $args );

    if ( is_wp_error( $response ) ) {
        return $response; // Return the WP_Error object directly
    }

    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );

    if ( json_last_error() !== JSON_ERROR_NONE ) {
        return new \WP_Error( 'json_decode_error', 'Failed to decode JSON response.' );
    }

    return $data;
}
?>

In this code:

  • We hook into the timber/twig/functions filter to add our custom function.
  • The remote_get_json function is defined, accepting a URL and optional arguments for wp_remote_get.
  • It uses wp_remote_get to make the request.
  • Error handling for WP_Error objects is crucial.
  • The response body is retrieved and decoded using json_decode.
  • A check for JSON decoding errors is included.
  • The decoded data (as a PHP associative array) or a WP_Error object is returned.

Utilizing the Custom Twig Function in Templates

Once registered, the remote_get_json function can be called directly within your Twig templates. This allows for dynamic content injection from external APIs.

{# Example: Fetching posts from an external WordPress REST API #}
{% set external_posts = remote_get_json('https://example.com/wp-json/wp/v2/posts', { 'headers': {'Accept': 'application/json'} }) %}

{% if external_posts is not instance of('WP_Error') %}
    {% if external_posts %}
        <h2>Latest Posts from External Site</h2>
        <ul>
            {% for post in external_posts %}
                <li><a href="{{ post.link }}">{{ post.title.rendered }}</a></li>
            {% endfor %}
        </ul>
    {% else %}
        <p>No external posts found.</p>
    {% endif %}
{% else %}
    <p>Error fetching external posts: {{ external_posts.get_error_message() }}</p>
{% endif %}

In this Twig snippet:

  • We call remote_get_json with the target API endpoint.
  • We pass an optional headers argument to ensure the API returns JSON.
  • Crucially, we check if the result is a WP_Error object before attempting to iterate over the data. This is essential for robust error handling.
  • If successful, we loop through the fetched posts and display their titles and links.

Advanced Scenarios: POST Requests and Authentication

The `WP_HTTP` API supports various request methods, including POST, PUT, DELETE, and more. You can create custom Twig functions for these as well, passing necessary data and authentication headers.

Example: `remote_post_json` Function

add_filter( 'timber/twig/functions', function( array $functions ) {
    $functions[] = new Twig_Function( 'remote_post_json', 'custom_timber_http_remote_post_json' );
    return $functions;
} );

/**
 * Sends a POST request with JSON data to a remote URL using WP_HTTP API.
 *
 * @param string $url The URL to send the POST request to.
 * @param array  $body The data to send in the request body (will be JSON encoded).
 * @param array  $args Optional. Additional arguments to pass to wp_remote_post.
 *                     See https://developer.wordpress.org/reference/functions/wp_remote_post/
 * @return array|WP_Error Decoded JSON response data or a WP_Error object on failure.
 */
function custom_timber_http_remote_post_json( string $url, array $body, array $args = [] ): array | \WP_Error {
    $default_args = [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept'       => 'application/json',
        ],
        'body'    => json_encode( $body ),
    ];

    $merged_args = array_merge_recursive( $default_args, $args );

    $response = wp_remote_post( $url, $merged_args );

    if ( is_wp_error( $response ) ) {
        return $response;
    }

    $body = wp_remote_retrieve_body( $response );
    $data = json_decode( $body, true );

    if ( json_last_error() !== JSON_ERROR_NONE ) {
        return new \WP_Error( 'json_decode_error', 'Failed to decode JSON response.' );
    }

    return $data;
}

When using this function in Twig, you would pass the data to be sent as the second argument:

{# Example: Submitting a form to an external API #}
{% set submission_data = {
    'name': 'John Doe',
    'email': '[email protected]',
    'message': 'Hello from Timber!'
} %}

{% set api_response = remote_post_json('https://api.external-service.com/submit', submission_data) %}

{% if api_response is not instance of('WP_Error') %}
    <p>Submission successful: {{ api_response.message }}</p>
{% else %}
    <p>Submission failed: {{ api_response.get_error_message() }}</p>
{% endif %}

Security and Performance Considerations

When building such extensions, security and performance are paramount:

  • Authentication: For authenticated requests, consider using WordPress’s built-in authentication mechanisms (e.g., OAuth, API keys) passed via headers. Avoid hardcoding sensitive credentials directly in the Twig or PHP code. Store them securely, perhaps in environment variables or WordPress options, and retrieve them within your PHP functions.
  • Rate Limiting: Be mindful of API rate limits. Implement caching strategies for responses to avoid excessive requests. WordPress transients API or object caching (e.g., Redis, Memcached) are excellent tools for this.
  • Timeouts: Configure appropriate timeouts for `wp_remote_get` and `wp_remote_post` to prevent your site from hanging if an external service is unresponsive. The `timeout` argument in the `$args` array is key here.
  • Error Handling: Comprehensive error handling, as demonstrated with `is_wp_error()` and `json_last_error()`, is non-negotiable. Log errors appropriately for debugging.
  • Input Validation: If your Twig functions accept user-provided input that is then passed to `WP_HTTP` calls, ensure rigorous sanitization and validation to prevent injection attacks or malformed requests.
  • Caching: Implement caching for API responses. This significantly improves performance and reduces load on both your server and the external API.
  • Implementing Caching with Transients API

    Here’s an enhanced version of `remote_get_json` that incorporates caching using the WordPress Transients API:

    add_filter( 'timber/twig/functions', function( array $functions ) {
        $functions[] = new Twig_Function( 'remote_get_json_cached', 'custom_timber_http_remote_get_json_cached' );
        return $functions;
    } );
    
    /**
     * Fetches JSON data from a remote URL using WP_HTTP API with caching.
     *
     * @param string $url The URL to fetch data from.
     * @param int    $cache_duration_seconds Duration in seconds to cache the response.
     * @param array  $http_args Optional. Arguments to pass to wp_remote_get.
     * @return array|WP_Error Decoded JSON data or a WP_Error object on failure.
     */
    function custom_timber_http_remote_get_json_cached( string $url, int $cache_duration_seconds = HOUR_IN_SECONDS, array $http_args = [] ): array | \WP_Error {
        // Generate a unique cache key based on URL and potentially important args
        $cache_key = 'remote_json_' . md5( $url . serialize( $http_args ) );
        $cached_data = get_transient( $cache_key );
    
        if ( false !== $cached_data ) {
            // Return cached data if available and valid
            return $cached_data;
        }
    
        $response = wp_remote_get( $url, $http_args );
    
        if ( is_wp_error( $response ) ) {
            return $response;
        }
    
        $body = wp_remote_retrieve_body( $response );
        $data = json_decode( $body, true );
    
        if ( json_last_error() !== JSON_ERROR_NONE ) {
            return new \WP_Error( 'json_decode_error', 'Failed to decode JSON response.' );
        }
    
        // Store the fetched data in transient cache
        set_transient( $cache_key, $data, $cache_duration_seconds );
    
        return $data;
    }
    

    Usage in Twig:

    {# Fetch posts, cache for 1 hour #}
    {% set external_posts = remote_get_json_cached('https://example.com/wp-json/wp/v2/posts', 3600, { 'headers': {'Accept': 'application/json'} }) %}
    
    {# ... rest of the template logic ... #}
    

    Conclusion

    By creating custom Twig functions that wrap the `WP_HTTP` API, you can seamlessly integrate dynamic external data into your Timber-powered WordPress sites. This approach offers a clean separation of concerns, enhances template readability, and leverages WordPress’s robust HTTP handling capabilities. Always prioritize security, performance, and thorough error handling in production deployments.

    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

    • Debugging Guide: Diagnosing PHP-FPM child process pool exhaustion in multi-site network environments with modern tools
    • Debugging and Resolving complex namespace class loading collisions issues during heavy concurrent database traffic
    • Step-by-Step Guide: Offloading high-frequency customer support tickets metadata writes to a Redis KV store
    • How to refactor legacy event ticket registers queries using modern WP_Query and custom Transient caching
    • Step-by-Step Guide: Offloading high-frequency member profile directories metadata writes to a Redis KV store

    Categories

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

    Recent Posts

    • Debugging Guide: Diagnosing PHP-FPM child process pool exhaustion in multi-site network environments with modern tools
    • Debugging and Resolving complex namespace class loading collisions issues during heavy concurrent database traffic
    • Step-by-Step Guide: Offloading high-frequency customer support tickets metadata writes to a Redis KV store

    Top Categories

    • DevOps & Cloud Scaling (962)
    • Performance & Optimization (873)
    • WordPress Plugin Development (726)
    • Debugging & Troubleshooting (662)
    • Security & Compliance (647)
    • SEO & Growth (492)

    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