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
  • 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
  • ララベル: 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 (?)

この関係がどのように定義されているかが間違っています。トーナメントには国が必要であり、トーナメントは国に属している必要があり、1 つの国ではありません。したがって、この変更を解決するには、関係を次のように変更します

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

これにより、両方のテーブルのフィールドを含む Tournament モデルが返されます。

HTH

于 2013-12-13T12:30:05.893 に答える
1

'with'句は'Country'を要求しますが、コードはそれを'country'として宣言します。

したがって、次のようにする必要があります。

$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

関係が Tournament モデルで宣言されていることを確認する必要があります。

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 に答える