admin管理员组

文章数量:1125772

I have a custom post type "Propietario" with several custom fields, and 3 of them: "dni", "email" and "phone" I need unique for all Propietario Post types. This CPT is only accesible throw admin wordpress page.

@vijay-pancholi's answer has made me understand what is the flow when registering new custom fields. And after this I have edited my answer.

I am using object-oriented programming for creating my CPT since it is part of a more complex plugin. The method involved, which stores the fields, is "properties_save_fields_owner". The code is more complex but I have tried to reduce it to show only the code involved for this problem:

 <?php

 class Propietario {
public function __construct() {
    add_action('init', array($this, 'registrar_cpt_propietario'));
    add_action('add_meta_boxes', array($this, 'propietarios_meta_box'));
    add_action('save_post', array($this, 'inmuebles_guardar_campos_propietario'));
}

    
/**
 * Registration Propietario CPT
 */
public function registrar_cpt_propietario() {
    $labels = array(
        'name' => 'Propietario',
        'singular_name' => 'Propietario',
        'menu_name' => 'Propietarios',
        'name_admin_bar' => 'Propietario',
        'add_new' => 'Añadir Propietario',
        ...
    );

    $args = array(
        'labels' => $labels,
        'public' => false,
        ...
    );
    
    register_post_type('propietario', $args);
}

/**
 * Add metabox "Datos del propietario"
 */
public function propietarios_meta_box() {
    add_meta_box('propietarios_info', 
        'Información del Propietario', 
        array($this, 'mostrar_campos_propietario'), 
        'propietario',
        'normal',
        'high' );
}

/**
 * Muestra los campos del propietario en el formulario de edición de propietarios.
 * @param WP_Post $post El objeto de entrada actual.
 */
public function mostrar_campos_propietario($post) {
    $nombre = get_post_meta($post->ID, 'nombre', true);
    $apellidos = get_post_meta($post->ID, 'apellidos', true);
    $email = get_post_meta($post->ID, 'email', true);
    $telefono = get_post_meta($post->ID, 'telefono', true);
    $dni = get_post_meta($post->ID, 'dni', true);
    ?>
    <div id="contenedor-propietario">
        <table class="form-table">
            <tr>
                <th><label for="nombre">Nombre*</label></th>
                <td><input type="text" name="nombre" id="nombre" value="<?php echo esc_attr($nombre ?? ''); ?>" required></td>
            </tr>
            
            ...
        </table>
    </div>
    <?php 
}


/**
 * Saves custom field values when saving an propietario
 * @param int $post_id ID of the current propietario
 */
function inmuebles_guardar_campos_propietario($post_id) {
    // Check if it's not an autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
    // Check if it's the correct post type
    if ('propietario' !== get_post_type($post_id)) return;

    //Check if there is already an owner with the same DNI, email or telefono
    $dni = isset($_POST['dni']) ? sanitize_text_field($_POST['dni']) : '';
    $email = isset($_POST['email']) ? sanitize_text_field($_POST['email']) : '';
    $telefono = isset($_POST['telefono']) ? sanitize_text_field($_POST['telefono']) : '';

    //Check if there is already an owner with the same DNI, email or telefono
    if (!empty($dni) || !empty($email) || !empty($telefono)) {
        $exists_propietario  = get_posts(array(
            'post_type' => 'propietario',
            'post_status' => 'publish',
            'meta_query' => array(
                'relation' => 'OR',
                array(
                    'key' => 'dni',
                    'value' => $dni,
                    'compare' => '='
                ),
                array(
                    'key' => 'email',
                    'value' => $email,
                    'compare' => '='
                ),
                array(
                    'key' => 'telefono',
                    'value' => $telefono,
                    'compare' => '='
                ),
            ),
        ));
    } else {
        $exists_propietario = array();
    }

    if (!empty($exists_propietario)) {
        wp_die('Ya existe un propietario con el mismo DNI, teléfono o email. <br> <a href="javascript:history.back()">Volver</a>', 'Error', array('response' => 400));
    }
        
    // Guardar los metadatos del propietario
    if (array_key_exists('nombre', $_POST)) {
        update_post_meta($post_id, 'nombre', sanitize_text_field($_POST['nombre']));
    }
    if (array_key_exists('apellidos', $_POST)) {
        update_post_meta($post_id, 'apellidos', sanitize_text_field($_POST['apellidos']));
    }
    if (array_key_exists('email', $_POST)) {
        update_post_meta($post_id, 'email', sanitize_text_field($_POST['email']));
    }
    if (array_key_exists('telefono', $_POST)) {
        update_post_meta($post_id, 'telefono', sanitize_text_field($_POST['telefono']));
    }
    if (array_key_exists('dni', $_POST)) {
        update_post_meta($post_id, 'dni', sanitize_text_field($_POST['dni']));
    } 
}

  }

 new Propietario();

After debugging, the main problem is that the method inmuebles_save_fields_propietario is executed several times. When I try to create a new CPT it runs right when the metabox opens clicking in "add new". That's why I added the line:

if (!empty($id) || !empty($email) || !empty($telephone)) {

And the code is correct, but even if the line is executed:

wp_die('There is already an owner with the same ID, phone number or email. <br> <a href="javascript:history.back()">Back</a>', 'Error', array('response' = > 400));

The method is executed again and for some reason that I don't know the CPT is registered. You register with empty fields, but a new Owner is created.

I have tried adding exit() after the wp_die, but there is no way I can prevent the method from being executed again, and therefore a new CPT is registered.

How Can I stop registration of CPT when display the error?

I have a custom post type "Propietario" with several custom fields, and 3 of them: "dni", "email" and "phone" I need unique for all Propietario Post types. This CPT is only accesible throw admin wordpress page.

@vijay-pancholi's answer has made me understand what is the flow when registering new custom fields. And after this I have edited my answer.

I am using object-oriented programming for creating my CPT since it is part of a more complex plugin. The method involved, which stores the fields, is "properties_save_fields_owner". The code is more complex but I have tried to reduce it to show only the code involved for this problem:

 <?php

 class Propietario {
public function __construct() {
    add_action('init', array($this, 'registrar_cpt_propietario'));
    add_action('add_meta_boxes', array($this, 'propietarios_meta_box'));
    add_action('save_post', array($this, 'inmuebles_guardar_campos_propietario'));
}

    
/**
 * Registration Propietario CPT
 */
public function registrar_cpt_propietario() {
    $labels = array(
        'name' => 'Propietario',
        'singular_name' => 'Propietario',
        'menu_name' => 'Propietarios',
        'name_admin_bar' => 'Propietario',
        'add_new' => 'Añadir Propietario',
        ...
    );

    $args = array(
        'labels' => $labels,
        'public' => false,
        ...
    );
    
    register_post_type('propietario', $args);
}

/**
 * Add metabox "Datos del propietario"
 */
public function propietarios_meta_box() {
    add_meta_box('propietarios_info', 
        'Información del Propietario', 
        array($this, 'mostrar_campos_propietario'), 
        'propietario',
        'normal',
        'high' );
}

/**
 * Muestra los campos del propietario en el formulario de edición de propietarios.
 * @param WP_Post $post El objeto de entrada actual.
 */
public function mostrar_campos_propietario($post) {
    $nombre = get_post_meta($post->ID, 'nombre', true);
    $apellidos = get_post_meta($post->ID, 'apellidos', true);
    $email = get_post_meta($post->ID, 'email', true);
    $telefono = get_post_meta($post->ID, 'telefono', true);
    $dni = get_post_meta($post->ID, 'dni', true);
    ?>
    <div id="contenedor-propietario">
        <table class="form-table">
            <tr>
                <th><label for="nombre">Nombre*</label></th>
                <td><input type="text" name="nombre" id="nombre" value="<?php echo esc_attr($nombre ?? ''); ?>" required></td>
            </tr>
            
            ...
        </table>
    </div>
    <?php 
}


/**
 * Saves custom field values when saving an propietario
 * @param int $post_id ID of the current propietario
 */
function inmuebles_guardar_campos_propietario($post_id) {
    // Check if it's not an autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
    // Check if it's the correct post type
    if ('propietario' !== get_post_type($post_id)) return;

    //Check if there is already an owner with the same DNI, email or telefono
    $dni = isset($_POST['dni']) ? sanitize_text_field($_POST['dni']) : '';
    $email = isset($_POST['email']) ? sanitize_text_field($_POST['email']) : '';
    $telefono = isset($_POST['telefono']) ? sanitize_text_field($_POST['telefono']) : '';

    //Check if there is already an owner with the same DNI, email or telefono
    if (!empty($dni) || !empty($email) || !empty($telefono)) {
        $exists_propietario  = get_posts(array(
            'post_type' => 'propietario',
            'post_status' => 'publish',
            'meta_query' => array(
                'relation' => 'OR',
                array(
                    'key' => 'dni',
                    'value' => $dni,
                    'compare' => '='
                ),
                array(
                    'key' => 'email',
                    'value' => $email,
                    'compare' => '='
                ),
                array(
                    'key' => 'telefono',
                    'value' => $telefono,
                    'compare' => '='
                ),
            ),
        ));
    } else {
        $exists_propietario = array();
    }

    if (!empty($exists_propietario)) {
        wp_die('Ya existe un propietario con el mismo DNI, teléfono o email. <br> <a href="javascript:history.back()">Volver</a>', 'Error', array('response' => 400));
    }
        
    // Guardar los metadatos del propietario
    if (array_key_exists('nombre', $_POST)) {
        update_post_meta($post_id, 'nombre', sanitize_text_field($_POST['nombre']));
    }
    if (array_key_exists('apellidos', $_POST)) {
        update_post_meta($post_id, 'apellidos', sanitize_text_field($_POST['apellidos']));
    }
    if (array_key_exists('email', $_POST)) {
        update_post_meta($post_id, 'email', sanitize_text_field($_POST['email']));
    }
    if (array_key_exists('telefono', $_POST)) {
        update_post_meta($post_id, 'telefono', sanitize_text_field($_POST['telefono']));
    }
    if (array_key_exists('dni', $_POST)) {
        update_post_meta($post_id, 'dni', sanitize_text_field($_POST['dni']));
    } 
}

  }

 new Propietario();

After debugging, the main problem is that the method inmuebles_save_fields_propietario is executed several times. When I try to create a new CPT it runs right when the metabox opens clicking in "add new". That's why I added the line:

if (!empty($id) || !empty($email) || !empty($telephone)) {

And the code is correct, but even if the line is executed:

wp_die('There is already an owner with the same ID, phone number or email. <br> <a href="javascript:history.back()">Back</a>', 'Error', array('response' = > 400));

The method is executed again and for some reason that I don't know the CPT is registered. You register with empty fields, but a new Owner is created.

I have tried adding exit() after the wp_die, but there is no way I can prevent the method from being executed again, and therefore a new CPT is registered.

How Can I stop registration of CPT when display the error?

Share Improve this question edited Feb 27, 2024 at 15:36 JJMontalban asked Feb 27, 2024 at 6:44 JJMontalbanJJMontalban 213 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

you can use the save_post hook to validate the uniqueness of email and phone fields before saving the post.

Replace seller with your actual post type slug and add below code in functions.php file

// Add custom meta box for Seller post type
function add_seller_meta_box() {
    add_meta_box(
        'seller_meta_box',
        'Seller Details',
        'render_seller_meta_box',
        'seller',
        'normal',
        'default'
    );
}
add_action('add_meta_boxes', 'add_seller_meta_box');

// Render the custom meta box fields
function render_seller_meta_box($post) {
    // Add your custom fields HTML inputs here
    echo '<label for="seller_email">Email:</label>';
    echo '<input type="text" id="seller_email" name="seller_email" value="' . get_post_meta($post->ID, 'seller_email', true) . '" /><br>';

    echo '<label for="seller_phone">Phone:</label>';
    echo '<input type="text" id="seller_phone" name="seller_phone" value="' . get_post_meta($post->ID, 'seller_phone', true) . '" /><br>';
}

// Save custom meta box data
function save_seller_meta_box_data($post_id) {
    // Check if it's not an autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;

    // Check if the current user has permission to edit the post
    if (!current_user_can('edit_post', $post_id)) return;

    // Check if it's the correct post type
    if ('seller' !== get_post_type($post_id)) return;

    // Validate uniqueness of email and phone fields
    $email = isset($_POST['seller_email']) ? sanitize_email($_POST['seller_email']) : '';
    $phone = isset($_POST['seller_phone']) ? sanitize_text_field($_POST['seller_phone']) : '';

    // Check if email or phone already exists
    $existing_sellers = get_posts(array(
        'post_type' => 'seller',
        'post_status' => 'publish',
        'meta_query' => array(
            'relation' => 'OR',
            array(
                'key' => 'seller_email',
                'value' => $email,
                'compare' => '='
            ),
            array(
                'key' => 'seller_phone',
                'value' => $phone,
                'compare' => '='
            )
        )
    ));

    if (!empty($existing_sellers)) {
        wp_die('A seller with this email or phone already exists.', 'Duplicate Seller', array('response' => 400));
    }

    // Save meta data
    update_post_meta($post_id, 'seller_email', $email);
    update_post_meta($post_id, 'seller_phone', $phone);
}
add_action('save_post', 'save_seller_meta_box_data');

I finally solved it by doing the validation before the registration process. In this way, the registration does not start until the fields are validated:

 /** Validation fields **/
function validar_datos_propietario($post_ID, $data) {
    if ('propietario' !== $data['post_type']) return;

    $dni = isset($_POST['dni']) ? sanitize_text_field($_POST['dni']) : '';
    $email = isset($_POST['email']) ? sanitize_text_field($_POST['email']) : '';
    $telefono = isset($_POST['telefono']) ? sanitize_text_field($_POST['telefono']) : '';

    $meta_query = array('relation' => 'OR');

    if (!empty($dni)) {
        $meta_query[] = array(
           'key' => 'dni',
           'value' => $dni,
           'compare' => '='
        );
    }

    $meta_query[] = array(
        'key' => 'email',
        'value' => $email,
        'compare' => '='
    );

    $meta_query[] = array(
        'key' => 'telefono',
        'value' => $telefono,
        'compare' => '='
    );

    $exists_propietario = get_posts(array(
        'post_type' => 'propietario',
        'post_status' => 'publish',
        'meta_query' => $meta_query,
    ));

    if (!empty($exists_propietario)) {
        wp_die('Ya existe un propietario con los mismos datos<br> <a href="javascript:history.back()">Volver</a>', 'Error', array('response' => 400));
    }

 }   
 add_action('pre_post_update', 'validar_datos_propietario', 10, 2);

with pre_post_update registration does not start until the fields are validated

本文标签: addpostmeta unique value for all custom posts