web-dev-qa-db-fra.com

Script pour dupliquer les catégories en tant que balises

J'ai un site avec 900+ messages, chacun avec environ 3-5 catégories. Je voudrais copier chacune des catégories pour en faire une balise et je recherche le code SQL pour le faire. Je ne veux pas supprimer ou écraser les catégories. (Je suppose que c'est la meilleure chose à faire à des fins de référencement?)

J'ai du mal à déterminer exactement ce qui doit être INSÉRÉ.

Ce que j'ai jusqu'à présent ... Ce sont les commentaires à la fin pour lesquels j'ai besoin d'aide.

global $wpdb;
$query = "
SELECT $wpdb->posts.ID, $wpdb->term_relationships.object_id, $wpdb->term_relationships.term_taxonomy_id, $wpdb->term_taxonomy.term_taxonomy_id, $wpdb->terms.term_id, $wpdb->terms.name, $wpdb->terms.slug
FROM $wpdb->posts
LEFT JOIN $wpdb->term_relationships ON
($wpdb_posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON
($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
LEFT JOIN $wpdb->terms ON
($wpdb->term_taxonomy.term_taxonomy_id = $wpdb->terms.term_id)
WHERE $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->term_taxonomy.taxonomy = 'category'
AND $wpdb->terms.name NOT LIKE '*%'
ORDER BY post_date DESC
";

$results = $wpdb->get_results($query);

$insert = "";

$wpdb->query($insert);

-- Next steps:
-- LOOP? {
--  INSERT INTO $wpdb->terms (name, slug)
--  VALUES (terms.name, terms.slug)
-- }
-- SELECT new term_id's for the above inserted names and slugs
-- LOOP? {
--  INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy)
--  VALUES (terms.term_id, post_tag)
-- }
-- SELECT new term_taxonomy_id's for the above inserted term_id's
-- LOOP? {
--  INSERT INTO $wpdb->term_relationships (term_taxonomy_id, object_id)
--  VALUES (term_taxonomy.term_taxonomy_id, post_id)
-- }
2
gram

Comme je le disais, nous préférerions utiliser les fonctions natives ici, ce qui est plus sûr et fait déjà tout le travail difficile pour vous. Nous devons faire très attention ici car il s’agit d’une opération très coûteuse. Si vous ne le faites pas correctement, votre site peut se bloquer en raison de l'expiration du délai

Votre flux de travail est également faux ici. Je voudrais d'abord créer toutes les balises, puis les insérer dans les messages. Vous essayez de faire tout à la fois.

Permet d’abord de saisir toutes les catégories et d’utiliser ces informations pour créer des tags. Notez juste:

  • post_tag étant une taxonomie non hiérarchique, il ne peut pas y avoir de noms en double. Les taxonomies hiérarchiques telles que category peuvent avoir des noms de termes en double dans différentes hiérarchies. Si vous avez des catégories portant le même nom, vous obtiendrez un objet WP_Error si vous voulez insérer des balises avec des noms en double. Pour éviter cela, nous allons simplement vérifier si une balise existe avant d'essayer de l'insérer.

  • Les tags ne peuvent pas avoir de relations parent/enfant, les catégories peuvent. Ainsi, lorsque nous dupliquons une catégorie en tant que terme, nous devrions définir explicitement tous les parents sur 0

Voici le code: (NOTE: Nous aurions besoin de PHP 5.4+ )

// Lets create our tags. We will use wp_insert_term hooked to init
add_action( 'init', function ()
{
    // Get all categories
    $categories = get_categories( ['hide_empty' => 0] );

    // Probably totally unnecessary, but check for empty $categories
    if ( !$categories )
        return;

    // Loop through the categories and create our tags
    foreach ( $categories as $category ) {
        // First make sure that there is no tag that exist with the same name
        if ( term_exists( $category->name, 'post_tag' ) )
            continue;

        // Set our arguments for our terms from $category
        $args = [
            'description' => $category->description,
            'parent'      => 0, // We can drop this, default is 0
            'slug'        => $category->slug,
        ];
        wp_insert_term( $category->name, 'post_tag', $args );
    } //endforeach
}, PHP_INT_MAX );

Vous devriez maintenant voir ces balises dans votre page d'administration Tag . Vous pouvez également supprimer le code car il n'est plus nécessaire.

Maintenant que nos balises sont créées, nous devons les ajouter à nos publications. Ici, il faut être prudent, car vous parlez de plus de 900 postes, nous ne voulons donc pas casser la banque.

Ce que nous ferons, c’est que nous interrogerons toutes ces publications, mais uniquement l’identifiant de la publication, qui permet d’économiser beaucoup de ressources. De plus, nous allons utiliser get_the_category qui sont mis en cache, donc cela ne nécessite pas d'appels de base de données supplémentaires, wp_get_post_categories ne sont pas mis en cache, donc c'est vraiment cher

Étant donné que wp_set_post_terms est coûteux, vous devrez peut-être diviser le texte suivant en plusieurs requêtes, mais je crois qu'une requête devrait suffire.

Permet d'attacher les balises à nos messages

add_action( 'template_redirect', function ()
{
    // Get all our posts
    $args = [
        'posts_per_page' => -1,
        'fields'         => 'ids', // Make the query lean
        // Add any additional query args here
    ];
    $q = new WP_Query( $args );

    if ( !$q->have_posts() )
        return;

    while ( $q->have_posts() ) {
    $q->the_post();

        // Get all the categories attached to the post
        $categories = get_the_category();
        if ( !$categories )
            continue;

        // Get the names from the categories into an array
        $names = wp_list_pluck( $categories, 'name' );
        // Loop through the names and make sure that the post does not already has the tag attached
        foreach ( $names as $key=>$name ) {
            if ( has_tag( $name ) )
                unset ( $names[$key] );
        }
        // Make sure we still have a valid $names array
        if ( !$names )
            continue; 

        // Finally, attach our tags to the posts
        wp_set_post_terms( 
            get_the_ID(), // Post ID 
            $names, // Array of tag names to attach
            'post_tag',
            true // Only add the tags, do not override
        );
    }
    wp_reset_postdata();
});

Vos messages devraient maintenant avoir des balises attachées à eux correspondant aux catégories. Vous pouvez également maintenant supprimer la fonction comme nous l'avons fait

5
Pieter Goosen

Vous avez demandé une solution SQL, mais SQL n’est pas (encore) ma spécialité, mais je pourrais quand même vous aider. SQL semble également inutile dans votre cas, car WordPress fournit tous les outils nessecary pour y parvenir.

Je ne recommande pas de l'exécuter plus d'une fois si vous supprimez des commentaires à la fin du code. Vous comprendrez quand vous y arriverez.

Ce code "copie" toutes les catégories de tous vos messages et les enregistre en tant que balises. Il ne supprime pas les catégories et ne définit pas non plus les nouvelles balises dans les publications. Si vous souhaitez également définir des balises sur des publications, faites-le moi savoir.

PS! Cela ne fonctionne correctement que si les catégories ne sont pas hiérarchisées, c'est-à-dire sans parents!

S'il vous plaît laissez-moi savoir s'il y a des problèmes. Ce code ne devrait pas faire de mal tant que vous ne supprimez pas les commentaires à la fin du code.


<?php
global $post;

//Get ALL the posts with query
$args = array(
              'post_type' => 'post',
              'post_status' => 'any'   //Change to 'publish', 'draft' or 'pending' if you don't want to get ALL post STATUSES
            );

$post_query = new WP_Query( $args );

//Declare new array of our categories which eventually become tags
$new_tags = array();

while ($post_query->have_posts()) : $post_query->the_post();

     //Get all the categories names of the post and save as an array variable
     $post_categories = wp_get_post_categories($post->ID, array('fields' => 'names') );

     //Loop through all categories
     foreach ( $post_categories as $category ) {

            //Check if category is already in array
            if ( ! in_array($category , $new_tags ) ) {

                 //Push category to array if it isn't in array yet
                 array_Push( $new_tags, $category );
            }
     }

endwhile;
wp_reset_postdata();

//VERY IMPORTANT - test first without making new tags and check if everything seems to be correct 
//PS! Compare the count of items in array (starts with 0 - it's 1 less because of that) with category count in WP admin area
print_r($new_tags);


//Add new tags programmatically - don't do it if you're sure that array is correct!!
/*
foreach ( $new_tags as $tag ) {
      wp_insert_term( $tag, 'post_tag' );
} 
*/
?>
1
N00b