Laravel - Access relationship through other - php

I have the following tables:
entries
- id
- category_id
- name
field
- id
- category_id
- name
field_values
- id
- entry_id
- field_id
- value
category
- id
- name
Each Category has certain fields. If I add an entry, I choose the category and I can enter the values for the field for the entry.
Let's say we have the Category "Venues". Venues has the custom field named "Capacity". If I add a news entry, I need to fill the field "Capacity".
This is how I read the fields and their values for an entry:
#foreach($data->field_values as $values)
{{$values->field->name}}: {{$values->value}}
#endforeach
I can only access the field table through the "field_values" table. Isn't it possible to access field directly from entry maybe with an hasManyThrough ?
This (in Entry Model):
public function fields()
{
return $this->hasManyThrough('App\Field', 'App\FieldValues');
}
throws the following mysql error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'fields.field_values_id' in 'on clause' (SQL: select `fields`.*, `field_values`.`entry_id` from `fields` inner join `field_values` on `field_values`.`id` = `fields`.`field_values_id` where `field_values`.`entry_id` in (3))
Why I need to add a field_values_id to Field? Isn't there a different approach?
I just want to foreach through entry->field and not do it by entry_field_values->field

If you just want to access the Fields for an entry, why not do a hasMany relationship ?
Entry Model:
public function fields()
{
return $this->hasMany('App\Field');
}
Then you can get all the fields for an entry as:
$fields = $entry->fields()->get();

Related

Laravel joins not working on 3 different tables

Model
Album::join('tracks', 'albums.track_id', '=', 'tracks.id')
->join('singers', 'tracks.singer_id', '=', 'singers.id')->get();
Snigers table
id - int
name - string
Tracks table
id -int
name - string
singers_id - JSON // example["1","2"]
Album table
id - int
name - string
tracks_id - JSON // example ["1","2"]
here first singers table after track table reference array of id multiple and next alums table reference track table id is also array.how to joins this three table
There's no need to use joins here, if you have a pivot table for these, here's what you can simply do:
In your models you can simply create a relation like this:
Album Model:
public function tracks() {
return $this->hasMany(Track::class);
}
public function singers() {
return $this->hasMany(Singer::class);
}
and then call it in your controller.
AlbumController.php
Album::where('id',1)->with('tracks','singers');
This will simply fetch all the records with Tracks and Singers that belong to Album id 1.

Laravel Model Relationships - What kind of relationship am I trying to create?

I have got 3 models associated with this question; Country, Manufacturer and Region.
I've simplified the tables for the sake of this question. I don't think anything else in the tables or any of the other models are anything to do with the problem.
My tables are set up like so;
manufacturers
- id
- name
countries
- id
- name
regions
- id
- name
- manufacturer_id
- country_id
What I want to be able to do is to write $manufacturer->countries in my blade and have it spit out the countries that are associated with a given manufacturer.
The models are currently related to each other like this;
Country.php
public function manufacturers()
{
return $this->hasMany(Manufacturer::class);
}
public function regions()
{
return $this->hasMany(Region::class);
}
Region.php
public function manufacturer()
{
return $this->belongsTo(Manufacturer::class);
}
public function country()
{
return $this->belongsTo(Country::class);
}
and where I'm having the problem, Manufacturer.php
I think I need a hasMany relationship. I've already got;
public function regions()
{
return $this->hasMany(Region::class);
}
and I would have thought I would have needed;
public function countries()
{
return $this->hasManyThrough(Country::class,Region::class);
}
but that leads to this error;
Column not found: 1054 Unknown column 'countries.region_id' in 'on clause' (SQL: select `countries`.*, `regions`.`manufacturer_id` as `laravel_through_key` from `countries` inner join `regions` on `regions`.`id` = `countries`.`region_id` where `regions`.`manufacturer_id` = 4)
so I tried swapping the classes round to give;
public function countries()
{
return $this->hasManyThrough(Region::class,Country::class);
}
but that leads to;
Column not found: 1054 Unknown column 'countries.manufacturer_id' in 'field list' (SQL: select `regions`.*, `countries`.`manufacturer_id` as `laravel_through_key` from `regions` inner join `countries` on `countries`.`id` = `regions`.`country_id` where `countries`.`manufacturer_id` = 4)
Does anyone know how I should be setting my relationships up in order to achieve what I want?
I also tried a belongsToMany relationship, which did bring back the countries, but multiple instances of the same country. I just want one instance of each country that appears in the regions table for any given manufacturer.
You are actually dealing with the many-to-many relationship.
In your case regions is a pivot table.
Kindly check belongsToMany.
In Laravel, the best relationship to apply is many to many relationship. What this means as applied to your case is that 1 country can have multiple manufacturers and 1 manufacturer can be in multiple countries.
If that is the case, you don't need to create a regions table, but rather a pivot table. The default naming convention in laravel is (singular and om alphabetic order), that is, country_manufacturer table and it will contain (You can always add an extra variable known as pivot value):
country_manufacturer
- id
- name // pivot value
- manufacturer_id
- country_id
Then, in the models, add belongsToMany relationship, i.e.
In Manufacturer model (without pivot) :
public function countries()
{
return $this->belongsToMany(Manufacturer::class);
}
In Country Model (With pivot):
public function manufacturers()
{
return $this->belongsToMany(Country::class)->withPivot('name');
}
Hence, you will be able to call $country->manufacturers() which will give you a list of all the manufacturers in the $country and the reverse is true: $manufacturer->countries will give you all the countries the manufacturer is based in.

Change the name of the column to be taken from the database

How can I change the questioned to the database which is automatically generated.I have in blade template this
{{\Illuminate\Support\Facades\Auth::user()->friends()->get()}}
and it generates
Unknown column 'friends.user_id' in 'where clause' (SQL: select * from `friends` where `friends`.`user_id` = 1 and `friends`.`user_id` is not null
because my column name is user_id1 insted user_id.
and I do not know why the query to the database takes the user_id value instead of user_id1. How can I change it ?
Define the custom foreign key in the friends relationship:
public function friends()
{
return $this->hasMany(Friend::class, 'user_id1');
}

Laravel Eloquent Eager Loading assumes incorrect pivot table column name

I have two tables in Laravel 5.4. Orders and Product which are joined by a many-to-many relationship
I'm trying to fetch all the orders together with the associated products like so:
$orders = Orders::with('products')->get();
My Order Model has this set up as
public function products()
{
return $this->belongsToMany('App\Product')
->withPivot('qty')
->withTimeStamps();
}
When I output the log I get the following error message:
Next Illuminate\Database\QueryException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'order_product.order_order_id' in 'field list' (SQL: select `products`.*, `order_product`.`order_order_id` as `pivot_order_order_id`, `order_product`.`product_product_id` as `pivot_product_product_id`, `order_product`.`qty` as `pivot_qty`, `order_product`.`created_at` as `pivot_created_at`, `order_product`.`updated_at` as `pivot_updated_at` from `products` inner join `order_product` on `products`.`product_id` = `order_product`.`product_product_id` where `order_product`.`order_order_id` in (66, 67, 70, 72, 73, 74) and `products`.`deleted_at` is null) in /home/vagrant/Projects/vcc-backoffice/vendor/laravel/framework/src/Illuminate/Database/Connection.php:647
The issue is that Laravel is looking for a table in the Pivot called "order_order_id" which doesn't exist. I haven't declared the column to be called that. My pivot table columns are called "order_id" and "product_id"
I don't know how Laravel assumes the pivot table names. Is there a way to specifically declare the column names in the pivot? Or have I made a mistake in my naming conventions?
Edit Order Model and try following code :
public function products()
{
return $this->belongsToMany('App\Product','order_product','order_id','product_id')
->withPivot('qty')
->withTimeStamps();
}
If you have two model named Order & Product and many_to_many relationship between them and their database table like orders & products then Laravel will search for a pivot table named order_product (model name in alphabetic order and joined by '_' ).
order_product table will composed of two columns order_id,product_id . This is the basic naming convention for pivot table in a nutshell :) .

How to find all id pivot from pivot table? (laravel 5.3)

I have a pivot table. The name is users_banks table. The table have field id, user_id, bank_id, status, account_name and account_number
Now, the pivot have 3 records
I display contain from pivot table using code like this :
$user_id = auth()->user()->id;
$user = $this->user_repository->find($user_id);
$account = array();
foreach($user->banks as $bank) {
$account[] = $bank;
}
dd($account);
The result display all record in the form of array. There exist value of field user_id, bank_id, status etc. But I don't find value of id
How can I find id from pivot table?
If the relationship is defined correctly you can use:
$bank->pivot->id
but make sure the user belongsToMany(Bank::class) and the bank belongsToMany(User::class) or else it wont work.

Categories