Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Eloquent with() method works with 'where' but doesn't work with 'Model::find()'

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();
    });
like image 921
soheil yo Avatar asked Oct 26 '25 10:10

soheil yo


1 Answers

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 before with() will be relevant (this thought may need to be updated).

You may need to read more on Eager Loading - in Laravel docs

like image 103
Oluwatobi Samuel Omisakin Avatar answered Oct 28 '25 22:10

Oluwatobi Samuel Omisakin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!