Laravel - Save on multiple models/relationships - php

I have 3 models: User, Campagin, CampaginType
User has many Campagin
Campagin belongs to CampaginType
(User does not related with CampaginType)
When I save a campaign (contains user_id and campaign_type_id field), how can I save 2 fields with a single command.
I try like:
$user->campaigns()->campaignType($campaignType)->create($campaignInfo);
But It not work! :(

public function store(Request $request)
{
Campaign::create($request->all());
$campaign = Campaign::where('unique_field', '=', $request->uniquefield)->first();
$campaign->users()->attach($request->user_id);
$campaign->campaign_type()->attach($request->campaign_type_id);
return redirect('your_destination_view');
}
Note
uniquefield is something that is unique to your campaign database table. You should also modify the models by adding the respective methods to make the eloquent relationship.

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.

Saving one to one relation in Laravel

A User has one (or zero) Company, and a Company belongs to one and only one User. I try to save a company for a user but it adds a new entry in database every time I re-trigger the save method. It's a one to one relation, so I though save method on User.
So Company has one method user():
public function user() {
return $this->belongsTo(User::class, 'user_id');
}
And User has one method company():
public function company() {
return $this->hasOne(Company::class, 'user_id');
}
I'm trying to save (so create or update) a user's company like this (in a Controller):
$company = new Company();
$company->name = 'Test';
User::findOrFail(1)->company()->save($company);
First time I run this code it creates the entry in database (OK), but second time it adds a new entry for the same user (Not OK). I thought it will only update the database entry.
Is it a glitch (or something I don't understand in one to one relation) in Laravel or am I doing something wrong? (I think and hope it's the second purpose)
Creating and updating need to treat differently. So check the existence of company attribute first.
$user = User::with('company')->findOrFail(1);
if ($user->company === null)
{
$company = new Company(['name' => 'Test']);
$user->company()->save($company);
}
else
{
$user->company->update(['name' => 'Test']);
}
Note that hasOne() does not guarantee that you will have one-to-one relationship, it just telling Eloquent how to create query. It works even you have multiple Company refer to same User, in such case when you call $user->company you will get first Company in the result data set from database.
$user = User::findOrFail(1);
$company = $user->company ?: new Company;
$company->name = 'Test';
$user->company()->save($company);
I'm trying to save (so create or update) a user's company
You can do exactly that with the updateOrCreate method:
User::findOrFail(1)->company()->updateOrCreate([],['name' => 'xyz']);
The first parameter of updateOrCreate is an empty array, because the companies id is determined by the hasOne relationship $user->company().
And by the way, I would recommend not using an auto-increment id field in a hasOne relationship. If you set user_id as primary in your company table, its technically not possible to create duplicate company rows for one user.

Laravel 5 Relations

Database Structure:
-Users Table
-user_id
-name
-...
-Follow Table
-user_id
-follow_id
so when user follow another it will be inserted in follow table
and when get user followers
$user = User::where('user_id',$id)->first();
$user['followers'] = $user->Followers;
$user['following'] = $user->Following;
return $user;
By This Relation in User Model Side
public function Followers()
{
return $this->hasMany('App\Follow','follow_id','user_id');
}
And By This Relation in Follow Model Side
public function getUserData()
{
return $this->belongsTo('App\User','user_id','user_id');
}
It Works Fine for me and it gaves me every id But the problem is
that i want to get information about every user returned from this relation
so i should call User Model for each user returned to get his information
or what ??
The way you have you many-to-many relationship set up is almost right.
Firstly, change the Followers() method to be followers() as Laravel follows the PSR-2 standard.
Secondly, this isn't essential but change the user_id column in the users table to be just id. This is a laravel convension that does not need to be followed, however, at this point I don't see any reason not to follow it. I am assuming that you have something like:
protected $primaryKey = 'user_id';
in your User model. If you change your user_id column to id you won't have to have the above declaration anymore.
(If you don't have that line in and you want to continue using user_id as the primary key you WILL have to add that line to your User model.
Thirdly, change the relationship type in followers() to be:
public function followers()
{
return $this->belongsToMany('App\User', 'follower', 'user_id', 'follow_id');
//follower is the table name, user_id is column that relates to the current model and follow_id is the column that is for the relationships
}
With all of the above done you can now get a user with all of their followers by doing:
$user = User::with('followers')->find($id);
This will allow you to get the followers by simply doing:
$user->followers
At this point you can not get rid of you Follow model as you generally wont need a model for a pivot table.
To get the following relationship just add:
public function following()
{
return $this->belongsToMany('App\User', 'follower', 'follow_id', 'user');
}
to your User model.
Again to access this you can either:
$user = User::with('following')->find($id);
or if you have already have the user model and the relationship isn't loaded you can:
$user->load('following'); //in this case following is the name of the method where you have declared the relationship.
For more information please refer to the documentation http://laravel.com/docs/5.1/eloquent-relationships#many-to-many and http://laravel.com/docs/5.1/eloquent
Hope this helps!

Laravel eager loading, loaded table fields

how can I choose which fields I want to get from the with ORM eloquent. For example
$tourTeams = Tournament::with('teams')->where('id', $tourId)->first();
From the teams relation I want only to get the name (without the id and timestamps).
I didn't it in the documentation. For the Tournament eloquent I can do it via the get function while passing it an array of fields names, like this: get(array('name', 'id')). But how do I do this on the Team eloquent?
Note: here is how Team related to Tournament, this code taken from the Tournament eloquent file:
public function teams()
{
return $this->belongsToMany('Team', 'Tournament_Team');
}
You can get specific columns from the relation like this:
$tourTeams = Tournament::with(['teams'=>function($q){
$q->select('id','name');
}])->where('id', $tourId)->first();

Laravel: Many to Many, how to insert data?

I've got for the first time in L4 the need to establish a many-to-many relationship. For what I understood, so far, I need three tables... I have the following:
users
- id
- username
- ...
platforms
- id
- title
- ...
users_platforms
- platform_id
- user_id
How can I now insert data into the users_platforms table? I have the User model and the Platform model. How should both these be related... and how the actual content is saved to the related table?
On hasMany relationships I would create a new user and then save it like $user->something()->save($something) but I naturally can't do something like that in here.
Thoughts?
Having a User model with your relation:
class User extends Eloquent {
public function platforms()
{
return $this->belongsToMany('Platform', 'users_platforms');
}
}
You just have to attach it:
$platform = new Platform;
$platform->name = 'OSX';
$platform->save();
$user = User::find(1);
$user->platforms()->attach($platform->id);

Categories