web-dev-qa-db-fra.com

Laravel Eloquent: plusieurs clés étrangères pour la relation

Je suis en train de porter un projet à Laravel.

J'ai deux tables de base de données qui sont dans une relation un à plusieurs. Ils sont rejoints par trois conditions. Comment modéliser cette relation dans Eloquent? 

Je ne suis pas censé modifier le schéma de la base de données, car il doit rester compatible avec les versions antérieures.

J'ai essayé ce qui suit, mais ça ne marche pas.

Le côté propriétaire:

use Illuminate\Database\Eloquent\Model;

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

Le côté inverse:

use Illuminate\Database\Eloquent\Model;

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

Exemple Route valeurs de base de données:

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

Exemple Trip valeurs de base de données:

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

Route et Trip ont d'autres attributs, ce que je n'ai pas inclus ici pour la brièveté.

Est-ce possible dans Eloquent?

4
Genti Saliu

J'ai dû faire face à un problème similaire. La solution fournie par @fab ne fonctionnera pas avec un chargement rapide car $ this-> source_fil e serait null au moment du traitement de la relation. Je suis venu avec cette solution

Après avoir installé Compoships et l'avoir configuré dans vos modèles, vous pouvez définir vos relations correspondant à plusieurs colonnes.

Le côté propriétaire:

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']);
    }
}

Le côté inverse:

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 prend en charge le chargement rapide.

6
topclaudy

Comme Jonathon déjà mentionné, vous pouvez essayer d’ajouter une clause where- à votre relation: 

use Illuminate\Database\Eloquent\Model;

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

Le côté inverse:

use Illuminate\Database\Eloquent\Model;

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

Comment je voudrais aborder cela serait de faire quelque chose comme ça

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

}

Le fait de collecter toutes les relations simples et de les retourner en tant que collection unique, et bien entendu de procéder de la même manière pour l'inverse, devrait vous permettre de travailler avec des données.

OP a été modifié pour ne plus être pertinent, laissé en place si quelqu'un a besoin d'une réponse similaire

1
rchatburn