简体   繁体   中英

CakePHP edit multiple records at once

I have a HABTM relationship between two tables: items and locations , using the table items_locations to join them.

items_locations also stores a bit more information. Here's the schema

items_locations(id, location_id, item_id, quantity)

I'm trying to build a page which shows all the items in one location and lets the user, through a datagrid style interface, edit multiple fields at once:

Location: Factory XYZ
 ___________________________
|___Item____|___Quantity___|
| Widget    |          3   |
| Sprocket  |          1   |
| Doohickey |         15   |
----------------------------

To help with this, I have a controller called InventoryController which has:

var $uses = array('Item', 'Location');  // should I add 'ItemsLocation' ?

How do I build a multidimensional form to edit this data?


Edit:

I'm trying to get my data to look like how Deceze described it below but I'm having problems again...

// inventory_controller.php
function edit($locationId) {

    $this->data = $this->Item->ItemsLocation->find(
        'all',
        array(
            "conditions" => array("location_id" => $locationId)
        )
    );

when I do that, $this->data comes out like this:

Array (
    [0] => Array (
        [ItemsLocation] => Array (
            [id] => 16
            [location_id] => 1
            [item_id] => 1
            [quantity] => 5
        )
    )
    [1] => Array (
        [ItemsLocation] => Array (/* .. etc .. */)
    )
)

If you're not going to edit data in the Item model, it probably makes most sense to work only on the join model. As such, your form to edit the quantity of each item would look like this:

echo $form->create('ItemsLocation');

// foreach Item at Location:

echo $form->input('ItemsLocation.0.id'); // automatically hidden
echo $form->input('ItemsLocation.0.quantity');

Increase the counter ( .0. , .1. , ...) for each record. What you should be receiving in your controllers $this->data should look like this:

array(
    'ItemsLocation' => array(
        0 => array(
            'id' => 1,
            'quantity' => 42
        ),
        1 => array(
            ...

You can then simply save this like any other model record: $this->Item->ItemsLocation->saveAll($this->data) . Adding an Item to a Location is not much different, you just leave off the id and let the user select the item_id .

array(
    'location_id' => 42,  // prepopulated by hidden field
    'item_id' => 1        // user selected
    'quantity' => 242
)

If you want to edit the data of the Item model and save it with a corresponding ItemsLocation record at the same time, dive into the Saving Related Model Data (HABTM) chapter. Be careful of this:

By default when saving a HasAndBelongsToMany relationship, Cake will delete all rows on the join table before saving new ones. For example if you have a Club that has 10 Children associated. You then update the Club with 2 children. The Club will only have 2 Children, not 12.

And:

3.7.6.5 hasAndBelongsToMany (HABTM)

unique : If true (default value) cake will first delete existing relationship records in the foreign keys table before inserting new ones, when updating a record. So existing associations need to be passed again when updating.


Re: Comments/Edit

I don't know off the top of my head if the FormHelper is intelligent enough to autofill Model.0.field fields from a [0][Model][field] structured array. If not , you could easily manipulate the results yourself:

foreach ($this->data as &$data) {
    $data = $data['ItemsLocation'];
}
$this->data = array('ItemsLocation' => $this->data);

That would give you the right structure, but it's not very nice admittedly. If anybody has a more Cakey way to do it, I'm all ears. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM