Using pluck() helper function in laravel - laravel

I'm building a small application on laravel 5.5 where I'm getting a list of multiple users with there information, from the forms as below format:
{
"name":"Test",
"description":"Test the description",
"users":[
{
"value":"XYZabc123",
"name":"Nitish Kumar",
"email":"nitishkumar#noeticitservices.com"
},
{
"value":"MFnjMdNz2DIzMJJS",
"name":"Rajesh Kumar Sinha",
"email":"rajesh#noeticitservices.com"
}
]
}
I just want to get the value key form the users array via laravel collection something like this:
$userIds = $request->users->pluck('value');
so that I can put them into query:
$user = User::all()->whereIn('unique_id', $userIds);
May be I'm doing most of the things wrong but my main motive is to use laravel collection or helper functions and make a cleaner code for this:
$teamData['name'] = $request->name;
$teamData['description'] = $request->description;
$teamData['unique_id'] = str_random();
$users = $request->users;
$team = Team::create($teamData);
if($team)
{
$userIds = [];
foreach ($users as $user)
{
$getUser = User::where('unique_id', $user['value'])->get()->first();
$userIds [] = $getUser->id;
}
$team->users()->attach($userIds);
return response()->json(['message' => 'Created Successfully'], 200);
}
return response()->json(['message' => 'Something went wrong'], 500);
I'm still learning collections, any suggestions is appreciated. Thanks

Data that come from $request (form) isn't a collection. It's an array. If you need it to be collection, you should convert it to collection first.
PS. If you have multiple DB actions in single method, It's good to have DB transaction.
\DB::transaction(function () use ($request) {
// convert it to collection
$users = collect($request->users);
$team = Team::create([
'name' => $request->name,
'description' => $request->description,
'unique_id' => str_random(),
]);
$team->users()->attach($users->pluck('value')->toArray());
});
// HTTP Created is 201 not 200
return response()->json(['message' => 'Created Successfully'], 201);
or you'll need something like this:
return \DB::transaction(function () use ($request) {
$users = collect($request->users);
$team = Team::create([
'name' => $request->name,
'description' => $request->description,
'unique_id' => str_random(),
]);
$team->users()->attach($users->pluck('value')->toArray());
return response()->json([
'message' => 'Created Successfully',
'data' => $team,
], 201);
});

I just want to get the value key form the users array via laravel collection
Just use map then:
$userIds = $request->users->map(function($user) {
return $user->value; // or $user['value'] ? not sure if this is an array
});
Edit:
if $request->users is not a collection, make it one before calling map:
$users = collect($request->users);
$userIds = $users->map(function($user) {
return $user->value; // or $user['value'] ? not sure if this is an array
});

Related

Laravel Livewire Dynamic Form Data Not Working

Quite new to Laravel Livewire. I'm trying to create a dynamic form for application but I couldn't quite understand how to attach additional data when storing.
The user selects the instructor(faculty_id), schoolyear(sy) and semester(sem). And new schedule and option to add more rows()
This is from my controller store() method
public function store()
{
$order = Emp_sched::create([
'faculty_id'=>$this->faculty_id,
'sem'=>$this->sem,
'sy'=>$this->sy,
]);
foreach ($this->createScheds as $sched) {
$order=(['corsdes' => $sched['corsdes']],
['c_time' => $sched['c_time']], ['day' => $sched['day']], ['room' => $sched['room']]);
}
return 'Schedules Saved!';
}
You must call Model::create inside loop
public function store()
{
foreach ($this->createScheds as $sched) {
$createArray = array_merge([
'faculty_id' => $this->faculty_id,
'sem' => $this->sem,
'sy' => $this->sy,
],[
'corsdes' => $sched['corsdes'],
'c_time' => $sched['c_time'],
'day' => $sched['day'],
'room' => $sched['room'],
]);
Emp_sched::create($createArray);
}
return 'Schedules Saved!';
}

Laravel : array_push not working in collection->each() iterator

I have grouped collection and I iterate it using each() function.Inside the each function I want to add element to some array.But it is not working.Any idea?
$dataSet1 = [];
$appointments = [
['department' => 'finance', 'product' => 'Chair'],
['department' => 'marketing', 'product' => 'Bookcase'],
['department' => 'finance', 'product' => 'Desk'],
];
$groupData = collect($appointments)->groupBy('department');
$groupData->each(function ($item, $key) {
Log::info($key); //Show correct output in log
array_push($dataSet1, $key); //ERROR
array_push($dataSet1, 'A');//ERROR
});
Laravel version : 8.35.1
You need to pass the array to the function with use:
$groupData->each(function ($item, $key) use (&$dataSet1) {
Log::info($key); //Show correct output in log
array_push($dataSet1, $key); //ERROR
array_push($dataSet1, 'A');//ERROR
});
Pass-by-reference (&) is needed as long as $dataSet1 is not an object instance.

how to perform bulk update with change check in laravel?

I am using laravel, I am using this code in the update function. works fine, but is it possible to save lines of code with bulk insertion?
Example: $product->update($request->all());
But first check if they have sent new data to update.
My Function Update:
public function update(ProductUpdateRequest $request, Product $product)
{
$data = Product::findOrFail($product->id);
$data->category_id = $request->category_id;
$data->name_product = $request->name_product;
$data->description = $request->description;
$data->stock = $request->stock;
$data->price_buy = $request->price_buy;
$data->price_sale = $request->price_sale;
$data->status = $request->status;
if ($data->isDirty()) {
$data->update($request->all());
return response()->json([
'color' => 'green',
'message' => 'CATEGORY EDIT'
]);
} else {
return response()->json([
'color' => 'red',
'message' => 'NO CHANGE DETECTED'
]);
}
}
You can use fill() method to fill the model with data without committing to database. Do the dirty check and then save. Eg:
public function update(ProductUpdateRequest $request, Product $product)
{
$product->fill($request->all()); //no need to use product->find since $product with the id is already injected
if ($product->isDirty()) {
$product->update($request->all()); //or use $product->save(); since model is alraedy filled with new data
return response()->json([
'color' => 'green',
'message' => 'CATEGORY EDIT'
]);
} else {
return response()->json([
'color' => 'red',
'message' => 'NO CHANGE DETECTED'
]);
}
}
Do note that save method actually checks if the model is dirty. So, if you do not want to send custom messages based on whether the model was changed or not, you could just call save() instead of update() without the dirty check.

Additional data in Laravel Resource

I use Laravel resource from the controller:
$data = Project::limit(100)->get();
return response()->json(ProjectResource::collection($data));
I like to pass additional information to the ProjectResource. How it's possible? And how can i access the additional data?
I tried like this:
$data = Project::limit(100)->get();
return response()->json(ProjectResource::collection($data)->additional(['some_id => 1']);
But it's not working.
What's the right way?
I like to access the some_id in the resource like this.
public function toArray($request)
{
return [
'user_id' => $this->id,
'full_name' => $this->full_name,
'project_id' => $this->additional->some_id
];
}
In your controller don't wrap return Resource in response()->json.
Just return ProjectResource.
So like:
$data = Project::limit(100)->get();
return ProjectResource::collection($data)->additional(['some_id => 1']);
Sorry for misunderstanding the question.
I don't think there is an option to pass additional data like this. So you will have to loop over the collection and add this somehow.
One option is to add to resources in AnonymousCollection. For example:
$projectResource = ProjectResource::collection($data);
$projectResource->map(function($i) { $i->some_id = 1; });
return $projectResource;
and then in ProjectResource:
return [
'user_id' => $this->id,
'full_name' => $this->full_name,
'project_id' => $this->when( property_exists($this,'some_id'), function() { return $this->some_id; } ),
];
Or add some_id to project collection befour passing it to ResourceCollection.

Laravel isDirty method mass assignment

My code is saving data of only one field(efirst) if it's changed by the isDirty() method, and it's working correctly. How can I achieve the same result if I have ten fields without writing each field name?
Controller:
public function update(TeacherRequest $request, $id)
{
$teacher = Teacher::find($id);
$teacher->efirst = $request->efirst;
if ($teacher->isDirty()) {
$new_data = $teacher->efirst;
$old_data = $teacher->getOriginal('efirst');
if ($teacher->save()) {
$teacher->update($request->except('qual_id', 'id', 'profile_pic'));
DB::table('teacher_logs')->insert(
[
'user_id' => $user->id,
'teacher_id' => $teacher->id,
'old_value' => $old_data,
'new_value' => $new_data,
]);
}
}
}
If you don't want to write $teacher->field = $request->value; a bunch of times, you may use a loop:
foreach($request->except("_token") AS $field => $value){
$teacher->{$field} = $value;
}
if($teacher->isDirty()){
$new_data = [];
$old_data = [];
foreach($request->except("_token") AS $field => $value){
$new_data[$field] = $value;
$old_data[$field] = $teacher->getOriginal($field);
}
}
Note: You'll need to convert $new_data and $old_data to arrays so you can reference each field and value properly, and do some additional logic on the insert of your teacher_logs table to handle, but that should give you an idea.

Resources