如何在古腾堡选项面板中查询多个帖子类型?

时间:2021-02-10 作者:dingo_d

我正在使用React select,以便创建一个阻止选项,该选项将为我提供根据所选帖子类型选择帖子类型和帖子的选项。基本上,如果我没弄错的话,Gutenberg插件中正在使用的查询块。

enter image description here

现在最困扰我的是,我无法找到从所选选项中获取所有帖子的最佳方法。

例如,我可以获取所有允许的帖子类型,如下所示:

    const postTypeOptions = useSelect((select) => {
        const { getPostTypes } = select(\'core\');

        const items = getPostTypes() ?? [];

        const data = items.filter((element) => manifest.allowed.postTypes.find((item) => element.slug === item)) ?? [];

        return data.map((item) => {
            return {
                label: item.labels.name,
                value: item.slug,
                taxonomies: item.taxonomies,
            };
        }) ?? [];
    });
我在我的区块的选项部分,我有一个清单。json,在这里我可以过滤允许的帖子类型(我不需要所有可用的帖子类型)。

上面的代码将要做的是,当我选择我的块时,它将执行API获取,以使用getPostTypes(), 在我看来,这相当于wp.data.select(\'core\').getPostTypes().

现在,可以使用getEntityRecords() 喜欢

wp.data.select( \'core\' ).getEntityRecords( \'postType\', \'post\' )
这将给我的职位在我的WP。我可以更换post 任何自定义帖子类型都可以获取该自定义帖子类型的帖子。

但问题是我无法从多个帖子类型中获得所有帖子。

原因是在这下面getEntityRecords 正在Ping API端点,无法一次从多个帖子类型中从一个端点检索所有帖子。

那么我该如何解决这个问题呢?创建一个自定义端点,该端点将根据作为端点参数传递的内容返回所有帖子?正在提取useSelect 不是很好,因为每次我碰到方块都会触发。使用来自的内容wp.data.select 使用缓存和反应存储来避免这种情况。

任何关于如何实现这一目标的建议都会非常有用。

2 个回复
最合适的回答,由SO网友:dingo_d 整理而成

好的,经过一些研究,我得到了我需要的结果:

// Fetch all posts based on the selected postType.
const postsOptions = useSelect((select) => {
    const { getEntityRecords } = select(\'core\');
    const { isResolving } = select(\'core/data\');

    const postTypeSlugs = [...postType].map((element) => element.value) ?? [];

    if (!postTypeSlugs.length) {
        return [
            {
                label: __(\'No Filter used\', \'slug\'),
                value: \'\',
            }
        ]
    }

    const postList = [];

    postTypeSlugs.forEach((postType) => {
        const args = [\'postType\', postType, {per_page: -1}];

        if (!isResolving(\'core\', \'getEntityRecords\', args)) {
            const result = getEntityRecords(\'postType\', postType, {per_page: -1});

            if (result !== null) {
                postList.push(result);
            }
        }
    });

    if (typeof(postList[0]) !== \'undefined\') {
        return [
            {
                label: __(\'No Filter used\', \'slug\'),
                value: \'\',
            },
            ...postList[0].map((item) => {
                if (isEmpty(item)) {
                    return {};
                } else {
                    return {
                        label: item.title.rendered || \'\',
                        value: item.id || \'\',
                    };
                }
            }),
        ];
    }
});
加上来自here, 检查数组是否为空

const isEmpty = a => Array.isArray(a) && a.every(isEmpty);
这似乎奏效了。不太好看,但可以完成这项工作(据我所知,没有额外的api调用)。

SO网友:Kalle

因为我在做研究的时候无意中发现了这条线索,但它并没有给我带来我想要的结果。因此,我决定在这里注册,以指出我获取具有多种帖子类型的帖子的需要的方法。

有一点是restAPI本身不接受多个post类型。我想这就是为什么getEntityRecords也不提供这种功能的原因。

1)我注册了一个新的RestAPI端点,以便在使用它时能够查询多个帖子类型:

//PHP
add_action( \'rest_post_query\', function( $args, $request ){
    $post_types = $request->get_param( \'type\' );
    if( ! empty( $post_types ) ){
        if( is_string( $post_types ) ){
            // filtering posttypes, seperated with comma into an array, ignoring square brackets
            $post_types = explode( \',\', str_replace( array( \'[\', \']\') , \'\', $post_types ) );
            foreach ( $post_types as $key => $post_type ){
                $object =  get_post_type_object( $post_type );
                if( ! $object || ! $object->show_in_rest   ){
                    unset( $post_types[ $key ] );
                }
            }
        }
        $args[ \'post_type\' ] = $post_types;
    } else {
        // fallback: no type defined, return post as default
        $args[ \'post_type\' ] = \'post\';
    }
    return $args;
}, 10, 2 );
通过使用浏览器调用新的API端点,轻松检查它

https://*yoururl.com*/wp-json/wp/v2/posts?per_page=10&categories=0&type=posts,page
我不再使用古腾堡函数getEntityRecords来获取帖子。我选择了这种性能方面的方式,以避免多次调用getEntityRecords。

2)在我的古腾堡街区,我创建了一个钩子来调用:

export default function useFetchPosts( url ) {
    const [data, setData] = useState( null );
    useEffect(() => {
        async function loadData() {
            const response = await fetch( url );
            if(! response.ok ) {
                return false;
            }
            const posts = await response.json();
            setData(posts);
        }
        loadData();
    }, [url]);
    return data;
}
3)要获得帖子,我只需在编辑块中这样称呼它:

// parsedCategories and
// parsedPostTypes  have to set and parsed by you before ofcourse ;)
const numberposts = 10;
const postFields = \'&_fields=id,author,link,title,_links\';
const posts = useFetchPosts( \'https://\'+window.location.host+\'/wp-json/wp/v2/posts?per_page=\'+numberposts+\'&categories=\'+parsedCategories+\'&_embed=author&type=\'+parsedPostTypes+\'&orderby=date&order=desc\'+postFields );
查看restAPI参考以了解可用的参数和参数:https://developer.wordpress.org/rest-api/using-the-rest-api/global-parameters/

干杯

相关推荐