在私有命名空间路由上使用REST API(V2)Java脚本客户端

时间:2016-07-19 作者:Dalton Rooney

我在一个项目中使用了最新版本的REST API插件,并将我的路由添加到了一个单独的名称空间(如中所建议的那样the documentation). API中包含的javascript客户端根据中的公共路由自动创建模型和集合wp/v2 命名空间。

有人知道是否可以扩展内置客户端以使用自定义名称空间,并自动解析根端点以生成我的私有API的模型和集合吗?

1 个回复
SO网友:jgraup

要修改rest url prefix 您可以筛选rest_url_prefix. 但这只是改变了/wp-json/ 每个命名空间使用的前缀。

正在尝试修改wp/v2 意味着修改插件,名称空间在几个地方进行了硬编码,如;WP_REST_Post_Statuses_Controller.

添加您自己的custom endpoints, register_rest_route 核心就是要做到这一点。

<?php
add_action( \'rest_api_init\', function () {
    register_rest_route( \'your-namespace-here/v1\', \'/author/(?P<id>\\d+)\', array(
        \'methods\' => \'GET\',
        \'callback\' => \'my_awesome_func\',
    ) );
} );
你得多看看discovery process 查看为您的API自动构建的内容。

这个controller pattern 的示例WP REST API Plugin 应该可以让您很好地了解什么可以进入WP REST控制器。

add_action( \'rest_api_init\', function () {

    /*
     *      /wp-json/vendor/v1
     */

    $routes = new Slug_Custom_Route();
    $routes->register_routes();

});


class Slug_Custom_Route extends WP_REST_Controller {

    /**
     * Register the routes for the objects of the controller.
     */
    public function register_routes() {
        $version = \'1\';
        $namespace = \'vendor/v\' . $version;
        $base = \'route\';
        register_rest_route( $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 ),
            ),
        ) );
        register_rest_route( $namespace, \'/\' . $base . \'/(?P<id>[\\d]+)\', array(
            array(
                \'methods\'         => WP_REST_Server::READABLE,
                \'callback\'        => array( $this, \'get_item\' ),
                \'permission_callback\' => array( $this, \'get_item_permissions_check\' ),
                \'args\'            => array(
                    \'context\'          => array(
                        \'default\'      => \'view\',
                    ),
                ),
            ),
            array(
                \'methods\'         => WP_REST_Server::EDITABLE,
                \'callback\'        => array( $this, \'update_item\' ),
                \'permission_callback\' => array( $this, \'update_item_permissions_check\' ),
                \'args\'            => $this->get_endpoint_args_for_item_schema( false ),
            ),
            array(
                \'methods\'  => WP_REST_Server::DELETABLE,
                \'callback\' => array( $this, \'delete_item\' ),
                \'permission_callback\' => array( $this, \'delete_item_permissions_check\' ),
                \'args\'     => array(
                    \'force\'    => array(
                        \'default\'      => false,
                    ),
                ),
            ),
        ) );
        register_rest_route( $namespace, \'/\' . $base . \'/schema\', array(
            \'methods\'         => WP_REST_Server::READABLE,
            \'callback\'        => array( $this, \'get_public_item_schema\' ),
        ) );
    }

    /**
     * Get a collection of items
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|WP_REST_Response
     */
    public function get_items( $request ) {
        $items = array(); //do a query, call another class, etc
        $data = array();
        foreach( $items as $item ) {
            $itemdata = $this->prepare_item_for_response( $item, $request );
            $data[] = $this->prepare_response_for_collection( $itemdata );
        }

        return new WP_REST_Response( $data, 200 );
    }

    /**
     * Get one item from the collection
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|WP_REST_Response
     */
    public function get_item( $request ) {
        //get parameters from request
        $params = $request->get_params();
        $item = array();//do a query, call another class, etc
        $data = $this->prepare_item_for_response( $item, $request );

        //return a response or error based on some conditional
        if ( 1 == 1 ) {
            return new WP_REST_Response( $data, 200 );
        }else{
            return new WP_Error( \'code\', __( \'message\', \'text-domain\' ) );
        }
    }

    /**
     * Create one item from the collection
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|WP_REST_Request
     */
    public function create_item( $request ) {

        $item = $this->prepare_item_for_database( $request );

        if ( function_exists( \'slug_some_function_to_create_item\')  ) {
            $data = slug_some_function_to_create_item( $item );
            if ( is_array( $data ) ) {
                return new WP_REST_Response( $data, 200 );
            }
        }

        return new WP_Error( \'cant-create\', __( \'message\', \'text-domain\'), array( \'status\' => 500 ) );


    }

    /**
     * Update one item from the collection
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|WP_REST_Request
     */
    public function update_item( $request ) {
        $item = $this->prepare_item_for_database( $request );

        if ( function_exists( \'slug_some_function_to_update_item\')  ) {
            $data = slug_some_function_to_update_item( $item );
            if ( is_array( $data ) ) {
                return new WP_REST_Response( $data, 200 );
            }
        }

        return new WP_Error( \'cant-update\', __( \'message\', \'text-domain\'), array( \'status\' => 500 ) );

    }

    /**
     * Delete one item from the collection
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|WP_REST_Request
     */
    public function delete_item( $request ) {
        $item = $this->prepare_item_for_database( $request );

        if ( function_exists( \'slug_some_function_to_delete_item\')  ) {
            $deleted = slug_some_function_to_delete_item( $item );
            if (  $deleted  ) {
                return new WP_REST_Response( true, 200 );
            }
        }

        return new WP_Error( \'cant-delete\', __( \'message\', \'text-domain\'), array( \'status\' => 500 ) );
    }

    /**
     * Check if a given request has access to get items
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|bool
     */
    public function get_items_permissions_check( $request ) {
        //return true; <--use to make readable by all
        return current_user_can( \'edit_something\' );
    }

    /**
     * Check if a given request has access to get a specific item
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|bool
     */
    public function get_item_permissions_check( $request ) {
        return $this->get_items_permissions_check( $request );
    }

    /**
     * Check if a given request has access to create items
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|bool
     */
    public function create_item_permissions_check( $request ) {
        return current_user_can( \'edit_something\' );
    }

    /**
     * Check if a given request has access to update a specific item
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|bool
     */
    public function update_item_permissions_check( $request ) {
        return $this->create_item_permissions_check( $request );
    }

    /**
     * Check if a given request has access to delete a specific item
     *
     * @param WP_REST_Request $request Full data about the request.
     * @return WP_Error|bool
     */
    public function delete_item_permissions_check( $request ) {
        return $this->create_item_permissions_check( $request );
    }

    /**
     * Prepare the item for create or update operation
     *
     * @param WP_REST_Request $request Request object
     * @return WP_Error|object $prepared_item
     */
    protected function prepare_item_for_database( $request ) {
        return array();
    }

    /**
     * Prepare the item for the REST response
     *
     * @param mixed $item WordPress representation of the item.
     * @param WP_REST_Request $request Request object.
     * @return mixed
     */
    public function prepare_item_for_response( $item, $request ) {
        return array();
    }

    /**
     * Get the query params for collections
     *
     * @return array
     */
    public function get_collection_params() {
        return array(
            \'page\'                   => array(
                \'description\'        => \'Current page of the collection.\',
                \'type\'               => \'integer\',
                \'default\'            => 1,
                \'sanitize_callback\'  => \'absint\',
            ),
            \'per_page\'               => array(
                \'description\'        => \'Maximum number of items to be returned in result set.\',
                \'type\'               => \'integer\',
                \'default\'            => 10,
                \'sanitize_callback\'  => \'absint\',
            ),
            \'search\'                 => array(
                \'description\'        => \'Limit results to those matching a string.\',
                \'type\'               => \'string\',
                \'sanitize_callback\'  => \'sanitize_text_field\',
            ),
        );
    }
}
当您直接转到命名空间的端点时/wp-json/vendor/v1 您应该看到:

{
    "namespace": "vendor\\/v1",
    "routes": {
        "\\/vendor\\/v1": {
            "namespace": "vendor\\/v1",
            "methods": ["GET"],
            "endpoints": [{
                "methods": ["GET"],
                "args": {
                    "namespace": {
                        "required": false,
                        "default": "vendor\\/v1"
                    },
                    "context": {
                        "required": false,
                        "default": "view"
                    }
                }
            }],
            "_links": {
                "self": "http:\\/\\/example.com\\/wp-json\\/vendor\\/v1"
            }
        },
        "\\/vendor\\/v1\\/route": {
            "namespace": "vendor\\/v1",
            "methods": ["GET", "POST", "GET", "POST"],
            "endpoints": [{
                "methods": ["GET"],
                "args": []
            }, {
                "methods": ["POST"],
                "args": []
            }, {
                "methods": ["GET"],
                "args": []
            }, {
                "methods": ["POST"],
                "args": []
            }],
            "_links": {
                "self": "http:\\/\\/example.com\\/wp-json\\/vendor\\/v1\\/route"
            }
        },
        "\\/vendor\\/v1\\/route\\/(?P<id>[\\\\d]+)": {
            "namespace": "vendor\\/v1",
            "methods": ["GET", "POST", "PUT", "PATCH", "DELETE", "GET", "POST", "PUT", "PATCH", "DELETE"],
            "endpoints": [{
                "methods": ["GET"],
                "args": {
                    "context": {
                        "required": false,
                        "default": "view"
                    }
                }
            }, {
                "methods": ["POST", "PUT", "PATCH"],
                "args": []
            }, {
                "methods": ["DELETE"],
                "args": {
                    "force": {
                        "required": false,
                        "default": false
                    }
                }
            }, {
                "methods": ["GET"],
                "args": {
                    "context": {
                        "required": false,
                        "default": "view"
                    }
                }
            }, {
                "methods": ["POST", "PUT", "PATCH"],
                "args": []
            }, {
                "methods": ["DELETE"],
                "args": {
                    "force": {
                        "required": false,
                        "default": false
                    }
                }
            }]
        },
        "\\/vendor\\/v1\\/route\\/schema": {
            "namespace": "vendor\\/v1",
            "methods": ["GET", "GET"],
            "endpoints": [{
                "methods": ["GET"],
                "args": []
            }, {
                "methods": ["GET"],
                "args": []
            }],
            "_links": {
                "self": "http:\\/\\/example.com\\/wp-json\\/vendor\\/v1\\/route\\/schema"
            }
        }
    },
    "_links": {
        "up": [{
            "href": "http:\\/\\/example.com\\/wp-json\\/"
        }]
    }
}
突出的两个主要方面是:

\'args\' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE )
以及

\'args\'     => array (
    \'force\' => array (
        \'default\' => false,
    ),
),
另一个传球的例子$argsregister_rest_route 将显示在命名空间根目录中:

register_rest_route( "{$root}/{$version}", \'/products\', array(
        array(
            \'methods\'         => \\WP_REST_Server::READABLE,
            \'callback\'        => array( $cb_class, \'get_items\' ),
            \'args\'            => array(
                \'per_page\' => array(
                    \'default\' => 10,
                    \'sanitize_callback\' => \'absint\',
                ),
                \'page\' => array(
                    \'default\' => 1,
                    \'sanitize_callback\' => \'absint\',
                ),
                \'soon\' => array(
                    \'default\' => 0,
                    \'sanitize_callback\' => \'absint\',
                ),
                \'slug\' => array(
                    \'default\' => false,
                    \'sanitize_callback\' => \'sanitize_title\',
                )

            ),

            \'permission_callback\' => array( $this, \'permissions_check\' )
        ),
    )

);
再看远一点,get_data_for_route 用于收集discovery endpoints 而且是filterable 具有rest_endpoints_descriptionget_data_for_route. 因此,从理论上讲,如果默认设置不能满足您的需要,您可以使用该过滤器为您的私有API添加模型和/或集合。

因此,将所有这些放在一起并覆盖自动端点:

function my_awesome_func( WP_REST_Request $request) {
    return "awesome! " . $request->get_param( \'id\' );
}

add_action( \'rest_api_init\', function() {
    register_rest_route( \'my-thing/v1\', \'/awesome/(?P<id>\\d+)\', array (
        \'methods\'  => \'GET\',
        \'callback\' => \'my_awesome_func\',
    ) );
} );

add_filter( \'rest_endpoints_description\', function( $data ) {

    if ( $data[ \'namespace\' ] === \'my-thing/v1\' ) {

        $data[ \'endpoints\' ] = array (
            \'foo\'     => \'bar\',
            \'my\'      => \'custom-api\',
            \'awesome\' => \'it really is\',
        );
    }

    return $data;
} );

/*
 {
    "namespace": "my-thing\\/v1",
    "routes": {
        "\\/my-thing\\/v1": {
            "namespace": "my-thing\\/v1",
            "methods": ["GET"],
            "endpoints": {
                "foo": "bar",
                "my": "custom-api",
                "awesome": "it really is"
            },
            "_links": {
                "self": "http:\\/\\/example.com\\/wp-json\\/my-thing\\/v1"
            }
        },
        "\\/my-thing\\/v1\\/awesome\\/(?P<id>\\\\d+)": {
            "namespace": "my-thing\\/v1",
            "methods": ["GET"],
            "endpoints": {
                "foo": "bar",
                "my": "custom-api",
                "awesome": "it really is"
            }
        }
    },
    "_links": {
        "up": [{
            "href": "http:\\/\\/example.com\\/wp-json\\/"
        }]
    }
}
*/

相关推荐

安装和卸载WP-REST-API插件后API返回空白响应

WordPress/WooCommerce API在我的网站上被破坏:http://example.com/wp-json/wp/v2/posts 和http://example.com/wp-json/wc/v2/products 两者都返回空白响应。运行Python请求response = requests.get(\'http://<mysite>.com/wp-json/wp/v2/posts\', auth=HTTPBasicAuth(*auth)) 给出的响应(在调试器中