Saving one to one relation in Laravel - php

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.

Related

Can't access data from the Users table from a function in controller

I'm trying to use a function to soft delete 2 rows in a database, one is from a table I made called persona and the other one is from the users table that laravel makes with Auth, My users table have a foreign key associated to the persona table called idPersona. What I'm trying to do is to soft delete the row from the persona table that matches the id parameter and after that soft delete the row in users where the attribute idPersona matches the id parameter that the function recieved.
I'm going to post the Controller function code
Controller function code
public function deleteMedico($id){
$medico = Persona::findOrFail($id);
$medico->estado =False;
$personaID = $medico->id;
$user= new User();
$user->where('idPersona',$personaID);
var_dump($user);
}
I'm going to try to explain what I'm trying to do with this controller, I use the findOrFail function to find the row I'm trying to self delete from the persona table, after I found it I set estado to false in this way soft deleting the row. After that I try to get an User instance, look for the users table where idPersona matches the id of the row that was soft deleted.
The code for self deleting it would be almost the same than with the persona table but the problem is I can't find the row in the users table, gonna post the var_dump I get of $user.
Also gonna post how my database looks in case it is useful
I have no idea what I need to do to get the row of the users table where the idPersona attribute matches the id attribute from the personas table. I'm new in Laravel so sorry if this question is repetitive or is nothing to hard. p
Your syntax is wrong.
// $user = new User();
// $user->where('idPersona',$personaID);
$user = User::where('idPersona', $personaID)->firstOrFail();
This should fix the syntax but there are simpler ways to do this in your code.
Route model binding
Route::get('deleteMedico/{persona}', ...);
Eloquent Relationships
// Persona.php
public function user()
{
return $this->hasOne(User::class, 'idPersona');
}
public function deleteMedico(Persona $persona)
{
$persona->fill(['estado' => false])->save();
$persona->user->fill(['estado' => false])->save();
}
You forgot the get method.
User::where('idPersona',$personaID)->get();

Laravel 5.0 get the id of the row inserted in a pivot table after attach

I have a newsletter and block model that has a many to many relation. When I attach a block to a newsletter I want the id of the row that was insterted in the pivot table.
This is what I tried but results in "null"
$newsletter = Newsletter::findOrFail($newsletterId);
$newsletterBlock = $newsletter->blocks()->attach($blockId);
dd($newsletterBlock);
Although this question is old, however nobody gave the right answer. If you are in a situation that your pivot table has a primary key.
Using withPivot method is useful when you want get the id when you load the related model. However when you attach something you can not get the pivot_id;
In these situations best thing to do is to use a model that is connected to the pivot table, then only thing you need to do is inserting into pivot table using its model instead of attaching two models together.
in this example, first create a model called BlockNewsLetter if it is necessary fill the $table and $fillable attributes of the model and then you are good to go.
$newsletter = Newsletter::findOrFail($newsletterId);
$blockNewsLetterPivot = BlockNewsLetter::updateOrCreate([
'block_id' => $block_id ,
'newsLetter_id' => $newsletter->id
]);
$inserted_pivot_id = $blockNewsLetterPivot->id;
Try this, haven't test it but this should work:
/** Newsletter.php */
public function blocks()
{
return $this->belongsToMany('App\Block')
->withPivot('id');
}
Then in your controller:
$newsletter = Newsletter::findOrFail($newsletterId);
$newsletter->blocks()->attach($blockId);
// then you could:
foreach($newsletter->blocks as $block)
{
dd($block->pivot->id);
}
Check this section of the docs.

get a values using many to many relations on laravel 5 models

i'm really new working with laravel 5.0, so I got this problem when I try to retrieve a result using a model. I have a users table, with a list of users who can be a manager or not, they can have assigned one or more companies, or none, a company table with companies which can have one or many managers, and a pivot table that I called companies_managers. I set up the relations in every model like this:
/***User model***/
public function companies()
{
return $this->belongsToMany('App\Company', 'companies_managers','id', 'manager_id');
}
and the same in Company model
public function managers()
{
return $this->belongsToMany('App\User', 'companies_managers', 'id', 'company_id');
}
I want to get the managers assigned to a company using a company id to get it, but it just gave me an huge object without the values I looking for (the names of the managers assigned to that company). This is the code that I tried:
$managers = Company::find($id)->managers();
I would appreciate any help you can give me
Using ->managers() (with the brackets) doesn't actually return the associated managers, but rather a Builder instance (the "huge object"), which you can then chain with additional parameters before finally retrieving them with ->get() (or another closure, like ->first(), ->paginate(), etc)
Using ->managers (without the brackets), will attempt to access the associated managers, and execute any additional logic to retrieve them.
So, you have 2 options:
$company = Company::with(["managers"])->findOrFail($id);
$managers = $company->managers;
Or
$company = Company::findOrFail($id);
$managers = $company->managers()->get();
Both of those will perform the necessary logic to pull the managers. ->with() and no brackets is slightly more efficient, doing it all in a single query, so bear that in mind.
You just need to split out your code;
// this will find the company based on the id, or if it cannot find
// it will fail so will abort the application
$company = Company::findOrFail($id);
// this uses the active company record and gets the managers based
// on the current company
$managers = $company->managers;
Thank you for your help guys, I solved the issue fixing the relations in the models to this:
return $this->belongsToMany('App\Company', 'companies_managers', 'manager_id', 'company_id');
and this
return $this->belongsToMany('App\User', 'companies_managers', 'company_id', 'manager_id');
The IDs that I had set were not the correct ones for belongsToMany function
And this
$managers = Company::find($id)->managers();
was a problem too, was a dumb mistake of my part. I solved the return of Builder instance using just return instead of dd(), in that way I got the values I looking for. Thanks everyone!

Intermediate Table with Laravel

I'm working in a Webapp and I have a problems to work with a intermediate table, these are my tables in mysql:
User:
Integer:id
String:name
String:email
String:phone
Exercise:
Integer:id
String:name
String:description
User_Exercise:
Integer:id
Integer:id_user
Integer:id_exercise
Integer:record
So, what I want to do is that when I create an exercise, it be created one row for each user with the exercise-id that I have created it before. Later the user could change his record in this exercise.
I have thought to create a model to handle the user_exercise's table but I don't know if there is some way to do this better or not.
So, There are some way to do this without create a new model?
PD: Sorry for my terrible english
You don't need a seperate model for User_Exercise
You can use $this->belongsToMany from base Model i.e., User
Note :
For insert process you can get the parent id by
$insertUser = User::create($userData);
then
$insertUser->id for taking the last insert id
And then to retrieve with respect to User_Exercise you shall use $this->belongsToMany from your User Model
Example
Have this in your User Model
public function getUser() {
return $this->belongsToMany('App\User', 'excercise_name', 'user_id', 'excercise_id')->select(array('exercise.id', 'excercise.name'));
}
And Get the data you need from any Controller like this
$userData = User::find($userId)->getUser;

Laravel - Save on multiple models/relationships

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.

Categories