web-dev-qa-db-fra.com

A un à travers Laravel Eloquent

J'ai trois tables garages, cars, securities.

Les titres sont ceux qui gardent une voiture en sécurité, vous pouvez avoir plus d'une sécurité, mais une seule sécurité ne peut garder qu'une seule voiture en sécurité. Le garage est l'endroit où se trouve la voiture et les titres aussi.

Ce que je veux, c'est lister tous les titres et connaître le nom du garage qu'il est. Le problème est que securities n'a pas de colonne contenant l'id du garage, seulement l'id de la voiture qu'il garde en sécurité, mais la voiture a l'id du garage.

Laravel Eloquent a une méthode appelée hasManyThrough, mais securities en a une garage à cars uniquement.

Voici les tableaux:

table de garages:

-----------------------------------
|garage_id|garage_name|garage_size|
-----------------------------------
|        1|   Garage 1|        200|
-----------------------------------
|        2|   Garage 2|        400|
-----------------------------------

tableau des voitures:

---------------------------
|car_id|car_name|garage_id|
---------------------------
|     1|   Car 1|        1|
---------------------------
|     2|   Car 2|        1|
---------------------------
|     3|   Car 3|        2|
---------------------------

tableau des titres:

----------------------------------
|security_id|security_name|car_id|
----------------------------------
|          1|  Security 1|      1|
----------------------------------
|          2|  Security 2|      1|
----------------------------------
|          3|  Security 3|      2|
----------------------------------
|          4|  Security 4|      3|
----------------------------------

La sortie doit être:

Security 1 is on Garage 1
Security 2 is on Garage 1
Security 3 is on Garage 1
Security 4 is on Garage 2

Et j'ai les modèles:

Le code est de lister les garages, mais je veux faire des choses similaires mais lister les titres (juste pour que vous ayez une idée de la structure).

$garages = Garages::with(['cars', 'securities'])->get();

$garages->transform(function($garages) {
    return array(
        'garage_name'      => $garage->garage_name,
        'count_cars'       => $garage->cars->count(),
        'count_securities' => $garage->securities->count(),
   );
});

class Garages extends Eloquent
{
    public function cars()
    {
        return $this->hasMany('cars');
    }

    public function securities()
    {
        return $this->hasMany('securities');
    }
}

class Cars extends Eloquent
{
}

class Securities extends Eloquent
{
}

Et juste pour souligner encore une fois: je veux avoir le nom du garage lié à la voiture que la sécurité garde.

Juste pour le rendre encore plus facile à comprendre, si je fais ceci:

$securities = Securities::with(['cars'])->get();

class Securities extends Eloquent
{
    public function cars()
    {
        return $this->hasOne('cars');
    }
}

Je ne recevrai que le garage_id de cars table en tant que relations. Ce que je veux vraiment, c'est le nom du garage.

[relations:protected] => Array
    (
        [cars] => Cars Object
            (
                ...
                [attributes:protected] => Array
                    (
                        ...
                        [car_name] => Car 1
                        [garage_id] => 1
                        ...
26
yayuj

Il semble que vous ne reliez pas correctement les objets. Décomposons cela:

Si un Garage a plusieurs Car puis un Car appartient à Garage, permet de poursuivre avec cette idée à l'esprit.

  • Garage A plusieurs Car
  • Car A plusieurs Security
  • Security Appartient à Car
  • Garage Possède plusieurs Security à Car

Dans Eloquent, vous pouvez simplement aller de l'avant et applaudir ces relations, cela devrait fonctionner compte tenu du schéma que vous avez publié ci-dessus.

class Garage extends Eloquent
{
    public function cars()
    {
        return $this->hasMany('cars');
    }

    public function securities()
    {
        return $this->hasManyThrough('Security', 'Car');
    }
}

class Car extends Eloquent
{
    public function securities()
    {
        return $this->hasMany('Security');
    }

    // ADDED IN SECOND EDIT

    public function garage()
    {
        return $this->belongsTo('Garage');
    }       
}

class Security extends Eloquent
{
    public function car()
    {
        return $this->belongsTo('Car');
    }
}

Et ça devrait être ça.

EDIT: Vous pouvez accéder à toutes ces relations à partir de n'importe quel modèle tant qu'il existe un chemin que vous pouvez dessiner d'un modèle à un autre en utilisant une combinaison de ces relations. Vérifiez cela par exemple:

$security = Security::with('car.garage')->first();

récupérera d'abord la relation Security enregistre et charge Car dessus, puis il fait un pas de plus et charge toutes les relations Garage sur chaque Car objet chargé sous Security modèle.

Vous pouvez y accéder en utilisant cette syntaxe:

$security->car->garage->id

// Other examples
$garage = Garage::with('cars.securities')->first();

foreach($garage->cars as $car)
{
    foreach($cars->securities as $security)
    {
        echo "Car {$car->id} has {$security->id} assigned to it";
    }
}

De plus, notez que les objets de relation sont une instance de Collection donc vous avez toutes les méthodes fantaisistes telles que ->each(), ->count(), ->map() disponibles sur leur.

33
Gufran

J'ai rencontré récemment un problème similaire et j'ai pu faire quelque chose comme ceci:

class Cars extends Eloquent
{
    public function garage()
    {
        return $this->hasOne('Garages');
    }
}

class Securities extends Eloquent
{
    public function car()
    {
        return $this->hasOne('Cars');
    }

    public function garage()
    {
        return $this->car->garage();
    }
}

Cela vous donne les titres a une relation de garage et vous pouvez faire quelque chose comme:

$securities = Securities::with('garage')->get();

foreach($securities as $security)
{
    echo $security->security_name . ' is on ' . $security->garage->garage_name;
}
14
Eric Tucker

Cela concerne votre demande initiale.

hasOneThrough sera disponible en Laravel 5.8

https://github.com/laravel/framework/pull/26057/files

6
danrichards