Работа с meta полями (custom fields) и картинками в WordPress ускоряемся в 10 раз.

Если ваша тема активно использует механизм мета полей 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

meta['ads_email']?>

А теперь как вывести первую картинку в шаблоне.

files[0]):?>
   

Здесь есть тонкий момент все атачменты – картинки или другие файлы zip или rar архивы будут сортироваться по времени и все они будут содержатся в массиве $files, поэтому чтобы все правильно отобразилось картинку надо загружать первой.
Ну а теперь выводим все картинки в виде превьюшек со сcылкой на основную картинку.

          
files as $key=>$value):?> post_mime_type,'image/') === false ) continue;?>

Цикл выведет все картинки, дополнительно реализованна проверка mime type у файла if(strstr($value->post_mime_type,’image/’) === false ) continue; в данном случае только изображения.

Напомню что все эти конструкции мы применяем внутри основного цикла вашего шаблона темы!
if ( have_posts() ) : while ( have_posts() ) : the_post();

Обсуждение на сайте:

Рубрика:  марта 19, 2009.
/ » » »


Похожие записи:

6 Responses to Работа с meta полями (custom fields) и картинками в WordPress ускоряемся в 10 раз.

  1. Дмитрий says:

    Здравствуйте, не подскажете более подробно как этим пользоваться, у меня из картинки берутся из custom filds вот таким образом:
    <a href=”"><img class=”preview” width=”133″ height=”100″ src=”ID, “preview”, true); ?>” />
    Как использовать Ваш код, заранее спасибо!

  2. admin says:

    ну да все правильно на 2 запроса больше, очевидно ваша тема не настолько активно использует мета поля так что нет смысла внедрять этот код

  3. dak says:

    а как вывести полный список городов расположения со ссылками, например в виджете?

  4. admin says:

    Используйте текстовый виджет например

  5. dak says:

    то есть вручную набирать ссылки?

  6. admin says:

    Ну да типа того лично просто сделал отдельный файл и inclode вставил вот и все

ili.com.ua/news/za-prazdnik-ukraintsyi-namusorili-menshe-chem-fanyi-evro-2012.html
ili.com.ua/news/ukraina-predsedatelstvuet-v-obse.html
ili.com.ua/news/gai-snova-proveryaet-voditeley.html
ili.com.ua/news/zhurnalistyi-ustanovili-u-zdaniya-mvd-ukrainyi-palatku-2.html

Новости

  • В Украине предложили возобновить призыв
  • Визовый режим между Украиной и Россией
  • Эффективная система безопасности
  • Самоотверженный поступок жительниц села Феськи
  • Состоится ли встреча замглав МИД СНГ?
  • Тягнибок разрешил выступать в Верховной Раде на русском
  • Ефремов расскажет, кто виноват
  • Комментарии


    Расширеный поиск +

    Другие статьи

    Объявления

    Мои проекты на WordPress

    , - специализированная доска объявлений по недвижимости на стоимость сборки $300 с установкой.
    городская доска объявлений, основные разделы: недвижимость, транспорт, услуги, работа, куплю-продам. Стоимость сборки $300 с установкой.
    - разработка, поддержка.

    Счетчики

    our blog