Если ваша тема активно использует механизм мета полей WordPress то это приведет к неизбежным потерям производительности т.к. каждый вызов get_post_meta или get_post_custom может генерировать лишний SQL к базе данных, если данных нет в кеш. Особенно заметно это будет при создании списка категории или главной страницы, когда эти функции вызываются в теле основного цикла.
Чтобы этого избежать можно подключить фильтр posts_results в фильтре мы получим результат последней выборки – массив постов, далее собираем все ID и формируем новый запрос в таблицу postmeta забираем там сразу все meta для всех постов и это будет намного быстрее чем каждый раз дергать выше упомянутые функции.
// этот фильтр добавляем в function.php
function ads_addImgMeta($posts){
global $wpdb, $wp_query;
if(is_admin() or is_page() ) return $posts;
// сохраняем состояние объекта $wp_query и $wpdb
if(version_compare( phpversion(), '5.0', '>=' )){
$wpdb_save = clone($wpdb);
$wp_query_save = clone($wp_query);
} else{
$wpdb_save = $wpdb;
$wp_query_save = $wp_query;
}
$ar_post_id = array();
foreach ($posts as $key => $post) {
$ar_post_id[] = $post->ID;
$ar_link[$post->ID] = & $posts[$key];
}
$st_id = @implode("','", $ar_post_id);
// складываем получаем общий список
$st_id = implode("','", $ar_post_id);
$query = "SELECT * FROM $wpdb->postmeta
WHERE post_id IN ('$st_id') ";
$meta = $wpdb->get_results($query);
if(!sizeof($meta))return $posts;
// теперь цепляем meta дане к постам
$uploads_dir = wp_upload_dir('baseurl');
foreach ($meta as $row) {
$meta_value = maybe_unserialize($row->meta_value);
$ar_link[$row->post_id]->meta[$row->meta_key] = $meta_value;
}
// востанавливаем состояние объектов
unset( $wpdb, $wp_query );
$wpdb = & $wpdb_save;
$wp_query = & $wp_query_save;
unset( $wpdb_save, $wp_query_save );
return $posts;
}
add_filter('posts_results', 'ads_addImgMeta');
Вот так вот одним махом теперь все мета поля сидят у нас в $post. Используйте в теле основного цикла if ( have_posts() ) : while ( have_posts() ) : the_post(); доступ к вашим полям $post->meta[meta_key]
А вот если мы используем WordPress как CMS, часто возникает задача добавлять картинки к короткому анонсу поста, то есть когда html код тега img надо удалить или надо использовать цитату (http://codex.wordpress.org/Template_Tags/the_excerpt) совмесно с картинкой вот как здесь
В этом случае нужно потратится на еще один SQL и получить сразу все атачменты для сразу всех постов а затем для всех ID получить мета поля. Привожу код:
function AddImgMeta($posts){
// можно исключить категории в которых не надо поулучать meta
if(is_admin() or is_category('307,3,5,4')) return $posts;
global $wpdb, $wp_query;
// сохраняем состояние объекта $wp_query и $wpdb
if(version_compare( phpversion(), '5.0', '>=' )){
$wpdb_save = clone($wpdb);
$wp_query_save = clone($wp_query);
} else{
$wpdb_save = $wpdb;
$wp_query_save = $wp_query;
}
$ar_post_id = array();
foreach ($posts as $key => $post) {
$ar_post_id[] = $post->ID;
$ar_link[$post->ID] = & $posts[$key];
}
$st_id = @implode("','", $ar_post_id);
//сначала добываем атачменты
$query = "SELECT $wpdb->posts.* FROM $wpdb->posts
WHERE $wpdb->posts.post_parent IN('$st_id')
AND $wpdb->posts.post_parent
AND $wpdb->posts.post_type = 'attachment'";
$files = $wpdb->get_results($query);
// получаем список id атачментов
$ar_file_id = array();
foreach ($files as $key=>$file) {
$ar_file_id[] = $file->ID;
$ar_link[$file->ID] = & $files[$key];
}
// складываем получаем общий список
$ar_all_id = @array_merge($ar_post_id,$ar_file_id);
$st_id = implode("','", $ar_all_id);
$query = "SELECT * FROM $wpdb->postmeta WHERE post_id IN ('$st_id') ";
$meta = $wpdb->get_results($query);
if(!sizeof($meta))return $posts;
// теперь цепляем meta дане к постам
$uploads_dir = wp_upload_dir('baseurl');
foreach ($meta as $row) {
$meta_value = maybe_unserialize($row->meta_value);
//'thumbnail' | 'medium' |
if('_wp_attachment_metadata'==$row->meta_key AND sizeof($meta_value) ){
$imgUrl = strstr ($meta_value['file'], '/wp-content');
if(!$imgUrl){
$imgUrl = $uploads_dir['baseurl'].'/'. $meta_value['file'];
}
$dirname = dirname($imgUrl);
$thumbUrl = $dirname.'/'.$meta_value['sizes']['thumbnail']['file'];
$mediumUrl = $dirname.'/'.$meta_value['sizes']['medium']['file'];
$ar_link[$row->post_id]->imgUrl = $imgUrl;
$ar_link[$row->post_id]->thumbUrl = $thumbUrl;
$ar_link[$row->post_id]->mediumUrl = $mediumUrl;
}
$ar_link[$row->post_id]->meta[$row->meta_key] = $meta_value;
}
// теперь цепляем атачменты к постам
foreach ($files as $row) {
$ar_link[$row->post_parent]->files[$row->menu_order] = $row;
}
// востанавливаем состояние объектов
unset( $wpdb, $wp_query );
$wpdb = & $wpdb_save;
$wp_query = & $wp_query_save;
unset( $wpdb_save, $wp_query_save );
return $posts;
}
add_filter('posts_results', 'AddImgMeta');
Сначала получаем ID всех постов из массива $posts, делаем первый SELECT для всех постов получаем все атачменты (см. SQL оператор IN) затем получаем ID всех атачментов напомню, что атачменты это такие же посты только без текста и хранятся они в одной таблице. Складываем два массива $ar_all_id = @array_merge($ar_post_id,$ar_file_id); и делаем запрос теперь уже в таблицу postmeta получаем все мета поля.
Надо также сказать, что WP хранит дополнительную информацию о закачанных картинках в тех же самых мета полях глвное нас интересует поля с именем _wp_attachment_metadata здесь хранятся ссылки на две превьюшки маленькую и среднюю которые автоматически нарезаются WP при загрузке изображений.
Мы обработаем эти данные и создадим дополнительно 3 свойства imgUrl thumbUrl mediumUrl которые содержат соответственно полный url на кртинку, url на маленькую превьюшку и url на среднюю картинку.
Чтобы посмотреть, что где лежит распечатайте переменную $post в теле основного цикла
echo ‘<pre>’; print_r( $post ); echo ‘</pre>’;
Да ! самое главное не путайте где массив, а где свойство объекта а то получите фатальную ошибку.
Чтобы все разложить по полочкам приведу пример что же мы получим в переменной $post .
stdClass Object
(
[ID] => 900
[post_author] => 2
[post_date] => 2009-03-23 16:06:03
[post_date_gmt] => 2009-03-23 13:06:03
[post_content] => Паркетная доска Barlinek это пол высочайшего класса, изготовленный из древесины, не подверженной процессам модификации. Отлично соединяет эстетические качества с легкостью монтажа и обновления. Паркетная доска Барлинек обеспечивает высокую термическую и акустическую изоляцию, имеет большое [post_title] => Продажа паркетной доски!!!
[post_category] => 0
[post_excerpt] =>
[post_status] => publish
[comment_status] => closed
[ping_status] => closed
[post_password] =>
[post_name] => prodazha-parketnoj-doski
[to_ping] =>
[pinged] =>
[post_modified] => 2009-03-23 16:06:03
[post_modified_gmt] => 2009-03-23 13:06:03
[post_content_filtered] =>
[post_parent] => 0
[guid] => http://wtb.od.ua/?p=900
[menu_order] => 0
[post_type] => post
[post_mime_type] =>
[comment_count] => 0
[meta] => Array
(
[ads_location] => 0
[ads_url] =>
[ads_phone] => 096-358-94-21 / 093-050-35-43
[ads_email] => morabend_sin@mail.ru
[ads_password] => qwewe
[ads_basecat] => 6
[ads_files] => Array
(
[0] => 899
)
)
[files] => Array
(
[0] => stdClass Object
(
[ID] => 899
[post_author] => 0
[post_date] => 2009-03-23 16:05:40
[post_date_gmt] => 2009-03-23 13:05:40
[post_content] =>
[post_title] => barlinek4.jpg
[post_category] => 0
[post_excerpt] =>
[post_status] => inherit
[comment_status] => open
[ping_status] => closed
[post_password] =>
[post_name] => barlinek4jpg
[to_ping] =>
[pinged] =>
[post_modified] => 2009-03-23 16:05:40
[post_modified_gmt] => 2009-03-23 13:05:40
[post_content_filtered] =>
[post_parent] => 900
[guid] => http://wtb.od.ua/wp-content/uploads/2009/03/barlinek4.jpg
[menu_order] => 0
[post_type] => attachment
[post_mime_type] => image/jpeg
[comment_count] => 0
[meta] => Array
(
[_wp_attached_file] => 2009/03/barlinek4.jpg
[_wp_attachment_metadata] => Array
(
[width] => 274
[height] => 480
[hwstring_small] => height='96' width='54'
[file] => 2009/03/barlinek4.jpg
[sizes] => Array
(
[thumbnail] => Array
(
[file] => barlinek4-150x150.jpg
[width] => 150
[height] => 150
)
[medium] => Array
(
[file] => barlinek4-171x300.jpg
[width] => 171
[height] => 300
)
)
[image_meta] => Array
(
[aperture] => 0
[credit] =>
[camera] =>
=>
[created_timestamp] => 0
[copyright] =>
[focal_length] => 0
[iso] => 0
[shutter_speed] => 0
[title] =>
)
)
)
[imgUrl] => http://wtb.od.ua/wp-content/uploads/2009/03/barlinek4.jpg
[thumbUrl] => http://wtb.od.ua/wp-content/uploads/2009/03/barlinek4-150x150.jpg
[mediumUrl] => http://wtb.od.ua/wp-content/uploads/2009/03/barlinek4-171x300.jpg
)
)
)
Вывести любое мета поле например ads_email
=$post->meta['ads_email']?>
А теперь как вывести первую картинку в шаблоне.
if($post->files[0]):?>
Здесь есть тонкий момент все атачменты – картинки или другие файлы zip или rar архивы будут сортироваться по времени и все они будут содержатся в массиве $files, поэтому чтобы все правильно отобразилось картинку надо загружать первой.
Ну а теперь выводим все картинки в виде превьюшек со сcылкой на основную картинку.
Цикл выведет все картинки, дополнительно реализованна проверка mime type у файла if(strstr($value->post_mime_type,’image/’) === false ) continue; в данном случае только изображения.
Напомню что все эти конструкции мы применяем внутри основного цикла вашего шаблона темы!
if ( have_posts() ) : while ( have_posts() ) : the_post();
Здравствуйте, не подскажете более подробно как этим пользоваться, у меня из картинки берутся из custom filds вот таким образом:
<a href=”"><img class=”preview” width=”133″ height=”100″ src=”ID, “preview”, true); ?>” />
Как использовать Ваш код, заранее спасибо!
ну да все правильно на 2 запроса больше, очевидно ваша тема не настолько активно использует мета поля так что нет смысла внедрять этот код
а как вывести полный список городов расположения со ссылками, например в виджете?
Используйте текстовый виджет например
то есть вручную набирать ссылки?
Ну да типа того лично просто сделал отдельный файл и inclode вставил вот и все