如何在Timber PostQuery中注册未存入数据库的抓取数据?
解决Timber PostQuery无法获取API动态数据的方案
我之前也碰到过类似的问题——Timber的Post对象字段大多是受保护的,没法直接修改,但我们可以通过自定义Post类或者Timber内置过滤器来把API数据注入到Post实例里,让PostQuery能正常获取到这些动态内容。下面是两种最实用的方法:
方法一:自定义扩展Timber\Post类(推荐)
这种方式最灵活,能直接重写Post的默认方法(比如标题、内容的获取逻辑),完全贴合你的需求:
创建自定义Post类
在主题的functions.php或者单独的类文件里定义一个继承自Timber\Post的类,在构造函数里拉取API数据,还可以重写标题、内容的获取方法:class SyncedPost extends Timber\Post { public function __construct($pid = null, $args = []) { parent::__construct($pid, $args); // 调用你的API获取数据,这里假设你有一个根据标题取数据的函数 $api_data = $this->fetch_api_data_by_title($this->post_title); if ($api_data) { // 把API数据存在custom字段里,Twig里可以直接通过{{ post.custom.api_title }}访问 $this->custom['api_title'] = $api_data['title']; $this->custom['api_content'] = $api_data['content']; } } // 重写标题方法,优先返回API的标题 public function get_title() { if (!empty($this->custom['api_title'])) { return $this->custom['api_title']; } // 没有API数据时返回默认标题 return parent::get_title(); } // 重写内容方法,同理 public function get_content() { if (!empty($this->custom['api_content'])) { return $this->custom['api_content']; } return parent::get_content(); } // 封装API请求逻辑(可以单独抽出来,这里为了示例放在类里) private function fetch_api_data_by_title($title) { // 你的API请求代码,比如wp_remote_get $response = wp_remote_get('https://your-api-url.com/posts?title=' . urlencode($title)); if (is_wp_error($response)) return false; $body = wp_remote_retrieve_body($response); return json_decode($body, true); } }让PostQuery使用自定义类
用Timber的timber/post/class过滤器,指定特定帖子类型使用我们的自定义类:add_filter('timber/post/class', function($class_name, $wp_post) { // 替换成你的同步帖子类型,比如'synced_post' if ($wp_post->post_type === 'synced_post') { return 'SyncedPost'; } // 其他帖子类型保持默认 return $class_name; }, 10, 2);
这样,当你用Timber\PostQuery查询时,返回的每个帖子实例都会自动拉取API数据,你在Twig里直接用{{ post.title }}或者{{ post.content }}就能拿到API里的内容了。
方法二:用Timber过滤器注入数据(快速实现)
如果不想自定义类,也可以用timber/post/after_fetch过滤器,在Post实例创建后直接注入API数据:
add_filter('timber/post/after_fetch', function($timber_post, $wp_post) { // 只处理目标帖子类型 if ($wp_post->post_type !== 'synced_post') return $timber_post; // 拉取API数据 $api_data = fetch_api_data_by_title($wp_post->post_title); if (!$api_data) return $timber_post; // 把数据添加到custom字段,Twig里通过{{ post.custom.api_title }}访问 $timber_post->custom['api_title'] = $api_data['title']; $timber_post->custom['api_content'] = $api_data['content']; // 如果要替换默认的标题和内容,还可以用专门的过滤器 add_filter('timber/post/title', function($title) use ($api_data) { return $api_data['title'] ?: $title; }, 10, 1); add_filter('timber/post/content', function($content) use ($api_data) { return $api_data['content'] ?: $content; }, 10, 1); return $timber_post; }, 10, 2);
性能优化小技巧
如果一次查询多个帖子,每个帖子单独调用API会很慢,建议批量拉取API数据:
// 先执行查询 $query_args = [ 'post_type' => 'synced_post', 'posts_per_page' => -1, ]; $posts_query = new Timber\PostQuery($query_args); // 批量提取所有帖子标题 $all_titles = wp_list_pluck($posts_query->posts, 'post_title'); // 批量请求API(需要你的API支持批量查询) $api_batch_data = fetch_api_data_by_titles($all_titles); // 用过滤器注入批量数据 add_filter('timber/post/after_fetch', function($timber_post) use ($api_batch_data) { if (isset($api_batch_data[$timber_post->post_title])) { $data = $api_batch_data[$timber_post->post_title]; $timber_post->custom['api_title'] = $data['title']; $timber_post->custom['api_content'] = $data['content']; } return $timber_post; });
这样就能避免多次API请求,大幅提升页面加载速度。
内容的提问来源于stack exchange,提问作者Stan Derksen
相关产品推荐
相关产品推荐

