WordPress как на ладони
Недорогой хостинг для сайтов на WordPress: wordpress.jino.ru

wp_update_post() WP 1.0.0

Обновляет запись (пост) в Базе Данных WordPress.

Для того, чтобы функция работала правильно, необходимо указать идентификатор (ID) поста, который будет обновляться.

Функция ожидает (ей нужно передавать) экранированные данные. Т.е. нельзя использовать wp_unslash() для полученных $_POST данных. Если это сделать, будет двойное удаление экранируемых слэшей!

Эта функция является оберткой для wp_insert_post().

Если ревизии записей включены, при обновлении прошлые данные не удаляются, а становятся ревизией. При этом, все связи (с произвольными полями, категориями, метками) переходят к основной записи.

Категории

Категории нужно передватсья в виде массива чисел (ID категорий к которым будет прикреплена запись). Это касается и случаев, когда указывается только одна категория для записи - все равно передаем так: array(1).

Внимание

Если нужно использовать wp_update_post() (обновить запись) во время хука save_post, обязательно сделайте проверку на тип поста - чтобы он не был revision. Дело в том, что когда wp_update_post() используется во время хука save_post (например, для произвольных метаблоков), обычно создается бесконечный цикл. Это получается потому что save_post вызывается дважды, если включены ревизии: первый раз при создании ревизии, второй раз при обновлении основного поста. В результате, цикл замыкается и создаются бесконечное множество ревизий.

Тоже самое происходит во время срабатывания хука edit_attachment, если во время него вызывается функция wp_update_post() с параметром ID, которое относится к вложению (attachment).

Вот пример, показывающий как нужно действовать в ситуации, когда wp_update_post() вызывает ошибку при использовании его во время хука save_post:

add_action( 'save_post', 'my_function' );
function my_function( $post_id ){
	if ( ! wp_is_post_revision( $post_id ) ){
		// удаляем этот хук, чтобы он не создавал бесконечного цикла
		remove_action('save_post', 'my_function');

		// обновляем пост, когда снова вызовется хук save_post
		wp_update_post( $my_args );

		// снова вешаем хук
		add_action('save_post', 'my_function');
	}
}
Будущая публикация поста

Если вы планируете публикацию черновика в будущем и используете для этого функцию wp_update_post(), то функция не будет работать, если не указать параметр $my_post->edit_date = true. WP игнорирует параметр post_date, если обновляется черновик, но не в случае, когда указан параметр edit_date = true.

Заметки

Использует: wp_restore_post_revision()

Работает на основе: wp_insert_post()

Хуков нет.

Возвращает

Число/0/WP_Error.

  • ID обновленной записи — при удачной операции.
  • 0 или WP_Error (при включенном параметре $wp_error) — если обновить запись не удалось.

Использование

wp_update_post( $post, $wp_error );
$post(массив|объект)

Ассоциативный массив данных, содержащий данные о посте, которые нужно обновить. Ключи массива идентичны полям таблицы wp_posts в Базе Данных WordPress.

Указывать ID в массиве обязательно! (пример: $my_post['ID'] = 37;).

Понимает все параметры которые можно передать wp_insert_post().
По умолчанию: array()

$wp_error(true/false)
true — включает возврат объекта WP_Error при ошибке.
По умолчанию: false

Примеры

Перед тем как использовать функцию нужно собрать массив данных, который затем передать в качестве параметра. Массив должен содержать те данные, которые мы хотим обновить.

Отличие этой функции от wp_insert_post() в том, что здесь нет необходимости передавать все данные, можно указать только те, которые нужно обновить, остальные данные будут скопированы из уже имеющихся в базе данных.

#1. Обновим контент у записи 37:

// Создаем массив данных
$my_post = array();
$my_post['ID'] = 37;
$my_post['post_content'] = 'Здесь новый контент записи';

// Обновляем данные в БД
wp_update_post( wp_slash($my_post) );
Поля, которые можно изменить

Это массив полей, которые содержит любая запись WordPress.

WP_Post Object (
	[ID]                    => 1
	[post_author]           => 1
	[post_date]             => 2010-03-26 09:27:40
	[post_date_gmt]         => 2010-03-26 05:27:40
	[post_content]          => Контент записи...
	[post_title]            => Название записи
	[post_excerpt]          => 
	[post_status]           => publish
	[comment_status]        => open
	[ping_status]           => open
	[post_password]         => 
	[post_name]             => post_name
	[to_ping]               => 
	[pinged]                => http://wp-kama.ru/dopolnitelnyie-knopki
	[post_modified]         => 2014-02-10 10:31:17
	[post_modified_gmt]     => 2014-02-10 06:31:17
	[post_content_filtered] => 
	[post_parent]           => 0
	[guid]                  => http://wp-kama.ru/post_name
	[menu_order]            => 0
	[post_type]             => post
	[post_mime_type]        => 
	[comment_count]         => 41
	[filter]                => raw
)

Список изменений

С версии 1.0.0 Введена.

Код wp update post: wp-includes/post.php WP 5.2.3

<?php
function wp_update_post( $postarr = array(), $wp_error = false ) {
	if ( is_object( $postarr ) ) {
		// Non-escaped post was passed.
		$postarr = get_object_vars( $postarr );
		$postarr = wp_slash( $postarr );
	}

	// First, get all of the original fields.
	$post = get_post( $postarr['ID'], ARRAY_A );

	if ( is_null( $post ) ) {
		if ( $wp_error ) {
			return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) );
		}
		return 0;
	}

	// Escape data pulled from DB.
	$post = wp_slash( $post );

	// Passed post category list overwrites existing category list if not empty.
	if ( isset( $postarr['post_category'] ) && is_array( $postarr['post_category'] )
			&& 0 != count( $postarr['post_category'] ) ) {
		$post_cats = $postarr['post_category'];
	} else {
		$post_cats = $post['post_category'];
	}

	// Drafts shouldn't be assigned a date unless explicitly done so by the user.
	if ( isset( $post['post_status'] ) && in_array( $post['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) && empty( $postarr['edit_date'] ) &&
			( '0000-00-00 00:00:00' == $post['post_date_gmt'] ) ) {
		$clear_date = true;
	} else {
		$clear_date = false;
	}

	// Merge old and new fields with new fields overwriting old ones.
	$postarr                  = array_merge( $post, $postarr );
	$postarr['post_category'] = $post_cats;
	if ( $clear_date ) {
		$postarr['post_date']     = current_time( 'mysql' );
		$postarr['post_date_gmt'] = '';
	}

	if ( $postarr['post_type'] == 'attachment' ) {
		return wp_insert_attachment( $postarr, false, 0, $wp_error );
	}

	return wp_insert_post( $postarr, $wp_error );
}

Cвязанные функции

Из раздела: Вставка, удаление, обновл.

18 комментов
Полезные 2 Все
  • qazomard www.aktv.ru

    Ребят, помогите кто-нибудь.

    Мой wordpress парсит видео с ютюба и рутуба. Но парсит только заголовок, текст, тхумб (так было задумано). Контент публикуется ежедневно.

    Вобщем понадобилось, чтобы теперь видеофрейм вставлялся в публикацию при первом просмотре статьи. Делать это вручную не хочется, - слишком много постов. План на то, что все посты со временем обновятся, а новые уже будут с фреймом.

    Написал функцию, делаю магию-проверку при загрузке страницы и вызываю wp_update_post с дополненным контентом.

    Активацию функции оставил на пользователей (сам я, бывает не захожу на сайт с неделю - публикую со стороны). Но тут проблема: если страницу открыл неавторизованный пользователь (бот или еще кто-то), то iframe режется. На авторизованных опираться не хочется: сайт новостной, - а на таких редко логинятся, да и долго...

    К делу.

    Должно быть:

    <div class="flex-video widescreen video-container" 
    style="margin: 0 auto;text-align:center;" 
    itemtype="http://schema.org/VideoObject">
    				<iframe  frameborder="0" 
    				allowfullscreen="allowfullscreen" 
    				webkitAllowFullScreen mozallowfullscreen allowfullscreen 
    				src="//www.youtube.com/embed/'.$video_id[7].'"></iframe>
    </div>

    А в публикацию уходит только:

    <div class="flex-video widescreen video-container" 
    style="margin: 0 auto;text-align:center;" 
    itemtype="http://schema.org/VideoObject">
    </div>

    Видимо что-то связанное с unfiltered_html

    Вопрос: как обновить пост в обход этого фильтра?

    Ответить4.9 года назад #
    • DNIWE

      Видимо речь идет о WordPress старой версии, попробуйте такой хук:

      function tinymce_add_iframe($initArray) {
      	$initArray['extended_valid_elements'] = "iframe[id|class|title|style|align|frameborder|height|longdesc|marginheight|marginwidth|name|scrolling|src|width]";
      	return $initArray;
      }
      
      add_filter('tiny_mce_before_init', 'tinymce_add_iframe');
      Ответить4.9 года назад #
      • qazomard www.aktv.ru

        Нет, WP 4.0, но попробую

        Ответить4.9 года назад #
        • qazomard www.aktv.ru

          Нет, не работает.

          Вот код функции:

          function input_video_frame($host = 'rutube.ru', $video_id = NULL) {
          	return;
          	global $post;
          
          	preg_match("/flex-video widescreen video-container/", $post->post_content, $matches);    
          if(count($matches)==0) {
          
          	switch($host){
          		case'rutube.ru':
          			$embed = '  
          
          				<div class="flex-video widescreen video-container" style="margin: 0 auto;text-align:center;" itemtype="http://schema.org/VideoObject">
          				<iframe  frameborder="0" allowfullscreen="allowfullscreen" webkitAllowFullScreen mozallowfullscreen allowfullscreen src="//rutube.ru/video/embed/'.$video_id[4].'"></iframe>
          				</div>';
          		break;
          
          		case'youtube.com':
          		case'gdata.youtube.com':
          		case'www.youtube.com':
          			$embed = '  
          
          				<div class="flex-video widescreen video-container" style="margin: 0 auto;text-align:center;" itemtype="http://schema.org/VideoObject">
          				<iframe  frameborder="0" allowfullscreen="allowfullscreen" webkitAllowFullScreen mozallowfullscreen allowfullscreen src="//www.youtube.com/embed/'.$video_id[7].'"></iframe>
          				</div>';
          		break;
          
          	}
          $new_post = $post->post_content."<br>$embed";
          
          $new_post_atr = array(
          	'ID' => $post->ID,
          	'post_content' => $new_post,
          );
          
          wp_update_post( $new_post_atr );
          return $new_post; 
          
          	}  else { return NULL; } 
          }

          В итоге div вставляется, но без iframe:
          http://picture-host.ru/v.php?id=72a4f5d4f80dec8b8cc9af6d4ac0eaf1

          Ответить4.9 года назад #
  • Евгений

    Здравствуйте! очень полезный у Вас сайт! Я делетан в этом деле, но очень нравится! Подскажите правильный путь

    Я написал плагин интернет магазина, есть две проблемы, решаются они одинаково - это wp_update_post и wp_mail.

    Мне нужно что бы при оформлении заказа создавалась статья с контентентом состоящим из корзины товаров:

    Решение которое работает но не устраивает

    if (isset($_POST['buy'])) {
    	foreach ($_SESSION['goods'] as $key => $value) {
    		$array[] = get_the_post_thumbnail($key, 'thumbnail');
    		$array[] = get_the_title($key);
    		 }
    	 $content = serialize($array);
    	 $buy_post = array(
    	'post_title' => '',
    	'post_content' => $content,
    	'post_status' => 'draft',
    	'post_type' => 'orders'
    	 );
    
       $buy_ID = wp_insert_post( $buy_post );
    
    	 // Создаем массив данных
    	   $my_post = array();
    	   $my_post['ID'] = $buy_ID;
    	   $my_post['post_title'] = 'Заказ № '.$buy_ID;
    	 // Обновляем данные в БД
    	   wp_update_post( $my_post );
    
    }

    если так

    if (isset($_POST['buy'])) {
    	foreach ($_SESSION['goods'] as $key => $value) 
    	 // Создаем массив данных
    	   $my_post = array();
    	   $my_post['ID'] = $buy_ID;
    	   $my_post['post_title'] = 'Заказ № '.$buy_ID;
    	   $my_post['post_content'] = $value;
    	 // Обновляем данные в БД
    	   wp_update_post( $my_post );
      }
    }

    то соответственно записывает только последний перебор.

    Еще вариант подключить фаил в контент

    require_once SG_PLUGIN_PATH . 'cart/cart_action.php';

    но в контент записывает тупо 1.

    Задача: записать в контент таблицу со значениями из массива, аналогично и для wp_mail может что то подскажете, седых волос уже это прибавило!
    Спасибо!

    1
    Ответить4.8 года назад #
    • Второй вариант можно сделать так:

      if (isset($_POST['buy'])) {
      	$my_post = array(); // Создаем массив данных
      	$my_post['ID'] = $buy_ID;
      	$my_post['post_title'] = 'Заказ № '.$buy_ID;
      	$my_post['post_content'] = ''; // Создаем пустое поле в массиве
      	$i = 0;
      	foreach ($_SESSION['goods'] as $key => $value) {
      		$my_post['post_content'] .= $value; //Добавляем к полю данные
      		if ($i > 0) { $my_post['post_content'] .= '<br>'; }
      		$i += 1;
      	}
      	wp_update_post( $my_post ); // Обновляем данные в БД
      }

      ЗЫ: Вы в цикле каждый раз создавали массив, а необходимо создать его 1 раз. Далее переменной или же элементу массива добалять/дозаписывать данные.

      2
      Ответить4.8 года назад #
      • Евгений

        Спасибо большое! очень полезно! не раз пользовался

        $content .=

        но в голову даже в голову не приходило что данные добавляются в переменную, а не в контентmosking

        Ответить4.8 года назад #
        • Попробуйте сделать поаналогии и с 'wp_mail' - создать переменную, в которую будете "добавлять" данные или в элемент массива.

          Всегда рад помочь - удачи...

          1
          Ответить4.8 года назад #
  • Вячеслав

    А что происходит с пустыми полями - они остаются без изменения или обнуляются? Например хочу изменить только имя поста, достаточно в аргументах передать только его?

    Ответить4.5 года назад #
    • Kama7602

      Все поля которые не указаны, останутся прежними (при обновлении поля предварительно получаются из БД, потом заменяются все указанные, а затем записываются новые собранные данные в БД)...

      Ответить4.5 года назад #
  • source geekelectronics.org

    Если wp_update_post режет iframe и скрипты, то надо просто перед его использованием отключить фильтры

    // Отключаем фильтры
      remove_filter('content_save_pre', 'wp_filter_post_kses'); 
      remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');

    Теперь используем wp_update_post

    // Включаем фильтры
      add_filter('content_save_pre', 'wp_filter_post_kses'); 
      add_filter('content_filtered_save_pre', 'wp_filter_post_kses');
    1
    Ответить2 года назад #
    • Kama7602

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

      Ответить2 года назад #
  • Роман

    Приветствую. Подскажите плиз, нет времени проверять. Если использовать wp_update_post для вставки записи кроме ее добавления то будет ли она работать?
    То есть к примеру что бы не проверять существование записи в базе перед обновлением, просто всегда использовать апдейт. Айдишник не указыаать а указывать все остальное что нужно. Будет ли она работать и возвращать айди? Заранее спасибо за ответ.
    пс. это лучший сайт о впрессе. мое почтение

    Ответить1.7 года назад #
    • Kama7602

      ID надо указывать для обновления... Чтобы обновлялась запись, ВП нужно знать какая это запись, по другому никак unknw

      Ответить1.7 года назад #
  • @ adward6 cimetrica.ru

    Подскажите пожалуйста, как мне перевести в черновики (в WooCommerce) все товары определенной категории?

    Я правильно понимаю, что нужно рыть в эту сторону:

    wp_update_post(array(
    				'ID' => $product['product_id'],
    				'post_status' => 'draft'
    				));

    Либо же утащить в черновики выделенные товары, как то например так:

    Ответитьмесяц назад #
    • Эдвард...
      Вы же программист, у Вас такой шикарный сайт, хорошие деньги берёте за разработку...

      Ответитьмесяц назад #
      • @ adward6 cimetrica.ru

        Решено sql-запросом:

        UPDATE wp_posts SET post_status = 'draft' WHERE post_type = 'product' AND post_status = 'publish'
        Ответитьмесяц назад #
      • @ adward6 cimetrica.ru

        о каком сайте речь, кстати? smile

        Ответитьмесяц назад #
Здравствуйте, !     Войти . Зарегистрироваться