0

I have this question on Stack Overflow but thought here might be a better place for it...

I'm almost certainly doing something stupid - or rather not doing something obvious that I should have done. I'm writing a plugin to expose a function via http POST so I can send JSON to my wordpress app and store it in the db. I'm using the WP REST API plugin and have followed the "Adding custom endpoints" guide here http://v2.wp-api.org/extending/adding/

My plugin is as follows:-

# Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

require_once(ABSPATH . 'wp-content/plugins/rest-api/plugin.php');
require_once(dirname(__FILE__) . '/classes/myPlugin.php');
require_once(dirname(__FILE__) . '/classes/myController.php');

// Action hook to initialize the plugin
add_action('rest_api_init', array('myPlugin_Class', 'init' ));

register_activation_hook(__FILE__, array('myPlugin_Class', 'on_activation'));
register_deactivation_hook(__FILE__, array('myPlugin_Class', 'on_deactivation'));
register_uninstall_hook(__FILE__, array('myPlugin_Class', 'on_uninstall'));

The myPlugin_Class is just an encapsulation of the main plugin bits... It holds a reference to a static class myController which extends WP_REST_Controller. The plugin class excerpt with its init method and constructor is as follows:-

class MyPlugin_Class
{
    private static $instance;
    private static $myController = null;

    public static function init()
    {
        if(self::$instance == null) {
           self::$instance = new MyPlugin_Class();
        }
        return self::$instance;
    }

    private function __construct()
    {
        Static::$myController = MyController::init();
        Static::$myController->register_routes();
        flush_rewrite_rules();
    }

    public static function on_activation()
    {
        Static::init();

        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "activate-plugin_{$plugin}" );

        //Register routes and don't forget to flush
        $this->myController->register_routes();
        flush_rewrite_rules();
    }
}

The Controller class excerpt is as follows:-

class MyController extends WP_REST_Controller {

    private static $instance;
    private $namespace = 'api/vendor/v1';
    private $base = 'default';

    private function __construct(){
    }

    public static function init() {
        if(self::$instance == null) {
            self::$instance = new MyController();
        }
        return self::$instance;
    }

    /**
    * Register the routes for the objects of the controller.
    */
    public function register_routes() {
        $base = $this->default-base;
        register_rest_route( $this->namespace, '/' . $base, array(
            array(
                'methods'         => WP_REST_Server::READABLE,
                'callback'        => array( $this, 'get_items' ),
                'permission_callback' => array( $this, 'get_items_permissions_check' ),
                'args'            => array(

                ),
            ),
            array(
                'methods'         => WP_REST_Server::CREATABLE,
                'callback'        => array( $this, 'create_item' ),
                'permission_callback' => array( $this, 'create_item_permissions_check' ),
                'args'            => $this->get_endpoint_args_for_item_schema( true ),
            ),
        ) );
    }
}

I cant get the routes to register. Upon activation, in the call to register_rest_route, I get the error:-

Fatal error: Call to a member function register_route() on null in .../wp-content/plugins/rest-api/plugin.php on line 92

The function register_route() from the REST API Plugin

function register_rest_route( $namespace, $route, $args = array(), $override = false ) {

    /** @var WP_REST_Server $wp_rest_server */
    global $wp_rest_server;

    if ( isset( $args['callback'] ) ) {
        // Upgrade a single set to multiple
        $args = array( $args );
    }

    $defaults = array(
        'methods'         => 'GET',
        'callback'        => null,
        'args'            => array(),
    );
    foreach ( $args as $key => &$arg_group ) {
        if ( ! is_numeric( $arg_group ) ) {
            // Route option, skip here
            continue;
        }

        $arg_group = array_merge( $defaults, $arg_group );
    }

    if ( $namespace ) {
        $full_route = '/' . trim( $namespace, '/' ) . '/' . trim( $route, '/' );
    } else {
        // Non-namespaced routes are not allowed, with the exception of the main
        // and namespace indexes. If you really need to register a
        // non-namespaced route, call `WP_REST_Server::register_route` directly.
        _doing_it_wrong( 'register_rest_route', 'Routes must be namespaced with plugin name and version', 'WPAPI-2.0' );

        $full_route = '/' . trim( $route, '/' );
    }

    $wp_rest_server->register_route( $namespace, $full_route, $args, $override );
}

Where does this global $wp_rest_server get created (or in my case not created)?

i.e. what did I forget to do?

Bonus question:-

Should I call the flush_rewrite_rules() in the rest_api_init hook, the register_activation_hook or both?

1 Answer 1

2

Add to your __construct function:

add_action( 'rest_api_init',[$this, 'register_routes'] );

And the rest api will take it from there. No need to process routes in your activation functions, and no need to flush the rules.

The $wp_rest_server is constructed after the plugins are loaded. Hence it is null when you instantiate your class in the plugin.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.