web-dev-qa-db-fra.com

wp_insert_post () renvoie l'ID de publication correct, aucun échec, mais le contenu de la publication n'est pas mis à jour.

Donc, j'ai un plugin qui utilise Ajax pour construire dynamiquement le contenu de la publication pièce par pièce pour un type de publication personnalisé. Une fois que l'utilisateur a créé sa page, il clique sur Mettre à jour/Publier et Ajax envoie l'intégralité de la page construite au fichier plugin principal PHP où j'essaie d'appeler wp_insert_post().

Voici mon code pertinent (et oui, le var new_content est défini et correct):

jQuery.ajax({
    url: ajaxurl,
    method: 'POST',
    data : {
        update_or_create: '1',
        post_content: new_content,
        post_title: jQuery('#title').val(),
        pid: jQuery('#post_ID').val(),
        action : "update_or_save_zen_page"
    } , 
    success : function(data, textStatus, XMLHttpRequest) {
            //alert(data);
            console.log(data);           // the data sent to the php file is correct
            console.log(textStatus);     // reads 'success'
            console.log(XMLHttpRequest); // normal from what I can tell, "readyState: 4"
    },
    error : function(XMLHttpRequest, textStatus, errorThrown) {
            alert("An unknown error has occurred"); // this does not fire
            //console.log(data);
            //console.log(textStatus);
            //console.log(errorThrown);
            //console.log(XMLHttpRequest);
    }
});

Voici le code php sur lequel ce message est posté:

function pbfcz_save_zen_page() {

    $pid = ( is_numeric($_POST['pid']) ? $_POST['pid'] : 0);
    $the_content = sanitize_post_field ('post_content', $_POST['post_content'], $pid);
    $the_title = sanitize_text_field ( $_POST['post_title'] );

    $post_array = array (
        'ID'           => $pid,
        'post_title'   => $the_title,
        'post_content' => $the_content, // at this point, $the_content is correct
        'post_status'  => 'publish',
        'post_type'    => 'zen_page'
    );

    $insert = wp_insert_post( $post_array, true ); // this returns the ID every time, meaning successful update, but it is not always successful

    //echo $insert;      // this is always the post ID, meaning success
    echo $the_content; // this is still correc

   wp_die();}

Lorsque l'utilisateur sélectionne enregistrer, j'ai suivi les données jusqu'à l'argument de wp_insert_post(). C'est toujours correct. La fonction renvoie TOUJOURS l'identifiant de publication, ce qui signifie qu'elle a réussi. Je ne reçois pas un WP_Error retourné ni des erreurs de code HTML telles que 404 ou 500 ou quelque chose du genre.

Je ne reçois pas non plus d'erreur dans la console des outils de développement de chrome. Mais il met à jour PARFOIS avec succès - peut-être que tous les essais sur 10 fonctionnent.

J'ai essayé d'utiliser GET au lieu de POST

J'ai essayé de supprimer le 'post_status' => 'publish' des arguments.

J'ai essayé de convertir le post_content en UTF8 en utilisant utf8_encode().

J'ai essayé d'utiliser post_content_filtered plutôt que post_content.

Rien ne semble fonctionner, et cela fonctionne de manière aléatoire, et je ne peux pas trouver de motif.

Le seul autre élément d’information dont je dispose est peut-être lié au fait que les images ont du mal à se charger sur cette même page. S'il y a une image dans le contenu de la page, des erreurs telles que

"net :: ERR_SPDY_PING_FAILED" ou "net :: ERR_CONNECTION_RESET"

ou:

"net :: ERR_CONNECTION_CLOSED"

parfois lors du chargement de la page. Le serveur essaie de charger l'image pendant plus d'une minute, puis expire (mais l'image est déjà affichée sur la page pendant toute cette minute, puis lorsqu'il disparaît, l'image disparaît).

Quelqu'un peut-il suggérer pourquoi cela ne fonctionne pas (avec zéro erreur), mais fonctionne-t-il parfois? Merci à tous d'avance et laissez-moi savoir si vous avez besoin de plus de code ou de fond.

1
Jeremy Muckel

Ne cherchez plus à rappeler votre rappel AJAX, il existe déjà un endpoint API REST qui est bien testé et qui effectue tout cela immédiatement:

example.com/wp-json/wp/v2/zen_page

Mettons donc en file d'attente un script d'assistance pour nous donner l'URL et un jeton de sécurité/nonce:

wp_enqueue_script( 'wp-api' );

Vous devrez must activer l'API REST pour votre type d'article personnalisé en ajoutant cette option lors de l'enregistrement de votre type d'article. Si vous ne le faites pas, les noeuds finaux zen_page rest ne seront pas créés par core:

'show_in_rest' => true

Puis ajustez le JS:

var post_id = 1;
jQuery.ajax({
    url: wpApiSettings.root + 'wp/v2/zen_page/'+post_id,
    method: 'POST',
    beforeSend: function ( xhr ) {
        xhr.setRequestHeader( 'X-WP-Nonce', wpApiSettings.nonce );
    },
    data : {
        content: 'post content goes here',
        title:   'test post',
        status:  'publish'
    }
}).fail( function( response ) {
    // failure
    console.log( 'failure' );
    console.log( response );
}).done( function( response ) {
    // success!
    console.log( 'success' );
    console.log( response );
}).;

WP inclut automatiquement l'objet wpApiSettings lorsque vous mettez en file d'attente wp-api et dataprend ces valeurs . Pour ce faire, vous aurez besoin d'un cookie de connexion actif. Si ce n'est pas une option, vous pouvez créer de nouveaux terminaux

Si vous souhaitez en créer une nouvelle, envoyez une demande POST ici:

example.com/wp-json/wp/v2/zen_page

Si vous souhaitez en mettre à jour une, envoyez une demande POST ici:

example.com/wp-json/wp/v2/zen_page/2

Où 2 est l'ID de publication que vous souhaitez mettre à jour. Envoyez une demande DELETE pour le supprimer. Dans une API REST, vous ne transmettez pas d'ID de publication ni d'actions, mais vous utilisez des URL, de la même manière que des URL différentes chargent des pages différentes, des points de terminaison différents effectuent des opérations différentes. Vous pouvez GET/POST/DELETE/PUT, et ce sont tous les types de requête HTTP standard, pas un paramètre transmis dans la demande.

Notes de suivi

rest_base

Cela vous permettra de modifier le noyau utilisé pour créer le noeud final, par exemple.

'rest_base' => 'bananas'

changera l'URL de vos points de terminaison en wp/v2/bananas. Notez que vous ne souhaitez pas nommer cette pages car il existe déjà un noeud final pages fourni par core.

zen_page

Cela pourrait en fait être mieux si vous utilisiez simplement le type de message page et une taxonomie personnalisée pour différencier les pages zen_page des pages normales.

Ça ne marche pas

L'API REST est conçue pour indiquer pourquoi cela n'a pas fonctionné, par exemple. si j'essaie de visiter wp-json/wp/v2/skjlfnvlkdjfv j'aurai:

{"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}}

et si j'essaie d'utiliser le noeud final wp-json/wp/v2/settings en mode navigation privée:

{"code":"rest_forbidden","message":"Sorry, you are not allowed to do that.","data":{"status":403}}

L'administrateur AJAX renverra 0 dans tous ces scénarios. Soyez donc reconnaissant, mais faites attention aux messages d'échec ou d'erreur. Ici, nous avons vu que j’essayais de faire une demande à un noeud final qui n’existait pas, puis de nouveau à un noeud final pour lequel je n’avais pas d’autorisation, car j’étais déconnecté.

2
Tom J Nowell

Grâce à @TomJNowell, j'ai pu utiliser wp_insert_post (), ce qui ne fonctionnerait pas, et mettre à jour mes publications avec la version php de l'API REST.

J'ai dû:

1) Inclure 'show_in_rest' => true dans l'enregistrement de mon type de message personnalisé.

2) Mettre en file d'attente le script d'assistance: wp_enqueue_script( 'wp-api' );

3) Utilisez ce php pour gérer la demande de publication jQuery

add_action('wp_ajax_update_or_save_zen_page', 'pbfcz_save_zen_page', 99999);
function pbfcz_save_zen_page() {
    $pid = $_POST['pid'];
    $the_content = sanitize_post_field ('post_content', $_POST['post_content'], $pid);
    $the_title = sanitize_text_field ( $_POST['post_title'] );  
    $the_content = str_replace('\"', '"', $the_content);

    $_rest = new WP_REST_Request('PUT', '/wp/v2/zen_page/' . $pid);
    $_rest->set_param( 'title', $the_title);
    $_rest->set_param( 'status', 'publish');
    $_rest->set_param( 'content', $the_content);

    $response = rest_do_request($_rest);
    echo 'done';

    wp_die(); // do not remove
}

Mon jQuery n'a pas beaucoup changé par rapport à la question initiale, publiant ici pour plus de clarté:

jQuery.ajax({
        url: ajaxurl,
        method: 'POST',
        data : {
            post_content : new_content,
            post_title   : jQuery('#title').val(),
            pid          : post_id,
            action       : "update_or_save_zen_page"
        } , 
        success : function(data, textStatus, XMLHttpRequest) {
            //console.log(data);          
        },
        error : function(XMLHttpRequest, textStatus, errorThrown) {
            alert("An unknown error has occurred and the ajax request to create/update the post has failed.");
        }
});
0
Jeremy Muckel