Laravel 4 Eloquent返回错误的ID

时间:2013-10-02 16:05:28

标签: php sql laravel laravel-4

我的数据库中有3个表:

  1. 广告活动
  2. 用户
  3. 公司
  4. 一家公司可能有一些用户。一个用户可能有一些活动。用户(具有管理员权限)可以对属于其公司的任何广告系列执行某些操作。所以,我想检查是否 他是否正在与他的竞选活动进行这些行动(在最后一种情况下,我会返回“拒绝访问”等内容。)

    我的状况

    Campaign::join('users', 'users.id', '=', 'campaigns.user_id')
            ->where('users.company_id', '=', Auth::user()->company->id)
            ->where('campaigns.id', '=', Input::get('id'))
            ->first();
    

    所以,如果我获得了独特的广告系列 - 没关系,如果我得到了空 - 出了点问题,并且当他处理其他公司广告系列时,我向用户发送“拒绝访问权限”。

    此代码生成下一个查询:

    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.idcampaigns.user_id = 8)。

    我无法弄清楚为什么会这样。即使我的SQL查询有问题(我怀疑是phpmyadmin返回正确的结果),我得到了条件campaigns.id = Input::get('id'),其中Input::get('id') = 13。为什么要更改ID?

    当然,我可以分两步执行此安全检查,例如先获取广告系列,然后检查 $campaign->user->company->id = Auth::user()->company->id但只是想知道......

3 个答案:

答案 0 :(得分:23)

如果您在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)

要解决此问题,您可以添加一个select子句,仅选择广告系列列:

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();

答案 1 :(得分:4)

这似乎是Eloquent库中的限制。它不应该使用最后一个" id"而应该更加主动地搜索" id"查询的主表。或者使用"作为"在SQL语句中。

另一种解决方案是唯一地命名每个表的id字段。例如user.user_id,campaigns.campaign_id。这会与其他表中的外键冲突,因此将外键命名为campaigns.user_fid。

答案 2 :(得分:1)

如果要控制使用重复列的实际表,只需按特定顺序将表添加到数组中。最后一个是->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',
        ])