我有一个名为的自定义帖子类型(CPT)event
。我有一个带有几个字段的类型的元框。我想在发布事件之前验证一些字段。例如,如果未指定事件的日期,则我想显示一条提示性的错误消息,请保存该事件以供将来编辑,但禁止发布该事件。没有所有必要信息的CPT帖子的“待处理”状态是否是正确的处理方式?
进行CPT字段验证并阻止发布帖子的最佳做法是什么,但是将其保存以备将来编辑。
非常感谢,达莎
我有一个名为的自定义帖子类型(CPT)event
。我有一个带有几个字段的类型的元框。我想在发布事件之前验证一些字段。例如,如果未指定事件的日期,则我想显示一条提示性的错误消息,请保存该事件以供将来编辑,但禁止发布该事件。没有所有必要信息的CPT帖子的“待处理”状态是否是正确的处理方式?
进行CPT字段验证并阻止发布帖子的最佳做法是什么,但是将其保存以备将来编辑。
非常感谢,达莎
Answers:
您可以停止将帖子与所有较小的JQuery hack一起保存,并在使用ajax保存在客户端或服务器端之前验证字段:
首先,我们添加JavaScript以捕获submit / publish事件,并在实际提交之前使用它来提交我们自己的ajax函数:
add_action('wp_print_scripts','my_publish_admin_hook');
function my_publish_admin_hook(){
if (is_admin()){
?>
<script language="javascript" type="text/javascript">
jQuery(document).ready(function() {
jQuery('#post').submit(function() {
var form_data = jQuery('#post').serializeArray();
form_data = jQuery.param(form_data);
var data = {
action: 'my_pre_submit_validation',
security: '<?php echo wp_create_nonce( 'pre_publish_validation' ); ?>',
form_data: form_data
};
jQuery.post(ajaxurl, data, function(response) {
if (response.indexOf('True') > -1 || response.indexOf('true') > -1 || response === true || response) {
jQuery('#ajax-loading').hide();
jQuery('#publish').removeClass('button-primary-disabled');
return true;
}else{
alert("please correct the following errors: " + response);
jQuery('#ajax-loading').hide();
jQuery('#publish').removeClass('button-primary-disabled');
return false;
}
});
return false;
});
});
</script>
<?php
}
}
然后我们创建函数进行实际验证:
add_action('wp_ajax_my_pre_submit_validation', 'pre_submit_validation');
function pre_submit_validation(){
//simple Security check
check_ajax_referer( 'pre_publish_validation', 'security' );
//do your validation here
//all of the form fields are in $_POST['form_data'] array
//and return true to submit: echo 'true'; die();
//or your error message: echo 'bal bla bla'; die();
}
您可以随时添加一些条件检查my_publish_admin_hook
功能,以仅针对您的帖子类型进行验证,以增加针对您的帖子类型的功能,并在客户端进行验证,但我更喜欢在服务器端进行验证。
pre_submit_validation
配合
my_publish_admin_hook
块确实拦截了客户端的提交后提交-但随后对pre_submit_validation
执行服务器端验证的服务器(在中的pre-official-submit )进行了AJAX调用。
该方法有两个步骤:第一,用于保存自定义metabox字段数据的功能(已保存到save_post),第二,用于读取新的post_meta(您刚刚保存的),对其进行验证并修改结果的函数。必要时保存(也钩到save_post,但是在第一个之后)。验证器功能(如果验证失败)实际上将post_status更改回“ pending”,从而有效地防止发布该发布。
由于save_post函数被调用很多,因此每个函数都有检查,仅在用户打算发布时才执行,并且仅针对您的自定义帖子类型(mycustomtype)执行。
我通常还会添加一些自定义通知消息,以帮助用户了解为什么他们的帖子未发布,但是在此处添加这些消息有点复杂...
我尚未测试此确切的代码,但这是我在大规模自定义帖子类型设置中所做的简化版本。
add_action('save_post', 'save_my_fields', 10, 2);
add_action('save_post', 'completion_validator', 20, 2);
function save_my_fields($pid, $post) {
// don't do on autosave or when new posts are first created
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' ) return $pid;
// abort if not my custom type
if ( $post->post_type != 'mycustomtype' ) return $pid;
// save post_meta with contents of custom field
update_post_meta($pid, 'mymetafield', $_POST['mymetafield']);
}
function completion_validator($pid, $post) {
// don't do on autosave or when new posts are first created
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' ) return $pid;
// abort if not my custom type
if ( $post->post_type != 'mycustomtype' ) return $pid;
// init completion marker (add more as needed)
$meta_missing = false;
// retrieve meta to be validated
$mymeta = get_post_meta( $pid, 'mymetafield', true );
// just checking it's not empty - you could do other tests...
if ( empty( $mymeta ) ) {
$meta_missing = true;
}
// on attempting to publish - check for completion and intervene if necessary
if ( ( isset( $_POST['publish'] ) || isset( $_POST['save'] ) ) && $_POST['post_status'] == 'publish' ) {
// don't allow publishing while any of these are incomplete
if ( $meta_missing ) {
global $wpdb;
$wpdb->update( $wpdb->posts, array( 'post_status' => 'pending' ), array( 'ID' => $pid ) );
// filter the query URL to change the published message
add_filter( 'redirect_post_location', create_function( '$location','return add_query_arg("message", "4", $location);' ) );
}
}
}
对于多个metabox字段,只需添加更多完成标记并检索更多post_meta并进行更多测试。
您必须在ajax上检查/验证您的元字段值,即当用户单击“发布/更新”按钮时。在这里,我正在验证具有元字段“ product_number”的woocommerce产品的空值。
add_action('admin_head-post.php','ep_publish_admin_hook');
add_action('admin_head-post-new.php','ep_publish_admin_hook');
function ep_publish_admin_hook(){
global $post;
if ( is_admin() && $post->post_type == 'product' ){
?>
<script language="javascript" type="text/javascript">
(function($){
jQuery(document).ready(function() {
jQuery('#publish').click(function() {
if(jQuery(this).data("valid")) {
return true;
}
//hide loading icon, return Publish button to normal
jQuery('#publishing-action .spinner').addClass('is-active');
jQuery('#publish').addClass('button-primary-disabled');
jQuery('#save-post').addClass('button-disabled');
var data = {
action: 'ep_pre_product_submit',
security: '<?php echo wp_create_nonce( "pre_publish_validation" ); ?>',
'product_number': jQuery('#acf-field-product_number').val()
};
jQuery.post(ajaxurl, data, function(response) {
jQuery('#publishing-action .spinner').removeClass('is-active');
if ( response.success ){
jQuery("#post").data("valid", true).submit();
} else {
alert("Error: " + response.data.message );
jQuery("#post").data( "valid", false );
}
//hide loading icon, return Publish button to normal
jQuery('#publish').removeClass('button-primary-disabled');
jQuery('#save-post').removeClass('button-disabled');
});
return false;
});
});
})(jQuery);
</script>
<?php
}
}
之后添加ajax处理函数,
add_action('wp_ajax_ep_pre_product_submit', 'ep_pre_product_submit_func');
function ep_pre_product_submit_func() {
//simple Security check
check_ajax_referer( 'pre_publish_validation', 'security' );
if ( empty( $_POST['product_number'] ) || empty( $_POST['file_attachment'] ) ) {
$data = array(
'message' => __('Please enter part number and specification document.'),
);
wp_send_json_error( $data );
}
wp_send_json_success();
}
只是想添加它,以使用Bainternet的解决方案来读取post变量,您将不得不$_POST['form_data']
使用PHP parse_str
函数来解析字符串(只是为了节省一些研究时间)。
$vars = parse_str( $_POST['form_data'] );
然后,您可以使用来访问每个变量$varname
。例如,如果您有一个名为“ my_meta”的元字段,则可以这样访问它:
$vars = parse_str ( $_POST['form_data'] )
if ( $my_meta == "something" ) { // do something }