So I have two tables named 'customers' and 'billing_addresses'.
I also have two models named 'Customer' and 'BillingAddress'.
In the billing_addresses table, there are multiple addresses, each having an 'id'.
In the customers table, each customer has an 'billing_address_id' value corresponding to one of the entries in the billing_addresses table.
What I managed to create so far is:
// Customer relationship method(in the model file)
public function address()
{
return $this->hasOne('App\BillingAddress','id');
}
/////////
// BillingAddress relationship method(in the model file)
public function customer()
{
return $this->hasMany('App\Customer','id');
}
I am indeed getting the right data when I do something like Customer::with('address');
but I feel like there is a better approach for all this as I'm also getting
BadMethodCallException
Call to undefined method
Illuminate\Database\Eloquent\Relations\HasOne::getForeignKey()
when I try to filter with datatables(can't tell if its related but first I'd want to have the best approach on the relationships).
Thank you!
What you want to achieve is this:
// Customer Model
public function address()
{
return $this->belongsTo('App\BillingAddress');
}
// BillingAddress Model
public function customer()
{
return $this->hasMany('App\Customer');
}
You need the belongsTo on your Customer Model because you have the Billing id stored within the Customer table. Eloquent will automatically match the billing id to the foreign Key in your customer model. You just need to follow Eloquente naming conventions for foreign keys. Look here for more infos.
Eloquent Relations
A custom can have multiple billing addresses. So it customer can have many addresses and an address belongs to a customer.
// Customer Model
public function addresses()
{
return $this->belongsTo('App\BillingAddress', 'customer_id');
}
// BillingAddress Model
public function customer()
{
return $this->hasMany('App\Customer', 'billing_address_id');
}
Then you can do : Customer::with('addresses')->get();
Secondly, make sure you are passing correct foreign key column as second parameter to the relationship methods. See documentation for reference
The second error is probably causing because of incorrect foreign key column passed as second argument.
Related
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.
I have 3 tables:
customer: fields: id, name
item: fields: id, name
customer_items: fields: customer_id, item_id, qty
Customer and Item have their separate Models as we would expect.
Question: How would I relate these two(Customer and Item) without having a pivot model.
I want to directly get customer items using $customer->items instead of doing $customer->customerItem->items which I find unnecessary since I don't want to track customerItems & customer by item.
Also, I cannot directly use customer_items table for Item model as I might need to retrieve all items in its controller.
As pointed out by #kerbholz (but they didn't create an answer so here it is), in your customer model you need the following function:
public function items()
{
return $this->belongsToMany('App\Item');
}
Which assumes your Item model class sits within App. You may also do the reverse in your Item model.
Now you should be able to do $customer->items and get a collection of items.
If you want to include the qty field then you need:
public function items()
{
return $this->belongsToMany('App\Item')->withPivot('qty');
}
Note that you still need the pivot table, you can't escape that, but you can now navigate it in a more elegant manner.
creat customer_items table and include custmer_item_id and user_id . in User model include this function
public function basket() // example
{
return $this->belongsToMany(User::class, 'customer_items', 'user_id', 'custmer_item_id');
}
i having two relationship model in my project.
CarPool & Ride & User.
In my CarPool model
public $with=['user','ride'];
public function user(){
return $this->belongsTo('App\User');
}
public function ride(){
return $this->hasMany('App\Ride');
}
In my ride model
public $with=['user','carpool'];
public function user(){
return $this->belongsTo('App\User');
}
public function carpool(){
return $this->belongsTo('App\CarPool');
}
In my expected scenario, when user enter to "My Ride" page, it will display all ride took by user.(For example users took 3 rides).So the list having 3 column. Each ride column having carpool information and driver information.
In my controller, i use this to get the ride belongs to user.
$user_id=Auth::user()->id;
$rides= Ride::where('user_id',$user_id)->get();
But after i check the result. Seem like the carpool relationship has not connected because there was null. Is my relationship not correct?
My table in database
car_pools Table
rides Table
Problems solved, although is not eagle loading but still can work in another ways. I changed my ride model by removing the carpool. So now is
public $with=['user'];
Then i call the data by {{ $ride->carpool->title }}
Not same with my expectation but at least working.
It really looks like you don't have car_pool_id fields in the rides table that has related CarPool ID in it.
If you have this fields, but the name is different, add the foreign key name to the relationship:
public function carpool()
{
return $this->belongsTo('App\CarPool', 'custom_column_name');
}
Try after giving foreign-key and primary key both in the relation mapping function.
Because sometimes if you are just giving foreign key, Then the model will try to connect to the other model with its primary key. If you are not using the primary key for relation specify the other key in the relation function.
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');
}
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;
}