I just want to ask why upset method in eloquant ORM we can update records with "Composite" primary keys, and we can not do that with updateOrCreate ? !!! I have a table that users insert and update in most of times and it's not a good idea to have one Primary Key "id" !!
if you are not using the model events you can Mute events for your action to avoid the error.
https://laravel.com/docs/8.x/eloquent#muting-events
ModelName::withoutEvents(function (){
ModelName::updateOrCreate(
[
'id' => 'test',
'second_id' => 0
],
[
'data' => 'some data'
]
);
});
Related
I have this table that contains my site settings:
I would want to update all records at once with data that comes from a form.
The data looks like this:
$data = [
"brand" => "bbb"
"mail" => "kontakt#aaa.pl"
"phone" => "111"
"site-name" => "test"
];
Now I would like to update that with key of the associative array and with it value.
I tried:
DB::table('settings')->update($data);
But there is an error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'brand' in 'field list' (SQL: update `settings` set `brand` = bbb, `mail` = kontakt#aaa.pl, `phone` = 111, `site-name` = test)
Obviously it thinks that brand is a column name.
So I transformed the $data to this array:
$data = [
0 => [
"name" => "brand"
"value" => "bbb"
]
1 => [
"name" => "mail"
"value" => "kontakt#aaa.pl"
]
2 => [
"name" => "phone"
"value" => "111"
]
3 => [
"name" => "site-name"
"value" => "test"
]
];
and now the error is:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '0' in 'field list' (SQL: update `settings` set `0` = {"name":"brand","value":"bbb"}, `1` = {"name":"mail","value":"kontakt#aaa.pl"}, `2` = {"name":"phone","value":"111"}, `3` = {"name":"site-name","value":"test"})
So now it thinks that index of each row in array is column name and at this place i have no idea how to do this...
Can anyone help me please?
I came to this solution although i think it looks ugly and there should be a better way to do this, if no better answers will be given i will mark my answer as correct
$data = [
"brand" => "bbb"
"mail" => "kontakt#aaa.pl"
"phone" => "111"
"site-name" => "test"
];
foreach($data as $key=>$d) {
DB::table('settings')->where('name','=',$key)->update(['value' => $d]);
}
Your table looks something like you can only take a set of data and update it with time. Why because there are no foreign key relations.
if that is the case then why not have brand_name, mail, phone and site_name for settings columns,
Your migrations
public function up()
{
Schema::create('settings', function (Blueprint $table) {
$table->string('brand_name');
$table->string('mail');
$table->string('phone');
$table->string('site_name');
$table->timestamps();
});
}
In your model?
protected $fillable = ['brand_name', 'mail', 'phone', 'site_name'];
or
protected $guarded = [];
In your controller
public function method(Request $request)
{
// You can also abstract this in to a custom request class
$request->validate([
'brand_name' => 'required',
'mail' => 'required',
'phone' => 'required',
'site_name' => 'required',
]);
// Add data if record doesn't exist, update when it does
// To use the validated method on request all needed fields must be required
Settings::updateOrCreate($request->validated())
}
Should in case I was wrong you can still check out Laravel Mass Update
https://laravel.com/docs/8.x/eloquent#mass-updates
Laravel Upserts
https://laravel.com/docs/8.x/eloquent#upserts
You can use upsert to update multiple records
First transform data to add column name using collection
$data=collect($data)->transform(function ($value,$name){
return ["name"=>$name,"value"=>$value];
})->values()->toArray();
and here i used model
Setting::upsert($data,["name"],["value"]);
To understand Upserts
Upsert perform multiple "upserts" in a single query
first argument consists of the values to insert or update
second argument lists the column(s) that uniquely identify records within the associated table.
third and final argument is an array of the columns that should be updated if a matching record already exists in the database.
Also important point
All databases systems except SQL Server require the columns in the
second argument provided to the upsert method to have a "primary" or
"unique" index.
It means in your mysql table settings column name to be unique index or else it will insert as new row
Ref:https://laravel.com/docs/8.x/eloquent#upserts
consider i have 2 models that have the pivot relationship many to many between them . now when i want to insert the pivot table how can i achieve it currently i am doing this :
DB::table('model1_model2')
->insert([
'something' => $something,
'something2' => $something2,
]);
and i kinda feel that its not right and i have do save it with some relation ship or sync !! any idea how to do this ?
EDIT‌:
Added relationship
public function accommodationRoom()
{
return $this->belongsToMany(AccommodationRoom::class)->withPivot('guest_first_name','guest_last_name','guest_cell_phone','guest_nationality_id');
}
As mentioned in the Inserting & Updating Related Models - Many To Many Relationships documentation:
When attaching a relationship to a model, you may also pass an array of additional data to be inserted into the intermediate table:
$model1->accommodationRoom()->attach($accommodationRoomId, [
'something' => $something,
'something2' => $something2,
]);
If you're attaching multiple relations then you would would pass a multidimensional array with the keys are the id of the relation and the values are the arrays of additional data:
$model1->accommodationRoom()->attach( [
1 => ['something' => $something, 'something2' => $something2,],
3 => ['something' => 'something else', 'something2' => $something2,],
]);
The same is true for the sync() method as well.
I have these tables currently:
User table
id (primary key), name, email
User Model
protected $fillable = ['name', 'email'];
protected $visible = ['id','name','email'];
//Relationship
public function customAttributes()
{
return $this->hasMany('App\Models\UserAttribute');
}
UserAttribute Table
user_id, attribute_id, value //user_id and attribute_id is a composite key, both foreignkeys acting as primary keys establishing an unique combination
UserAttribute Model
protected $fillable = ['user_id', 'attribute_id','value'];
protected $visible = ['user_id', 'attribute_id','value'];
I'll use the following example to explain the issue:
$user = $this->user->create(['name' => 'admin', 'email' => 'admin#admin.com']);
//This works
$user->customAttributes()->save(new \App\Models\UserAttribute(['user_id' => $user->id, 'attribute_id' => 1, 'value' => 'Just a custom1']));
//This does not work
$user->customAttributes()->create([new \App\Models\UserAttribute(['user_id' => $user->id, 'attribute_id' => 1, 'value' => 'Just a custom1'])]);
I could just repeat the save for every custom that I want since it works, but I'm trying to figure out why create doesn't work.
The error I'm getting when I use create is (and yes, I've checked the record exists in the table that isn't listed here):
Cannot add or update a child row: a foreign key constraint fails (`testdatabase`.`user_attributes`,
CONSTRAINT `user_attributes_attribute_id_foreign` FOREIGN KEY (`attribute_id`) REFERENCES `attributes` (`id`))
This is the query it's trying to execute:
insert into `user_attributes` (`user_id`) values (1)
I'm just curious at why this doesn't work with create, I'm not sure if it's something related to this specific scenario (create to a composite key table by relationship). It's somewhat ignoring the value and attribute_id field in the query that is executing
try this:
$user->customAttributes()->create(['user_id' => $user->id, 'attribute_id' => 1, 'value' => 'Just a custom1']);
customAttributes() already returns you instance of UserAttribute model, you don't need to enject that dependency when you use create() method via that relation
your query should be like below;
$user->customAttributes()->insert([
[
'user_id' => $user->id,
'attribute_id' => 1,
'value' => 'Just a custom1'
],
[
'user_id' => $user->id,
'attribute_id' => 2,
'value' => 'Just a custom2'
],
]);
I want to update data using 'typeId', 'type_id' is not a primary key.
While this code is work, if we use other primary key.
Unable to update record.
getting following error :
{"__type":"com.amazon.coral.validate#ValidationException","message":"The provided key element does not match the schema"}
$response = $this->dbo->updateItem([
'TableName' => $this->tableName,
'Key' => [
'typeId' => ['S' => "qtwr234"]
],
'ExpressionAttributeValues' => [
':val1' => ['N' => '1']
],
'UpdateExpression' => 'set count = :val1',
'ReturnValues' => 'ALL_NEW'
]);
According the error message you're receiving
This error occurs when your key (hash / primary key) doesn't not match in parameters your passing to update the data in table.
Solution :
Run listTables commands and check for key element you created while creating elements.
Now, replace that key element in query parameters.
Thanks
I am facing a problem in Laravel 5.3 that I looked the docs and also searched web but didn't find anything on it.
I am using Laravel Relationships to join two tables. Now I want the data to be inserted on both the tables at the same time after the user submits a form. The catch in this is the first table is the primary one say "users" and second one "xyz" belongsTo the first table. The table "xyz" contains "users_id" column that connects both the tables. And obviously "users_id" is the "id" column of "users" table.
Now the problem arriving is that I want to insert the data in "users" table (that is easily done) and "xyz" table at the same time. The User::create() function will create the user data easily and it is working also but for inserting the data in "xyz" table I will be needing the "user_id" column data and ID will not be generated until the user is created as ID column has Auto-Increment attribute activated.
Code:
$user = new User;
$inputArry = array('data1' => $request['field1'],
'data2' => $request['field2'],
'data3' => $request['field3'],
);
$user->create($inputArry);
$user->xyz()->create([
'user_id' => $user->id,
'name' => $request['name'],
'about' => $request['desc'],
'tag' => $request['tag'],
]);
Above is the code that I am using for this purpose but it is giving me a error.
Error:
QueryException in Connection.php line 761:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'soft_id' cannot be null (SQL: insert into `xyz` (`user_id`, `name`, `about`, `tag`, `updated_at`, `created_at`) values (, John, I am John, dev, 2016-11-09 21:01:29, 2016-11-09 21:01:29))
One way of inserting related table is using relations as:
$user = User::create($user_inputs);
$xyz = $user->xyz()->create($xyz_inputs);
It will automatically fills the user_id in the xyz table.
If you need insert many items, use createMany or saveMany method.
For example:
$post = App\Post::find(1);
$post->comments()->createMany([
[
'message' => 'A new comment.',
],
[
'message' => 'Another new comment.',
],
]);
In the offical laravel docs:
https://laravel.com/docs/5.6/eloquent-relationships#inserting-and-updating-related-models
You can create them like this instead of saving them on same time...
$id = User::create($input_arr)->id;
Xyz::create([
'user_id' => $id,
...
]);