Laravel UpdateOR Create not work with relationship - laravel

I want to update my related table on laravel 5.4
my code
$id = $request->id;
$find = Presal::find($id);
$find->user_id = $request->customer_id;
$find->proposalid = $request->proposalid;
$psal = $find->save();
if ($psal) {
foreach ($request->service_item_id as $key => $n) {
$find->proposalService()->updateOrCreate([
'service_item_id' => $request->service_item_id[$key],
'start_date' => $request->start_date[$key],
'end_date' => $request->end_date[$key],
'service_type_id' => $request->service_type_id[$key],
'vendor_submit' => $request->vendor_submit[$key],
]);
}
}
Here always my code create a new row in proposalService but not update.
How can I make create if new and Update if exist.

updateOrCreate() takes 2 arguments (2 arrays). First array, you pass the element you want to check, usually the primary key and some other element. It then checks if those elements exist, else, create a new one.
$find->proposalService()->updateOrCreate(
[
'service_item_id' => $request->service_item_id[$key],
'service_type_id' => $request->service_type_id[$key]
],
[
'start_date' => $request->start_date[$key],
'end_date' => $request->end_date[$key],
'vendor_submit' => $request->vendor_submit[$key]
]
);
Here I used service_item_id and service_type_id as first argument to check if they already exist.

Related

Laravel Validating An Array in Update Method unique filter

I am new to Laravel. I try to validate an array in Laravel 9.
for using a unique filter I have a problem.
at first, I try to use this way
$rules = [
'*.id' => 'integer|required',
'*.key' => 'string|unique.settings|max:255|required',
'*.value' => 'array|nullable|max:255',
];
For the Create method, this works, but for updating, the logic is wrong. I need to ignore the current field.
for the update, I try to use this way
private function update(): array
{
foreach ($this->request->all() as $keys => $values) {
// dd($values['id']);
$rules[$keys .'.id' ] = 'integer|required';
$rules[$keys .'.key'] = ['string|max:255|required', Rule::unique('settings', 'key')->ignore($values['id'])];
$rules[$keys .'.value'] = 'array|nullable|max:255';
}
// dd($rules);
return $rules;
}
I got this error
BadMethodCallException: Method Illuminate\Validation\Validator::validateString|max does not exist. in file /Users/mortezashabani/code/accounting/vendor/laravel/framework/src/Illuminate/Validation/Validator.php on line 1534
how can I validate an array in the update method in Laravel 9?
PS: without Rule::unique('settings','key')->ignore($values['id'])] all filter is works without any problem
hello you can try this code in your function
$validated = $request->validate([
'id' => 'required',
'key' => 'string|unique.settings|max:255|required',
'value' => 'array|nullable|max:255',
]);

Pass array into a single column in Laravel

i am trying to pass some values into a single column in laravel database table.
The values are like this 20,45,67,89
but i want them to enter into the colume like this
===USER_ID====
20
45
67
89
I have tried like below, but not working..any suggestions ?
foreach ($request->val2 as $value){
$str_explode = explode(",",$value);
DB::table('retirement')->insertGetId([
'user_id' => $str_explode,
'amount' => $request->val1,
'week' => $request->week
]);
}
Hope this will work
foreach ($request->val2 as $value){
$str_explode = explode(",",$value);
$insert = [];
foreach($str_explode as $str){
$insert[] = [
'user_id' => $str,
'amount' => $request->val1,
'week' => $request->week
];
}
DB::table('retirement')->insert($insert);
I'm not sure i understood your question clearly, i'm assuming you want to insert array to a column:
did you try to set the column in migration to Json?
did you set the $casts in the model to json or array?
protected $casts = [ 'user_id' => 'array' ];
then when you do this, you can have an array added to that column like
Posts::create(['user_id'=>[1,2,3,4]]);
normally the user_id field is set to unsignedBigInt(), that type will not accept anything but integers, you gotta check the migration column type first.
explode() is returning an array, not a single value, that's why it will fail. Instead, you should loop through all values like this:
foreach ($request->val2 as $value){
$str_explode = explode(",",$value);
foreach($str_explode as $str){
DB::table('retirement')->insertGetId([
'user_id' => $str,
'amount' => $request->val1,
'week' => $request->week
]);
}
}
As a side advice, as you are not saving the id returned by insertGetID, you can simply use insert. Moreover, it's usually a good practice to use create because this way you will also save timestamps for created and updated.

YII2: custom sorting in search model

Please, help me with such a problem:
1) I have default search model of Users.
2) I need a list of users. And first in this list always must be user with login 'admin', and second - with login 'finance', and then all others sorted by id.
My method in UserController
public function actionUsersList() {
$searchModel = new UserSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->renderPartial('users-list', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
As I understood I have to change params of search in this line, to add sort conditions
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
But how exactly can I do this?
You can do that by adding following code to your action:
$dataProvider->sort->attributes['id'] = [
'asc' => [
new \yii\db\Expression("FIELD(login, 'finance', 'admin') DESC"),
'id' => SORT_ASC,
],
'desc' => [
new \yii\db\Expression("FIELD(login, 'finance', 'admin') DESC"),
'id' => SORT_DESC,
],
'label' => $searchModel->getAttributeLabel('id'),
];
$dataProvider->sort->defaultOrder = ['id' => SORT_ASC];
The field function returns the position of first parameter among other parameters or 0 if the value is not present among them. So for 'admin' it will return 2, for 'finance' 1 and for others 0. If you order DESC by that you will get the required order.
Other option is to add this definitions for sort into the search method of UserSearch model as suggested in mahsaa's answer. It depenends if you want to use this sorting in different actions.
In UserSearch class, add sort to ActiveDataProvider:
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => [
'login' => SORT_ASC,
'id' => SORT_DESC,
],
]]);
It first sorts by login and then id.

Why stored duplicate rows to table

I have custom query for adding parsed remote posts to table:
foreach ($parsedPosts as $post) {
$hasRemotePostAlready = Post::where('remote_post_id', $post->id)->first();
if(null === $hasRemotePostAlready) {
$data = [
'title' => $post->title,
'description' => $post->description,
'remote_post_id' => $post->id
];
Post::create($data);
}
}
Variable $parsedPosts has more then 3500 posts and when I run my script to add posts then any remote posts duplicated. Why they posts duplicated and why not work my condition:
$hasRemotePostAlready = Post::where('remote_post_id', $post->id)->first();
How I can fix duplicating rows problem in my case?
You can use firstOrCreate or updateOrCreate methods for this case, take a look at the documentation
In your case try this:
$hasRemotePostAlready = Post::firstOrCreate(
[
'remote_post_id' => $post->id // columns to check if record exists
],
[
'title' => $post->title,
'description' => $post->description
]
);

Will Model::updateOrCreate() update a soft-deleted model if the criteria matches?

Let's say I have a model that was soft-deleted and have the following scenario:
// EXISTING soft-deleted Model's properties
$model = [
'id' => 50,
'app_id' => 132435,
'name' => 'Joe Original',
'deleted_at' => '2015-01-01 00:00:00'
];
// Some new properties
$properties = [
'app_id' => 132435,
'name' => 'Joe Updated',
];
Model::updateOrCreate(
['app_id' => $properties['app_id']],
$properties
);
Is Joe Original now Joe Updated?
OR is there a deleted record and a new Joe Updated record?
$variable = YourModel::withTrashed()->updateOrCreate(
['whereAttributes' => $attributes1, 'anotherWhereAttributes' => $attributes2],
[
'createAttributes' => $attributes1,
'createAttributes' => $attributes2,
'createAttributes' => $attributes3,
'deleted_at' => null,
]
);
create a new OR update an exsiting that was soft deleted AND reset the softDelete to NULL
updateOrCreate will look for model with deleted_at equal to NULL so it won't find a soft-deleted model. However, because it won't find it will try to create a new one resulting in duplicates, which is probably not what you need.
BTW, you have an error in your code. Model::updateOrCreate takes array as first argument.
RoleUser::onlyTrashed()->updateOrCreate(
[
'role_id' => $roleId,
'user_id' => $user->id
],
[
'deleted_at' => NULL,
'updated_at' => new \DateTime()
])->restore();
Like this you create a new OR update an exsiting that was soft deleted AND reset the softDelete to NULL
Model::withTrashed()->updateOrCreate([
'foo' => $foo,
'bar' => $bar
], [
'baz' => $baz,
'deleted_at' => NULL
]);
Works as expected (Laravel 5.7) - updates an existing record and "undeletes" it.
I tested the solution by #mathieu-dierckxwith Laravel 5.3 and MySql
If the model to update has no changes (i.e. you are trying to update with the same old values) the updateOrCreate method returns null and the restore() gives a Illegal offset type in isset or empty
I got it working by adding withTrashed so that it will include soft-deleted items when it tries to update or create. Make sure deleted_at is in the fillable array of your model.
$model = UserRole::withTrashed()->updateOrCreate([
'creator_id' => $creator->id,
'user_id' => $user->id,
'role_id' => $role->id,
],[
'deleted_at' => NULL
])->fresh();
try this logic..
foreach ($harga as $key => $value) {
$flight = salesprice::updateOrCreate(
['customerID' => $value['customerID'],'productID' => $value['productID'], 'productCode' => $value['productCode']],
['price' => $value['price']]
);
}
it work for me

Resources