我一直在玩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
如何通过雄辩地实现为我生成相同的SQL?
答案 0 :(得分:1)
如果我想出一个例子,我认为这对您来说将是一个完整的用户 我们有用户 角色和 Role_User 表 我们已将用户连接到角色,并属于属于我们,并且我们要使用select:
用户模型:
function Roles()
{
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
}
在我们的控制器中,我们可以像下面这样写任何选择:
class exampleController extends Controller
{
public function index()
{
User::with(['Roles'=>function($query){$query->where(....)->get();}])->get();
}
}
您可以在查询中使用任何选择,然后返回您想要的任何内容。
如果您需要在选择中使用任何变量,请务必小心
波纹管格式
class exampleController extends Controller
{
public function index()
{
$var =...;
User::with(['Roles'=>function($query) use ($var){$query->where(....,$var)->get();}])->get();
}
}
我希望这能解决您的问题...
答案 1 :(得分:0)
似乎我误解了wherePivot()
的工作方式,将代码更改为以下工作方式:
public function getBillingAddress(){
return $this->addresses()->wherePivot('is_billing', '=', true)->get()->first->all();
}
在新代码试图调用数据透视表的is_billing列以进一步过滤现有表的情况下,旧代码试图通过已被其过滤的内容对其进行过滤,但是由于它是内部联接,因此它正在返回所有行(至少我认为?)
无论哪种方式,这个问题都可以解决,希望这对以后的人有所帮助。