0
votes

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'
    )
)
1
Are you sure that you want to associate a Product with a Good as well as an Item? There's not generally something wrong with that, but CakePHP can't handle that automatically, it can only save associations in one direction, that is parents or children, what you're trying is saving a sibling dataset so to speak. The stupid data structure requirement of CakePHP 2.x can be a little distracting, but basically Item isn't nested in Product, and that won't work. You'd have to manually issue multiple save's and provide the foreign keys accordingly. - ndm
Well, I am not quite sure. So what you are trying to say is that it cannot be done via a one transaction. If I would do it other way, I could simply first save an Item than save other to and access the items id since it is saved. But I am not sure it is good if it is not done in one transaction. Problem is, maybe the database design is flawed in itself. But I have a project with fixed organization and I cannot find better design. It is demanded that all products have a unique id, and since products can be goods, services etc, the only unique id they will have is in Items, so maybe that is ok. - Младен Карић
Maybe the best solution is to simply drop products table since it seems quite redundant. - Младен Карић
Well, I can't really give you any advise on that, it's hard to tell without knowing about the full picture. But note that you can manually issue transactions: book.cakephp.org/2.0/en/models/transactions.html. $this is a model instance in that case, and you'd need to set the atomic option to false in your save calls: book.cakephp.org/2.0/en/models/…. - ndm

1 Answers

1
votes

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']);