42

如果我的问题的答案很明显,请提前道歉。在我将它发布到这里之前,我已经对这个主题进行了尽职调查。

我的大部分框架经验都来自使用 CodeIgniter,所以我从来没有使用过 ORM 的实践经验。(CI 确实有一些现成的 ORM 解决方案,但我从未使用过它们。)

我想在 Laravel 的 Eloquent ORM 中使用内置的 ORM 功能,在运行查询时自动将锦标赛和国家/地区表连接在一起,并返回包含锦标赛数据及其相关国家/地区数据的数据集。

也就是说,我希望 Eloquent 自动识别外键关系,这样我就可以运行一个查询(例如 Tournament:: with('Country')->all()),它将返回整个锦标赛和国家数据集。

如果我以从未打算使用的方式使用 Eloquent,请立即阻止我!我的困惑可能更多是因为我试图将一个站不住脚的解决方案混在一起,而不是语法或编码错误。

我想在 Eloquent 中复制的查询

SELECT * FROM tournaments LEFT JOIN countries ON tournaments.country_id = countries.id

PHP 中的预期结果

我希望收到一个 Tournament 对象数组(在 PHP 中),其中单个 Tournament 对象看起来像:

  • 比赛.id
  • 比赛年
  • 锦标赛.country_id
  • 锦标赛.created_at
  • 锦标赛.updated_at
  • 国家.id
  • 国家代码
  • 国家名称
  • 国家.url
  • country.created_at
  • country.updated_at

迄今为止我所做的失败尝试

我在一个虚拟控制器方法中运行了所有这些尝试,并将结果作为格式化字符串输出到分析器。

失败的尝试#1:

虚拟控制器中的 PHP 代码:

$tournaments = Tournament::with('Country')->all();

生成以下查询:

SELECT * FROM `tournaments`

尝试 #1 返回:

包含锦标赛对象的数组,这些对象仅包含锦标赛表中的列。

失败的尝试 #2

虚拟控制器中的 PHP 代码:

$tournaments = Tournament::with('Country')->first();

生成以下错误:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'tournament_id' in 'where clause'

SQL: SELECT * FROM `countries` WHERE `tournament_id` IN (?)

Bindings: array (
0 => '1',
)

其他失败的尝试

我尝试了各种命名约定的组合(例如列、表等),但均无济于事。我还尝试在 Fluent 中创建查询,效果很好,但要求我指定我想要避免的连接。

我的环境

  • PHP: 5.3.13
  • MySQL:5.1.53
  • 拉拉维尔:3.2.3

表之间的关系

  • 一对一的关系
  • 锦标赛必须有一个国家(有一个外键约束来执行它)
  • 一个国家可以属于许多其他关系(例如,参与者,此处未显示,具有出生国家)

国家表

CREATE TABLE `countries` (                                                                                                                                                                                                                 
`id` int(11) NOT NULL AUTO_INCREMENT,                                                                                                                                                                                                       
`code` varchar(4) NOT NULL,                                                                                                                                                                                                                 
`name` varchar(25) NOT NULL,                                                                                                                                                                                                                
`url` varchar(25) NOT NULL,                                                                                                                                                                                                                 
`created_at` datetime NOT NULL,                                                                                                                                                                                                             
`updated_at` datetime NOT NULL,                                                                                                                                                                                                            
PRIMARY KEY (`id`),                                                                                                                                                                                                                        
UNIQUE KEY `countries_code_unique` (`code`),                                                                                                                                                                                               
KEY `countries_url_index` (`url`)                                                                                                                                                                                                          
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=latin1

比赛桌

CREATE TABLE `tournaments` (                                                                                                                                                                                                             
`id` int(11) NOT NULL AUTO_INCREMENT,                                                                                                                                                                                                       
`year` int(11) NOT NULL,                                                                                                                                                                                                                    
`country_id` int(11) NOT NULL,                                                                                                                                                                                                              
`created_at` datetime NOT NULL,                                                                                                                                                                                                             
`updated_at` datetime NOT NULL,                                                                                                                                                                                                             
PRIMARY KEY (`id`),                                                                                                                                                                                                                         
UNIQUE KEY `tournaments_year_unique` (`year`),                                                                                                                                                                                             
KEY `tournaments_country_id_foreign` (`country_id`),                                                                                                                                                                                      
CONSTRAINT `tournaments_country_id_foreign` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE CASCADE                                                                                                                  
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=latin1

国家模型 (countries.php)

class Country extends Eloquent {
    public static $timestamps = true;
    public static $table = 'countries';
}

锦标赛模型 (tournaments.php)

class Tournament extends Eloquent {
    public static $timestamps = true;

    public function country()
    {
        return $this->has_one('Country');
    }
}
4

4 回答 4

10

由于他设法得到以下错误,显然with('Country')with('country')没有任何不同:

Column not found: 1054 Unknown column 'tournament_id' in 'where clause'

SQL: SELECT * FROM `countries` WHERE `tournament_id` IN (?)

错误的关系是如何定义的:锦标赛必须有一个国家,而锦标赛需要属于一个国家,而不是一个国家。所以为了解决这个改变关系

public function country()
{
    return $this->belongs_to('Country');
}
于 2012-06-20T15:59:53.927 回答
2

根据雄辩的文档:

注意:查询构建器上可用的所有方法在查询 Eloquent 模型时也可用。

所以考虑到这一点:

DB::table("tournament")->join("countries","tournaments.country_id","=","countries.id")->get();

应该可以在 Eloquent 中复制。我个人使用刚才您可能想要使用的查询构建器版本,但当我有机会并更新它时,我会尝试使用 Eloquent 进行测试。

更新:

是的,使用 Eloquent 的查询构建器方法,您可以:

Tournament::join("countries","tournaments.country_id","=","countries.id")->get();

这将返回一个包含两个表字段的锦标赛模型。

高温高压

于 2013-12-13T12:30:05.893 回答
1

您的“with”子句要求输入“国家”,但您的代码将其声明为“国家”。

所以,应该:

$tournaments = Tournament::with('Country')->all();

是:

$tournaments = Tournament::with('country')->all();

因为在您的锦标赛模型中,您已将其定义为:

public function country()
{
    return $this->has_one('Country');
}

进行此更改是否可以解决问题?

于 2012-06-19T11:48:56.040 回答
0

你必须确保你的关系在你的锦标赛模型中声明:

public function country() {
    return $this->has_one('Country');
}

此外,您必须在 Country 模型中声明相反的内容:

public function tournament() {
    return $this->belongs_to('Tournament');
}

此时,您可以访问与国家对象关联的锦标赛对象,如下所示:

$tournaments = Tournament::with('country')->all();
foreach ($tournaments as $tournament) {
    echo $tournament->country;
}

让我知道这是否显示了锦标赛的每个对应国家。

于 2013-05-01T08:47:13.020 回答