Obține meta_id împreună cu meta_key și meta_value

19 aug. 2013, 23:48:26
Vizualizări: 21.1K
Voturi: 5

Este cumva posibil să folosești get_post_meta sau get_post_custom și să ai meta_id returnat împreună cu meta_value? De exemplu:

$data = get_post_meta( $post_id, 'my_key' );
// returnează aceasta:
array( 0 => array('myvalue1', 1002 ), 1 => array( 'myvalue2', 1003 ));

Ideea de bază este că, deoarece pot exista mai multe meta_values pentru același meta_key, ar trebui să cunosc meta_id pentru a putea actualiza/șterge în mod fiabil datele meta ale postării.

5
Comentarii

get_post_meta(); necesită al treilea parametru ca fiind true, pe care îl lipsești get_post_meta( $post_id, 'my_key', true );

Anjum Anjum
20 aug. 2013 00:03:50

@Anjum Al treilea parametru nu este obligatoriu, este opțional. Dacă treci al treilea parametru true vei obține doar o singură valoare... deci pentru OP, trecerea acelui parametru este greșită.

gmazzap gmazzap
20 aug. 2013 00:06:02

@G. M Ce spune WordPress codex: $single (boolean) (opțional) Dacă este setat la true atunci funcția va returna un singur rezultat, ca șir de caractere. Dacă este false sau nu este setat, atunci funcția returnează un array cu câmpurile personalizate. Acest lucru poate să nu fie intuitiv în contextul array-urilor serializate. Dacă obții un array serializat cu această metodă, vei dori ca $single să fie true pentru a obține de fapt un array deserializat înapoi. Dacă treci false sau îl lași necompletat, vei avea un array cu un singur element, iar valoarea de la indexul 0 va fi șirul serializat. Default: false

Anjum Anjum
20 aug. 2013 00:10:14

@Anjum este exact ceea ce am spus. Dar dacă citești întrebarea: pot exista multiple meta_values pentru același meta_key înțelegi că în acest caz utilizarea celui de-al treilea parametru ca true este greșită.

gmazzap gmazzap
20 aug. 2013 00:14:19

Da, în cazul meu trebuie să obțin multiple meta_values pentru același meta_key.

ragulka ragulka
20 aug. 2013 10:21:59
Toate răspunsurile la întrebare 6
0

Această funcție a funcționat pentru mine:

function get_complete_meta( $post_id, $meta_key ) {
  global $wpdb;
  $mid = $wpdb->get_results( $wpdb->prepare("SELECT * FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s", $post_id, $meta_key) );
  if( $mid != '' )
    return $mid;

  return false;
}

va returna un array de obiecte precum:

Array
(
    [0] => stdClass Object
        (
            [meta_id] => 1002
            [post_id] => 1
            [meta_key] => my_key
            [meta_value] => my_value
        )
    [1] => stdClass Object
        (
            [meta_id] => 1003
            [post_id] => 668
            [meta_key] => my_key
            [meta_value] => another value
        )
)
8 nov. 2013 14:39:57
6

Nu cunosc o funcție/metodă din Core pentru a prelua meta datele postării cu cheia. Asta nu înseamnă că nu există definitiv una. Poate exista. Nu știu totul despre WordPress, doar mă prefac :) Sau poate mi-a scăpat din minte acum.

Totuși, al patrulea parametru al update_post_meta este pentru a te asigura că actualizezi doar valoarea dorită în cazurile în care există mai multe chei.

$prev_value
(mixed) (opțional) Valoarea veche a câmpului personalizat pe care dorești să o modifici. Acest lucru este pentru a diferenția între mai multe câmpuri cu aceeași cheie. Dacă este omis, iar există mai multe înregistrări pentru această postare și cheie meta, toate valorile meta vor fi actualizate.

Transmiți valoarea salvată anterior în acel al patrulea parametru și atunci doar acea intrare va fi actualizată.

delete_post_meta funcționează similar, dar cu al treilea parametru, nu al patrulea.

20 aug. 2013 00:00:08
Comentarii

@s_ha_dum cum simți că acest răspuns este legat de întrebare, întrebătorul are nevoie să obțină meta id prin meta key și post id, ceea ce funcția mea va returna.

Anjum Anjum
20 aug. 2013 00:16:54

OP spune: "Ideea de bază este că, deoarece pot exista mai multe meta_values pentru aceeași meta_key, ar trebui să cunosc meta_id pentru a actualiza/șterge în mod fiabil post meta." Adică, problema/preocuparea este cu actualizarea fiabilă a post meta acolo unde există mai multe chei. Partea care spune "ar trebui să cunosc meta_id pentru a actualiza/șterge în mod fiabil post meta" este greșită. Nu este necesar și codul WordPress Core adoptă o abordare diferită a problemei.

s_ha_dum s_ha_dum
20 aug. 2013 00:25:45

Cred că OP are o problemă XY în întrebare, cu alte cuvinte.

s_ha_dum s_ha_dum
20 aug. 2013 00:26:22

Am ajuns la o concluzie similară în răspunsul meu: http://wordpress.stackexchange.com/a/110780/178

hakre hakre
20 aug. 2013 00:36:54

Am încercat de fapt această soluție, dar mi se pare puțin incomod să mă bazez pe valoarea meta atunci când lucrez cu valori meta serializate. Speram să existe o modalitate de a obține meta_id împreună cu meta_values, astfel încât să pot folosi update_metadata_by_mid și delete_metadata_by_mid

ragulka ragulka
20 aug. 2013 10:21:08

Ce anume este incomod? Procesul este invizibil din partea ta. Nucleul (Core) se ocupă de treabă.

s_ha_dum s_ha_dum
20 aug. 2013 16:29:55
Arată celelalte 1 comentarii
1

adaugă acest cod în functions.php

function get_mid_by_key( $post_id, $meta_key ) {
    global $wpdb;
    $mid = $wpdb->get_var( $wpdb->prepare("SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s", $post_id, $meta_key) );
    if( $mid != '' )
    return (int) $mid;

    return false;
}

și apoi apelează unde dorești în felul următor

$meta_id = get_mid_by_key( your_post_id, 'your_meta_key' );
19 aug. 2013 23:57:13
Comentarii

Aceasta funcționează doar atunci când există o singură instanță a unui meta_key dat. Va eșua când există mai multe meta_values cu același meta_key.

ragulka ragulka
20 aug. 2013 10:09:49
0

Este ciudat că WordPress oferă funcții pentru a obține, actualiza și șterge meta date prin meta_id începând cu versiunea 3.3, dar până în versiunea 3.7 nu are nicio funcție care să returneze ID-ul meta. Așadar, folosind funcțiile de bază din meta.php ca referință, am implementat următoarele funcții pentru a putea prelua atât ID-urile meta, cât și valorile.

Soluție

Folosește funcția personalizată de mai jos get_post_meta_db() pentru a obține ID-urile și valorile cheilor meta, apoi folosește funcțiile WordPress update_meta() și delete_meta() pentru a manipula meta datele postării.

De exemplu:

$meta = get_post_meta_db( $post_id, 'my_key', true ); // Returnează array( 
//   'post_id' => 5, 
//   'meta_id' = 33, 
//   'meta_key' => 'my_key', 
//   'meta_value' => 'the_value_for_my_key' );
update_meta( $meta['meta_id'], $meta['meta_key'], 'new_value' );

Iată definițiile funcțiilor personalizate:

/**
 * Alternativă la get_post_meta(), pentru a prelua meta_ids. @see get_meta_db()
 */
function get_post_meta_db( $post_id, $meta_key = null, $single = false, $meta_val = null, $output = OBJECT ){
    return get_meta_db( 'post', $post_id, $meta_key, $meta_val, $single, $output );
}

/**
 * Alternativă la get_metadata(). Diferențe:
 *  - returnează toate câmpurile meta (în loc de doar meta_values)
 *  - ocolește filtrele/acțiunile meta
 *  - interoghează baza de date, ocolind cache-ul
 *  - returnează meta_values brute (în loc să deserializeze array-uri)
 *
 * @param string $meta_type Tipul de obiect pentru care sunt meta datele (ex: comment, post, sau user)
 * @param int    $object_id ID-ul obiectului pentru care sunt meta datele
 * @param string $meta_key  Opțional. Cheia meta de preluat. Implicit, returnează toate meta datele pentru obiectul specificat.
 * @param mixed  $meta_val  Opțional. Dacă este specificat, va returna doar rândurile cu această meta_value.
 * @param bool   $single    Opțional. Dacă true, returnează un singur rând, altfel returnează un array de rânduri.
 * @param string $output    Opțional. Orice constantă ARRAY_A | ARRAY_N | OBJECT | OBJECT_K. @see wpdb::get_results()
 *
 * @return array Un singur rând de meta date, array de rânduri, array gol dacă nu sunt potriviri, sau false dacă a apărut o eroare.
 */
function get_meta_db( $meta_type, $object_id = null, $meta_key = null, $meta_val = null, $single = false, $output = OBJECT ){

    if( !$meta_type || !$table = _get_meta_table( $meta_type ) ) 
        return false;

    // Construiește interogarea
    global $wpdb;
    $query = $wpdb->prepare( "SELECT * FROM $table", $object_id );
    // Adaugă condițiile transmise la interogare
    $where = array();
    if( $object_id = absint( $object_id ) )
        $where[] = $wpdb->prepare( sanitize_key( $meta_type.'_id' ).' = %d', $object_id );
    if( !empty($meta_key) )
        $where[] = $wpdb->prepare( 'meta_key = %s', wp_unslash( $meta_key ) );
    if( null !== $meta_val )
        $where[] = $wpdb->prepare( 'meta_value = %s', maybe_serialize(wp_unslash($meta_val)));
    if( !empty($where) )
        $query .= ' WHERE '.implode(' AND ', $where );
    if( $single )
        $query .= ' LIMIT 1';

    $rows = $wpdb->get_results( $query, $output );

    if( empty( $rows ) )
        return ( $single ? null : array() );

    /* 
    Decomentează această secțiune pentru a avea această funcție să deserializeze valori (ca get_metadata())
    NOTĂ: Aceasta poate fi implementată mai eficient folosind array_map
    // Deserializare meta_values serializate
    foreach( $rows as &$r ){
        $v =& ($output==ARRAY_A ? $r['meta_value'] : $output==ARRAY_N ? $r[3] : $r->meta_value );
        $v = maybe_unserialize( $v );
    } */

    return ( $single ? reset( $rows ) : $rows );
}

Note:

  • Aceste funcții interoghează baza de date, așa că folosiți-le cu moderație!
  • Această implementare urmează convenția văzută în get_metadata_by_mid(), prin neutilizarea pre-filtrelor "get_post_metadata"/"get_user_metadata" și prin neactualizarea cache-ului.
  • În cazul meu, aveam nevoie doar de date brute, așa că, spre deosebire de get_metadata_by_mid(), această implementare nu deserializează valorile meta.
  • Aceste funcții permit selectarea meta datelor după post_id/user_id, cheie meta, valoare meta sau orice combinație a acestora.
6 nov. 2013 19:47:45
0

Ideea de bază este că, deoarece pot exista multiple valori meta (meta_values) pentru aceeași cheie meta (meta_key), ar trebui să cunosc meta_id-ul pentru a putea actualiza/șterge în mod fiabil metadatele postului.

Ceea ce numiți meta_id aici, tehnic nu există în Wordpress. Există doar post_id-ul, care este și ID-ul pentru toate metadatele (în terminologia meta, acesta este object_id).

Pe lângă acesta, există meta_key și, așa cum ai menționat corect, deoarece pot exista mai multe valori pentru același meta_key pe același object_id, apare ambiguitatea deoarece totul depinde de ordinea în care baza de date prezintă valorile - și asta doar indirect, deoarece valorile meta au și propriul cache, object cache.

Deci, chiar dacă poți vedea un meta_id în baza de date, acesta nu este utilizat decât pentru a avea o cheie primară în baza de date.

Acesta nu face parte din rezultatul bazei de date care este utilizat în codul PHP al WordPress din zona utilizatorului și, prin urmare, nu face parte din meta-cache și nu ajunge niciodată în funcțiile API-ului meta (deoarece acestea accesează baza de date prin API-ul meta cache).

Ceea ce duce la concluzia finală:

Deoarece vorbești despre meta_id și acesta există doar în baza de date (tabelul dbprefix_postmeta), întrebarea ta se poate referi doar la ștergerea/actualizarea unei intrări în acel tabel. Operațiuni SQL normale ar trebui să fie suficiente.

20 aug. 2013 00:33:13
0

Funcția de bază a WordPress has_meta returnează tablouri asociative de metadate. Fiecare tablou de metadate conține meta_id.

Return

(array[]) Tablou de tablouri de metadate pentru ID-ul postării specificat.

  • '...$0' (array) Tablou asociativ de metadate.
    • 'meta_key' (string) Cheia meta.
    • 'meta_value' (mixed) Valoarea meta.
    • 'meta_id' (string) ID-ul meta ca șir numeric.
    • 'post_id' (string) ID-ul postării ca șir numeric.

Puteți actualiza și șterge în mod fiabil valorile meta care au aceeași cheie meta folosind has_meta împreună cu update_metadata_by_mid și delete_metadata_by_mid.

În exemplul OP, pentru a actualiza array('myvalue1', 1002) și a șterge array('myvalue2', 1003):

$metadata = has_meta( $post_id );

foreach ( $metadata as $item ) {
    // Convertim șirul numeric meta_id în întreg
    $meta_id    = intval( $item[ 'meta_id' ] );
    $meta_key   = $item[ 'meta_key' ];
    $meta_value = $item[ 'meta_value' ];

    if ( $meta_key === 'my_key' && $meta_value === 'myvalue1' ) {
        update_metadata_by_mid( 'post', $meta_id, 'new value' );
    } else if ( $meta_key === 'my_key' && $meta_value === 'myvalue2' ) {
        delete_metadata_by_mid( 'post', $meta_id );
    }
}

Referință: has_meta este folosit de WordPress core pentru a popula câmpurile din panoul Câmpuri Personalizate.

1 sept. 2022 20:26:10