web-dev-qa-db-ja.com

Laravel Eloquent:関係の複数の外部キー

私はプロジェクトをLaravelに移植中です。

相互に1対多の関係にある2つのデータベーステーブルがあります。これらは3つの条件によって結合されます。 Eloquentでこの関係をモデル化するにはどうすればよいですか?

データベーススキーマは他のものとの下位互換性を維持する必要があるため、データベーススキーマを変更することは想定されていません。

次のことを試しましたが、うまくいきません。

所有側:

use Illuminate\Database\Eloquent\Model;

class Route extends Model
{
    public function trips()
    {
        return $this->hasMany('Trip', 'route_name,source_file', 'route_name,source_file')
    }
}

逆側:

use Illuminate\Database\Eloquent\Model;

class Trip extends Model
{
    public function routes()
    {
        return $this->belongsTo('Route', 'route_name,source_file', 'route_name,source_file');
    }
}

Routeデータベース値の例:

id    | route_name     | source_file
---------------------------------------
1     | Berlin - Paris | file1.xls   
2     | Madrid - London| file2.xls
3     | Berlin - Paris | file3.xls

Tripデータベース値の例:

id        | route_name           | source_file | duration
---------------------------------------------------------
1         | Berlin - Paris       | file1.xls   | 78
2         | Madrid - London      | file2.xls   | 241
3         | Berlin - Paris       | file3.xls   | 65
1         | Berlin - Paris       | file1.xls   | 95
1         | Berlin - Paris       | file1.xls   | 65

RouteTripには他の属性がありますが、簡潔にするためにここには含めませんでした。

Eloquentでこれは可能ですか?

9
Genti Saliu

同様の問題に対処しなければなりませんでした。 @fabが提供するソリューションは、$ this-> source_fileがnullになるため、積極的なロードでは機能しません。 関係が処理されるとき。 このソリューション を思いつきました

Compoships をインストールし、モデルで構成した後、複数の列に一致する関係を定義できます。

所有側:

use Illuminate\Database\Eloquent\Model;
use Awobaz\Compoships\Compoships;

class Route extends Model
{
    use Compoships;

    public function trips()
    {
        return $this->hasMany('Trip', ['id', 'route_name', 'source_file'], ['route_id', 'route_name', 'source_file']);
    }
}

逆側:

use Illuminate\Database\Eloquent\Model;
use Awobaz\Compoships\Compoships;

class Trip extends Model
{
    use Compoships;

    public function route()
    {
        return $this->belongsTo('Route', ['route_id', 'route_name', 'source_file'], ['id', 'route_name', 'source_file']);
    }
}

Composhipsは、Eager Loadingをサポートしています。

15
topclaudy

Jonathon ですでに述べたように、関係にwhere-句を追加してみることができます。

use Illuminate\Database\Eloquent\Model;

class Route extends Model
{
    public function trips()
    {
        return $this->hasMany('Trip', 'route_name')->where('source_file', $this->source_file);
    }
}

逆側:

use Illuminate\Database\Eloquent\Model;

class Trip extends Model
{
    public function routes()
    {
        return $this->belongsTo('Route', 'route_name')->where('source_file', $this->source_file);
    }
}
5
fab

私がこれに取り組む方法は、このようなことをすることです

class A
{
    public function b1()
    {
        return $this->hasMany('B', 'prop1', 'prop1')
    }
    public function b2()
    {
        return $this->hasMany('B', 'prop2', 'prop2')
    }
    public function b3()
    {
        return $this->hasMany('B', 'prop3', 'prop3')
    }

   public function getBsAttribute()
    {
        $data = collect([$this->b1, $this->b2, $this->b3]);
        return $data->unique();
    }

}

すべての単一のリレーションを収集し、それらを一意のコレクションとして返します。明らかに逆のリレーションに対しても同じことを行うと、処理するデータが得られるはずです。

OPは修正されたため、関連性がなくなり、同様の回答が必要な場合は残されました

2
rchatburn