Ottieni meta_id insieme a meta_key e meta_value
È in qualche modo possibile ottenere con get_post_meta
o get_post_custom
il meta_id restituito insieme al meta_value
? Per esempio:
$data = get_post_meta( $post_id, 'my_key' );
// restituisce questo:
array( 0 => array('myvalue1', 1002 ), 1 => array( 'myvalue2', 1003 ));
L'idea di base è che poiché potrebbero esserci più meta_values per lo stesso meta_key
, dovrei conoscere il meta_id
per poter aggiornare/eliminare in modo affidabile i meta del post.
Questa funzione ha funzionato per me:
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;
}
restituirà un array di oggetti come:
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
)
)

Non sono a conoscenza di una funzione/metodo di WordPress Core per recuperare i meta dei post con la chiave. Questo non significa che non esista definitivamente. Potrebbe esserci. Non so tutto su WordPress, faccio solo finta :) O forse mi è sfuggito in questo momento.
Tuttavia, il quarto parametro di update_post_meta
serve a garantire che aggiorni solo il valore che desideri aggiornare nei casi in cui ci sono più chiavi.
$prev_value
(mixed) (opzionale) Il vecchio valore del campo personalizzato che desideri modificare. Questo serve a differenziare tra diversi campi con la stessa chiave. Se omesso, e ci sono più righe per questo post e meta chiave, tutti i valori meta verranno aggiornati.
Inserisci il valore precedentemente salvato in quel quarto parametro e solo quella voce verrà aggiornata.
delete_post_meta
funziona in modo simile, ma con il terzo parametro invece del quarto.

@s_ha_dum come valuti la pertinenza di questa risposta alla domanda? Chi ha posto la domanda necessita di ottenere l'id meta tramite la chiave meta e l'id del post, cosa che la mia funzione restituirà.

L'OP afferma: "L'idea di base è che, poiché potrebbero esserci più meta_values per la stessa meta_key, dovrei conoscere il meta_id per aggiornare/eliminare in modo affidabile i post meta." Cioè, il problema/preoccupazione riguarda l'aggiornamento affidabile dei post meta quando ci sono più chiavi. La parte che dice "dovrei conoscere il meta_id per aggiornare/eliminare in modo affidabile i post meta" è errata. Non è necessario e il codice di WordPress Core adotta un approccio diverso al problema.

Penso che l'OP abbia un problema XY nella domanda, in altre parole.

Arrivo a una conclusione simile nella mia risposta: http://wordpress.stackexchange.com/a/110780/178

Ho effettivamente provato questa soluzione, ma mi sembra un po' strano fare affidamento sul meta value quando si ha a che fare con meta valori serializzati. Speravo ci fosse un modo per ottenere il meta_id insieme ai meta_values, in modo da poter usare update_metadata_by_mid
e delete_metadata_by_mid

aggiungi questo codice nel tuo 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;
}
e poi chiamalo dove vuoi in questo modo
$meta_id = get_mid_by_key( your_post_id, 'your_meta_key' );

È strano che WordPress fornisca funzioni per ottenere, aggiornare ed eliminare i meta tramite meta_id dalla versione 3.3, ma a partire dalla versione 3.7 non abbia alcuna funzione che restituisca l'id del meta. Quindi, utilizzando le funzioni principali da meta.php come riferimento, ho implementato le seguenti funzioni per poter recuperare sia gli id dei meta che i loro valori.
Soluzione
Utilizza la funzione personalizzata get_post_meta_db()
qui sotto per ottenere gli id e i valori delle chiavi meta, poi usa le funzioni di WordPress update_meta()
e delete_meta()
per manipolare i post meta.
Ad esempio:
$meta = get_post_meta_db( $post_id, 'my_key', true ); // Restituisce 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' );
Ecco le definizioni delle funzioni personalizzate:
/**
* Alternativa a get_post_meta(), per recuperare i meta_id. @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 );
}
/**
* Alternativa a get_metadata(). Differenze:
* - restituisce tutti i campi meta (invece di solo meta_values)
* - bypassa i filtri/azioni dei meta
* - interroga il database, bypassando la cache
* - restituisce i meta_values grezzi (senza unserializzare gli array)
*
* @param string $meta_type Tipo di oggetto a cui è associato il metadata (es. comment, post, o user)
* @param int $object_id ID dell'oggetto a cui è associato il metadata
* @param string $meta_key Opzionale. Chiave del metadata da recuperare. Di default, restituisce tutti i metadata per l'oggetto specificato.
* @param mixed $meta_val Opzionale. Se specificato, restituirà solo le righe con questo meta_value.
* @param bool $single Opzionale. Se true, restituisce una singola riga, altrimenti un array di righe.
* @param string $output Opzionale. Una delle costanti ARRAY_A | ARRAY_N | OBJECT | OBJECT_K. @see wpdb::get_results()
*
* @return array Singola riga di metadata, array di righe, array vuoto se nessun risultato, o false in caso di errore.
*/
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;
// Costruisci la query
global $wpdb;
$query = $wpdb->prepare( "SELECT * FROM $table", $object_id );
// Aggiungi condizioni alla query
$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() );
/*
Scommenta questa sezione per far sì che la funzione unserializzi i valori (come get_metadata())
NOTA: Questo può essere implementato più efficientemente usando array_map
// Unserializza i meta_values serializzati
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:
- Queste funzioni interrogano il database, quindi usale con parsimonia!
- Questa implementazione segue la convenzione vista in
get_metadata_by_mid()
, non utilizzando i pre-filtri"get_post_metadata"
/"get_user_metadata"
e non aggiornando la cache. - Nel mio caso, avevo bisogno solo dei dati grezzi, quindi a differenza di
get_metadata_by_mid()
, questa implementazione non unserializza i valori dei meta. - Queste funzioni permettono di selezionare i metadata per post_id/user_id, meta key, meta value, o qualsiasi combinazione di questi.

L'idea di base è che poiché possono esserci più valori
meta_values
per la stessameta_key
, dovrei conoscere l'meta_id
per poter aggiornare/eliminare in modo affidabile i meta dei post.
Ciò che chiami meta_id
qui tecnicamente non esiste in Wordpress. Esiste l'post_id
e quello è anche l'id per tutti i meta (nel linguaggio meta questo è l'object_id
).
Accanto a ciò c'è la meta_key
e come giustamente scrivi, poiché può esserci più di un valore per ogni meta_key
sullo stesso object_id
, c'è ambiguità perché tutto dipende dall'ordine in cui il database presenta i valori qui - e solo indirettamente, perché i valori meta hanno anche la loro cache, l'object cache.
Quindi anche se puoi vedere un meta_id
nel database, non viene ulteriormente utilizzato se non per avere una chiave primaria nel db.
Non fa parte del risultato del database che viene utilizzato all'interno del codice PHP di Wordpress e quindi non fa parte della meta-cache e quindi non arriva mai alle funzioni dell'API meta (perché accedono al database tramite l'API della meta cache).
Il che porta alla conclusione finale:
Poiché parli di meta_id
e questo esiste solo nel database (tabella dbprefix_postmeta
), la tua domanda può significare solo eliminare/aggiornare una voce in quella tabella. Semplici operazioni SQL normali dovrebbero essere sufficienti.

La funzione core di WordPress has_meta
restituisce array associativi di metadati. Ogni array di metadati contiene il meta_id
.
Valore di ritorno
(array[]) Array di array di metadati per l'ID del post specificato.
- '...$0' (array) Array associativo di metadati.
- 'meta_key' (string) Chiave del meta.
- 'meta_value' (mixed) Valore del meta.
- 'meta_id' (string) ID del meta come stringa numerica.
- 'post_id' (string) ID del post come stringa numerica.
È possibile aggiornare ed eliminare in modo affidabile i valori dei meta che condividono la stessa chiave utilizzando has_meta
insieme a update_metadata_by_mid
e delete_metadata_by_mid
.
Nell'esempio dell'OP, per aggiornare array('myvalue1', 1002)
ed eliminare array('myvalue2', 1003)
:
$metadata = has_meta( $post_id );
foreach ( $metadata as $item ) {
// Converti la stringa numerica meta_id in un intero
$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 );
}
}
Riferimento: has_meta
viene utilizzato dal core di WordPress per popolare i campi del form nel pannello Campi Personalizzati.
