首页 文章

无法获得自动创建联接的说法

提问于
浏览
37

如果我的问题的答案显而易见,请提前道歉 . 在我发布这篇文章之前,我已经在研究这个主题时做了尽职调查 .

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

I would like to use built-in ORM functionality in Laravel's Eloquent ORM to automatically join the tournaments and countries tables together when running a query ,并返回包含锦标赛数据及其相关国家/地区数据的数据集 .

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

如果我以一种从未打算使用的方式使用Eloquent,请立即停止我!我的困惑可能更多的是我试图将一个难以维持的解决方案混合在一起而不是语法或编码错误 .

在Eloquent中查询我想要复制的内容

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

PHP中的预期结果

我希望收到一系列Tournament对象(在PHP中),其中单个Tournament对象如下所示:

  • tournaments.id

  • tournaments.year

  • tournaments.country_id

  • tournaments.created_at

  • tournaments.updated_at

  • countries.id

  • countries.code

  • countries.name

  • countries.url

  • countries.created_at

  • countries.updated_at

我做的失败尝试失败了

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

尝试失败#1:

虚拟控制器中的PHP代码:

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

生成以下查询:

SELECT * FROM `tournaments`

尝试#1返回:

包含Tournament对象的数组,仅包含锦标赛表中的列 .

尝试失败#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

  • Laravel: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 回答

  • 9

    根据Eloquent文档:

    注意:查询Eloquent模型时,查询构建器上提供的所有方法也可用 .

    所以考虑到这一点:

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

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

    UPDATE:

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

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

    这将返回包含两个表的字段的Tournament模型 .

    HTH

  • 2

    您的“with”子句要求“国家/地区”,但您的代码将其声明为“国家/地区” .

    那么,应该:

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

    是:

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

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

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

    做这个改变能解决吗?

  • 0

    您必须确保在锦标赛模型中宣布您的关系:

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

    此外,您必须在您的国家/地区模型中声明相反的内容:

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

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

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

    如果这显示比赛的每个对应国家,请告诉我 .

  • 1

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

    Column not found: 1054 Unknown column 'tournament_id' in 'where clause'
    
    SQL: SELECT * FROM `countries` WHERE `tournament_id` IN (?)
    

    如何定义关系有什么不对: A tournament must have a country 将是一个需要属于一个国家的锦标赛,而不是一个国家 . 所以解决这个改变的关系

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

相关问题