Duplicate entry while using updateOrCreate() - php

I'm using (latest) Lumen, which could be the culprit to my error.
When I'm using updateOrCreate():
User::updateOrCreate(
['username' => $user->username],
[
'email' => $user->email,
'password' => $user->password,
'foreign_id' => $user->foreign_id,
'client_id' => $user->client_id,
'status' => $user->active,
'user_level' => (integer) $user->user_level
]
);
on one of my models, I get mysql error:
"SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'user#name.com' for key 'users_username_unique' (SQL: insert into `users` (`username`,
because it tries to insert duplicate value for one of my unique columns (username).
So, function itself exists, I dont get any errors, and it works for first inserts, but once it reaches functionality of checking if DB entry exists and needs only to update it, it still wants to create new entry, but with duplicated value.
Laravel itself has updateOrCreate(): https://laravel.com/docs/8.x/eloquent#upserts in its Eloquent. Is Eloquent in Lumen somehow crippled on this function?
When looking through the code of Laravel or Lumen, I cannot find this function implemented, the closest is updateOrFail()...

User::updateOrCreate(
[
'username' => $user->username,
'foreign_id' => $user->foreign_id
],
[
'email' => $user->email,
'password' => $user->password,
'client_id' => $user->client_id,
'status' => $user->active,
'user_level' => (integer) $user->user_level
])
// first array must contains all the primary/composite keys which makes the it a unique records

Related

Laravel 8.x - Storing data with Eloquent Relationship

I've got a User model that hasOne Membership model, with a users table and a memberships table (each entry in the memberships table has a foreign key linked to a user_id).
I've made a registration page that lets the user have a 7 days trial period on the membership but I'm having trouble storing the data.
This is the dd() of the data in the registration form:
"_token" => "ckRlMligEyTwu7ssOi4TmesycbsPpVQlrJ4jQaBd"
"username" => "JaneDoe"
"password" => "password"
"password_confirmation" => "password"
"expiration" => "2021-04-30"
Now in my controller I've got the following store() method:
public function store(Request $request) {
// validating
$this->validate($request, [
'username' => ['required', 'max:200'],
'password' => 'required|confirmed',
'expiration' => 'required'
]);
// storing
User::create([
'username' => $request->username,
'password' => Hash::make($request->password),
'expiration' => $request->expiration
]);
}
This won't store anything in the memberships table and I have no idea how to correctly write the store method using the Model's Eloquent Relationships declared.
Thanks for the help.
EDIT:
While trying to make some sense i've modified the store() function, now looks like this:
public function store(Request $request) {
// validating
$this->validate($request, [
'username' => ['required', 'max:200'],
'password' => 'required|confirmed',
'expiration' => 'required'
]);
// storing
User::create([
'username' => $request->username,
'password' => Hash::make($request->password)
])->membership(Membership::create([
'expiration' => $request->expiration
]));
}
Now seems like Laravel doesn't know where to get the user_id of the newly created user, like the error suggests:
SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into `memberships` (`expiration`, `updated_at`, `created_at`)
Your solution is to do:
User::create([
'username' => $request->username,
'password' => Hash::make($request->password)
])->membership()->create([
'expiration' => $request->expiration
]);
Using the relation (membership() not membership as an attribute) will already know the relation key (user_id in this case).
You can see more info about this in the documentation.
Other way of doing same is:
$membership = new Membership([
'expiration' => $request->expiration
]);
User::create([
'username' => $request->username,
'password' => Hash::make($request->password)
])->membership()->save($membership);
More info about save() on the documentation.

how to get last inserted id in laravel 5.4

I am new to laravel and try to add record in db. record is successfully inserted but now i need to getLast inserted id.
Insert record array here:
User::insert(
[
'first_name' => $data->first_name,
'last_name' => $data->last_name,
'email' => $data->signup_email,
'contact' => $data->signup_contact,
'role_id' => $data->role_id,
'password' => bcrypt($data->password_contact),
'confirm_passsword'=>bcrypt($data->confirmpassword_contact),
'created_at' => date('Y-m-d'),
'updated_at' => date('Y-m-d'),
]
);
Thanks to all for any help.
Just replace "insert" with "insertGetId". Thats it.

Insert record Many to Many relation in laravel at same time

I have three tables users,roles and role_user I want to insert record on that tables with minimum query using eloquent. My current code of insertation
User::create([
'name' => 'admin',
'email' => 'admin#test.pk',
'password' => bcrypt('admin123'),
]);
//create default roles while installation of application
$roles = array(
array('name' => 'admin', 'display_name' => 'Administrator User', 'description' => 'system admin user'),
array('name' => 'registered', 'display_name' => 'Registered User', 'description' => 'free user')
);
foreach ($roles as $key => $role)
{
Role::create($role);
}
//relation between users and roles
User::find(1)->roles()->attach(1);
In above code i am creating a user then creating two roles then inserting record in pivot table(role_user). I want to know is there any otherway that i insert the record on these table at same time with one eloquent query Or there is anyother better way?
Unfortunately it is not possible to insert rows in more than one table at the same time.
Best what I can think of is that:
$user = User::create([
'name' => 'admin',
'email' => 'admin#test.pk',
'password' => bcrypt('admin123'),
]);
//create default roles while installation of application
$roles = [
['name' => 'admin', 'display_name' => 'Administrator User', 'description' => 'system admin user'],
['name' => 'registered', 'display_name' => 'Registered User', 'description' => 'free user']
];
Role::insert($roles);
//relation between users and roles
$user->roles()->attach(1);
With this example You save two queries:
Laravel calls only one insert query, instead of two when inserting roles;
Laravel does not select User from database - using variable instead;

Laravel, phpunit fails due to empty foreign key

I'm getting this error while running a phpunit test:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'profile_id' cannot be null (SQL: insert into `comments` (`description`, `status`, `profile_id`, `project_id`, `updated_at`, `created_at`) values (Awesome Comment, active, , 21, 2016-01-29 00:05:21, 2016-01-29 00:05:21))
As you can see it is sending an empty id for the profile_id and I'm creating the profile before creating the comment. Here is the code of my test:
public function testProjectCommentCreation()
{
$category = factory(\App\Category::class)->create();
$category->projects()->save(factory(\App\Project::class)->make());
$profile = factory(\App\Profile::class)->make([
'name' => 'John',
'last_name' => 'Snow',
'skills' => 'php'
]);
$category->projects[0]->comments()->save(factory(\App\Comment::class)->make([
'description'=>'Awesome Comment',
'status'=>'active',
'profile_id'=>$profile->id
]));
$this->post(route('api.projects.comments.store', ["projects" => $category->projects[0]->id]), $category->projects[0]->comments->jsonSerialize(), $this->jsonHeaders)
->seeInDatabase('comments', ['project_id' => $category->projects[0]->id])
->assertResponseOk();
}
A Project belongs to a Category and a Comment belongs to a Project and a Profile, so I need to send both foreign keys values profile_id and project_id, the problem is that I'm not sure how to retrieve the id of the profile I created.
These are the factories I use:
$factory->define(App\Profile::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'last_name' => $faker->name,
'status' => 'active',
'avatar' => str_random(10),
'skills'=> str_random(10),
'notifications'=>'on'
];
});
$factory->define(App\Comment::class, function (Faker\Generator $faker) {
return [
'description' => str_random(10),
'status' => 'active',
'profile_id' => 1,
'project_id' => 1
];});
$factory->define(App\Category::class, function (Faker\Generator $faker) {
return [
'description' => str_random(10),
'status' => 'active'
];});
$factory->define(App\Project::class, function (Faker\Generator $faker) {
return [
'description' => str_random(10),
'status' => 'active',
'privacy' => 'false'
];});
I've tested the construction of each type of Object and it is working, what I'm failing is to create a Comment since I need to create a Profile first and retrieve the id and for some reason using $profile->id is pulling null
The problem is that your profile is not saved to the database, when using make().
For you to be able to use/assign the foreign key profile_id from $profile, you need to create() the factory model, and not just make() it.
$profile = factory(\App\Profile::class)->create([
'name' => 'John',
'last_name' => 'Snow',
'skills' => 'php'
]);
That should do the trick.

Create record with Relation Laravel 5.1

Hi i have the next code for create my records
Institution::create($request->all());
User::create([
'name' => $request['name'],
'lastname' => $request['lastname'],
'phone' => $request['phone'],
'email' => $request['email'],
'password' => $request['password'],
'state' => 1,
'profile_id' => 1,
'institution_id' => Institution::max('id'),
]);
The last attributes for the User thats correct implement so?
The last 3 user attributes , it is correct to do it that way? or is there a better
Using Institution::max('id') creates a race condition. Since the create() static method of Eloquent::Model returns the newly-created model, you can just do:
$institution = Institution::create($request->all());
User::create([
'name' => $request['name'],
'lastname' => $request['lastname'],
'phone' => $request['phone'],
'email' => $request['email'],
'password' => $request['password'],
'state_id' => 1,
'profile_id' => 1,
'institution_id' => $institution->id,
]);
Creating a record with known parent ids is generally fine if your goal is to minimize the number of database queries and you have the ids of the related models.
Another way to do it, though it triggers more update queries, is to use Eloquent's built-in methods for adding related models. For example:
$institution = Institution::create($request->all());
$state = State::find(1);
$profile = Profile::find(1);
$user = new User([
'name' => $request['name'],
'lastname' => $request['lastname'],
'phone' => $request['phone'],
'email' => $request['email'],
'password' => $request['password']
]);
$user->state()->associate($state);
$user->profile()->associate($profile);
$user->profile()->associate($institution);
$user->save();
However, in this situation, since the related models are not already loaded, and you know their ids, there is no need to fetch them only to associate them with the User.

Categories