CakePHP 3 - คุณจะแก้ไขข้อมูลที่เกี่ยวข้องด้วยตนเองและบันทึกทั้งหมดได้อย่างไร

ฉันทำการค้นหาเพื่อดึงข้อมูลเอนทิตีหนึ่งรายการและมีหนึ่งในเอนทิตีที่เกี่ยวข้องซึ่งมีหลายเอนทิตี

ข้อมูลที่ดึงมามีลักษณะเช่นนี้ในแง่ง่ายๆ:

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
        }
    ]
}

ฉันต้องการแก้ไขฟิลด์ในเอนทิตีหลักและฟิลด์ในเอนทิตีที่มีอยู่ด้วยตนเอง

ฉันสามารถแก้ไขเอนทิตีหลักได้อย่างง่ายดายดังนี้:

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

วิธีเดียวที่ฉันสามารถค้นหาการแก้ไขเอนทิตีที่มีอยู่ได้คือทำแพตช์แยกต่างหาก ซึ่งสามารถทำได้หลายวิธี นี่คือหนึ่ง:

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

จากนั้นฉันต้องการบันทึกทั้งหมด:

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

ปัญหาคือข้อมูลที่เกี่ยวข้องไม่ได้รับการบันทึก และสาเหตุเป็นเพราะ $order->payment_instalments ไม่ถูกทำเครื่องหมายเป็น "สกปรก" เนื่องจากมีแพตช์แยกกัน ดังนั้นทางออกเดียวที่ฉันพบคือทำเครื่องหมายว่าสกปรกด้วยตนเอง:

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

จากนั้นการบันทึกจะทำงาน

สิ่งนี้ดูค่อนข้างยุ่งสำหรับฉัน และคงจะยุ่งกว่านี้มากหากฉันต้องแพตช์เอนทิตีที่มีอยู่หลายรายการ ฉันไม่พบเอกสารหรือความช่วยเหลือใด ๆ เกี่ยวกับวิธีดำเนินการอย่างถูกต้อง/หรูหรา

มีวิธีแก้ไขทั้งเอนทิตีหลักและเอนทิตีที่มีอยู่ในครั้งเดียว และทำให้ระบบรับรู้โดยอัตโนมัติว่าข้อมูลที่มีอยู่สกปรกหรือไม่


person BadHorsie    schedule 27.01.2017    source แหล่งที่มา


คำตอบ (1)


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

แน่นอนว่าในกรณีนี้ส่วน 0 => เป็นทางเลือก ฉันได้ใส่ไว้เพื่อให้ชัดเจนยิ่งขึ้นว่าข้อมูลอยู่ในอาร์เรย์ที่ซ้อนกัน

สาเหตุที่บันทึกเฉพาะคำสั่งซื้อเท่านั้นและไม่ใช่บันทึกที่เกี่ยวข้องอยู่ที่นี่:

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

payment_instalments จำเป็นต้องทำเครื่องหมายว่าสกปรกเช่นกัน สิ่งนี้จะเกิดขึ้นโดยอัตโนมัติเมื่อคุณแก้ไขอย่างถูกต้อง

person Greg Schmidt    schedule 27.01.2017
comment
ข้อมูลที่เกี่ยวข้องมีอยู่แล้วในอาร์เรย์ที่ซ้อนกัน วิธีเดียวที่ฉันจะทำให้มันทำงานได้คือการเพิ่ม $order->dirty('payment_instalments', true); การเปลี่ยนแปลงของฉันไม่ได้โพสต์โดยแบบฟอร์มด้วยตนเอง ฉันกำลังแก้ไขข้อมูลด้วยตนเอง ดังนั้นวิธีที่ถูกต้องในการแก้ไขเอนทิตีที่เกี่ยวข้องในกรณีนี้คืออะไร (เนื่องจากไม่ใช่ array เมื่อคุณทำการค้นหา ซึ่งเป็นอาร์เรย์ของเอนทิตีใน payment_instalments) - person BadHorsie; 27.01.2017
comment
@BadHorsie วิธีที่ถูกต้องแสดงไว้ที่นี่ในคำตอบ นั่นคือวิธีที่คุณจะทำ ความจริงที่ว่าคุณสมบัติดั้งเดิมมีอาร์เรย์ของเอนทิตีนั้นไม่เกี่ยวข้อง หรือพูดดีกว่าว่าจำเป็นจริงๆ เพื่อให้ marshaller สามารถแพตช์/รวมข้อมูลได้อย่างถูกต้อง - person ndm; 27.01.2017
comment
@BadHorsie เมื่อคุณลองโค้ดของฉัน ผลลัพธ์ $order จะเป็นอย่างไร โปรดทราบว่าจำเป็นอย่างยิ่งที่ id สำหรับเรกคอร์ดที่เกี่ยวข้องจะรวมอยู่ในข้อมูลที่คุณส่งไปยัง patchEntity เนื่องจากเป็นวิธีค้นหาเอนทิตีที่จำเป็นต้องได้รับการแก้ไข - person Greg Schmidt; 27.01.2017
comment
@ndm ตกลง ฉันอยู่กับคุณ ดังนั้น เพียงแค่แก้ไขเอนทิตีโดยให้ข้อมูลในรูปแบบอาเรย์ แล้วผู้จัดสรรจะรวมเอนทิตีเข้ากับเอนทิตี - person BadHorsie; 28.01.2017