I want to have relationship between 3 tables, using Laravel Eloquent with() method.
this is my code (relationships are set in models):
$request_form = RequestForm::find(7)->with(['RequestFormsCheck' => function ($q) {
$q->orderBy("created_at", "DESC")->with('RequestFormsCheckOptions');
}])->get();
dd($request_form);
but this code returns all request forms except returning only id = 7
this is output:
Collection {#895 ▼
#items: array:4 [▼
0 => RequestForm {#796 ▶}
1 => RequestForm {#797 ▶}
2 => RequestForm {#798 ▶}
3 => RequestForm {#799 ▶}
]
}
when I replace ->get() with ->first() it returns just request form, but its id is 1 :(
but this code works great:
$request_form = RequestForm::where('id', 7)->with(['RequestFormsCheck' => function ($q) {
$q->orderBy("created_at", "DESC")->with('RequestFormsCheckOptions');
}])->first();
dd($request_form->toArray());
and this is its output (this is what I expect to get):
array:12 [▼
"id" => 7
"name" => "Jack"
"email" => "[email protected]"
"telephone" => null
"description" => "..."
"site" => "http://branch.local/"
"item_id" => 10
"lang" => "en"
"read" => 1
"created_at" => "2018-05-15 11:09:47"
"updated_at" => "2018-05-20 05:24:41"
"request_forms_check" => array:1 [▼
0 => array:8 [▼
"id" => 1
"request_form_id" => 7
"type" => 2
"request_forms_check_options_id" => null
"description" => "custom note"
"created_at" => "2018-05-15 11:48:36"
"updated_at" => "2018-05-15 11:48:36"
"request_forms_check_options" => null
]
]
]
these are my migrations:
Schema::create('request_forms', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 100)->nullable();
$table->string('email', 100)->nullable();
$table->string('telephone', 20)->nullable();
$table->text('description')->nullable();
$table->string('site', 100);
$table->integer('item_id');
$table->string('lang');
$table->timestamps();
});
and
Schema::create('request_forms_check_options', function (Blueprint $table) {
$table->increments('id');
$table->string('title', 500);
$table->timestamps();
});
and this
Schema::create('request_forms_checks', function (Blueprint $table) {
$table->increments('id');
$table->integer('request_form_id')->unsigned();
$table->foreign('request_form_id')->references('id')->on('request_forms')->onDelete('cascade');
$table->tinyInteger('type')->comment("1: option, 2:description");
$table->integer('request_forms_check_options_id')->unsigned()->nullable();
$table->foreign('request_forms_check_options_id')->references('id')->on('request_forms_check_options')->onDelete('cascade');
$table->text('description')->nullable();
$table->timestamps();
});
First I'll refer you to this answer but for record sake I'll explain again as I understand:
When you use find() method an instance of the Model is returned already (this is not query builder), this is why using with() on the result of find will do a fresh query on the database then calling get() on that returns the entire records whereas calling first() will return the first record (by id).
I suggested ways to go about this in case you still want to stick with find()
Let the find() come after the query (eager loaded). Example:
$request_form = RequestForm::with(['RequestFormsCheck' => function ($q) {
$q->orderBy("created_at", "DESC")->with('RequestFormsCheckOptions');
}])->find(7);
Use load() after find (Lazy loaded) - You have the result then load the related models. Example:
$request_form = RequestForm::find(7)->load(['RequestFormsCheck' => function ($q) {
$q->orderBy("created_at", "DESC")->with('RequestFormsCheckOptions');
}]);
Stick with calling with() ( the one that worked) on the whole query before invoking the final result. I think this is the best way to do it, since you need only one RequestForm, then many relations to that
My general understanding where
with()works is on query builder, therefore you must still be getting together the query beforewith()will be relevant (this thought may need to be updated).
You may need to read more on Eager Loading - in Laravel docs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With