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

save_post хук-событие . WP 1.5.2

Событие срабатывающее всякий раз, когда запись (пост, страница) создается или обновляется, в том числе при публикации через импорт, xmlrpc или по email.

Данные записи передаются во втором параметре $post, но их также, как правило, можно получить через $_POST, $_GET или глобальную переменную global $post_data. Когда и что используется, зависит от того, как запись редактируется. Например, "быстрое редактирование" (quick edits) использует $_POST.

С версии 3.7 появился точно такой же хук save_post_(post_type). Где вместо post_type нужно указать название типа записи и событие будет срабатывать только при сохранении/добавлении записи этого типа. Выглядит хук так:

do_action( "save_post_{$post->post_type}", $post_ID, $post, $update );

save_post - это копия хука wp_insert_post.

Хук edit_post - такой же как и save_post, но срабатывает только при обновлении записи.

Хук срабатывает в самом конце, после обновления данных поста, очистки кэша и прочих действий.

Хук срабатывает после того, как был сброшен объектный кэш поста. Поэтому если изменяются какие-то данные поста на этом хуке, то кэш поста нужно сбросить еще раз

// очистим кэш поста
clean_post_cache( $post_ID );

Или нужно использовать хук wp_insert_post_data или wp_insert_attachment_data. Только эти хуки срабатывают до сброса кэша, но они не будут работать при вызове функции wp_publish_post().

Внимание! Зацикливание

В хуке save_post нужно аккуратно использовать функцию wp_update_post(). Потому что она повторно взывает этот хук и так код попадет в бесконечный цикл... Как этого избежать смотрите ниже в примере #3. Также об этом написано в описании функции wp_update_post().

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

add_action( 'save_post', 'action_function_name_85245', 10, 3 );
function action_function_name_85245( $post_ID, $post, $update ) {
	// Действие...
}
$post_ID(строка)
ID записи, которая обновляется.
$post(объект)
Объект записи, которая обновляется. Объект такой же как обычно в глобальной переменной $post.
$update(логический)
true — это обновление записи.
false — это добавление новой записи.

Примеры

#1 Отправка email при обновлении записи

Этот демонстративный пример, показывает как, всякий раз когда запись обновляется отправлять письмо администратору сайта с сообщением об обновлении:

add_action( 'save_post', 'my_project_updated_send_email' );
function my_project_updated_send_email( $post_id ) {

	// Если это ревизия, то не отправляем письмо
	if ( wp_is_post_revision( $post_id ) || get_post($post_id)->post_status != 'publish' )
		return;

	$post_title = get_the_title( $post_id );
	$post_url = get_permalink( $post_id );
	$subject = 'Запись была обновлена';

	$message = "На вашем сайте следующая запись была обновлена:\n\n";
	$message .= $post_title . ": " . $post_url;

	// Отправляем письмо.
	wp_mail( get_option('admin_email'), $subject, $message );
}

#2 Произвольный тип записи "book"

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

/**
 * Сохраняем метаданные записи при сохранении поста.
 */
add_action( 'save_post', 'save_book_meta' );
function save_book_meta( $post_id ) {
	// слаг лучше указать единожды и использовать во всех кодах 
	// связанных с типом записи, как это принято в классах
	$slug = 'book';

	// Проверяем тип записи, если не boo то выходим.
	if ( $slug != $_POST['post_type'] )
		return;

	// Обновляем метаданные записи.

	if ( isset( $_REQUEST['book_author'] ) ) {
		update_post_meta( $post_id, 'book_author', sanitize_text_field( $_REQUEST['book_author'] ) );
	}

	if ( isset( $_REQUEST['publisher'] ) ) {
		update_post_meta( $post_id, 'publisher', sanitize_text_field( $_REQUEST['publisher'] ) );
	}

	// inprint - это чекбокс.
	if ( isset( $_REQUEST['inprint'] ) ) {
		update_post_meta( $post_id, 'inprint', TRUE );
	} else {
		update_post_meta( $post_id, 'inprint', FALSE );
	}
}

В этом примере, проверку if ( $slug != $_POST['post_type'] ), можно заменить: вместо события save_post, можно использовать save_post_book.

#3 Как избежать зацикливания

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

// Эта функция делает все записи в дефолтной категории частными
add_action( 'save_post', 'set_private_categories' );
function set_private_categories( $post_id ){
	// Получим реальный ID поста, если это ревизия
	if ( $parent_id = wp_is_post_revision( $post_id ) ) 
		$post_id = $parent_id;

	// Получим ID категории по умолчанию из опций
	$defaultcat = get_option( 'default_category' );

	// Проверим находится ли пост в категории по умолчанию
	if ( in_category( $defaultcat, $post_id ) ) {
		// Удаляем хук, чтобы не было зацикливания
		remove_action( 'save_post', 'set_private_categories' );

		// обновляем запись. В это время срабатывает событие save_post
		wp_update_post( array( 'ID' => $post_id, 'post_status' => 'private' ) );

		// Ставим хук обратно
		add_action( 'save_post', 'set_private_categories' );
	}
}

Эта часть кода, должна быть обязательно:

// Удаляем хук, чтобы не было зацикливания
remove_action( 'save_post', 'set_private_categories' );

// обновляем запись. В это время срабатывает событие save_post
wp_update_post( array( 'ID' => $post_id, 'post_status' => 'private' ) );

// Ставим хук обратно
add_action( 'save_post', 'set_private_categories' );

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

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

Где вызывается хук

wp_insert_post()
save_post
wp_publish_post()
save_post
WP_Customize_Manager::trash_changeset_post()
save_post
wp-includes/post.php 4260
do_action( 'save_post', $post_ID, $post, $update );
wp-includes/post.php 4396
do_action( 'save_post', $post->ID, $post, true );
wp-includes/class-wp-customize-manager.php 3101
do_action( 'save_post', $post->ID, $post, true );

Где используется хук в ядре WP

wp-includes/default-filters.php 477
add_action( 'save_post', 'delete_get_calendar_cache' );
19 комментов
Полезные 1 Вопросы 2 Все