CakePHP 3 - Bagaimana cara Anda menambal data terkait secara manual, dan menyimpan semuanya?

Saya melakukan pencarian untuk mengambil satu entitas dan memuat salah satu entitas terkaitnya, yang memiliki Banyak.

Data yang diambil terlihat seperti ini secara sederhana:

object(App\Model\Entity\Order) {

    'id' => '67839',
    'price' => (int) 100,
    'payment_instalments' => [
        (int) 0 => object(Cake\ORM\Entity) {

            'id' => (int) 43150,
            'order_id' => '67839',
            'amount' => (int) 100
        }
    ]
}

Saya ingin mengubah kolom pada entitas utama dan kolom pada entitas tertampung secara manual.

Saya dapat memodifikasi entitas utama dengan mudah seperti ini:

$order = $orders->patchEntity($order, [
    'price' => 200
]);

Satu-satunya cara saya dapat memodifikasi entitas yang ada di dalamnya adalah dengan melakukan tambalan terpisah padanya. Hal ini dapat dilakukan dengan berbagai cara. Ini salah satunya:

$instalments = TableRegistry::get('PaymentInstalments');
$instalment = $order->payment_instalments[0];
$order->payment_instalments[0] = $instalments->patchEntity(instalment , [
    'amount' => 200
]);

Lalu saya ingin menyimpan semua:

$orders->save($order, ['associated' => 'PaymentInstalments']);

Masalahnya adalah data terkait tidak disimpan, dan alasannya adalah karena $order->payment_instalments tidak ditandai sebagai "kotor" karena ditambal secara terpisah. Jadi satu-satunya solusi yang saya temukan adalah menandainya secara manual sebagai kotor:

$order->dirty('payment_instalments', true);

Maka penyelamatan akan berhasil.

Ini tampaknya cukup berantakan bagi saya, dan akan menjadi jauh lebih berantakan jika saya harus menambal beberapa entitas yang ada di dalamnya. Saya tidak dapat menemukan dokumentasi atau bantuan apa pun tentang bagaimana hal ini seharusnya dilakukan dengan benar/elegan.

Apakah ada cara untuk memodifikasi entitas utama dan entitas tertampung sekaligus, dan membuatnya secara otomatis mengenali bahwa data tertampung itu kotor?


person BadHorsie    schedule 27.01.2017    source sumber


Jawaban (1)


$order = $orders->patchEntity($order, [
    'price' => 123, // Change data on the order itself
    'payment_instalments' => [
        0 => [
            'id' => 43150,
            'amount' => 123,
        ]
    ]
]);

Bagian 0 => tentu saja opsional dalam kasus ini. Saya telah meletakkannya di sana untuk memperjelas bahwa datanya ada dalam array bersarang.

Alasan mengapa hanya menyimpan pesanan itu sendiri dan bukan catatan terkait ada di sini:

'[dirty]' => [
    'price' => true
],

payment_instalments perlu ditandai sebagai kotor juga. Itu akan terjadi secara otomatis ketika Anda melakukan patch dengan benar.

person Greg Schmidt    schedule 27.01.2017
comment
Data terkait sudah ada dalam array bersarang. Satu-satunya cara agar saya dapat membuatnya berfungsi adalah dengan menambahkan secara manual $order->dirty('payment_instalments', true); Perubahan saya tidak diposting oleh formulir, saya memodifikasi data secara manual, jadi apa cara yang benar untuk menambal entitas terkait dalam contoh ini (karena ini bukan array saat Anda melakukan pencarian; itu adalah array entitas di payment_instalments). - person BadHorsie; 27.01.2017
comment
@BadHorsie Cara yang benar ditunjukkan di sini dalam jawabannya, itulah cara Anda melakukannya. Fakta bahwa properti asli menampung serangkaian entitas tidak relevan, atau lebih baik dikatakan properti tersebut sebenarnya diperlukan agar marshaller dapat menambal/menggabungkan data dengan benar. - person ndm; 27.01.2017
comment
@BadHorsie, ketika Anda mencoba kode saya, seperti apa hasilnya $order? Perhatikan bahwa id untuk catatan terkait harus disertakan dalam data yang Anda teruskan ke patchEntity, karena dengan cara itulah data tersebut akan menemukan entitas yang perlu ditambal. - person Greg Schmidt; 27.01.2017
comment
@ndm Oke, aku bersamamu. Jadi cukup modifikasi entitas dengan menyediakan data dalam format array, dan marshaller akan menggabungkannya ke dalam entitas. - person BadHorsie; 28.01.2017