Laravel belongsTo() column naming issue - php

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.

Related

Laravel table relationship to pivot table

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.

Laravel Many-to-many relationship using pivot table

I'm creating an application wherein users can be assigned to multiple organisations, and organisations can have many users - many-to-many relationships.
I want to be able to do something like this:
$user->organisations()->get() as well as $organisation->users()->get()
I have a users table...
I have an organisations table...
Uh! users-organisations, organisations-users!
and I have a user_orgs pivot/mapping/etc. table
Note
The user_orgs table has an org_id field, and a user_id field.
Eloquent assumes and expects organisation_user - but that is not what I have named my table, nor do I want to rename.
I set up the following
App/Organisation.php
public function users(){
return $this->belongsToMany("App\User");
}
and on user:
App/User.php
public function organisations(){
return $this->belongsToMany("App\Organisation");
}
And then I test this:
Route::get('/test-route', function(){
$u = App\User::first();
return $u->organisations()->get();
});
and get the following error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db.organisation_user' doesn't exist (SQL: select organisations.*, organisation_user.user_id as pivot_user_id, organisation_user.organisation_id as pivot_organisation_id from organisations inner join organisation_user on organisations.id = organisation_user.organisation_id where organisation_user.user_id = 1)
The two questions in my mind are, one; how do I specify to Eloquent, to use user_orgs instead of assuming organisation_user, the same way I can override the tableName or primaryKey on a model? Two: how can I specify the foreignKey column, such that it uses user_orgs.org_id and not user_orgs.organisation_id?
But please do suggest alternatives.
Thanks all, in advance.
You can set the name of the pivot table by passing it as the second argument to the belongsToMany() relationship, like below:
public function users(){
return $this->belongsToMany("App\User", "user_orgs");
}
public function organisations(){
return $this->belongsToMany("App\Organisation", "user_orgs");
}
Documentation:
https://laravel.com/docs/5.8/eloquent-relationships#many-to-many
As mentioned previously, to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method.

Laravel Eloquent relationship fetching third table/relation value

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.

hasOne relationship in Laravel not working?

I have a one to one relationship I am trying to get to work in laravel.
I have a user and an alert table I am trying to use.
Primarykey of User table is id and another id in there is called id_custom.
In the Alerts table I have id_custom as the primary key.
Here is the relationship in the users model:
public function alerts()
{
return $this->hasOne('Alerts', 'id_custom');
}
Here is the alerts model:
alerts->profit` (where `profit` is a column in the `Alerts` table.
What am I doing wrong?
Your hasOne method is currently looking for user_id in your alerts table. You need to explicitly set the foreign and local key you're looking for.
return $this->hasOne('Model', 'foreign_key', 'local_key');
Source
In your instance if would be
return $this->hasOne('Alerts', 'id_custom', 'id');
You would make things much tidier for yourself if you changed the User attribute id_custom to alert_id.
Then you could change the method in your User.php model to alert and do:
public function alert()
{
return $this->hasOne('Alerts');
}

How to assign relation when working with pivot table in Laravel 4?

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!

Categories