Script para duplicar categorías como etiquetas

2

Tengo un sitio con más de 900 publicaciones, cada una con aproximadamente 3-5 categorías. Me gustaría copiar cada una de las categorías para ser una etiqueta y estoy buscando el código SQL para hacer precisamente eso. No quiero borrar o sobrescribir las categorías. (¿Supongo que es lo mejor que se puede hacer para fines de SEO?)

Estoy teniendo dificultades para entender exactamente qué se debe INSERTAR.

Lo que tengo hasta ahora ... Son los comentarios al final con los que necesito ayuda.

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)
-- }
    
pregunta gram 16.12.2015 - 17:25

2 respuestas

4

Como dije, preferiríamos usar funciones nativas aquí, que son más seguras y ya hacen todo el trabajo duro por usted. Tenemos que ser muy cuidadosos aquí ya que esta es una operación muy costosa de ejecutar. No hacer esto correctamente puede bloquear su sitio debido al tiempo de espera

Tu flujo de trabajo también es incorrecto aquí. Primero crearía todas las etiquetas, y después de eso, insertaría las etiquetas en las publicaciones. Estás tratando de hacer todo de una vez.

Primero nos permite capturar todas las categorías y usar esa información para crear etiquetas. Solo nota:

  • post_tag no es una taxonomía jerárquica, no puede tener nombres duplicados, las taxonomías jerárquicas como category pueden tener nombres de término duplicados dentro de diferentes jerarquías. Si tiene categorías con los mismos nombres, obtendrá un objeto WP_Error si intentará insertar etiquetas con nombres duplicados. Para evitarlo, simplemente verificaremos si existe una etiqueta antes de intentar insertarla

  • Las etiquetas no pueden tener relaciones padre / hijo, las categorías pueden. Entonces, cuando duplicamos una categoría para que sea un término, deberíamos establecer todos los padres explícitamente en 0

Aquí está el código: ( NOTA : requeriríamos 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 );

Ahora debería ver estas etiquetas en la página de administración de Etiqueta . También puede eliminar el código ya que ya no es necesario.

Ahora que hemos creado nuestras etiquetas, debemos agregarlas a nuestras publicaciones. Aquí deberíamos tener cuidado ya que estamos hablando de más de 900 publicaciones, por lo que no queremos romper el banco.

Lo que haremos es consultar todas esas publicaciones, pero solo las ID de las publicaciones que ahorran mucho en recursos. Además, usaremos get_the_category que se almacenan en caché, por lo que no requiere llamadas db adicionales, wp_get_post_categories no se almacenan en caché, por lo que es realmente caro

Debido a que wp_set_post_terms es caro, quizás deba dividir lo siguiente en un par de consultas, pero Creo que una consulta debería ser suficiente

Permite adjuntar las etiquetas a nuestras publicaciones

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();
});

Tus publicaciones ahora deben tener etiquetas adjuntas que coincidan con las categorías. Ahora también puede eliminar la función cuando hayamos terminado

    
respondido por el Pieter Goosen 16.12.2015 - 20:35
1

Usted solicitó la solución de SQL, pero SQL no es (todavía) mi especialidad, pero aún puedo ayudarlo. SQL también parece inútil en su caso porque WordPress proporciona todas las herramientas necesarias para lograrlo.

No recomiendo ejecutar esto más de una vez si elimina los comentarios del final del código. Lo entenderás cuando llegues allí.

Este código "copia" todas las categorías de todas tus publicaciones y las guarda como etiquetas. No elimina categorías y tampoco establece nuevas etiquetas para las publicaciones. Si también quieres establecer etiquetas para publicaciones, avísame.

¡PS! ¡Solo funciona correctamente si las categorías no son jerárquicas sin padres!

Por favor, hágamelo saber si hay algún problema. Este código no debería causar ningún daño en la medida en que no elimines los comentarios del final del código.

<?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' );
} 
*/
?>
    
respondido por el N00b 16.12.2015 - 18:15

Lea otras preguntas en las etiquetas