WordPress

php — Jak mogę sprawdzić, czy wartość pola acf nie jest duplikatem podczas dodawania posta?

  • 4 grudnia, 2021
  • 5 min read
php — Jak mogę sprawdzić, czy wartość pola acf nie jest duplikatem podczas dodawania posta?


Oto sposób na sprawdzenie poprawności podczas wpisywania wartości w polu ACF, umieszczania kodu w pliku functions.php motywu lub tworzenia dla niego wtyczki: Musisz zmienić wartości właściwości $fieldName, $fieldKey na prawidłowe wartości swojej dziedziny —są to nazwa pola i klucz pola tego samego pola, które sprawdzamy

class MyPrefix_MetaFieldValidation
{
    protected static $instance;
    
    protected $fieldName="original-title-mcpedl"; // <- Change this with the ACF field name
    protected $fieldKey = 'field_61abaa164244a'; // <- Change this with the field key
    
    protected $ajaxAction = 'myprefix_validate_title';

    protected function __construct()
    {
    }

    public function run()
    {
        add_filter('acf/validate_value/key=' . $this->fieldKey, [$this, 'acfValidation'], 10, 2);
        add_action('wp_ajax_' . $this->ajaxAction, [$this, 'ajaxValidation']);
        add_action('admin_footer', [$this, 'ajaxValidationJS']);
    }

    /**
     * Print the Validation JS on the post edit screen.
     */
    public function ajaxValidationJS()
    {
        if(! $this->isPostEditScreen()) {
            return;
        }

        $nonce = wp_create_nonce($this->ajaxAction);
        ?>
        <script>
            jQuery(document).ready(function(){
                jQuery('#acf-<?= $this->fieldKey; ?>').on('keyup', function (){
                    var field = jQuery(this);
                    var value = field.val();

                    if(! value) {
                        return;
                    }
                    var post_id = jQuery('#post_ID').val();
                    var formatError = function(msg) {
                        return '<div class="acf-notice -error acf-error-message"><p>' + msg + '</p></div>';
                    }

                    jQuery.ajax({
                        url: ajaxurl,
                        data: {"action": "<?= $this->ajaxAction; ?>", "nonce" : "<?= $nonce; ?>", "post_id" : post_id, "meta_value" : value },
                        type: "POST",
                        complete : function(response) {
                            var json = response.responseJSON;
                            field.parents('.acf-input').find('.acf-notice').remove();
                            if(response.status != 200) {
                                field.parents('.acf-input').prepend(formatError('Network or server error!'));
                                return;
                            }
                            if(! json.valid) {
                                field.parents('.acf-input').prepend(formatError(json.msg));
                            }
                        }
                    });
                });
            });
        </script>
    <?php
    }

    /**
     * Perform the ajax validation on the meta field
     */
    public function ajaxValidation()
    {
       $postId = $_REQUEST['post_id'] ? intval($_REQUEST) : 0;
       $metaValue = $_REQUEST['meta_value'] ? $_REQUEST['meta_value'] : '';
       $nonce = $_REQUEST['nonce'] ? $_REQUEST['nonce'] : '';

       if(! wp_verify_nonce($nonce, $this->ajaxAction)) {
           $this->ajaxResponse([
               'valid' => false,
               'msg' => 'Invalid nonce supplied'
           ]);
       }

       if(! $metaValue) {
           $this->ajaxResponse([
               'valid' => true,
               'msg' => 'Empty value'
           ]);
       }

        $existingTitle = $this->metaValueExists($this->fieldName, $metaValue, $postId);

       if($existingTitle) {
            $this->ajaxResponse([
                'valid' => false,
                'msg' => 'This title is already exists for the post id ' . $existingTitle->post_id,
            ]);
        }

        $this->ajaxResponse([
            'valid' => true,
            'msg' => '',
        ]);
    }

    public function acfValidation($valid, $value)
    {
        if(empty($value)) {
            return $valid;
        }

        $postId = isset($_POST['post_id']) ? intval($_POST['post_id']) : null;

        $existingTitle = $this->metaValueExists($this->fieldName, $value, $postId);

        if($existingTitle) {
            $valid = 'This title is already exists for the post id ' . $existingTitle->post_id;
        }

        return $valid;

    }

    /**
     * Create an ajax response
     * @param array $data
     */
    protected function ajaxResponse($data)
    {
        header('Content-Type: application/json;charset=UTF-8');
        echo json_encode($data);
        exit;
    }

    /**
     * Check if we are on the post editing screen
     * @return bool
     */
    protected function isPostEditScreen()
    {
        global $pagenow;
        return (is_admin() && ('post.php' === $pagenow || 'post-new.php' === $pagenow));
    }

    /**
     * Check if a given meta value is already in the database
     * @param string $metaKey
     * @param string $metaValue
     * @param null|int $currentPostId
     * @return false|object
     */
    protected function metaValueExists($metaKey, $metaValue, $currentPostId = null) {

        // Return early if the supplied meta key or value is empty
        $metaValue = trim($metaValue);
        if (empty($metaKey) || empty($metaValue)) {
            return false;
        }

        // Ensure that the supplied post id is integer
        $currentPostId = intval($currentPostId);

        // Query the wp_postmeta table for the meta value and meta key
        global $wpdb;
        $query = "SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE '%s' AND meta_value LIKE '%s'";

        // Exclude the current post id only if it is not empty
        if($currentPostId) {
            $query .= " AND post_id != $currentPostId";
        }

        $result = $wpdb->get_row($wpdb->prepare($query, $metaKey, $metaValue));

        // Return the database row object or false if no record found
        return ($result) ?: false;
    }

    public static function getInstance()
    {
        if(! static::$instance) {
            static::$instance = new static();
        }

        return static::$instance;
    }

}
// Run our plugin
MyPrefix_MetaFieldValidation::getInstance()->run();

Oto, co zrobiliśmy w poprzednim kodzie:

Warto przeczytać!  javascript — Jak przekształcić krótki kod w blok

Umieściłem cały nasz kod w osobnej klasie „MyPrefix_MetaFieldValidation”

Zmieniłem trochę kod, który umieściłeś w swoim pytaniu, tak aby metoda sprawdzania poprawności „metaValueExists” była oddzielona od metody działającej na „acf/validate_value”, ponieważ musimy jej użyć w innym miejscu.

Zmieniłem też zapytanie odpowiedzialne za pobranie duplikatu rekordu z bazy danych na lżejsze.

Usunąłem użycie ukrytego pola niestandardowego, które zawiera identyfikator posta, ponieważ istnieje już pole zawierające bieżący identyfikator posta.

Stworzyłem nową akcję ajax administratora „ajaxValidation”, która zużywa metodę sprawdzania poprawności i odpowiada wynikiem JSON.

Kod JS używa jQuery do tworzenia żądania ajax za każdym razem, gdy użytkownik wpisuje wartość w polu niestandardowym, które chcemy zweryfikować, i wyświetla błąd, jeśli wpisana wartość jest zduplikowana.

Notatka: Ten kod wyświetli użytkownikowi błąd tylko podczas wstawiania wartości w polu niestandardowym, ale nie uniemożliwi użytkownikowi zapisania posta jako wersji roboczej.


Źródło