Laravel show data 3 table - php

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)

Related

laravel eloquent pivot with primary id to reference to another pivot

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.

Laravel: Sorting a collection with a many to many relationship

I have two tables: assessments and benchmarks. benchmarks has a field called content. There is a many to many relationship between them: assessment_benchmark. I want to sort a collection of records from the assessment_benchmark table by the content attribute of the corresponding benchmark. I have tried:
$sorted = AssessmentBenchmark::all()->sortBy(function($assessmentBenchmark){
return $assessmentBenchmark->benchmark->content;
});
But this just does not work (it just returns the original order). However, when I return $assessmentBenchmark->comment for example, it does work (comment is a field in assessment_benchmark).
The models look like this:
class AssessmentBenchmark extends Model
{
public function benchmark()
{
return $this->belongsTo(Benchmark::class);
}
public function assessment()
{
return $this->belongsTo(Assessment::class);
}
}
class Benchmark extends Model
{
public function assessments()
{
return $this->belongsToMany(Assessment::class);
}
}
class Assessment extends Model
{
public function benchmarks()
{
return $this->belongsToMany(Benchmark::class);
}
}
Well, you can use below query for sorting, I'm gonna use Assessment model, because, I'm never use pivot modal before. Actually, I never had pivot model..
$assessments = Assessment::with(["benchmarks"=>function($query){
$query->orderBy("content","DESC");
}])
With method aşso provide you eagerloading, so when you put $assessments in iteration , you won't make new query for each relation
From chat discussion, it found that you have pivot field and for that you can change your belongsToMany relationship like this
class Benchmark extends Model
{
public function assessments()
{
return $this->belongsToMany(Assessment::class)->withPivot('comment','score')->withTimestamps();
}
}
class Assessment extends Model
{
public function benchmarks()
{
return $this->belongsToMany(Benchmark::class)->withPivot('comment','score')->withTimestamps();
}
}
Now fetch data
$assessment = Assessment::with(['benchmarks' => function($query){
$query->orderBy('content', 'desc');
}])->find($assessmentId);
In view you can render it like this
#foreach($assessment->benchmarks as $benchmark)
<tr>
<td>{{$benchmark->id}}</td>
<td>{{$benchmark->name}}</td>
<td>{{$benchmark->pivot->score}}</td>
<td>{{$benchmark->pivot->comment}}</td>
</tr>
#endforeach
For update you can use updateExistingPivot
For details check ManyToMany relationship https://laravel.com/docs/5.6/eloquent-relationships#many-to-many

Get laravel data with relation between tables

I have the following data models:
class Cliente extends Model
{
public function sector()
{
return $this->belongsTo(Sector::class,'sectoresId');
}
}
class Sector extends Model
{
public function sectorLanguage()
{
return $this->hasMany(SectorLanguage::class,'sectoresId');
}
public function cliente()
{
return $this->hasMany(ClienteLanguage::class,'sectoresId');
}
}
class SectorLanguage extends Model
{
public function sector()
{
return $this->belongsTo(Sector::class,'sectoresId');
}
public function idioma()
{
return $this->belongsTo(Idioma::class,'idiomasId');
}
}
I want to recover all the active clients and the name of the sector to which it belongs, if I do something like this
$cliente = Cliente::where('active','1');
When I run $client I can not enter the attribute
foreach($cliente as $cli) {
$cli->sector->sectorLanguage->nombre;
}
Why? It only works for me when I find it by id
$cliente = Cliente::find(1);
echo $cliente->sector->sectorLanguage->nombre;
How can I get what I need without resorting to doing SQL with Query Builder.
Thank you very much, greetings.
According to your defined relations, the Sector has many sectorLanguage, it means you're receiving a collection, so you should work on an object like this:
$cliente->where('active', 1)
->first()
->sector
->sectorLanguage
->first()
->nombre;
Cliente::where('active', 1) and sectorLanguage gives you the collection, so you
should first get the first item from $cliente & sectorLanguage and then apply the
desired relationship
Hope it should work!

Summing and grouping according to city and payment type with laravel eloquent

I have three different tables: cities, payment_types and payments. I want to create summary report for the payments.
cities table:
And then payments type table:
And payments table:
What I want to get is (I want to create this summary)
so, according to summary city doesn't repeat and grouped by payment_types.
How can I create this query with Eloquent?
First you need to create proper relations for your eloquent models, like this:
City.php
class City extends Model {
public function payments() {
return $this->hasMany('App\Payment');
}
}
PaymentType.php
class PaymentType extends Model {
public function payments() {
return $this->hasMany('App\Payment');
}
}
Payment.php
class Payment extends Model {
public function city() {
return $this->belongsTo('App\City');
}
public function payment_type() {
return $this->belongsTo('App\PaymentType');
}
public function scopeFromCity($query, $cityId) {
return $query->where('city_id', $cityId);
}
}
After this initial setup, you are ready to go to create your report:
// Get all cities from DB
$cities = \App\City::all();
// Loop through each city
$cities->each(function($city) {
// Print city id and name
echo "City ID {$city->id}\n";
echo "City Name {$city->name}\n";
// Now we will fetch all unique payment types for this city
// and we will loop through each of them
// calculating the total of payments done
// for this payment type and city_id
$paymentTypes = \App\PaymentType::whereIn('id', \App\Payment::where('city_id', $city->id)->lists('payment_type_id'));
$paymentTypes->distinct()->get()->each(
function($paymentType) use ($city) {
echo "Payment type {$paymentType->type}\n";
$total = $paymentType->payments()->fromCity($city->id)->sum('payment');
echo "Total {$total}\n";
});
});
You can find more information about Eloquent from the documentation, Taylor has explained everything very well with examples.

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