- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我过去曾在多个网站上使用过 WordPress REST API 版本 1 (V1)。我广泛使用的一项功能是能够在单个查询中调用多种帖子类型。
在 WP REST API 版本 1 中,我能够使用以下端点获取包含来自 book
和 movie
帖子类型的帖子的列表:
http://example.com/wp-json/posts?type[]=book&type[]=movie
我已经设置了我的自定义帖子类型,以便可以从 api 访问它们并且可以像这样调用它们:
http://example.com/wp-json/wp/v2/book/
http://example.com/wp-json/wp/v2/movie/
在 WP REST API 版本 2 (V2) 中实现此目的的最佳方法是什么?我研究了自定义端点,但我不确定这是否是对我来说最好的解决方案 (http://v2.wp-api.org/extending/adding/)。可能有十几种自定义帖子类型,我需要根据用户输入的他们希望看到的内容类型来运行动态查询。
如果有人以前解决过类似问题,我愿意接受想法或建议。
谢谢大家!
更新:
我在 WP-API 问题论坛上被告知这在 V2 中是不可能的:https://github.com/WP-API/WP-API/issues/2567
这对我来说完全没有意义。在 WordPress 中,我可以为 movie
创建一个帖子类型,为 book
创建另一个帖子类型,并且两者都可以共享 genre
的自定义分类。使用 WP_Query
,我可以在一个循环中查询这两种帖子类型,如果我愿意,可以根据类型查询。为什么 WordPress 的 REST API 不包括同时查询这两个的基本功能,特别是因为它在 V1 中运行良好?如果没有此功能,我将无法将我当前的 Web 应用程序从 V1 更新到 V2。
我现在的问题是,是否有人成功创建了可以创建此功能的端点?
最佳答案
我正是需要您所要求的功能,所以我制作了一个自定义端点。它只公开了对多个帖子的 WP_REST_Server::READABLE
请求,但它似乎工作得很好。
大多数 post-type 特定的东西被简单地转发到 WP_REST_Posts_Controller 实例,这些实例为每个查询结果实例化。我希望这会降低与其他插件或 future API 更新出现兼容性问题的风险。
请随意使用以下代码:
/**
* Custom endpoint for querying for multiple post-types.
* Mimics `WP_REST_Posts_Controller` as closely as possible.
*
* New filters:
* - `rest_multiple_post_type_query` Filters the query arguments as generated
* from the request parameters.
*
* @author Ruben Vreeken
*/
class WP_REST_MultiplePostType_Controller extends WP_REST_Controller
{
public function __construct()
{
$this->version = '2';
$this->namespace = 'websiteje/v' . $this->version;
$this->rest_base = 'multiple-post-type';
}
/**
* Register the routes for the objects of the controller.
*/
public function register_routes()
{
register_rest_route($this->namespace, '/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_params(),
),
));
}
/**
* Check if a given request has access to get items
*
* @return bool
*/
public function get_items_permissions_check($request)
{
return true;
}
/**
* 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)
{
$args = array();
$args['author__in'] = $request['author'];
$args['author__not_in'] = $request['author_exclude'];
$args['menu_order'] = $request['menu_order'];
$args['offset'] = $request['offset'];
$args['order'] = $request['order'];
$args['orderby'] = $request['orderby'];
$args['paged'] = $request['page'];
$args['post__in'] = $request['include'];
$args['post__not_in'] = $request['exclude'];
$args['posts_per_page'] = $request['per_page'];
$args['name'] = $request['slug'];
$args['post_type'] = $request['type'];
$args['post_parent__in'] = $request['parent'];
$args['post_parent__not_in'] = $request['parent_exclude'];
$args['post_status'] = $request['status'];
$args['s'] = $request['search'];
$args['date_query'] = array();
// Set before into date query. Date query must be specified as an array
// of an array.
if (isset($request['before'])) {
$args['date_query'][0]['before'] = $request['before'];
}
// Set after into date query. Date query must be specified as an array
// of an array.
if (isset($request['after'])) {
$args['date_query'][0]['after'] = $request['after'];
}
if (is_array($request['filter'])) {
$args = array_merge($args, $request['filter']);
unset($args['filter']);
}
// Ensure array of post_types
if (!is_array($args['post_type'])) {
$args['post_type'] = array($args['post_type']);
}
/**
* Filter the query arguments for a request.
*
* Enables adding extra arguments or setting defaults for a post
* collection request.
*
* @see https://developer.wordpress.org/reference/classes/wp_user_query/
*
* @param array $args Key value array of query var to query value.
* @param WP_REST_Request $request The request used.
*
* @var Function
*/
$args = apply_filters("rest_multiple_post_type_query", $args, $request);
$query_args = $this->prepare_items_query($args, $request);
// Get taxonomies for each of the requested post_types
$taxonomies = wp_list_filter(get_object_taxonomies($query_args['post_type'], 'objects'), array('show_in_rest' => true));
// Construct taxonomy query
foreach ($taxonomies as $taxonomy) {
$base = !empty($taxonomy->rest_base) ? $taxonomy->rest_base : $taxonomy->name;
if (!empty($request[$base])) {
$query_args['tax_query'][] = array(
'taxonomy' => $taxonomy->name,
'field' => 'term_id',
'terms' => $request[$base],
'include_children' => false,
);
}
}
// Execute the query
$posts_query = new WP_Query();
$query_result = $posts_query->query($query_args);
// Handle query results
$posts = array();
foreach ($query_result as $post) {
// Get PostController for Post Type
$postsController = new WP_REST_Posts_Controller($post->post_type);
if (!$postsController->check_read_permission($post)) {
continue;
}
$data = $postsController->prepare_item_for_response($post, $request);
$posts[] = $postsController->prepare_response_for_collection($data);
}
// Calc total post count
$page = (int) $query_args['paged'];
$total_posts = $posts_query->found_posts;
// Out-of-bounds, run the query again without LIMIT for total count
if ($total_posts < 1) {
unset($query_args['paged']);
$count_query = new WP_Query();
$count_query->query($query_args);
$total_posts = $count_query->found_posts;
}
// Calc total page count
$max_pages = ceil($total_posts / (int) $query_args['posts_per_page']);
// Construct response
$response = rest_ensure_response($posts);
$response->header('X-WP-Total', (int) $total_posts);
$response->header('X-WP-TotalPages', (int) $max_pages);
// Construct base url for pagination links
$request_params = $request->get_query_params();
if (!empty($request_params['filter'])) {
// Normalize the pagination params.
unset($request_params['filter']['posts_per_page']);
unset($request_params['filter']['paged']);
}
$base = add_query_arg($request_params, rest_url(sprintf('/%s/%s', $this->namespace, $this->rest_base)));
// Create link for previous page, if needed
if ($page > 1) {
$prev_page = $page - 1;
if ($prev_page > $max_pages) {
$prev_page = $max_pages;
}
$prev_link = add_query_arg('page', $prev_page, $base);
$response->link_header('prev', $prev_link);
}
// Create link for next page, if needed
if ($max_pages > $page) {
$next_page = $page + 1;
$next_link = add_query_arg('page', $next_page, $base);
$response->link_header('next', $next_link);
}
return $response;
}
/**
* Determine the allowed query_vars for a get_items() response and prepare
* for WP_Query.
*
* @param array $prepared_args
* @param WP_REST_Request $request
*
* @return array $query_args
*/
protected function prepare_items_query($prepared_args = array(), $request = null)
{
$valid_vars = array_flip($this->get_allowed_query_vars($request['type']));
$query_args = array();
foreach ($valid_vars as $var => $index) {
if (isset($prepared_args[$var])) {
/**
* Filter the query_vars used in `get_items` for the constructed
* query.
*
* The dynamic portion of the hook name, $var, refers to the
* query_var key.
*
* @param mixed $prepared_args[ $var ] The query_var value.
*/
$query_args[$var] = apply_filters("rest_query_var-{$var}", $prepared_args[$var]);
}
}
// Only allow sticky psts if 'post' is one of the requested post types.
if (in_array('post', $query_args['post_type']) || !isset($query_args['ignore_sticky_posts'])) {
$query_args['ignore_sticky_posts'] = true;
}
if ('include' === $query_args['orderby']) {
$query_args['orderby'] = 'post__in';
}
return $query_args;
}
/**
* Get all the WP Query vars that are allowed for the API request.
*
* @return array
*/
protected function get_allowed_query_vars($post_types)
{
global $wp;
$editPosts = true;
/**
* Filter the publicly allowed query vars.
*
* Allows adjusting of the default query vars that are made public.
*
* @param array Array of allowed WP_Query query vars.
*
* @var Function
*/
$valid_vars = apply_filters('query_vars', $wp->public_query_vars);
/**
* We allow 'private' query vars for authorized users only.
*
* It the user has `edit_posts` capabilty for *every* requested post
* type, we also allow use of private query parameters, which are only
* undesirable on the frontend, but are safe for use in query strings.
*
* To disable anyway, use `add_filter( 'rest_private_query_vars',
* '__return_empty_array' );`
*
* @param array $private_query_vars Array of allowed query vars for
* authorized users.
*
* @var boolean
*/
$edit_posts = true;
foreach ($post_types as $post_type) {
$post_type_obj = get_post_type_object($post_type);
if (!current_user_can($post_type_obj->cap->edit_posts)) {
$edit_posts = false;
break;
}
}
if ($edit_posts) {
$private = apply_filters('rest_private_query_vars', $wp->private_query_vars);
$valid_vars = array_merge($valid_vars, $private);
}
// Define our own in addition to WP's normal vars.
$rest_valid = array(
'author__in',
'author__not_in',
'ignore_sticky_posts',
'menu_order',
'offset',
'post__in',
'post__not_in',
'post_parent',
'post_parent__in',
'post_parent__not_in',
'posts_per_page',
'date_query',
);
$valid_vars = array_merge($valid_vars, $rest_valid);
/**
* Filter allowed query vars for the REST API.
*
* This filter allows you to add or remove query vars from the final
* allowed list for all requests, including unauthenticated ones. To
* alter the vars for editors only, {@see rest_private_query_vars}.
*
* @param array {
* Array of allowed WP_Query query vars.
*
* @param string $allowed_query_var The query var to allow.
* }
*/
$valid_vars = apply_filters('rest_query_vars', $valid_vars);
return $valid_vars;
}
/**
* Get the query params for collections of attachments.
*
* @return array
*/
public function get_collection_params()
{
$params = parent::get_collection_params();
$params['context']['default'] = 'view';
$params['after'] = array(
'description' => __('Limit response to resources published after a given ISO8601 compliant date.'),
'type' => 'string',
'format' => 'date-time',
'validate_callback' => 'rest_validate_request_arg',
);
$params['author'] = array(
'description' => __('Limit result set to posts assigned to specific authors.'),
'type' => 'array',
'default' => array(),
'sanitize_callback' => 'wp_parse_id_list',
'validate_callback' => 'rest_validate_request_arg',
);
$params['author_exclude'] = array(
'description' => __('Ensure result set excludes posts assigned to specific authors.'),
'type' => 'array',
'default' => array(),
'sanitize_callback' => 'wp_parse_id_list',
'validate_callback' => 'rest_validate_request_arg',
);
$params['before'] = array(
'description' => __('Limit response to resources published before a given ISO8601 compliant date.'),
'type' => 'string',
'format' => 'date-time',
'validate_callback' => 'rest_validate_request_arg',
);
$params['exclude'] = array(
'description' => __('Ensure result set excludes specific ids.'),
'type' => 'array',
'default' => array(),
'sanitize_callback' => 'wp_parse_id_list',
);
$params['include'] = array(
'description' => __('Limit result set to specific ids.'),
'type' => 'array',
'default' => array(),
'sanitize_callback' => 'wp_parse_id_list',
);
$params['menu_order'] = array(
'description' => __('Limit result set to resources with a specific menu_order value.'),
'type' => 'integer',
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
);
$params['offset'] = array(
'description' => __('Offset the result set by a specific number of items.'),
'type' => 'integer',
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
);
$params['order'] = array(
'description' => __('Order sort attribute ascending or descending.'),
'type' => 'string',
'default' => 'desc',
'enum' => array('asc', 'desc'),
'validate_callback' => 'rest_validate_request_arg',
);
$params['orderby'] = array(
'description' => __('Sort collection by object attribute.'),
'type' => 'string',
'default' => 'date',
'enum' => array(
'date',
'id',
'include',
'title',
'slug',
),
'validate_callback' => 'rest_validate_request_arg',
);
$params['orderby']['enum'][] = 'menu_order';
$params['parent'] = array(
'description' => __('Limit result set to those of particular parent ids.'),
'type' => 'array',
'sanitize_callback' => 'wp_parse_id_list',
'default' => array(),
);
$params['parent_exclude'] = array(
'description' => __('Limit result set to all items except those of a particular parent id.'),
'type' => 'array',
'sanitize_callback' => 'wp_parse_id_list',
'default' => array(),
);
$params['slug'] = array(
'description' => __('Limit result set to posts with a specific slug.'),
'type' => 'string',
'validate_callback' => 'rest_validate_request_arg',
);
$params['status'] = array(
'default' => 'publish',
'description' => __('Limit result set to posts assigned a specific status.'),
'sanitize_callback' => 'sanitize_key',
'type' => 'string',
'validate_callback' => array($this, 'validate_user_can_query_private_statuses'),
);
$params['filter'] = array(
'description' => __('Use WP Query arguments to modify the response; private query vars require appropriate authorization.'),
);
$taxonomies = wp_list_filter(get_object_taxonomies(get_post_types(array(), 'names'), 'objects'), array('show_in_rest' => true));
foreach ($taxonomies as $taxonomy) {
$base = !empty($taxonomy->rest_base) ? $taxonomy->rest_base : $taxonomy->name;
$params[$base] = array(
'description' => sprintf(__('Limit result set to all items that have the specified term assigned in the %s taxonomy.'), $base),
'type' => 'array',
'sanitize_callback' => 'wp_parse_id_list',
'default' => array(),
);
}
return $params;
}
/**
* Validate whether the user can query private statuses
*
* @param mixed $value
* @param WP_REST_Request $request
* @param string $parameter
*
* @return WP_Error|boolean
*/
public function validate_user_can_query_private_statuses($value, $request, $parameter)
{
if ('publish' === $value) {
return true;
}
foreach ($request["type"] as $post_type) {
$post_type_obj = get_post_type_object($post_type);
if (!current_user_can($post_type_obj->cap->edit_posts)) {
return new WP_Error('rest_forbidden_status', __('Status is forbidden'), array(
'status' => rest_authorization_required_code(),
'post_type' => $post_type_obj->name,
));
}
}
return true;
}
}
要注册端点,您可以使用如下内容:
add_action('rest_api_init', 'init_wp_rest_multiple_post_type_endpoint');
function init_wp_rest_multiple_post_type_endpoint()
{
$controller = new WP_REST_MultiplePostType_Controller();
$controller->register_routes();
}
关于php - 使用 WP REST API V2 (WordPress) 查询多个帖子类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38059805/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!