Convertește meta_field în taxonomii

Convertește meta_field în taxonomii

De multe ori în WP se ajunge să fie folosită structura greșită de date. Mai exact, în loc de a ține datele în taxonomii, se țin în meta data. (sau invers, dar am întâlnit mai rar situația asta).

Ca regulă de bază: ții în meta dacă este o informație unică pentru postul respectiv, ții în taxonomie dacă mai există și alte posturi cu aceleași informații.

Exemple de date de ținut în meta: ISBN-ul unei publicații, excerpt-ul, rating, ediția. Exemple de date de ținut în taxonomii: autorii unei publicații, editura, genul, anul publicării.

Avantajele acestei abordări sunt multiple:

  1. Ca admin, poți găsi rapid informația. Vrei cărțile scrise de GRRM? Perfect, te duci în taxonomia autori și îl selectezi.
  2. Ca dezvoltator poți creea query-uri complexe și performante. Vrei cărțile scrise de GRRM și publicate de Nemira între anii 2010 și 2012? WP_Query cu un tax_query simplu și ai scăpat fără să omori serverul.
  3. Vrei să afișezi toți autorii? un get_terms este suficient, la fel, fără să omori serverul.
  4. Ai UI built in. Nu te mai complici cu ACF, Carbon Fields, Toolset sau mai știu eu ce.

Taxonomiile se creează ușor (la fel și custom post types) și… cam aia e.

Cum migrezi?

Dar ce faci dacă totuși s-a nimerit să începi proiectul cu meta și ți-ai dat seama pe parcurs că niște taxonomii sunt mai potrivite? După ce înregistrezi taxonomiile, faci următoarea chestie: iei toate ID-urile postărilor buclucașe și le parsezi corespunzător.

Este important ca atât hook-ul să se întâmple după ce s-a înregistrat taxonomia și post type (în mod corect, asta se întâmpla la init):

add_action('init', function () {
    $posts = get_posts([
        'post_type' => 'book',
        'post_status' => 'any',
        'fields' => 'ids',
        'posts_per_page' => -1,
    ]);

    array_walk($posts, 'ntz_migrate_acf_to_taxonomies');

    die('migrated fields to taxonomies');
}, 99);

După care ne apucăm să facem terms din taxonomii:


function ntz_maybe_insert_term($name, $tax){
    if (empty($name)) { return; }

    $term = get_term_by('name', $name, $tax, ARRAY_A);

    if (!$term) {
        $term = wp_insert_term($name, $tax, []);
    }

    if (is_wp_error($term)) {
        print_r($term);
        die();
    }

    return (int) $term['term_id'];
}

function ntz_migrate_acf_to_taxonomies($postID)
{
    $fields = [];

    $fields['book-author'] = get_field('field_5e163acf0fa50', $postID);

    foreach ($fields as $tax => $field) {
        if (empty($field)) { continue; }
        $terms = [];

        if (!is_array($field)) {
            $field = explode(',', $field);
        }

        foreach ($field as $termName) {
            $terms[] = ntz_maybe_insert_term(trim($termName), $tax);
        }

        $terms = array_filter($terms);
        if (!empty($terms)) {
            $insert = wp_set_object_terms($postID, $terms, $tax);

            if (is_wp_error($insert)) {
                print_r($insert);
                die();
            }
        }
    }
}

Și … cam asta e tot.

Exemplul de mai sus este dintr-un site care folosește ACF:

$fields['book-author'] = get_field('field_5e163acf0fa50', $postID);

Dar la fel de bine se poate folosi și meta nativ:

$fields['book-author'] = get_post_meta($postID, 'book-authors', true);

După ce faci toată treaba asta, faci un refresh la o pagină oarecare, aștepți puțin (depinde cât de multe posturi ai) și… gata. Poți șterge codul de mai sus, migrarea este completă.

2 Comentarii

George a scris

Asemenea operatiuni prefer sa le rulez implementand o comanda custom in WP cli. Iar daca nu am access la consola, le rulez folosind Action Scheduler-ul (package dezvoltat de WooCommerce). In felul acesta… migration-ul ruleaza smooth atat pe local, cat si in productie (indiferent daca sunt zeci de mii de posts).
Evident, daca rulezi operatiunea doar local… poate ca nu merita intotdeauna sa pierzi timpul cu lucruri sofisticate. :)

Adaugă un comentariurăspuns pentru

Poți adăuga bucăți de cod folosind [code]codul tău aici[/code], [js][/js], [php][/php] etc.

Link-urile în context sunt binevenite. Comentariile fără nume/email valid sunt șterse.
PS: Comentariul NU este editabil.

Acest sit folosește Akismet pentru a reduce spamul. Află cum sunt procesate datele comentariilor tale.

Site-ul blog.iamntz.com utilizează cookie-uri. Continuarea navigării presupune acceptarea lor. Mai multe informații.

windows apple dropbox facebook twitter