web-dev-qa-db-fra.com

wp_set_object_terms et les tableaux

J'ai besoin d'ajouter une catégorie à environ 2 500 articles et j'ai besoin d'utiliser une requête SQL ou wp_set_object_terms avec PHP. Je regarde wp_set_object_terms pour pouvoir ajouter une catégorie sans affecter les catégories actuellement assignées.

La fonction ci-dessous qui utilise wp_set_object_terms' (à partir du Codex WordPress) ajoute une ou plusieurs catégories d'un tableau (dans le cas de l'exemple, catégories 6 et 8) à la publication avec l'ID de 42 (dans l'exemple).

Mais je dois pouvoir ajouter un tableau d'identifiants de publication ($object_id), pas un tableau de catégories.

Selon https://codex.wordpress.org/Function_Reference/wp_set_object_terms , $object_id doit être un entier unique.

Comment utiliser un tableau de ~ 2500 identifiants postaux pour $object_id? Dois-je effectuer une boucle pour chaque boucle, parcourir le tableau et traiter chaque ajout de catégorie à chaque ID de publication, un à la fois?

De https://codex.wordpress.org/Function_Reference/wp_set_object_terms :

// An array of IDs of categories we to add to this post. (Not using an array)
$cat_ids = array( 6, 8 );

// Add these categories, note the last argument is true.
// (42 is the $object_id; I will hardcode the category ID)
$term_taxonomy_ids = wp_set_object_terms( 42, $cat_ids, 'category', true );

if ( is_wp_error( $term_taxonomy_ids ) ) {
    // There was an error somewhere and the terms couldn't be set.
} else {
    // Success! These categories were added to the post.
}
4
markratledge

Je doute que cela justifie l’effort d’écriture de requêtes SQL personnalisées pour seulement 2500 publications.

Dans la fonction wp_set_object_terms( $object_id, ... ), nous avons:

$object_id = (int) $object_id;

il est donc exact qu’il ne faut entrer qu’un seul identifiant de poste.

Donc, vous auriez besoin de boucler sur votre tableau $post_ids mais il pourrait suffire d'utiliser l'astuce wp_defer_term_counting()1):

/**
 * Add terms to posts (with debug display)
 */
function wpse_terms_to_posts( $terms, $taxonomy, $append, &$post_ids )
{
    wp_defer_term_counting( true );

    print '<ul>';
    foreach( (array) $post_ids as $post_id )
    {
        $tt_ids = wp_set_object_terms( $post_id, $terms, $taxonomy, $append );

        print '<li>';
        if( is_wp_error( $tt_ids ) )
            printf(
                'Problem adding terms to post_id: %d - Error: %s',
                $post_id,
                $tt_ids->get_error_message()
            );
    else
            print 'Success adding terms to post_id: ' . $post_id ;
        print '</li>';
    }
    print '</ul>';

    wp_defer_term_counting( false );
}

Ici, nous passons $post_ids par référence au cas où il serait très volumineux.

Utilisation (PHP 5.4+):

wpse_terms_to_posts(
    $terms     = [ 6, 8 ],
    $taxonomy  = 'category',
    $append    = true,
    $post_ids  = [ 123, 234, 345 ]
);

Nous pourrions même découper le tableau $post_ids si 2500 est trop pour notre système en une seule exécution.

Voici un exemple d'utilisation de la fonction avec admin-ajax.php avec une telle fonctionnalité découpée en tranches:

Nous créons notre propre action avec:

/**
 * Custom wp ajax action to activate our wpse_terms_to_posts() function
 * 
 * Example: /wp-admin/admin-ajax.php
 *          ?action=wpse-terms-to-posts&wpse_offset=0&wpse_length=500
 */
add_action( 'wp_ajax_wpse-terms-to-posts', function()
{
    $offset = filter_input( INPUT_GET, 'wpse_offset', FILTER_SANITIZE_NUMBER_INT );
    $length = filter_input( INPUT_GET, 'wpse_length', FILTER_SANITIZE_NUMBER_INT );

    // Check for user capability and non empty user input:
    if( current_user_can( 'manage_options' ) && '' !== $offset && '' !== $length  )
    {
        print '<h3>Start:</h3>';      
        $start = microtime( true );

        // Settings - Edit to your needs:
        $terms     = [ 6, 8 ];
        $taxonomy  = 'category';
        $append    = true;
        $post_ids  = [ 123, 234, 345, 456, 567, 678, 789 ];

        // Add terms to posts:
        wpse_terms_to_posts (
            $terms,
            $taxonomy,
            $append,
            array_slice( $post_ids, $offset, $length )
        );

        printf( '<h3>Done in %f seconds</h3>', microtime( true ) - $start );         
        exit();
    }

} );

où nous utilisons les paramètres wpse_offset et wpse_length GET pour découper le tableau posts.

Si nous voulons découper le tableau post ids en morceaux de 500, nous pouvons l’activer manuellement avec:

/wp-admin/admin-ajax.php?action=wpse-terms-to-posts&wpse_offset=0&wpse_length=500

/wp-admin/admin-ajax.php?action=wpse-terms-to-posts&wpse_offset=500&wpse_length=500

/wp-admin/admin-ajax.php?action=wpse-terms-to-posts&wpse_offset=1000&wpse_length=500

/wp-admin/admin-ajax.php?action=wpse-terms-to-posts&wpse_offset=1500&wpse_length=500

/wp-admin/admin-ajax.php?action=wpse-terms-to-posts&wpse_offset=2000&wpse_length=500

De cette façon, nous pouvons vérifier les erreurs de terme.

J'espère que vous pourrez le modifier selon vos besoins.

1) wp_defer_term_counting() a été mentionné pour la première fois sur WPSE dans ce answer by @JanFabry

4
birgire