Можно ли в действии save_post определить, создается ли новая запись или обновляется существующая запись?
Можно ли в действии save_post определить, создается ли новая запись или обновляется существующая запись?
Ответы:
Начиная с версии WordPress 3.7. - IIRC - save_post
ловушка - больше информации о ловушке и ее использовании в Code Reference:save_post
и Codex:save_post
- есть третий параметр, $update
который можно использовать для определения именно этого.
@param int $ post_ID ID сообщения.
@param WP_Post $ post Опубликовать объект.
@param bool $ update Независимо от того, обновляется ли существующий пост или нет.
Заметка:
$update
это не всегда true
- вы можете увидеть и проверить это самостоятельно с помощью приведенного ниже кода. Это не хорошо документировано, хотя, возможно, далеко не оптимально названо, и, следовательно, создает обманчивые ожидания. Приведенный ниже код можно использовать для некоторой отладки, поэкспериментируйте с тем, когда перехватывать выполнение кода, потому что иначе вы не увидите информацию / сообщения. Я думаю, виновник в обманчивом поведении - обработка ревизий и автосохранение - которые могут быть отключены, но я не рекомендую это и не проверял это. Не уверен, что это требует Trac Ticket , поэтому я не открыл его, если вы так думаете, перейдите по ссылке и сделайте это самостоятельно. Кроме того, как указано в комментариях, если у вас есть конкретная проблема, напишите новый вопрос.
add_action( 'save_post', 'debug_save_post_update', 10, 3 );
function debug_save_post_update( $ID, $post, $update ) {
echo '<pre>';
print_r( $post ); echo '<br>';
echo '$update == ';
echo $update ? 'true' : 'false';
//conditions
if( ! $update && $post->post_status == "auto-draft" ) {
// applies to new post
echo ' && $post->post_status == "auto-draft"';
//die();
} else if ( ! $update ) {
// applies basically to the (auto saved) revision
//die();
} else {
// applies to updating a published post
// when there is a revision, which is normally the case,
// standard behavior of WordPress, then it is considered
// an update, which is where the confusion sets in
// there are other methods, like checking time or post status
// depending on your use case it might be more appropriate
// to use one of those alternatives
//die();
}
echo '</pre>';
//die();
}
$update
Параметр всегда верно , даже если это новый пост. Так что этот параметр бесполезен. Не уверен, работал ли он вообще когда-либо, но он точно работает не так, как задокументировано в последней версии WordPress 4.8.
wp_publish_post
, то да. Но это не так для его использования в wp_insert_post
. Я написал функцию отладки, я добавляю ее в ответ.
save_post
Крюк имеет 3 - й параметр , который всегда должен быть установлен в значение TRUE, поэтому не уверен , что это связано с другими крюками, не говоря уже о других крючков. Я говорю о крючке в вашем ответе. Это неверно
wp_insert_post()
, wp_publish_post()
. Последние есть только будущие посты, там $update
и так будет всегда true
. Иначе, в отношении wp_insert_post()
, $update
не всегда true
.
Способ, которым я выполняю эту проверку (в рамках подключенной функции), заключается в сравнении даты публикации и даты изменения (в GMT для стандартизации)
function check_new_vs_update( $post_id ){
$myPost = get_post($post_id);
$post_created = new DateTime( $myPost->post_date_gmt );
$post_modified = new DateTime( $myPost->post_modified_gmt );
if( abs( $post_created->diff( $post_modified )->s ) <= 1 ){
// New post
}else{
// Updated post
}
}
add_action('save_post', 'check_new_vs_update' );
Это работает, потому что даже при создании к записи прикреплена «измененная» дата, которая в точности совпадает с «созданной» датой, но мы допускаем отклонение в 1 секунду в любом случае, если секунда опрокидывается во время создания пост.
post_date_gmt
есть 2019-03-12 01:31:30
и post_modified_gmt
есть 2019-03-12 01:31:31
. :(
В итоге я просто проверил наличие пользовательского значения до его установки. Таким образом, если это новая запись, пользовательское значение еще не будет существовать.
function attributes_save_postdata($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!wp_verify_nonce($_POST['_attributes_noncename'], plugin_basename(__FILE__))) return;
if ('page' == $_POST['post_type']) {
if (!current_user_can('edit_page', $post_id)) return;
} else {
if (!current_user_can('edit_post', $post_id)) return;
}
$termid = get_post_meta($post_id, '_termid', true);
if ($termid != '') {
// it's a new record
$termid = 'update';
} else {
// it's an existing record
}
update_post_meta($post_id, '_termid', $termid);
}
add_action('save_post', 'attributes_save_postdata');
Пример ответа на вопрос «Ялоцин» с параметром «обновление»:
function save_func($ID, $post,$update) {
if($update == false) {
// do something if its first time publish
} else {
// Do something if its update
}
}
add_action( 'save_post', 'save_func', 10, 3 );
if($update)
либо сохранить новый блок первым, но использовать if( ! $update )
. Последний получит ОП в лучшую практику и предпочтительнее вашего метода стандартами кодирования WordPress в таких случаях, как троичный оператор
Вы можете использовать хук действия pre_post_update для кода обновления и save_post для нового почтового индекса. Работает до обновления поста.
save_post
Хук срабатывает как при создании и обновлении поста (после того, как WordPress сохранил его в базе данных). pre_post_update
срабатывает при обновлении сообщения, но до его обновления - это может быть важно.
Как намекнул Даршан Спасибо (и Стивен Харрис), вы можете использовать это pre_post_update
в своих интересах.
global $___new_post;
$___new_post = true;
add_action(
'pre_post_update',
function() {
global $___new_post;
$___new_post = false;
},
0
);
function is_new_post() {
global $___new_post;
return $___new_post;
}
Причина, по которой я использовал глобальные переменные, заключается в том, что function is_new_post() use ( &$new_post )
это недопустимо в PHP (шокирующее ...), поэтому включение этой переменной в область действия функции не работает - следовательно, глобальное.
Обратите внимание, что это действительно может быть надежно использовано только внутри / после save_post
события (которого обычно достаточно, по крайней мере, для того, что мы делаем с ним).
Когда сработает save_post, вся информация об этом посте уже доступна, поэтому теоретически вы можете использовать
function f4553265_check_post() {
if (!get_posts($post_id)) {
// if this is a new post get_posts($post_id) should return null
} else {
// $post_id already exists on the database
}
}
add_action('save_post','f4553265_check_post');
это не проверено, хотя. знак равно
save_post
самого сообщения, оно уже будет сохранено в базе данных - поэтому get_posts
вернет текущее сообщение.
Другой подход, который использует встроенную функцию и не добавляет базы данных, будет включать get_post_status()
.
$post_status = get_post_status();
if ( $post_status != 'draft' ) {
//draft
} else {
//not a draft: can be published, pending, etc.
}
Тем не менее, обратите внимание, что это может быть неуместно, если вы планируете позднее установить статус «черновик» - ваши инструкции будут повторены при следующем обновлении сообщения. В зависимости от контекста, вы можете рассмотреть различные строки, которые могут быть возвращены, get_post_status()
чтобы построить более подходящий сценарий.
См. Кодекс для get_post_status () и статуса сообщения
Возможные значения:
- «Опубликовать» - опубликованный пост или страница
- 'pending' - сообщение ожидает рассмотрения
- 'draft' - пост в состоянии черновика
- 'auto-draft' - недавно созданная запись без содержания
- «будущее» - публикация в будущем
- 'private' - не виден пользователям, которые не вошли в систему
- «Наследовать» - ревизия. смотри get_children.
- 'мусор' - сообщение находится в мусорном ведре. добавлено в версии 2.9.
save_post()
она выполняется впервые, но во время этого выполнения get_post_status()
уже возвращается «публикация», а не «черновик», даже если она находится только в процессе публикации.