Laravel 4 Eloquent 返回错误的 ID
Posted
技术标签:
【中文标题】Laravel 4 Eloquent 返回错误的 ID【英文标题】:Laravel 4 Eloquent returns wrong ID 【发布时间】:2013-10-09 02:33:12 【问题描述】:我的数据库中有 3 个表:
-
广告系列
用户
公司
一家公司可能有一些用户。一位用户可能有一些活动。用户(具有管理员权限)可以对属于其公司的任何活动执行某些操作。所以,我想检查是否 他是否在他的竞选活动中执行这些操作(在最后一种情况下,我返回类似“访问被拒绝”之类的内容)。
我的情况
Campaign::join('users', 'users.id', '=', 'campaigns.user_id')
->where('users.company_id', '=', Auth::user()->company->id)
->where('campaigns.id', '=', Input::get('id'))
->first();
因此,如果我有独特的活动 - 没关系,如果我得到 null - 出了点问题,我向用户发送“拒绝访问”,因为他正在处理其他公司的活动。
这段代码产生下一个查询:
array(3)
["query"]=>
string(148) "select * from `campaigns` inner join `users` on `users`.`id` = `campaigns`.`user_id` where `users`.`company_id` = ? and `campaigns`.`id` = ? limit 1"
["bindings"]=>
array(2)
[0]=>
string(1) "2"
[1]=>
string(2) "13"
["time"]=>
float(0.42)
使用 phpmyadmin 我尝试了相同的查询并获得了 ID = 13 的广告系列。 但是当我调试我的应用程序时,我发现
dd($campaign->id);
改为返回 8。 8 也等于campaigns.user_id
(该记录同时具有campaigns.id
和campaigns.user_id = 8
)。
我不知道为什么会这样。即使我的 SQL 查询有问题(我怀疑 phpmyadmin 返回了正确的结果),我也得到了条件campaigns.id = Input::get('id')
,Input::get('id') = 13
。为什么要更改 id?
当然,我可以分两步进行此安全检查,例如先获取广告系列,然后检查
$campaign->user->company->id = Auth::user()->company->id
但只是想知道...
【问题讨论】:
【参考方案1】:如果您在 phpMyAdmin 中运行此查询,您应该能够看到结果包含多个名为“id”的列。当 PHP 将查询结果解析为关联数组或对象时,键必须是唯一的!如果键发生冲突,将使用最后一列!
例子:
SQL 结果:
id user_id name id name company_id
1 2 Camp1 2 Pelle 1
PHP结果:
array (size=1)
0 =>
object(stdClass)[131]
public 'id' => string '2' (length=1)
public 'user_id' => string '2' (length=1)
public 'name' => string 'Pelle' (length=5)
public 'company_id' => string '1' (length=1)
要解决这个问题,您可以添加一个选择子句来仅选择广告系列列:
Campaign::select('campaigns.*')
->join('users', 'users.id', '=', 'campaigns.user_id')
->where('users.company_id', '=', Auth::user()->company->id)
->where('campaigns.id', '=', Input::get('id'))
->first();
【讨论】:
感谢您的帮助,Laravel 5 也一样 :)【参考方案2】:如果您想控制使用重复列的实际表,只需按特定顺序将表添加到数组中。最后一个是->id
属性。
->select([
'table1.*',
'table2.*',
'tags.*',
'companies.*',
'users.*',
])
这样您就可以保留使用join
选择的所有唯一列。
如果您想要特定表中的特定列,您可以使用AS
:
->select([
'table1.*',
'table2.*',
'tags.*',
'companies.*',
'users.*',
'table1.id AS table1_id',
'tags.name AS tag_name',
'companies.name AS company_name',
])
【讨论】:
【参考方案3】:这似乎是 Eloquent 库中的一个限制。与其使用最后一个“id”,不如更主动地搜索查询的主表的“id”。或者在 SQL 语句中使用“as”。
另一种解决方案是对每个表的 id 字段进行唯一命名。例如user.user_id,campaigns.campaign_id。这会与其他表中的外键发生冲突,因此将外键命名为campaign.user_fid。
【讨论】:
以上是关于Laravel 4 Eloquent 返回错误的 ID的主要内容,如果未能解决你的问题,请参考以下文章
带有 Codeception 的 Laravel 4 模型单元测试 - 未找到“Eloquent”类
Laravel Eloquent groupBy() 并且还返回每个组的计数
遍历数组集合并返回命名键值对(Laravel/Eloquent)
laravel 返回与 eloquent 和 laravel 的关系