ตรวจสอบการอัปเดตเทียบกับโพสต์ใหม่ในการดำเนินการ save_post


21

เป็นไปได้หรือไม่ภายในการกระทำ save_post เพื่อตรวจสอบว่ามีการสร้างโพสต์ใหม่หรือโพสต์ที่มีอยู่กำลังอัปเดตหรือไม่


ฉันไม่คิดว่ามันเป็นไปได้ ดูความคิดเห็นของฉันด้านล่าง @ คำตอบของ moraleida ทำไมคุณต้องรู้ว่ามันเป็นโพสต์ใหม่หรือการปรับปรุง? อาจมีวิธีแก้ปัญหาหรือแนวทางอื่น
Stephen Harris

คำตอบ:


16

ตั้งแต่ WordPress เวอร์ชั่น 3.7 - IIRC - the save_posthook - ข้อมูลเพิ่มเติมเกี่ยวกับ hook และการใช้งานที่การอ้างอิงรหัส:save_postและCodex:save_post - มีพารามิเตอร์ตัวที่สาม$updateซึ่งสามารถใช้เพื่อกำหนดได้

@param int $ post_ID รหัสโพสต์
@param WP_Post $ โพสต์วัตถุโพสต์
@param bool $ update ไม่ว่าจะเป็นโพสต์ที่มีอยู่จะถูกอัพเดทหรือไม่


บันทึก:

$updateไม่เสมอtrue- คุณสามารถดูและทดสอบด้วยตัวคุณเองด้วยรหัสด้านล่าง มันไม่ได้รับการบันทึกไว้อย่างดีแม้ว่าอาจจะห่างไกลจากชื่อที่เหมาะสมและด้วยเหตุนี้จึงสร้างความคาดหวังที่ทำให้เข้าใจผิด รหัสด้านล่างนี้สามารถใช้สำหรับการแก้ไขข้อบกพร่องบางอย่างเล่นรอบเมื่อมีการสกัดกั้นการดำเนินการรหัสเพราะมิฉะนั้นคุณจะไม่เห็นข้อมูล / ข้อความ ฉันคิดว่าผู้ร้ายที่มีพฤติกรรมหลอกลวงคือการจัดการการแก้ไขและการบันทึกอัตโนมัติ - ซึ่งอาจปิดใช้งานได้ แต่ฉันไม่แนะนำและไม่ได้ทดสอบ ไม่แน่ใจว่านี่จะรับประกันตั๋ว Tracหรือไม่ดังนั้นฉันไม่ได้เปิดถ้าคุณคิดอย่างนั้นโปรดไปที่ลิงค์และทำมันเอง นอกเหนือจากที่ระบุไว้ในความคิดเห็นหากคุณมีปัญหาเฉพาะให้โพสต์คำถามใหม่

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();
}

3
$updateพารามิเตอร์เป็นจริงเสมอแม้เมื่อมีการโพสต์ใหม่ ดังนั้นพารามิเตอร์นี้ไม่มีประโยชน์ ไม่แน่ใจว่ามันใช้งานได้จริงหรือไม่ แต่แน่นอนว่านรกไม่ทำงานในแบบที่บันทึกไว้ใน wordpress 4.8 เวอร์ชันล่าสุด
โซโลมอน Closson

@SolomonClosson ถ้าคุณดูwp_publish_postนั่นก็ใช่ wp_insert_postแต่ที่ไม่เป็นความจริงสำหรับการใช้งานใน ฉันได้เขียนฟังก์ชั่นการแก้ปัญหาฉันเพิ่มลงในคำตอบ
Nicolai

@SolomonClosson หากคุณมีปัญหาที่เป็นรูปธรรมโปรดถามคำถามใหม่ ดูคำอธิบายการแก้ไขสำหรับฟังก์ชั่นการดีบัก
Nicolai

save_postเบ็ดมีพารามิเตอร์ที่ 3 ที่ตั้งเสมอ TRUE จึงไม่แน่ใจว่าสิ่งนี้จะทำอย่างไรกับตะขออื่น ๆ ไม่พูดเกี่ยวกับตะขออื่น ๆ ฉันกำลังพูดถึงเบ็ดในคำตอบของคุณ สิ่งนี้ไม่ถูกต้อง
โซโลมอน Closson

@SolomonClosson wp_insert_post()ที่ผมกล่าวว่าเบ็ดที่เกิดขึ้นสองครั้งwp_publish_post(), หลังมีการโพสต์ในอนาคตเท่านั้นที่มีการตั้งค่าที่จะเสมอ$update trueมิฉะนั้นในการไปwp_insert_post(), ไม่ได้เสมอ$update true
Nicolai

11

วิธีที่ฉันทำการตรวจสอบนี้ (ภายในฟังก์ชั่น hooked) คือการเปรียบเทียบวันที่โพสต์และวันที่แก้ไข (ใน 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 วินาทีในกรณีที่มีการทำเครื่องหมายที่สองในระหว่างการสร้าง โพสต์


1
บางครั้งpost_date_gmtเป็น2019-03-12 01:31:30และเป็นpost_modified_gmt 2019-03-12 01:31:31:(
เขาอี้เฟย何一非

1
@ HeYifei 何一非จุดที่ดีถ้าการประมวลผลเริ่มต้นในตอนท้ายของวินาทีที่กำหนดนี้อาจเกิดขึ้น ฉันได้อัปเดตคำตอบแล้ว
James Cushing

Guys เพียงข้อมูล เบ็ดถูกใช้เพื่อเรียกคืนและลบโพสต์
เมลวิน

6

ฉันลงเอยเพียงแค่ตรวจสอบว่ามีค่าที่กำหนดเองก่อนที่จะตั้งค่าหรือไม่ ด้วยวิธีนี้ถ้าเป็นการโพสต์ที่สร้างขึ้นใหม่ค่าที่กำหนดเองจะยังไม่มีอยู่

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');

เพื่อให้ใช้งานได้คุณต้องสร้างฟิลด์ที่กำหนดเองโดยใช้ add_post_meta ก่อนหรือไม่?
MF1

สำหรับ Codex: [update_post_meta] อาจใช้แทนฟังก์ชัน add_post_meta () codex.wordpress.org/Function_Reference/update_post_meta
hereswhatidid

สิ่งนี้อาจล้มเหลวหากโพสต์ถูกสร้างขึ้นก่อนที่รหัสจะถูกเปิดใช้งานผ่านการเปิดใช้งานปลั๊กอิน โพสต์ที่เก่ากว่าไม่มีชุดเมตาดังนั้นการอัปเดตครั้งแรกสำหรับพวกเขาจะถือเป็นใหม่
Vasu Chawla

4

ตัวอย่างคำตอบ ialocin ด้วย "ปรับปรุง" paremeter:

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 );

2
วิธีที่ดีกว่าการจัดโครงสร้างนี้จะเป็นทั้งการวางบล็อกการปรับปรุงครั้งแรกที่ช่วยให้การทำif($update)หรือรักษาบล็อกใหม่ครั้งแรก if( ! $update )แต่การใช้ หลังจะได้รับ OP ไปสู่การปฏิบัติที่ดีขึ้นและเป็นที่ต้องการมากกว่าวิธีการของคุณโดยมาตรฐานการเข้ารหัส WordPress ในกรณีเช่นผู้ประกอบการที่สาม
James Cushing

1

คุณสามารถใช้ pre_post_update action hook สำหรับรหัสอัปเดตและ save_post สำหรับรหัสโพสต์ใหม่ ใช้งานได้ก่อนมีการอัปเดตโพสต์


4
save_posthook ถูกไล่ออกทั้งเมื่อโพสต์ถูกสร้างและอัปเดต (หลังจาก WordPress บันทึกไปยังฐานข้อมูลแล้ว) pre_post_updateถูกเรียกใช้เมื่อมีการอัปเดตโพสต์ แต่ก่อนโพสต์จะได้รับการอัปเดตซึ่งอาจมีความสำคัญ
Stephen Harris

1

ดังที่ Darshan Thanki พูดถึง (และ Stephen Harris เพิ่มเติมอย่างละเอียด) คุณสามารถใช้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;
}

เหตุผลที่ฉันใช้ globals นั้นเป็นเพราะfunction is_new_post() use ( &$new_post )ไม่ถูกต้องใน PHP (ตกตะลึง ... ) ดังนั้นการดึงตัวแปรนั้นลงในขอบเขตฟังก์ชั่นใช้งานไม่ได้ - ดังนั้นทั่วโลก

โปรดทราบว่าสิ่งนี้สามารถใช้งานได้อย่างน่าเชื่อถือภายใน / หลังจากsave_postเหตุการณ์ (ซึ่งโดยปกติจะเพียงพอแล้วอย่างน้อยสำหรับสิ่งที่เรากำลังทำอยู่)


0

เมื่อมีการทริกเกอร์ 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');

แม้ว่านี่จะยังไม่ได้ทดสอบ =)


3
เมื่อถึงเวลาที่คุณsave_postโพสต์ตัวเองจะถูกบันทึกไว้ในฐานข้อมูลแล้วดังนั้นget_postsจะส่งคืนโพสต์ปัจจุบัน
Stephen Harris

จริงเพียงตรวจสอบใน Codex ขอบคุณสำหรับหัวขึ้น.
moraleida

0

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()เพื่อสร้างสถานการณ์ที่เหมาะสมยิ่งขึ้น

ดู Codex สำหรับget_post_status ()และสถานะการโพสต์

ค่าที่เป็นไปได้คือ:

  • 'เผยแพร่' - โพสต์หรือหน้าที่เผยแพร่
  • 'รอการอนุมัติ' - โพสต์กำลังรอการตรวจสอบ
  • 'ฉบับร่าง' - โพสต์ในสถานะฉบับร่าง
  • 'auto-draft' - โพสต์ที่สร้างขึ้นใหม่โดยไม่มีเนื้อหา
  • 'อนาคต' - โพสต์เพื่อเผยแพร่ในอนาคต
  • 'ส่วนตัว' - ไม่ปรากฏแก่ผู้ใช้ที่ไม่ได้เข้าสู่ระบบ
  • 'สืบทอด' - การแก้ไข ดูที่ get_children
  • 'ถังขยะ' - โพสต์อยู่ในถังขยะ เพิ่มด้วยเวอร์ชัน 2.9

ฉันไม่คิดว่าจะทำสิ่งที่ขอ หากฉันสร้างโพสต์ใหม่จากนั้นกด 'เผยแพร่' save_post()จะถูกดำเนินการเป็นครั้งแรก แต่ในระหว่างการดำเนินการget_post_status()นั้นจะส่งคืน 'เผยแพร่' และไม่ใช่ 'ฉบับร่าง' แม้ว่าจะอยู่ในขั้นตอนการเผยแพร่เท่านั้น
cgogolin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.