Adamantium
Adamantium

Reputation: 7

Laravel Eloquent Many to Many to One relationship

I'm creating a laravel application where the user logins in and can create clients and fill out an applicant form that is linked to the client.

I'm trying to make a relationship with many users that each have many clients, which have one applicant. But I get the following error:

Error

I'm confused with whats wrong and with naming the functions.

ClientContoller:

    public function createApplicant(){
    $data = request()->validate([
        'name' => 'required',
        'dob' => 'required',
        'age' => 'required',
        'gender' => 'required',
        'ethnicity' => 'required',
        'country' => 'required',
        'interpreter' => '',
        'language' => 'required',
        'homeAddress' => 'required',
        'job' => 'required',
        'workAddress' => 'required',
        'email' => 'required',
        'phone' => 'required',
        'contact' => 'required',
        'extra' => 'required',
    ]);

    auth()->user()->clients()->applicant()->create([
            'name'=>$data['name'],
            'dob'=>$data['dob'],
            'age'=>$data['age'],
            'gender'=>$data['gender'],
            'ethnicity'=>$data['ethnicity'],
            'country'=>$data['country'],
            'interpreter'=>$data['interpreter'],
            'language'=>$data['language'],
            'homeAddress'=>$data['homeAddress'],
            'job'=>$data['job'],
            'workAddress'=>$data['workAddress'],
            'email'=>$data['email'],
            'phone'=>$data['phone'],
            'contact'=>$data['contact'],
            'extra'=>$data['extra'],
    ]);
    dd($data);
}

User Model:

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
use HasFactory, Notifiable;

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
    'name',
    'email',
    'password',
];

/**
 * The attributes that should be hidden for arrays.
 *
 * @var array
 */
protected $hidden = [
    'password',
    'remember_token',
];

/**
 * The attributes that should be cast to native types.
 *
 * @var array
 */
protected $casts = [
    'email_verified_at' => 'datetime',
];
public function clients(){
    return $this->hasMany(Client::class);
}


}

Client Model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Client extends Model
{
use HasFactory;
public $timestamps = false;

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
    'name',
    'email'
];

public function applicant(){
    return $this->hasOne(Applicant::class);
}
}

Applicant Model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Applicant extends Model
{
use HasFactory;

protected $fillable = [
    'fullName',
    'date_of_birth',
    'age',
    'gender',
    'ethnicity',
    'country',
    'interpreter',
    'language',
    'homeAddress',
    'job',
    'workAddress',
    'email',
    'phone',
    'contact',
    'extra'
];
}

applicants table

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class Applicants extends Migration
{

public function up()
{
    Schema::create('applicants', function (Blueprint $table) {
        $table->id();
        $table->string('fullName');
        $table->date('date_of_birth');
        $table->string('age');
        $table->string('gender');
        $table->string('ethnicity');
        $table->string('country');
        $table->boolean('interpreter');
        $table->string('language');
        $table->string('homeAddress');
        $table->string('job');
        $table->string('workAddress');
        $table->string('email')->unique();
        $table->string('phone');
        $table->string('contact');
        $table->string('extra');
        $table->rememberToken();
        $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::dropIfExists('applicants');
}
}

clients table

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class Clients extends Migration
{
/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('clients', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::dropIfExists('clients');
}
}

Any help would be greatly appreciated.

Thank you!

Upvotes: 0

Views: 66

Answers (1)

user194324
user194324

Reputation: 38

As Maksim mentioned, Laravel is confused which client it should create an applicant for. So, you need to specify it somehow. My suggestion is:

public function createApplicant(Request $request){
$data = request()->validate([
    'name' => 'required',
    'dob' => 'required',
    'age' => 'required',
    'gender' => 'required',
    'ethnicity' => 'required',
    'country' => 'required',
    'interpreter' => '',
    'language' => 'required',
    'homeAddress' => 'required',
    'job' => 'required',
    'workAddress' => 'required',
    'email' => 'required',
    'phone' => 'required',
    'contact' => 'required',
    'extra' => 'required',
]);

$client = Client::find($request->id);

$client->applicant()->create([
        'name'=>$data['name'],
        'dob'=>$data['dob'],
        'age'=>$data['age'],
        'gender'=>$data['gender'],
        'ethnicity'=>$data['ethnicity'],
        'country'=>$data['country'],
        'interpreter'=>$data['interpreter'],
        'language'=>$data['language'],
        'homeAddress'=>$data['homeAddress'],
        'job'=>$data['job'],
        'workAddress'=>$data['workAddress'],
        'email'=>$data['email'],
        'phone'=>$data['phone'],
        'contact'=>$data['contact'],
        'extra'=>$data['extra'],
]);
dd($data);
}

So, you need to form a request before sending data to controller, with an id field, where you specify, which exact client you want to create applicant for.

Alternatively, if you call it like

Route::post('/add_applicant/{id}', 'ClientController@createApplicant');

you could replace Request $request and $request->id with just $id. The main idea is just to pass an id parameter somehow.

However, you still can find a more elegant approach.

Upvotes: 0

Related Questions