简体   繁体   English

Laravel Eloquent with()方法与'where'一起使用但不适用于'Model :: find()'

[英]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 . 我希望使用Laravel Eloquent with() 方法在3个表之间建立关系。 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: 但是此代码返回所有request forms除了仅返回id = 7这是输出:

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 :( 当我用->first()替换->get() ,它只返回request form ,但其id为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" => "jack@gmail.com"
  "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). 当你使用find()方法时,已经返回了Model的一个实例(这不是查询构建器),这就是为什么在find的结果上使用with()会对数据库执行一个新的查询,然后在那个上调用get()返回整个记录,而调用first()将返回第一条记录(按id)。

I suggested ways to go about this in case you still want to stick with find() 我提出了一些方法来解决这个问题,以防你仍然想坚持使用find()

  • Let the find() come after the query (eager loaded). find()在查询之后(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. 查找后使用load() (延迟加载) - 您有结果然后加载相关模型。 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. 在调用最终结果之前,坚持在整个查询中调用with() (有效的)。 I think this is the best way to do it, since you need only one RequestForm, then many relations to that 我认为这是最好的方法,因为你只需要一个 RequestForm,然后需要很多关系

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). 我对with()工作的一般理解是在查询构建器上,因此在with()相关之前with()您仍然必须将查询聚集在一起(这种想法可能需要更新)。

You may need to read more on Eager Loading - in Laravel docs 您可能需要阅读有关Eager Loading的更多信息- 在Laravel文档中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM