Obține meta_id împreună cu meta_key și meta_value
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.
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
)
)

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.

@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.

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.

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

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

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

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' );

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.

Ideea de bază este că, deoarece pot exista multiple valori meta (
meta_values
) pentru aceeași cheie meta (meta_key
), ar trebui să cunoscmeta_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.

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.
