Laravel 5仅选择hasMany关系上的关系数据

时间:2016-03-16 15:28:36

标签: php laravel laravel-5

我正在构建一个具有projects且项目有plot_types的应用程序。

我希望能够检查当前项目下是否存在plot_type。

我有以下代码:

$testResult = $project->with(['plotTypes' => function($query) use ($row) {
            $query->where('name', $row->plot_name);
        }])->first()

这会生成以下MySQL:

select exists(select * from `projects` where exists (select * from `projects_plot_types` where `projects_plot_types`.`project_id` = `projects`.`id` and `name` = ?)) as `exists`

此SQL返回与$project对象无关的行。例如,当我dd($project)时,我得到:

#attributes: array:11 [▼
    "id" => "4"
    "name" => "xxx"
    "number" => "1234"
    "builder" => "1"
    "overall_budget" => "3456.00"
    "start_date" => "2016-03-31"
    "end_date" => "2016-04-30"
    "created_date" => "2016-03-16 15:22:05"
    "updated_date" => "2016-03-16 15:22:07"
  ]

然而,当我dd($testResult);时,它会给出;

#relations: array:1 [▼
"plotTypes" => Collection {#767 ▼
  #items: array:1 [▼
    0 => ProjectsPlotTypes {#770 ▼
      #table: "projects_plot_types"
      #fillable: array:2 [▶]
      +timestamps: false
      #connection: null
      #primaryKey: "id"
      #perPage: 15
      +incrementing: true
      #attributes: array:4 [▼
        "id" => "1"
        "project_id" => "1"
        "name" => "TYPE 1  - VENTILATION"
        "budget" => "324.67"
      ]

注意,上面的project_id显示1。这与当前项目无关,因为当前项目ID为4

为什么会这样?

2 个答案:

答案 0 :(得分:1)

这是ActiveRecord模型中可能令人困惑的部分之一。您的所有模型实例都包含用于检索模型实例的相同方法,因此很容易认为某些内容在某些方面确实不起作用。

调用$project->with(),这与调用Project::with()完全相同。即使您在项目实例上调用with(),也不会将加载的对象限制为仅与您的实例相关的对象。

当您致电$project->with()时,它首先要做的是为所有项目创建一个新查询,然后添加急切加载。然后调用first(),它只获取第一个项目记录,以及所有其急切加载的对象。

要获取特定项目的绘图类型,您有几个选项。

  1. 只需查询关系。 $project->plotTypes()为您提供与项目关联的所有绘图类型的基本查询。您可以添加约束并从那里获取记录。

    $plotTypes = $project->plotTypes()->where('name', $row->plot_name)->get();
    dd($plotTypes);
    
  2. 使用约束加载相关的绘图类型:

    // assume your project doesn't have any plottypes loaded yet
    $project = Project::find(1);
    
    // load the plottypes relation with constraints
    $project->load(['plotTypes' => function($query) use ($row) {
        $query->where('name', $row->plot_name);
    }]);
    dd($project->plotTypes);
    
  3. 过滤已加载的Collection相关绘图类型。 $project->plotTypes包含与您的项目相关的所有绘图类型,但您可以使用where()上的Collection方法(与查询中的where()不同)来过滤记录在Collection

    // assume your project already has all plotTypes loaded
    $project = Project::with('plotTypes')->find(1);
    
    // you just want to get a subset of those pre-loaded plottypes
    $plotTypes = $project->plotTypes->where('name', $row->plot_name);
    dd($plotTypes);
    

答案 1 :(得分:0)

使用whereHas方法进行过滤,而不是使用with

$testResult = $project->whereHas('plotTypes' => function($query) use ($row) {
        $query->where('name', $row->plot_name);
 })->with('plotTypes')->first();

此外,您想要获取所有相关记录还是仅第一个记录?

如果全部,则将第一个()更改为获取()

希望这有帮助