I'm pretty much new to opps and laravel both
So, to insert the values into my users and profiles table which hav OneToOne relationship, Here is how my store() method looks like
public function store(Requests\StoreNewUser $request)
{
// crate an objct of user model
$user = new \App\User;
// now request and assign validated input to array of column names in user table
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->email = $request->input('email');
$user->password = $request->input('password');
/* want to assign request input to profile table's columns in one go
*/
$user->profile()->user_id = $user->id; // foreign key in profiles table
$user->profile()->mobile_no = $request->input('mobile');
dd($user); // nothing related to profile is returned
}
I'm creating the new record, hence dd() never returns anything related to profile table.
Is this Because the $user object is not including relationship by default?
If yes Can i create the $user object which includes the associated relations in User Model ?
Or do i have to create two separate objects of each table and save() the data But then what is the significance of push() method ?
EDIT 1
P.S. yes, the relationships are already defined in User & Profile model
You may try something like the following. At first save the parent model like this:
$user = new \App\User;
$user->first_name = $request->input('first_name');
// ...
$user->save();
Then create and save the related model using something like this:
$profile = new \App\Profile(['mobile_no' => $request->input('mobile')]);
$user->profile()->save($profile);
Also make sure you have created the profile method in User model:
public function profile()
{
return $this->hasOne('App\Profile');
}
I thought i'd update this answer and make it applicable to Laravel 5 onwards. I'll use #The Alpha answer as a basis.
$profile = new \App\Profile(['mobile_no' => $request->input('mobile')]);
$user->profile()->associate($profile); // You can no longer call 'save' here
$user->profile()->save();
The reason for this is you can no longer call save on the belongsTo relation (or any other), this now returns an instance of Illuminate\Database\Query\Builder.
The clean way to do it now would be having on your User Class file:
public function profile()
{
return $this->hasOne(App\Profile::class);
}
and in your User Controller, the following store method:
public function store(Requests\StoreNewUser $request)
{
$user = App\User::create(
$request->only(
[
'first_name',
'last_name',
'email'
]
)
);
$user->password = Illuminate\Support\Facades\Hash::make($request->password);
//or $user->password = bcrypt($request->password);
$user->profile()->create(
[
'mobile_no' => $request->mobile;
]
);
dd($user);
}
I didn know if u were saving plain text password to you database or using a mutator on password attribute, anyhow the suggested above is a good practice I think
Is this Because the $user object is not including relationship by default? If yes Can i create the $user object which includes the associated relations in User Model ?
Yes you should create the relationship, they're not included by default.
In your User model you'd want to do something like this:
public function profile()
{
return $this->hasOne('App\Profile'); // or whatever your namespace is
}
This would also require you to have a Profile model created.
This would definitely answer your questions regarding inserting related models: http://laravel.com/docs/5.1/eloquent-relationships#inserting-related-models
As The Alpha mentioned, and you also eluded to, I think you need to save your user model first then you can add via relationship.
Related
This code does not seem to capture the user id from the session so I can use it as a foreign key in the database for the place the user is adding a comment to.
public function store(Request $request, $place_id) {
// find place in the database
$place = Place::find($place_id);
// find user in the database
$user = User::find(\Auth::id());
// create review instance
$review = new Review([
'review' => request('review'),
'rating' => request('rating')
]);
// save review (creating relationship) in the places table as reviews
$place - > reviews() - > save($review);
// save review (creating relationship) in the users table as reviews
$user - > reviews() - > save($review);
$reviewData = Review::find($review - > id);
if (request() - > wantsJson()) {
return $reviewData; // Returns JSON, thanks to Laravel Magicâ„¢
}
// return view
return view('place');
}
When creating models for relationships, use create instead of save.
$user->reviews()->create($review);
The create method will associate the relevant relationship id.
I can see that you are saving the $review twice. Once in place_reviews and once in user_reviews. Consider changing your database logic, so reviews belongs to User and Place instead. This would be a lot more sensible structure:
Controller
$review = new Review([
'review' => request('review'),
'rating' => request('rating')
]);
$review->user()->associate($user);
$review->place()->associate($place);
$review->save();
Review model
public function user()
{
return $this->belongsTo(User::class);
}
public function place()
{
return $this->belongsTo(Place::class);
}
Review table
$table->unsignedInteger('user_id');
$table->unsignedInteger('place_id');
User and place model
public function reviews()
{
return $this->hasMany(Review::class);
}
You also have the option to use belongs to many relationships, if one Review could relate to multiple Place.
Another tip:
You may also consider using findOrFail to ensure your user is valid. This way your code will throw an Exception if there is no user id, as opposed to proceeding with a null user, which could be cause for hard-to-find errors.
$userId = \Auth::id();
$user = User::findOrFail($userId);
You should do like this.
$user = \Auth::user();
if(!is_null($user)){
$user_id = $user->id;
}
I'm currently working on a quiz application with Laravel 5.6 and am having trouble with saving a new quiz record.
The two tables that are being inserted into are quizzes and user_quizzes. The quizzes table contains some basic quiz data such as:
quiz_name
quiz_description
quiz_pin
active
The user_quizzes table contains two foreign keys to reference which quiz belongs to a particular user.
user_id
quiz_id
The error is an integrity constraint violation when inserting into the user_quizzes table. It successfully inserts the quiz_id but the user_id is left as NULL. I am unsure how to ensure the user_id is also inserted as I'm using Eloquent.
The full error is:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'user_id' cannot be null (SQL: insert into `user_quizzes` (`quiz_id`, `user_id`) values (6, ))
I am making use of the QuizController, Quiz Model and User Model for saving the record. Here is my store() method in the QuizController:
public function store(Request $request)
{
$validator = $request->validate([
'quiz_name' => 'required|max:30',
'quiz_description' => 'required|max:500'
]);
$quiz = new Quiz(
[
'quiz_name' => $request->get('quiz_name'),
'quiz_description' => $request->get('quiz_description'),
'active' => '0',
'quiz_pin' => '5555', // hard coded for now
]
);
$quiz->save();
$user = new User;
$user->quizzes()->save($quiz);
return redirect()->route('quiz_host.dashboard.manage-quizzes')->with('quizCreated', 'Whoa ' . Auth::user()->username . ', you have created a quiz! Now it\'s time to add some questions');
}
My User Model is a follows:
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function activation()
{
return $this->hasOne('App\Models\Activation');
}
public function profile()
{
return $this->hasOne('App\Models\Profile');
}
public function quizzes()
{
return $this->belongsToMany(Quiz::class, 'user_quizzes', 'user_id', 'quiz_id');
}
}
and my Quiz model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Quiz extends Model
{
protected $table = 'quizzes';
protected $fillable = ['quiz_name', 'quiz_description', 'active', 'quiz_pin'];
public function user()
{
return $this->belongsToMany(User::class, 'user_quizzes', 'quiz_id', 'user_id');
}
}
Any guidance as to what I'm doing wrong would be greatly appreciated.
Reviewing your code
This is your controller:
QuizController.php
public function store(Request $request)
{
// your validations.
// Storing the quiz.
$quiz->save();
// User instance.
$user = new User;
// Storing the relationship.
$user->quizzes()->save($quiz);
// Returning the view.
return redirect()->route('quiz_host.dashboard.manage-quizzes')->with('quizCreated', 'Whoa ' . Auth::user()->username . ', you have created a quiz! Now it\'s time to add some questions');
}
Now, the problem here is related to the $user object.
When you do this:
$user = new User;
You are createing an instance of the User class, but this object isn't persisted yet into the database, what this means is that this object doens't have an id yet. You can confirm this doing dd($user->id), this will return null.
That's why when you do this:
$user->quizzes()->save($quiz);
It throws the SQL error, because you are calling a method to store the $primaryKey (id) of the $user object in the pivot table. But given that the $user object doens't have a primary key is trying to store a null value instead.
Solution
Now, I don't really know what is your "use case", but I will assume that the $user is the logged-in one, so to relate properly the relationship replace this:
// creating a User instance.
$user = new User;
with this:
// Logged-in user.
$user = auth()->user();
This will use the auth facade to get the actual logged-in user and return the object. Given that is a registered user it will have a proper id.
Alternative
If your use case is different and you will relate the quiz to a different user, do this instead:
// Some other user
$user = User::find($someId); // $user = User::find(5); for example
or this, to create a completely new User instance and relating a quiz to it:
// A new User
$user = new User;
$user->fill($someData);
$user-save(); // this will assign a primary key (id) to the object.
Now you can attach the related model to it.
Side note
Your users m--------m quizzes is a many to many relationship.
So, as the documentation says, the proper way to store a relatioship between the two objects is the attach() method:
$user->quizzes()->attach($quiz->id);
This method will create a record in the intermediate table (pivot) with the ids of the $user and $quiz objects.
To make it clear, new User will only create user model object, it is still not committed to DB.
When we try to call $user->quizzes()->save($quiz) it is will try to add an entry in user_quizzes pivot table, but user_id is empty, because user is still not created.
So you have to create a user entry in DB by calling $user->save() before adding it to pivot table.
$quiz->save();
$user = new User;
$user->save();
$user->quizzes()->save($quiz);
I'm using a role package which stores hasMany relational data in my database. So there is a users table and a user_roles table with foreign keys...etc...
I am updating the model using the following code:
$user = User::findOrFail($id);
$user->update(request()->all());
$user->syncRoles(request()->input('roles', []));
Is there any way I can keep a reference of the roles on the $user variable so they can be used after these lines of code run?
I'm asking because I'm using a logging system after the fact like so:
activity()->on($user)->by(auth()->user())->withProperties([
'user' => $user,
'roles' => request()->input('roles'),
])->log('Updated User');
Which I would like to condense to just:
activity()->on($user)->by(auth()->user())->withProperties($user)->log('Updated User');
You will need to refresh the model data from the database. E.g.
$user = $user->fresh('roles');
For example using lazy loading:
$user = User::findOrFail($id);
$roles = $user->roles;
and on your User Model you would create a HasMany relationship to roles table.
Eager loading:
$user = User::with('roles')->findOrFail($id);
Add the relationship in your User.php model :
public function roles(){
return $this->hasMany(Role::class);
}
Now simply call it in your code to get the roles like so:
$aUser = User::with('roles')->find($id);
$roles = $aUser->roles;
I am beginner in Laravel Framework.I have searched for my problem and get some solution but those are not solve my problem.So,
profiles table:
I want to need to fill up userID column when any user create a profiles.For this i am trying to code something like this:
Profile model:
public function users(){
return $this->belongsTo('App\User','userID');
}
And User Model:
public function profiles()
{
return $this->hasMany('App\Profile');
}
In this way its keep null value every time.How can i solve this?
Thanks in advanced.
So assuming you have the following (which you kind of do)
public function profiles()
{
return $this->belongsTo(\App\User::class); // we do not need to provide the user_id because laravel assume we are using that
}
<?php
// Profile.php (Model)
public function user()
{
$this->belongsTo(\App\User::class); // Again we do not need to provide the information because of the table / column names we are using
}
You have a few options, you can either when creating the profile, assign the user_id (as long as it is in the fillable fields.
$profile = new Profile;
$profile->user_id = \Auth::getId(); // current logged in user
$profile->somethingElse = 'abc';
$profile->save();
Or since we have a relationship you should be able to do something like this
$profile = new Profile;
$profile->somethingElse = 'abc';
// We will use the current logged in user again
Auth::user()->profiles()->save($profile); // will automagically fill in the user_id with the logged in user's id.
Hopefully that sheds some light
While inserting Data into Profile Table, you just need to do as follows:
$profile = new Profile();
$profile->userID = Auth::user()->id;
$profile->other_columns = 'values'
.....
$profile->save();
There is no need to join the tables for inserting the value in Profile Table for here. Hope this helps you
I have recently started working with Laravel and Eloquent, and was wondering about the lack of a find or create option for models. You could always write, for example:
$user = User::find($id);
if (!$user) {
$user = new User;
}
However, is there not a better way to find or create? It seems trivial in the example, but for more complex situations it would be really helpfully to either get an existing record and update it or create a new one.
Below is the original accepted answer for: Laravel-4
There is already a method findOrFail available in Laravel and when this method is used it throws ModelNotFoundException on fail but in your case you can do it by creating a method in your model, for example, if you have a User model then you just put this function in the model
// Put this in any model and use
// Modelname::findOrCreate($id);
public static function findOrCreate($id)
{
$obj = static::find($id);
return $obj ?: new static;
}
From your controller, you can use
$user = User::findOrCreate(5);
$user->first_name = 'John';
$user->last_name = 'Doe';
$user->save();
If a user with id of 5 exists, then it'll be updated, otherwise a new user will be created but the id will be last_user_id + 1 (auto incremented).
This is another way to do the same thing:
public function scopeFindOrCreate($query, $id)
{
$obj = $query->find($id);
return $obj ?: new static;
}
Instead of creating a static method, you can use a scope in the Model, so the method in the Model will be scopeMethodName and call Model::methodName(), same as you did in the static method, for example
$user = User::findOrCreate(5);
Update:
The firstOrCreate is available in Laravel 5x, the answer is too old and it was given for Laravel-4.0 in 2013.
In Laravel 5.3, the firstOrCreate method has the following declaration:
public function firstOrCreate(array $attributes, array $values = [])
Which means you can use it like this:
User::firstOrCreate(['email' => $email], ['name' => $name]);
User's existence will be only checked via email, but when created, the new record will save both email and name.
API Docs
Alternatively, in this case you can also use Laravel's function and search for id as an attribute, i.e.
$user = User::firstOrCreate(['id' => $id]);
Find or New based on primary key id
$user = User::findOrNew($id); // if exist then update else insert
$user->name= $data['full_name'];
$user->save();
First or New based on non-primary key single filed
// get the record where field_name=value else insert new record
$user = User::firstOrNew(['field_name'=>'value']);
$user->name= $data['full_name'];
$user->save();
First or New based on non-primary key multiple filed
// get the record where field_name1=value1 and field_name2=value2, else insert new record
$user = User::firstOrNew(['field_name1'=>'value1','field_name2'=>'value2']);
$user->name= $data['full_name'];
$user->save();
In Laravel 5:
There are two methods you may use to create models by mass assigning attributes: firstOrCreate and firstOrNew.
The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the given attributes.
The firstOrNew method, like firstOrCreate will attempt to locate a record in the database matching the given attributes. However, if a model is not found, a new model instance will be returned. Note that the model returned by firstOrNew has not yet been persisted to the database. You will need to call save manually to persist it:
// Retrieve the flight by the attributes, or create it if it doesn't exist...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
// Retrieve the flight by the attributes, or instantiate a new instance...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
Laravel 4 models have a built-in findOrNew method that does what you need:
$user = User::findOrNew($id);
You can use firstOrCreate (It's working with Laravel 4.2)
$bucketUser = BucketUser::firstOrCreate([
'bucket_id' => '1',
'user_id' => '2',
]);
returns found instance or new instance.