Oliver
Oliver

Reputation: 4091

CakePHP 3.0 saving belongsToMany data problems

I'm having trouble saving data in a belongsToMany association. This is the error I'm getting:

Fatal Error (1): Call to a member function get() on a non-object in [application/vendor/cakephp/cakephp/src/ORM/Association/BelongsToMany.php, line 854]

This is the piece of code causing trouble:

public function add(){
    $session = $this->request->session();
    $call = $this->Calls->newEntity([
        "user_id" => $this->Auth->user("id"),
        "customer_id" => $session->read("Customer.id"),
        "comment" => $this->request->data["comment"],
        "result_id" => $this->request->data["result_id"]
    ]);
    if($this->request->data["result_id"] === 0){
        $deliveryMode = $this->request->data["order"]["delivery"]["mode"];
        $order = new Order([
            "delivery" => $deliveryMode,
            "products" => [
                "_ids" => [1, 2]
            ]
        ]);

        if($deliveryMode === 1){
            $order->set("smartpost_delivery_id", $this->request->data["order"]["delivery"]["locations"][1]["id"]);
        }

        $call->order = $order;
    }
    $result = $this->Calls->save($call);
    if($result){
        $session->write("Customer.id", null);
        echo json_encode(["id" => $result->id]);
    } else{
        echo json_encode($call->errors());
        $this->response->statusCode(400);
    }
}

As we can see I'm trying to save a Call that has an Order attached to it and the part that is causing trouble is that I'm also trying to attach a list of Products ids to the Order to be saved to a jointable. If I remove the product ids, the Call and the Order are saved successfully.

4 tables are involved: calls, orders, products, orders_products. Here's a visual representation of the tables. The table objects' code has been auto-baked by the cake app. If needed, I can provide the code for them. Associations: Calls hasOne Order, Orders belongsToMany Products

Upvotes: 1

Views: 1376

Answers (1)

ndm
ndm

Reputation: 60503

You cannot save with the _ids key, you'll need entities with the appropriate primary key values.

The special _ids key is a convenience format that is handled by the marshaller when it converts data into entities. It will fetch the appropriate data from the datasource and replace the association property with a list of entities.

Long story short, do not create the Order entity manually, let the marshaller do it. You'd nost probably want to do that anyways since you are inserting user data into the entity wich should be validated first, which is why you should also add the smartpost_delivery_id value to the data before converting it into an entity:

$orderData = [
    "delivery" => $deliveryMode,
    "products" => [
        "_ids" => [1, 2]
    ]
];

if($deliveryMode === 1) {
    $orderData["smartpost_delivery_id"] =
        $this->request->data["order"]["delivery"]["locations"][1]["id"];
}

// Adjust the name of the association in case necessary
$order = $this->Calls->association('Orders')->newEntity($orderData);

See also

Upvotes: 3

Related Questions