Laravel Eloquent ManyToMany with Pivot,带有数据透视表中变量的辅助查询?

扎卡里·克雷格

我一直在玩 laravel 并遇到了一个奇怪的边缘案例,我无法弄清楚

我有以下表结构:

CREATE TABLE `community_address` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `address_id` int(10) unsigned NOT NULL,
  `community_id` int(10) unsigned NOT NULL,
  `is_billing` tinyint(1) NOT NULL DEFAULT '1',
  `is_service` tinyint(1) NOT NULL DEFAULT '1',
  `is_mailing` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
)

CREATE TABLE `communities` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
)

CREATE TABLE `addresses` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `address_1` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Street address',
  `address_2` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Street adddress 2 (Company name, Suite, etc)',
  `city` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'City',
  `state` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'State / Province',
  `zip` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Zip / Postal Code',
  `country_id` int(10) unsigned NOT NULL COMMENT 'Country ID',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
)

我用以下 Laravel 模型代表了一个社区

class Community extends Model
{
    public function addresses(){
        return $this->belongsToMany(Address::class, 'community_address', 'community_id',  'address_id');
    }
}

$community->addresses() 实际上只返回社区的地址,但说我想在数据透视表中按地址类型过滤(账单、邮寄等)

我可以试试这个:

   public function getBillingAddress(){
        return $this->addresses()->wherePivot('is_billing','=', true)->firstOrFail()->get();
    }

哪个确实返回结果,但是我的数据透视表中的每一行都与我的查询匹配,而不是在现有地址之外运行我的查询

所以我的第二个想法是像这样使用“and”布尔参数

 public function getBillingAddress(){
        return $this->addresses()->wherePivot('community_id', '=', $this->id, true)->wherePivot('is_billing','=', true)->firstOrFail()->get();
    }

这导致以下 SQL 出错(出于明显的原因),但看起来也不太像是在搜索我想要的东西,即使它确实有效?

select `addresses`.*, `community_address`.`community_id` as `pivot_community_id`, `community_address`.`address_id` as `pivot_address_id` from `addresses` inner join `community_address` on `addresses`.`id` = `community_address`.`address_id` where `community_address`.`community_id` = 2 1 `community_address`.`community_id` = 2 and `community_address`.`is_billing` = 1 limit 1 

在我看来,“and”值实际上不是布尔值,而是将值作为字符串直接打印到查询中。

我尝试了显而易见的方法,并尝试用“and”交换第四个参数,并生成了以下 sql,它不会失败,但会返回所有地址,而不仅仅是链接到我的社区的地址

select `addresses`.*, `community_address`.`community_id` as `pivot_community_id`, `community_address`.`address_id` as `pivot_address_id` from `addresses` inner join `community_address` on `addresses`.`id` = `community_address`.`address_id` where `community_address`.`community_id` = 2 and `community_address`.`community_id` = 2 and `community_address`.`is_billing` = 1 limit 1)

我在这里遗漏了一些明显的东西吗?

通过对结果 SQL 进行一些修补,我可以获得我想要的,这是以下原始 sql 查询:

select `addresses`.*,
       `community_address`.`community_id` as `pivot_community_id`,
       `community_address`.`address_id`   as `pivot_address_id`
from `addresses`
       inner join `community_address` on `addresses`.`id` = `community_address`.`address_id` and `community_address`.`community_id` = 2 and `community_address`.`is_billing` = 1
limit 1

如何通过 eloquent 实现为我生成的相同 SQL?

扎卡里·克雷格

似乎我误解了如何wherePivot()工作,将代码更改为以下工作:

   public function getBillingAddress(){
        return $this->addresses()->wherePivot('is_billing', '=', true)->get()->first->all();
    }

新代码试图调用数据透视表的 is_billing 列以进一步过滤现有表,旧代码试图通过已经过滤的内容对其进行过滤,但由于它是内连接,因此返回所有行(至少我认为?)

无论哪种方式,这都解决了,希望这可以帮助将来的某人。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章