laravel eloquent pivot with primary id to reference to another pivot - php

i have problem with relationship between pivot tables.
I have many to many relation between countries and streets but primary key of this (pivot table) has many to many relationship with numbers.
I need this listings (with eloquent):
$country = Country::findOrFail(1)->with('streets', 'numbers')
foreach ($country->streets as $street){
foreach($street->numbers as $number) {
$number;
}
}
Or exist any solution?
This is only example. Official name of tables are changed.
Example structure:
Table Countries
id
name
Table Streets
id
name
Table country_street
id
country_id
street_id
Table number_country_street
id
number_id
country_street_id
Table numbers
id
name
Thanks for help.

IMHO with your tables I would define an additional model: CountryStreet, something like that:
// CountryStreet
class CountryStreet extends Model
{
public function city()
{
return $this->belongsTo('App\City');
}
public function street()
{
return $this->belongsTo('App\Street');
}
public function numbers()
{
return $this->belongsToMany('App\Number', 'number_country_street');
}
}
// Country
class Country extends Model
{
public function streets()
{
return $this->hasManyThrough('App\Street', 'App\CountryStreet');
}
}
// Streets
class Street extends Model
{
public function countries()
{
return $this->hasManyThrough('App\Country', 'App\CountryStreet');
}
}
// Number
class Number extends Model
{
public function country_streets()
{
return $this->belongsToMany('App\CountryStreet', 'number_country_street');
}
}

#dparoli had good idea.
Sometimes for many-to-many relations using inheritance Pivot class, but does not matter for now.
So now we can use these code bellow for listings.
$country = Country::findOrFail(1);
foreach ($country->countryStreet as $countryStreet){
echo $countryStreet->street->name
foreach($countryStreet->numbers as $number) {
$number;
}
}
class Countries
public function countryStreet()
{
return $this->hasMany(CountryStreet::class, 'country_id', 'id');
}
Class CountryStreet with method block() using relation hasOne
Another implementation is up.

Related

laravel relationship between 3 tables - many-to-many

I have 3 tables (Models)
Advertise :
id
title
...
Value:
id
title
amount
....
Field:
id
name
title
...
and my pivot tables is like:
advertise_id
value_id
field_id
how can I set relations in my models and do a crud(please give me an example)?
all the relations are many to many
3 model classes accordingly:
class Advertise extends Model
{
public function fields()
{
return $this->belongsToMany(Field::class);
}
public function values()
{
return $this->belongsToMany(Value::class);
}
}
class Field extends Model
{
public function advertises()
{
return $this->belongsToMany(Advertise::class);
}
public function values()
{
return $this->belongsToMany(Value::class);
}
}
class Value extends Model
{
public function fields()
{
return $this->belongsToMany(Field::class);
}
public function advertises()
{
return $this->belongsToMany(Advertise::class);
}
}

Laravel show data 3 table

I have the following tables:
flights(id, title, number)
stations(id, title)
flight_price(id, price, flight_id, stationA_id, stationB_id)
flight_station(flight_id, station_id)
flight_station is a pivot table.
My models:
class Flight extends Model
{
public function stations()
{
return $this->belongsToMany('App\Model\Station', 'flight_station', 'flight_id', 'station_id')
}
// To attach data
public function prices()
{
return $this->belongsToMany('App\Model\FlightPrice', 'flight_price', 'flight_id', 'stationA_id')
->withPivot('price');
}
public function price()
{
return $this->hasMany('App\Model\FlightPrice', 'flight_id');
}
}
// Station
class Station extends Model
{
public function flights()
{
return $this->belongsToMany('App\Model\Flight', 'flight_station', 'station_id', 'flight_id');
}
}
class FlightPrice extends Model
{
protected $table = 'flight_price';
public function flights()
{
return $this->belongsToMany('App\Model\Flight', 'flight_price');
}
}
I need the next result (find by id flight):
|stationA_id|stationA_title||stationB_id|stationB_title|price|
Let's say you are trying to retrieve a flight like this:
$flight = Flight::with(['price', 'stations'])->find($id);
This returns a Flight model with the Price and Station models because you eager loaded the relationships.
Now $flight->price will return the Price model associated with the Flight model. If it is not a collection - which I believe is true - the foreach loop has little meaning (or at least not the one you expect). In fact it will loop through the public attributes of the Model class (incrementing, exists, wasRecentlyCreated and timestamps).
So the following piece of code will return 4 booleans.
foreach ($flight->price as $value) {
dump($value);
}
If you want to return the station identifiers, the station titles and the price for each flight then maybe try something like this:
foreach ($flight->stations as $station) {
dump($station->id);
dump($station->title);
}
// I assume the Price model has an attribute named value
dump($flight->price->value)

Laravel Relationship tables passing extra "s" with id name

I am getting "'lessons.subjects_id" while there is "subject_id" in lesson table. dont know where is problem in my relationship. My relationship models are as under:
class Lessons extends Model
{
public function subject()
{
return $this->belongsTo('Lea\Subjects');
}
public function category()
{
return $this->belongsTo('Lea\Category');
}
}
Subject Model is:
class Subjects extends Model
{
public function category()
{
return $this->belongsTo('Lea\Category');
}
public function Lessons()
{
return $this->hasMany('Lea\Lessons');
}
}
If you didn't respect the Laravel convention you have to teach him about yours ;) by adding you foreign key name.
In the documentation you have :
Eloquent determines the foreign key of the relationship based on the
model name. In this case, the Phone model is automatically assumed to
have a user_id foreign key. If you wish to override this convention,
you may pass a second argument to the hasOne method:
class Lessons extends Model
{
public function subject()
{
// your foreign key
return $this->belongsTo('Lea\Subjects', 'subject_id');
}
public function category()
{
return $this->belongsTo('Lea\Category');
}
}
And
class Subjects extends Model
{
public function category()
{
return $this->belongsTo('Lea\Category');
}
public function Lessons()
{
// your foreign key
return $this->hasMany('Lea\Lessons', 'subject_id');
}
}

Laravel Pivot Table and indirect relationship

I'm writing a survey with Laravel 4 and need the ability for users to be able to take the same survey multiple times (and have their answers saved as different instances.)
I currently have a pivot table called survey_user that links a user to an invited survey. A potentially positive side effect of the pivot table is that its primary key could be used to have unique survey instances.
My problem is figuring out how to get answers, specifically through the user model. Answers table would contain a foreign key to the primary of the pivot table.
My User model:
class User extends Eloquent {
public function surveys() {
return $this->belongsToMany('Survey', 'survey_user')
->withPivot('id', 'completed_at');
}
public function answers() {
// This should return all of the user's answers, irrespective of
// survey id's.
}
}
Tables:
surveys: id
users: id
survey_user: id, survey_id, user_id, completed_at
answers: survey_user_id, answer_text, ...
How might I accomplish this psuedo-relationship or perhaps a better way to structure?
Use relationships! Here's how I would do it:
class User extends Eloquent {
public function surveys() {
return $this->belongsToMany('Survey');
}
public function answers() {
return $this->hasMany('Answer');
}
}
class Survey extends Eloquent {
public function surveys() {
return $this->belongsToMany('User');
}
public function answers() {
return $this->hasMany('Answer');
}
}
class Answer extends Eloquent {
public function survey() {
return $this->belongsTo('Survey');
}
public function user() {
return $this->belongsTo('User');
}
}

Retrieving relationships of relationships using Eloquent in Laravel

I have a database with the following tables and relationships:
Advert 1-1 Car m-1 Model m-1 Brand
If I want to retrieve an Advert, I can simply use:
Advert::find(1);
If I want the details of the car, I could use:
Advert::find(1)->with('Car');
However, if I also want the detail of the Model (following the relationship with Car), what would the syntax be, the following doesn't work:
Advert::find(1)->with('Car')->with('Model');
Many thanks
It's in the official documentation under "Eager Loading"
Multiple relationships:
$books = Book::with('author', 'publisher')->get();
Nested relationships:
$books = Book::with('author.contacts')->get();
So for you:
Advert::with('Car.Model')->find(1);
First you need to create your relations,
<?php
class Advert extends Eloquent {
public function car()
{
return $this->belongsTo('Car');
}
}
class Car extends Eloquent {
public function model()
{
return $this->belongsTo('Model');
}
}
class Model extends Eloquent {
public function brand()
{
return $this->belongsTo('Brand');
}
public function cars()
{
return $this->hasMany('Car');
}
}
class Brand extends Eloquent {
public function models()
{
return $this->hasMany('Model');
}
}
Then you just have to access this way:
echo Advert::find(1)->car->model->brand->name;
But your table fields shoud be, because Laravel guess them that way:
id (for all tables)
car_id
model_id
brand_id
Or you'll have to specify them in the relationship.
Suppose you have 3 models region,city,hotels and to get all hotels with city and region then
Define relationship in them as follows:-
Hotel.php
class Hotel extends Model {
public function cities(){
return $this->hasMany(City::class);
}
public function city(){
return $this->belongsTo('App\City','city_id');
}
}
City.php
class City extends Model {
public function hotels(){
return $this->hasMany(Hotel::class);
}
public function regions(){
return $this->belongsTo('App\Region','region_id');
}
}
Region.php
class Region extends Model
{
public function cities(){
return $this->hasMany('App\City');
}
public function country(){
return $this->belongsTo('App\Country','country_id');
}
}
HotelController.php
public function getAllHotels(){
// get all hotes with city and region
$hotels = Hotel::with('city.regions')->get()->toArray();
}
will adding the relation function just ask for the relation needed
public function Car()
{
return $this->belongsTo(Car::class, 'car_id')->with('Model');
}
but if you want a nested relation just use the period in the with
Advert::with('Car.Model')->find(1);
but for multi-relation use the array
Advert::with('Car','Model')->find(1);

Categories