Bagaimana Anda menghapus nilai bidang dengan entity_metadata_wrapper ()?

20

Misalkan saya memiliki entitas dengan bidang field_foodi atasnya dan saya ingin menghapus nilai bidang itu.

Apa yang harus saya lewati $wrapper->set()?

Saya telah mencoba NULLdan array()dan keduanya menghasilkan pesan kesalahan.

joachim
sumber
1
Apakah Anda mencari metode EntityStructureWrapper::clear()atau EntityValueWrapper::clear()mungkin?
Clive
Memanggil ::clearsecara langsung tidak setara dengan menyetel bidang ke nilai kosong, karena tidak memanggil updateParentseperti halnya panggilan setdengan nilai kosong. Di antara hal-hal lainnya, updateParentpastikan bahwa yang setter callbackdidefinisikan dalam info properti (lihat drupalcontrib.org/api/drupal/… ) dipanggil.
Alice Heaton

Jawaban:

24

Masalahnya adalah Anda harus menetapkan nilai kosong yang kompatibel dengan tipe data bidang Anda. Jika tidak, Anda akan mendapatkan pengecualian yang diajukan. Lewat NULLatau array()saat string diharapkan akan memunculkan kesalahan.

Hal lain yang perlu diingat adalah bahwa data yang Anda lewati juga akan bergantung pada apakah bidang Anda adalah nilai tunggal, bidang multi-nilai, atau bidang dengan beberapa properti.

Jika bidang Anda adalah nilai tunggal (dan karenanya pembungkus untuk bidang tersebut adalah turunan dari EntityValueWrapper ) maka Anda harus menetapkannya sebagai nilai kosong yang kompatibel dengan tipe data yang dimaksud . Misalnya, dua metode berikut ini setara:

$wrapper->title = '';
$wrapper->title->set('');

Namun tiga contoh berikut ini akan memunculkan pengecualian, karena tipe data tidak kompatibel dengan titlebidang:

$wrapper->title->set();
$wrapper->title->set(NULL);
$wrapper->title->set(array());

Jika bidang Anda adalah bidang dengan beberapa properti (misalnya bidang teks yang diformat, yang mendefinisikan a valuedan formatproperti) dan dengan demikian merupakan contoh dari EntityStructureWrapper , maka array()atau NULLakan menjadi nilai kosong yang benar. Jadi, Anda dapat melakukan hal berikut:

$wrapper->field_formatted_text = array();
$wrapper->field_formatted_text = NULL;

Tetapi dalam kasus itu, melewatkan string kosong akan menimbulkan kesalahan. Perhatikan bahwa Anda bisa memilih untuk membuat valueproperti itu kosong, dalam hal ini string adalah tipe data yang benar:

$wrapper->field_formatted_text->value = '';

Akhirnya, jika bidang Anda adalah bidang multi-nilai (dan karenanya pembungkus Anda adalah turunan dari EntityListWrapper ) maka arrayatau NULLadalah nilai kosong yang benar, dan tiga baris berikut ini setara:

$wrapper->field_example_multiple->set();
$wrapper->field_example_multiple = array();
$wrapper->field_example_multiple = NULL;

Catatan: Memanggil clearmetode pada pembungkus tidak sama dengan menyetel bidang ke nilai kosong. Ketika bidang diatur ke nilai kosong, maka panggilan EntityMetadataWrapper :: updateParent pada pembungkus induk bidang. Ini memastikan antara lain bahwa yang setter callbackdidefinisikan oleh hook_entity_property_info disebut. Memanggil cleartidak melakukan itu.

Alice Heaton
sumber
1
Perhatikan bahwa jika bidangnya banyak dan diperlukan, tetapkan sebagai array()atau NULLbisa gagal, karena bidang itu tidak boleh kosong. Ini berbeda dari $nodepenugasan bidang normal , di mana Anda secara terprogram dapat menyimpan bidang wajib yang kosong (tidak akan menghemat melalui UI Drupal sendiri). Dalam kasus ini, solusinya adalah array(N), di mana N adalah ID dari entitas yang belum ada yang direferensikan. Perhatikan bahwa ini akan disimpan dengan ID itu, sehingga data Anda bisa dibilang "rusak" dalam arti relasional; tetapi seharusnya tidak memengaruhi lapisan tema jika Anda melakukan semua hal yang benar di sana (misalnya menggunakan Display Suite atau Panel).
JP
$w->field_allowed_regions->set(array(null));adalah satu-satunya opsi yang berfungsi untuk bidang referensi taksonomi multi-nilai saya.
Luar biasa
Dalam kasus saya, saya memiliki bidang referensi entitas dengan nilai tunggal. Berikut ini bekerja untuk saya: $ wrapper-> field_entity_reference-> set (NULL);
Marcos Buarque
3

Selanjutnya untuk jawaban dan komentar lain, jika bidangnya banyak dan diperlukan, seperti yang disebutkan sebelumnya Anda tidak dapat menggunakan

$wrapper->field_example_multiple->set()

$wrapper->field_example_multiple->set(NULL)

bahkan tidak $wrapper->field_example_multiple->set(array()),

tetapi Anda dapat menggunakan yang berikut jika Anda ingin menghapus bidang semua nilainya:

$wrapper->field_example_multiple->set(array(NULL));

Bahkan, ini berfungsi baik atau tidaknya bidang nilai berganda diatur ke 'wajib', jadi saya sarankan selalu gunakan ini, untuk memastikan bahwa kode Anda kuat.

(Tentu saja, jika bidangnya 'wajib' maka Anda mungkin tidak boleh benar-benar membersihkannya, tetapi kode Anda mungkin melakukan ini sebagai langkah awal untuk menghapus seluruh entitas atau sesuatu yang serupa, jadi ada kalanya mungkin sah saja.)

Martin Q
sumber
Ketahuilah bahwa menggunakan set `$ wrapper-> field_example_multiple-> (array (NULL))` akan menghasilkan elemen NULL dalam array data. Metode ini tidak menghapus nilai melainkan menetapkan array nilai ke NULLnilai tunggal .
Alex Skrypnyk
Poin bagus. Saya kira itu mengembalikan kita ke komentar saya tentang tidak membersihkan nilai yang diperlukan. Mungkin sengaja dibuat mustahil.
Martin Q
Pada kenyataannya, bidang yang diperlukan harus memiliki setidaknya satu nilai bukan nol. Jika Anda ingin mengatur ulang bidang multinilai yang diperlukan, cukup timpa dengan nilai baru. Yaitu:$product_display->field_product = array($product_id);
Interdruper
2

Tampaknya kompleksitas yang tercantum dalam komentar lain hanya relevan dengan bidang yang diperlukan. Jika bidang tidak diperlukan, maka ini seharusnya cukup sederhana:

$wrapper->field_foo = NULL;

Anda bisa menggunakan pembungkus untuk memeriksa properti bidang:

$properties = $wrapper->getPropertyInfo();
$field_required = !empty($properties['field_foo']['required']);

Bergantung pada konteksnya, Anda juga bisa mendapatkan properti dari satu bidang menggunakan:

$wrapper->getPropertyInfo('field_foo');
Giles B
sumber
1

Solusi lain untuk masalah ini bisa jadi EntityMetadataWrapper::clear

$entity_wrapper->field->clear()

Mouneer
sumber
Metode EntityMetadataWrapper :: clear dinyatakan sebagai "protected", sehingga tidak dapat dipanggil dari kode Anda: hanya metode "publik" yang dapat diakses langsung dari luar objek.
Interdruper