I'm confused on how to get my model setup in laravel with a table that is connected to a pivot table.
Here's the problem
Say I have
Locations
id
name
area_types
id
name
area_type_location (Pivot table)
id
location_id
area_type_id
area_test
id
area_type_location_id
clean
headCount
Relationship between the tables are different areas type belongs to different locations.
i.e: beach, 25m pools, kids pools, bbq, etc
area_test is connected to the pivot table because the test has to be generated from area that exists, in this case it is area that is registered under different locations. Thus it has to be tested daily, measured, etc.
I understand the structure between area_types and locations for many to many relationship, however I can't get over my head of how do i structure my area_test model? How do I get the data from locations table -> where are my test?
Should I create a model for my pivot table? Is that a good practice in laravel?
Does anyone has the same use case?
I read about eloquent has many through
relationship but I understand that it does not mention about getting through pivot table. I don't quite get if my use case is the same.
Thanks
Finally, apparently there are a couple of way to get data from locations table to area_tests
Tried at tinker and it works,
First Option
I need to create a Pivot model for my Pivot table:
class LocationAreaType extends Pivot{
public function location(){
return $this->belongsTo(Location::class);
}
public function areaType(){
return $this->belongsTo(AreaType::class);
}
public function AreaTests(){
return $this->hasMany(AreaTest::class, 'area_type_location_id');
}
}
I can use hasManyThrough relation that I need to create in my Location table
public function areaTests()
{
return $this->hasManyThrough(
AreaTest::class,
LocationAreaType::class,
'location_id',
'area_type_location_id');
}
this way I can get the areaTests easily by $location->areaTests, My problem was not determining the area_type_location_id as foreign. You need to determine this, apparently when I extends pivot and use hasMany laravel does not auto recognise the Foreign key by itself.
Second option
Another way to access it is from the relation table, I can define withPivot in the areaTypes() relation then access it like this:
$location->areaType[0]->pivot->areaTests
Since laravel only recognise foreign key from both tables location_id and area_type_id, I have to include the id of the pivot table to get the AreaTest table data
So in the Location model I have to get the column
public function areaTypes()
{
// Get the ID of the pivot table to get the poolTests table (connected with ID column)
return $this->belongsToMany(AreaType::class)
->using(AreaTypeLocation::class)
->withPivot('id');
}
There is no need to create a new model for pivot table.
Just declare in Location model below code:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function area_types()
{
return $this->belongsToMany('App\AreaType', 'area_type_location', 'location_id', 'area_type_id');
}
and declare below code in AreaType model:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function locations()
{
return $this->belongsToMany('App\Location', 'area_type_location', 'area_type_id', 'location_id');
}
every time you need to get for example the locations of an area_type in every controller, you can call the function like this: $areatype->locations()->get();
Don't forget to create area_type_location table migration.
Related
I have 3 tables in a database
Transaction {'id','bill_id','remark'}
Bills {'id','third_party','amount'}
ThirdParty {'id','company_name',remark}
The 'transaction' table has column bill_id coming from 'Bills' and Bills table has 'third_party' column which connected to ThirdParty table column -> 'id'
So here I am trying to fetch company_name using laravel eloquent relation
My Transaction model:
public function Bills()
{
return $this->hasOne('App\Bills','id','bill_id');
}
Bills:
public function third_party()
{
return $this->belongsTo('App\ThirdParty','third_party','id');
}
I am getting null value for company_name
Here is the query i am using
Transaction::with('Bills.third_party')->get();
And i have corrected in question (third_party_name) to company_name column name i wrote here was my old join query name which is visible in screenshot, basically i am trying to fetch company name.
Are you able to show all of your code? How does company_name get set to third_party_name?
You could probably also gain a lot by sticking to the laravel "conventions" or "suggested naming", this will give you a lot of functionality for free, and make your code easier to read, write and debug.
eg. Your relationship method names (Bills(), third_party()), but more importantly if you name your table fields in the "laravel way", you will get easier eloquent relationships as there will be no need to define the foreign keys etc.
I would be setting this up similar to:
Transaction {'id','bill_id','remark'}
Bills {'id','third_party_id','amount'} <- note the third_party_id
ThirdParty {'id','company_name',remark}
class Transaction extends Model
{
public function Bills()
{
return $this->hasOne('App\Bills');
}
}
class Bills extends Model
{
public function ThirdParty()
{
return $this->belongsTo('App\ThirdParty);
}
}
You should also define the inverse relationships.
It would be very beneficial to see the full code to see where the issue is.
I have the following setup:
|locations|products|reps|
|id,name |id,name |id,name,phone,etc|
I have also created this pivot table (location_products_rep):
|location_id|products_id|rep_id|
Calling the code below returns the values in the pivot table
foreach ($reps->repNames as $rep)
{
echo $rep->pivot->rep_id;
echo $rep->pivot->product_id;
echo $rep->pivot->location_id;
}
Result: 1 1 1 , which is correct. But what I need is the product name, rep name and location name.
How would i get it to read: Result: Frank Bananas China
OR
Am I better off to make a model for the pivot tabel and pull relations through there like a normal model would?
UPDATE
I ended up just making a model for the pivot table and pulling relations on that using
RepFinderPivot::with('repNames', 'repProducts', 'repLocation')
My original question stands but this works for now.
It seems to me that extending the belongsToMany relationships on your models and chaining into ->using(RelatedModel) would be better for you in this case. You wouldn't have to deal with an intermediate table as a result.
class Use extends Pivot
{
/**
* The users that belong to the role.
*/
public function reps()
{
return $this->belongsToMany('App\User')->using('App\Product');
}
}
Not sure if this would work or not since Product only has the rep_id.
I can't figure out how to make aliases for my table column names such that I can use Laravel's Eloquent belongsTo() functionality.
I have a groups table and and an activities table. The activities table references the groups table by organization_id rather than groups_id.
How do I write belongsTo in my Activity model as the following doesn't work.
public function group()
{
return $this->belongsTo('App\Group', 'organization_id');
}
What I'd like to write is:
App\Activity->group
In the code you have pasted laravel will think that the organization id is the column in your activities table which your are using as foreign key what you should do is :
public function group()
{
return $this->belongsTo('App\Group', 'organization_id', 'id');
}
in the above code you will get all results where activies.id = groups.organization_id;
UPDATE by Tim Peterson
My original code works. I migrated my DB for something else so that must have fixed everything.
Details
I have 3 tables :
catalog_downloads
export_frequencies
export_frequencies_catalog_downloads (Pivot Table)
Diagram
I am not sure if I set the relation between them correctly.
Please correct me if I am wrong.
Here is what I did
In CatalogDownload.php
public function export_frequencies(){
return $this->belongsToMany('ExportFrequency','export_frequencies_catalog_downloads','export_frequency_id','catalog_download_id');
}
In ExportFrequency.php
public function catalog_downloads(){
return $this->belongsToMany('CatalogDownload','export_frequencies_catalog_downloads','export_frequency_id','catalog_download_id');
}
Questions
According to my diagram - Did I assign the relationship correctly ?
I hope I didn't mix up between hasMany and belongsTo
Will I need a class or a model for a Pivot Table ?
Thanks
Since export_frequencies is in the CatalogDownload model you have to invert the ID's because the parameters of belongsToMany are as follows:
1. Name of the referenced (target) Model (ExportFrequency)
2. Name of the Pivot table
3. Name of the id colum of the referencing (local) Model (CatalogDownload in this case)
4. Name of the id colum of the referenced (target) Model (ExportFrequency in this case)
what leads to this function:
public function export_frequencies(){
return $this->belongsToMany('ExportFrequency','export_frequencies_catalog_downloads','export_frequency_id','catalog_download_id');
}
The other function was correct.
If you had some data in your pivot table, for instance a colum with the name someCounter then you will have to tell the relation to load that column when creating the pivot object like this:
public function export_frequencies(){
return $this->belongsToMany('ExportFrequency','export_frequencies_catalog_downloads','export_frequency_id','catalog_download_id')->withPivot('someCounter');
}
That will load the column and make it avalible like this:
$catalogDownload->export_frequencies()->first()->pivot->someCounter;
You will need a separate Pivot Model if you need to do some special handling for the fields or if that pivot itself has a relation of its own but then you might consider using a full blown model instead of a pure Pivot Model.
As an added note to the accepted answer, you are able to set up your many to many relationships without referencing the pivot table and the relevant id's as long as you follow a specific convention.
You can name your pivot table using singular references to the related tables, like 'catalog_download_export_frequency'. Notice the alphabetic order of the singular references.
Then you can simply do:
// CatalogDownload Model
public function exportFrequencies()
{
return $this->belongsToMany('ExportFrequency');
}
// ExportFrequency Model
public function catalogDownloads()
{
return $this->belongsToMany('CatalogDownload');
}
This will then allow you to run queries using the query builder or Eloquent like:
$catalogDownload->exportFrequencies()->get(); // Get all export frequencies for a specific CatalogDownload.
Or
$this->catalogDownload->with('exportFrequencies')->find($id); // Using eager loading and dependency injection, when CatalogDownload is assigned to $this->catalogDownload
Hope this helps!
I'm working on a project that has a many to many relationship between User and Club. This relationship works and I can get the respective objects with: $user->clubs. The pivot table I've named memberships. I can get the pivot data with $club->pivot. Foreign keys are defined for the memberships table in migrations.
However, I'd like the pivot table to be represented by a model so that I can easily update attributes of Membership such as role (Or even add a Role model to Membership!) or status.
I've looked at "Defining A Custom Pivot Model" in the docs, but what it says doesn't work for me, I get:
ErrorException
Argument 1 passed to Illuminate\Database\Eloquent\Model::__construct() must be of the type array, object given
I've also looked at this description of how to do it, but it's more or less the same as above.
Membership model:
class Membership extends Eloquent {
protected $table = 'memberships';
public function user()
{
return $this->belongsTo('User');
}
public function club()
{
return $this->belongsTo('Club');
}
}
Has anyone done this before?
This has been solved by a suggestion by a reddit user to extend Pivot in my Membership model. I also had to add ->withPivot('status', 'role')->withTimestamps() to the relationship declarations in the User and Club models.
You can do this by adding some manual code.
Your Membership model looks ok. You can get all clubs of a $user easily if you define method $user->clubs() where you get all the clubs manually.
clubs() {
$memberships=$this->memberships;
$clubs=new \Illuminate\Database\Eloquent\Collection();
foreach($memberships as $m) {
$clubs=$clubs->merge($m->clubs);
}
return $clubs;
}