Search code examples
phpcakephpcakephp-2.3

CakePHP - saving to more than two models using save associated


I am trying something more complicated. I have an Item which stores all general items, I have a Product which is an item and I have a Good which is a product and a item. So I have a form for entering value for the good and it shall save to all model related tables (items, products, goods). The reason for so many tables is because all tables shall have an id which is used later, example: product shall have its id which is used later for selling. Here is the controller:

public function add() {
    $this->load();

    if ($this->request->is('post')) {

$this->Item->create();
        $this->request->data['Item']['code'] = $finalCode;
        $this->request->data['Item']['is_deleted'] = false;
        $item = $this->Item->save($this->request->data);

        if(!empty($item)){
            $this->request->data['Product']['item_id'] = $this->Item->id;
            $this->request->data['Good']['item_id'] = $this->Item->id;

            debug($this->request->data['Product']['item_id']);
            debug($item);

            $this->Item->Product->save($this->request->data);
            $this->request->data['Good']['pid'] = $this->Product->id;
            $this->Item->Good->save($this->request->data);
        }

        if($this->Good->validationErrors || $this->Item->validationErrors || $this->Product->validationErrors){
            //ERRORS
        }
        else{
            //FAILS
        }
    }
}

EDIT: I have changed the controller and now the Item is never saved but Product and Good is saved and they are all mapped well, ids are ok but Item is not even in the db, althrough Product and Good have item_id set to a value which should be next in the db.

class Good extends AppModel {

    public $belongsTo = array(
        'Item' => array(
            'className' => 'Item',
            'foreignKey' => 'item_id',
        ),
        'Product' => array(
            'className' => 'Product',
            'foreignKey' => 'pid',
        )
    );
}

class Product extends AppModel {

    public $hasOne = array(
        'Good' => array(
            'className' => 'Good',
            'foreignKey' => 'pid',
            'dependent' => false,
        ),
    );
}

class Item extends AppModel{

    public $hasMany = array(
         'Good' => array(
        'className' => 'Good',
        'foreignKey' => 'item_id',
        'dependent' => false,
    ),
    'Product' => array(
        'className' => 'Product',
        'foreignKey' => 'item_id',
        'dependent' => false,
    ),
    );

}

Even the debugged $item looks ok but is not saved:

array(
    'Item' => array(
        'name' => 'Microcontrollers',
        'description' => 'Wire Jumpers Female-to-Female 30 cm',
        'weight' => '22',
        'measurement_unit_id' => '7',
        'item_type_id' => '29',
        'code' => 'GOD-34',
        'is_deleted' => false,
        'modified' => '2019-10-22 12:37:53',
        'created' => '2019-10-22 12:37:53',
        'id' => '120'
    ),
    'Good' => array(
        'status' => 'development',
        'hts_number' => '8473 30 20',
        'tax_group' => '20%',
        'eccn' => 'EAR99',
        'release_date' => array(
            'month' => '10',
            'day' => '22',
            'year' => '2019',
            'hour' => '10',
            'min' => '10',
            'meridian' => 'am'
        ),
        'is_for_distributors' => '1'
    ),
    'Product' => array(
        'project' => 'neqwww'
    )
)

Solution

  • I think the problem is with your code at the lines where you are saving the data.

    $this->Item->create();
    $this->Good->create();
    $this->Product->create();
    

    What is $this? If you create a item with "$this" and later try to create a "product", "$this" will not have the item_id.

    Try using something like this to save the item created.

    $item = $this->Item->create();
    

    Then, with that $item created, you could create a $product with the $item->id

    Update:

    From cakephp documentation.

    // Create: id isn't set or is null
    $this->Recipe->create();
    $this->Recipe->save($this->request->data);
    
    // Update: id is set to a numerical value
    $this->Recipe->id = 2;
    $this->Recipe->save($this->request->data);
    

    You must use $this->Item->save($data) to save the information into database.

    https://book.cakephp.org/2.0/en/models/saving-your-data.html

    Maybe the method create() is a bit unclear. It is used to restart the model state.

    So, it would be

    $item_saved = $this->Item->save($data['Item']);
    $data['Product']['item_id'] = $this->Item->getLastInsertId();
    $product_saved = $this->Product->save($data['Product']);
    

    Edit 2:

    Maybe it is because you didn't use create() before save the Item. Try this please:

    $this->Item->create();
    $item_saved = $this->Item->save($data['Item']);
    $data['Product']['item_id'] = $this->Item->getLastInsertId();
    $product_saved = $this->Product->save($data['Product']);