-1

I have 2 models: customer and customerName. In my customer Controller I try to create a method that update fields from both tables. Any idea? Thanks!

CustomerController

public function update(Request $request, Customer $customer)
{
    $customer = \App\CustomerName::where('customer_id', $customer->id)->first();  // if I remove this line I can update just "name" from first table

    $data = $request->validate([
        'name' => 'required|string',  //is in customer migration
        'first_name'=> 'required',    //is in customerName migration
        'last_name'=> 'required',     //is in customerName migration
    ]);
    $customer->update($data);

    return response($customer,200);
}

Customer Model

class Customer extends Model
{
    protected $fillable = ['name'];

    public function customerName()
    {
        return $this->hasOne('App\CustomerName');
    }

}

CustomerName Model

class CustomerName extends Model
{
    protected $fillable = ['first_name', 'last_name'];

    public function customer()
    {
        return $this->belongsTo('App\Customer');
    }
}
Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
Beusebiu
  • 1,433
  • 4
  • 23
  • 68

3 Answers3

2

Assuming customer always has record created for CustomerName, you should then use:

$customer->update(['name' => $data['name']);
$customer->customerName->update(\Arr::only($data, ['first_name', 'last_name']));

and additionally you should wrap this in database transaction like so:

\DB::transaction(function() use ($customer, $data) {
    $customer->update(['name' => $data['name']);
    $customer->customerName->update(\Arr::only($data, ['first_name', 'last_name']));
});

and of course you should remove this line:

$customer = \App\CustomerName::where('customer_id', $customer->id)->first();  // if I remove this line I can update just "name" from first table

because you should already have $customer object set using Route model binding.

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
2

Take a look at your code. You're overriding some variables by naming them the same thing:

public function update(Request $request, Customer $customer)
{
    $customer = \App\CustomerName::where('customer_id', $customer->id)->first();
    ...

Before the line $customer = \App\CustomerName..., $customer is an instance of Customer. After that line, it is an instance of CustomerName, and you no longer have access to the Customer instance. Simply change you naming:

public function update(Request $request, Customer $customer)
{
    $customerName = \App\CustomerName::where('customer_id', $customer->id)->first();
    // Or, $customerName = $customer->customerName;
    // You shouldn't have to query if your relationship is defined properly.
    ...

Next, save the values accordingly:

$customer->name = $request->input("name"); // or $data["name"]
$customer->save();

$customerName->first_name = $request->input("first_name"); // or $data["first_name"]
$customerName->last_name = $request->input("last_name"); // or $data["last_name"]
$customerName->save(); 

Set the values of $customer and $customerName accordingly, then call save() on both instances.

Tim Lewis
  • 27,813
  • 13
  • 73
  • 102
1

You're injecting the Customer instance, so you don't need to load it inside the function. Try this:

public function update(Request $request, Customer $customer)
{
    $data = $request->validate([
        'name' => 'required|string',  //is in customer migration
        'first_name'=> 'required',    //is in customerName migration
        'last_name'=> 'required',     //is in customerName migration
    ]);
    $customer->name = $data['name'];
    $customer->customerName->first_name = $data['first_name'];
    $customer->customerName->last_name = $data['last_name'];

    $customer->push(); // This saves the model AND the related models as well.
    return response($customer,200);
}
José A. Zapata
  • 1,187
  • 1
  • 6
  • 12