【问题标题】:Relationship queries in Eloquent ORMEloquent ORM 中的关系查询
【发布时间】:2017-03-16 19:16:20
【问题描述】:

我是 Laravel 的新手,在理解 Eloquent 中的查询时遇到了困难。我有两个型号 - 笔记本电脑和位置。假设我想查询属于某个位置的所有笔记本电脑,该位置的“库存”值为 1。在 SQL 中,这将是一个左连接,但我如何在 Eloquent 中做到这一点?我已经为这两个模型添加了关系,所以笔记本电脑模型有一个“位置”方法,但是我从那里去哪里呢?

【问题讨论】:

  • 你能告诉我们表结构和你的关系代码吗?
  • 是的,请发布您的数据库结构

标签: laravel eloquent


【解决方案1】:

您可以为此使用查询范围。它们在Laravel documentation

中有详细记录

在笔记本电脑模型中,您可以为库存检查编写范围:

public function scopeInStock($query)
{
    return $query->where('stock', 1);
}

为了保持干净,您可以在 Location 模型中创建另一个关系:

public function laptopsInStock()
{
   return $this->hasMany('Laptop')->inStock();
   // or this way:
   // return $this->laptops()->inStock();
}

现在要检索结果,有几个选项:

//all laptops
$location->laptops;

// in stock only
$location->laptopsInStock;

// eager loading
$location->with('laptopsInStock')->get();

【讨论】:

  • “库存”列在位置表中,而不是笔记本电脑表中。这是我的问题 - 我想要所有库存价值为 1 的所有位置的所有笔记本电脑。
  • 所以您只需要:$laptops = Laptop::inStock()->get();
  • 不行,我得到Column not found: 1054 Unknown column 'stock' in 'where clause'
  • 哦,对,您在 Location 表中有 stock 字段。尝试将 inStock 查询范围放在 Location 模型中并执行以下操作:$locations = Location::inStock()->with('laptops')->get();
  • 最后,我查询的一些数据!谢谢你。那么......我将如何注入用户可能输入的更多查询参数?例如,模型或模型的类型(因此每台笔记本电脑有两个表......),以及如何在不使每个页面加载生成一千万个 SQL 查询的情况下做到这一点?这在原始 SQL 中非常简单......
【解决方案2】:

由于您没有提供任何代码,所以我将从基本描述。

迁移

位置表

Schema::create('locations', function(Blueprint $table){
    $table->increments('id');
    $table->string('name');
    $table->timestamps();
});

笔记本电脑桌

Schema::create('laptops', function(Blueprint $table){
    $table->increments('id');
    $table->string('name');
    $table->integer('location_id')->unsigned();
    $table->integer('stock');
    $table->timestamps();

    $table->foreign('location_id')
          ->references('id')
          ->on('locations')
          ->onDelete('cascade')
          ->onUpdate('cascade');
});

模型

位置模型

class Location extends Model {
    public function laptops(){
        return $this->hasMany('\App\Laptop');
    }
}

笔记本电脑型号

class Laptop extends Model {
    public function location(){
        return $this->belongsTo('\App\Location');
    }
}

如果您已经创建了这样的应用,那么有多种方法可以实现目标。
这将查询属于某个位置且股票价值为1 的所有笔记本电脑。

1.

Laptop::where('location_id','some_location_id')->where('stock',1)->get();

2

Location::where('id','some_location_id')->with(['laptops' => function($query){
     $query->where('stock',1);
}])->get();

我希望这能解决您的问题。随时发表评论并提出任何问题。

【讨论】:

  • 感谢您的回复。我在迁移中没有外键 - 我的印象是模型中的 belongsTo 和 hasMany 声明就足够了?最终,我想返回一个从库存位置获取所有笔记本电脑的初始视图,但是这个查询将变得更加复杂,允许用户按型号、类型、位置等的任意组合进行过滤。我有一个类似的一对一- 与模型的许多关系。
  • 再补充一点,这段代码当前$laptops = Laptop::where('stock', 1)->get(); 会产生一个未找到列的错误。编辑:为了进一步澄清,我不想将结果限制在特定位置 - 我想要来自所有库存值为 1 的位置的结果。和/或我想要来自与用户选择匹配的所有笔记本电脑型号的结果。跨度>
  • column not found 错误是因为您试图访问表中不存在的列。
  • 另外,对于更复杂的设计,我建议您保持代码紧凑且基础更强大。 laracast 中有一些关于 eloquent 的视频,观看它们将帮助您使您的概念更强大。
猜你喜欢
  • 1970-01-01
  • 2015-01-21
  • 1970-01-01
  • 2015-04-09
  • 2023-04-01
  • 2013-11-30
  • 1970-01-01
  • 2015-10-29
  • 2021-06-10
相关资源
最近更新 更多