Update 2: Check out @NateWr method using add_post_meta
with the default post:
add_post_meta( 1, 'my_items', 1 );
add_post_meta( 1, 'my_items', 2 );
add_post_meta( 1, 'my_items', new \stdClass );
var_dump(get_post_meta(1, 'my_items', true));
echo "<br><br>";
var_dump(get_post_meta(1));
echo "<br><br>";
$GLOBALS['wp_object_cache']->stats();
And the results:
string(1) "1"
array(1) {
["my_items"]=>array(3) {
[0]=> string(1) "1"
[1]=> string(1) "2"
[2]=> string(19) "O:8:"stdClass":0:{}"
}
}
This time, it hits the cache but the meta value is different. Now, if I don't know meta_key
and I just use only post ID to retrieve and parse post meta manually, it's obvious that i will get wrong value.
Update 1: Check out @NateWr method using update_post_meta
with the default post:
update_post_meta(1, 'my_items', 1);
update_post_meta(1, 'my_items', 2);
update_post_meta(1, 'my_items', 3);
var_dump( get_post_meta(1) );
echo "<br><br>";
$GLOBALS['wp_object_cache']->stats();
Results:
array(1) {
["my_items"]=>array(1) {
[0]=>string(1) "3"
}
}
Look like Cache Hits
doesn't change and WordPress still return an meaningless array as meta_value
. Or I missed something?
Question:
I'm trying to avoid extra queries on templates by pre-fetching necessary data while the WP_Query
retrieving posts. This is basically how it looks like:
add_filter('the_posts', function($posts, $query)
{
if ( !is_admin() ) {
$mapper = new Vendor\PostMapper($GLOBALS['wpdb']);
foreach ($posts as $post) {
$post->post_link = get_permalink($post);
$post->post_meta = $mapper->getMetadata($post);
$post->post_thumbnail = $mapper->getThumbnail($post);
...
}
}
return $posts;
}, PHP_INT_MAX, 2);
Everything works fine but I feel unease while parsing metadata. By using metadata API, if I don't specify meta_key
, meta values are always arrays of only one element such as:
array(3) {
["_edit_last"]=>array(1) {
[0]=>string(1) "1"
}
["_edit_lock"]=>array(1) {
[0]=>string(12) "1467358332:1"
}
["_thumbnail_id"]=>array(1) {
[0]=>string(3) "767"
}
}
I think I will never be able to know all meta_key
. I also have no ideas why WordPress need to do that. The arrays look meaningless and it bothers me a lot.
So, given that meta_key
isn't required and I don't specify meta_key
, I really need your help to understand:
Q1: Can one meta_key
have multiple meta_value
? If not, why WordPress need to use an meaningless array as output for meta_value
?
Q2: Why WordPress don't unserialize all serialized meta values?
WP_Query
retrieves post metadata and stores it in object cache. That means that you can callget_post_meta( $post_id, 'my_first_meta_key', true);
and then callget_post_meta( $post_id, 'my_second_meta_key', true );
and keep making calls like that, and you won't be hitting the database every time. It will go to the object cache for the meta values. I'm not sure your exact application, but that may circumvent the issue for you.