Come aggiornare il valore update_post_meta come array

19 ott 2016, 12:00:56
Visualizzazioni: 59.1K
Voti: 9

Ho creato un nuovo campo personalizzato all'interno dei miei elementi del menu di navigazione come opzioni di selezione multipla usando update_post_meta() come segue

function YPE_update_custom_fields($menu_id, $menu_item_db_id, $menu_item_data) {
    if (is_array($_REQUEST['menu-item-content-multiple'])) {
        update_post_meta($menu_item_db_id, '_menu_item_content_multiple', $_REQUEST['menu-item-content-multiple'][$menu_item_db_id]);
    }
}
add_action('wp_update_nav_menu_item', 'YPE_update_custom_fields', 10, 3);

function YPE_setup_custom_fields($item) {
    $item->content_multiple = get_post_meta($item->ID, '_menu_item_content_multiple', true);
    return $item;
}
add_filter('wp_setup_nav_menu_item', 'YPE_setup_custom_fields');

Poi ho aggiunto un nuovo campo nel file Walker_Nav_Menu_Edit come segue

MODIFICATO

<?php
$select_options = array (
    'key_1' => 'option1', 
    'key_2' => 'option2', 
    'key_3' => 'option3'
); 
?>
<p class="field-content-multiple description description-thin">
<label for="edit-menu-item-content-multiple-<?php echo $item_id; ?>">
    <?php _e( 'Contenuto Multiplo' ); ?><br />
    <select name="menu-item-content-multiple[<?php echo $item_id; ?>][]" id="edit-menu-item-content-multiple-<?php echo $item_id; ?>" class="widefat code edit-menu-item-content-multiple" multiple="multiple">
            <?php foreach ($select_options as $key => $value): ?>
                <option value="<?php echo $key; ?>"  <?php echo selected(in_array($key, $item->content_multiple)); ?>><?php echo $value;?></option>
            <?php endforeach ?>
    </select>
</label>
</p>

Il mio codice funziona con il select box singolo senza alcun problema ma quando uso in_array() nei casi di selezione multipla restituisce questo errore

Warning: in_array() expects parameter 2 to be array, null given
3
Commenti

Il messaggio di errore è abbastanza descrittivo. Cosa non capisci? Per favore, spiega. in_array() richiede che il secondo parametro sia un array, controlla la documentazione PHP. Quindi, devi solo assicurarti che il secondo parametro che passi a in_array() sia un array. Questo è tutto riguardo al messaggio di errore. Inoltre, nota che questa domanda, così com'è, riguarda un errore generico di PHP, che è fuori dall'ambito di questo sito.

cybmeta cybmeta
19 ott 2016 12:50:28

@cybmeta dopo aver usato il codice della tua risposta e aver messo false in get_post_meta ora il secondo parametro $item->content_multiple è un array ma quando seleziono più opzioni salva solo l'ultima opzione e non salva tutte le opzioni selezionate

Shwan Namiq Shwan Namiq
19 ott 2016 15:13:05

Per favore, lascia i commenti sulla risposta nella risposta stessa, altrimenti può confondere altri utenti.

cybmeta cybmeta
19 ott 2016 15:19:29
Tutte le risposte alla domanda 2
14
22

Fai così:

$item->content_multiple = get_post_meta($item->ID, '_menu_item_content_multiple', true);

Nota come imposti il terzo parametro di get_post_meta() a true, il che significa che verrà restituito un solo valore. Se leggi la documentazione, vedrai che, se il terzo parametro è false, otterrai un array con tutti i valori per quel campo meta.

Ricorda che i campi meta possono essere unici o multipli. Oppure possono essere unici con una stringa di dati serializzata.

Così com'è, il tuo codice sembra memorizzare tutti i valori del select multiple in un unico campo meta. Quindi, ottieni un array nella richiesta e lo passi come valore singolo del campo meta. Quando il valore di un campo meta è un array, WordPress lo converte in una stringa serializzata prima di memorizzarlo nel database; questo viene fatto internamente con la funzione maybe_serialize(). Poi, quando provi a ottenere il valore del campo meta, se è una stringa serializzata, WordPress la passa attraverso maybe_unserialize(), così la stringa serializzata viene riconvertita nell'array:

Spieghiamo con un esempio generico.

Questo sarà l'array di valori da memorizzare nel database:

$values = [ 'red', 'yellow', 'blue', 'pink' ];

Se la tua chiave meta è "color", allora hai due opzioni:

Multiple voci per la stessa chiave meta

$values = [ 'red', 'yellow', 'blue', 'pink' ];
foreach( $values as $value ) {
    // Questo metodo usa `add_post_meta()` invece di `update_post_meta()`
    add_post_meta( $item_id, 'color', $value );
}

Ora, l'elemento identificato con $item_id avrà diverse voci per la chiave meta color. Poi, puoi usare get_post_meta() con il terzo parametro impostato a false e otterrai un array con tutti i valori:

// Non hai davvero bisogno di impostare il terzo parametro
// perché è false di default
$colors = get_post_meta( $item_id, 'color' );

// $colors dovrebbe essere un array con tutti i valori meta per la chiave color
var_dump( $colors );

Memorizzare l'array in una singola voce meta

In questo caso, l'array di valori viene serializzato prima di essere memorizzato nel database:

$values = [ 'red', 'yellow', 'blue', 'pink' ];
// WordPress fa questo automaticamente quando un array viene passato come valore meta
// $values = maybe_serialize( $values );
update_post_meta( $item_id, 'color', $values );

Ora, l'elemento identificato con $item_id avrà solo una voce per la chiave meta color; il valore è una stringa serializzata che rappresenta l'array originale. Poi, puoi usare get_post_meta(), con il terzo parametro impostato a true, poiché hai solo una voce, e poi deserializzare la stringa per ottenere nuovamente l'array:

$colors = get_post_meta( $item_id, 'color', true );
// WordPress fa questo automaticamente quando il valore meta è un array serializzato
// $colors = maybe_unserialize( $colors );

// $colors dovrebbe essere un array
var_dump( $colors );

Puoi seguire lo stesso approccio con il select multiple del tuo form.

Con una sola voce per la chiave meta:

if( ! empty( $_REQUEST['menu-item-content-multiple'][$menu_item_db_id] ) ) {
    $meta_field_value = $_REQUEST['menu-item-content-multiple'][$menu_item_db_id];
    // $meta_field_value verrà serializzata automaticamente da WordPress
    update_post_meta( $menu_item_db_id, '_menu_item_content_multiple', $meta_field_value );
}

Poi, puoi usare il valore come array:

 // Il valore restituito da get_post_meta() viene deserializzato automaticamente da WordPress
 $item->content_multiple = get_post_meta( $item->ID, '_menu_item_content_multiple', true );

Con multiple voci:

Il concetto qui è leggermente diverso; avrai diverse voci nel database con la stessa chiave meta, quindi devi usare add_post_meta() invece di update_post_meta() per aggiungere una nuova voce per ogni valore.

if( ! empty( $_REQUEST['menu-item-content-multiple'][$menu_item_db_id] ) ) {
    $values = $_REQUEST[ 'menu-item-content-multiple' . $menu_item_db_id ];
    foreach( $values as $value ) {
        add_post_meta( $menu_item_db_id, '_menu_item_content_multiple', $value );
    }
}

Ora, puoi usare get_post_meta() con il terzo parametro impostato a false (è il valore predefinito, quindi puoi ometterlo):

$item->content_multiple = get_post_meta( $item->ID, '_menu_item_content_multiple', false );

Entrambe le opzioni vanno bene, devi decidere quale sia migliore per organizzare i dati nel tuo progetto.

Nota a margine: dovresti fare un po' di sanificazione prima di usare i dati in input, ma non conosco i requisiti per te, ecco un esempio:

array_map( 'sanitize_text_field', wp_unslash( $_REQUEST['menu-item-content-multiple'][$menu_item_db_id] ) );
19 ott 2016 13:01:35
Commenti

Grazie, devo usare false invece di true. Ma hai usato true anche in get_post_meta !!!

Shwan Namiq Shwan Namiq
19 ott 2016 13:28:37

Come è scritto il tuo codice, no, devi usare il metodo serialize e unserialize. Per poter usare false in get_post_meta() dovresti memorizzare ogni valore del tuo select in una voce separata nel database, con la stessa chiave ma più volte, cioè usare update_post_meta() per ogni valore ma utilizzando sempre la stessa chiave; poi puoi usare false in get_post_meta() per ottenerli tutti. Spero di essermi spiegato.

cybmeta cybmeta
19 ott 2016 13:50:05

Ho aggiornato la risposta con, spero, una spiegazione migliore.

cybmeta cybmeta
19 ott 2016 13:59:53

Grazie, il tuo post ha risolto il messaggio di errore, ho modificato il mio post aggiungendo un campo personalizzato a selezione come nel mio file. Ma il problema è che quando seleziono più opzioni dopo il salvataggio delle impostazioni viene salvata solo l'ultima opzione e non tutte le opzioni selezionate, perché? C'è qualche errore nell'uso della funzione WordPress selected(); ? <?php echo selected(in_array($key, $item->content_multiple)); ?> (ho usato il tuo secondo codice dell'opzione)

Shwan Namiq Shwan Namiq
19 ott 2016 14:57:49

Nota che per utilizzare più voci per la stessa meta chiave, devi eseguire update_post_meta() per ogni valore, ma utilizzando la stessa chiave ogni volta, come ho fatto nella risposta.

cybmeta cybmeta
19 ott 2016 15:21:03

Sì, voglio più voci per la stessa meta chiave, ma non so come usare questo metodo, per favore aiutami e spiegamelo con del codice

Shwan Namiq Shwan Namiq
19 ott 2016 15:30:35

Continuiamo questa discussione nella chat.

Shwan Namiq Shwan Namiq
19 ott 2016 15:43:38

Scusa cybmeta ma ho un altro problema con la deselezione delle opzioni. Quando voglio deselezionare un'opzione già selezionata, dopo aver salvato le impostazioni rimane selezionata e non riesco più a deselezionare nessuna opzione dopo la selezione

Shwan Namiq Shwan Namiq
20 ott 2016 02:00:14

Usa semplicemente delete_post_meta() quando ne hai bisogno. Ho aggiunto un esempio base.

cybmeta cybmeta
20 ott 2016 10:39:08

Grazie, funziona ma non riesco a rimuovere tutte le opzioni selezionate, inoltre rimane la prima opzione selezionata. Il delete_post_meta non rimuove la prima opzione selezionata.

Shwan Namiq Shwan Namiq
20 ott 2016 14:06:26

WordPress serializza/deserializza automaticamente i dati degli array in un singolo campo meta (così come fanno le funzioni delle opzioni), non dovresti serializzare/deserializzare manualmente.

Milo Milo
20 ott 2016 18:10:16

@Milo perché delete_post_meta in questa risposta non deseleziona o rimuove la prima opzione selezionata.

Shwan Namiq Shwan Namiq
20 ott 2016 22:29:21

@Milo, ottimo rilevamento, ero confuso con la spiegazione nel codex e nel portale per sviluppatori, ma guardando il codice sorgente, posso confermare che WordPress esegue automaticamente la serializzazione/deserializzazione per noi; risposta aggiornata.

cybmeta cybmeta
21 ott 2016 09:59:41

@ShwanNamiq Penso sia meglio se pubblichi una nuova domanda per il tuo nuovo problema.

cybmeta cybmeta
21 ott 2016 10:10:47
Mostra i restanti 9 commenti
6

Non stai utilizzando correttamente la funzione selected(). La funzione selected() richiede 1 parametro obbligatorio e 2 opzionali. Nel tuo caso, è meglio utilizzare $selected e $current.

Manca l'underscore prima del nome del tuo meta-field nel nome del select.

Per selected():

selected( $selected, $current, $echo);

Puoi leggere di più a riguardo sul codex riferimento alla funzione selected()

Il tuo select dovrebbe essere così:

<select name="_menu-item-content-multiple[]" multiple>
     <?php 
        foreach ($select_options as $key => $value) {
            echo '<option value="'.$key.'" '.selected(in_array($key, $item->content_multiple), $key).'>'.$value.'</option>';
        }
     ?>
</select>
19 ott 2016 12:12:38
Commenti

Ho usato il tuo codice ma mostra ancora l'errore, penso che l'errore sia in $item->content_multiple che deve essere salvato come array perché $item->content_multiple salva anche un singolo valore e non salva più valori come array

Shwan Namiq Shwan Namiq
19 ott 2016 12:20:18

Ok, verifica che il nome del tuo meta-field sia sempre lo stesso, attualmente non lo è. Se vuoi che abbia il prefisso underscore, usa sempre questo underscore, e nomina il tuo select con underscore o con trattino. update_post_meta funziona ma nessun valore verrà salvato.

Benoti Benoti
19 ott 2016 12:26:45

Ho aggiunto più di 10 campi come il campo sopra e tutti funzionano senza problemi. Dico che l'errore è in $item->content_multiple perché questo campo salva anche un singolo valore e non salva più valori contemporaneamente perché non viene aggiornato come array. Prima del ciclo foreach quando metto $item->content_multiple = array(); funziona e non mi mostra alcun errore ma non salva i valori

Shwan Namiq Shwan Namiq
19 ott 2016 12:38:26

Non sono proprio sicuro, ma verifica il tipo di $item, è un oggetto o un array? ok il contenuto è un array, ma prova a convertirlo in un array per la funzione in_array, prima del ciclo foreach (array)$item e in selected() usalo come array in questo modo: $item['content_multiple']

Benoti Benoti
19 ott 2016 12:50:11

$item è un oggetto non un array()

Shwan Namiq Shwan Namiq
19 ott 2016 15:01:34

in_array() accetta solo un array come secondo parametro. Devi convertire il tuo oggetto in un array in questo modo: (array)$item, ma lascia il terzo argomento di get_post_meta a true (per ottenere l'oggetto e poi potrai convertirlo)

Benoti Benoti
19 ott 2016 15:16:32
Mostra i restanti 1 commenti