I have small Laravel project working on collection editing. I have eloquent as below.
public function Import(){
$org = LabGroup::get();
return $org;
}
The returned result as below,
[
{
id: 1,
uuid: "491cd440-79d0-11e9-a294-b93a2fd40038",
branch: 0,
name: "productA",
},
{
id: 2,
uuid: "491d0b70-79d0-11e9-aba8-4d9cdb66858f",
branch: 0,
name: "productB",
},
{
id: 3,
uuid: "491d0c20-79d0-11e9-a243-0d208e55c95a",
branch: 0,
name: "productC",
}
]
My need is to change all branch value from 0 to 1. I can do by loop through but I may use other better like 'map' that I'm not familiar. Any advise or guidance would be greatly appreciated, Thanks.
You can use map() in this way:
$org = LabGroup::get();
$org_branch_1 = $org->map(function ($item, $key) {
return [
'id' => $item->id,
'uuid' => $item->uuid,
'branch' => 1,
'name' => $item->name,
];
});
return $org_branch_1;
If you don't need the original collection you can use transform() in the same way:
$org = LabGroup::get();
return $org->transform(function ($item, $key) {
return [
'id' => $item->id,
'uuid' => $item->uuid,
'branch' => 1,
'name' => $item->name,
];
});
EDIT:
This will work too:
return LabGroup::get()->transform(function ($item, $key) {
$item->branch = 1;
return $item;
});
You can use eloquent update() method on your query:
$updatedOrg = LabGroup::get()->update(['branch' => 1]);
return $updatedOrg; \\Returns the result with the updated branch value.
Related
I have a small response from db model, and i colud rebase it and response in route, but i see error.
My Controller:
class PostController extends Controller {
public function getLastRecord() {
$lastRec = Post::latest('created_at')->first();
$res = [];
$res = collect($lastRec)->map(function($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
return $res;
}
}
I want that response will be array
['id': 1, 'rec_name': 'test_name', 'user': 1]
instead names from db
['post_id': 1, 'post_name': 'test_name', 'user_id': 1]
Error:
Attempt to read property "post_id" on int
When you collect() a single Record, then call ->map() (or other iterative methods), it loops over your Model's columns, not multiple Post records. You can solve this by wrapping $lastRec in an array, or using ->get() instead of ->first():
$lastRec = Post::latest('created_at')->first();
return collect([$lastRec])->map(function($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
// OR
$lastRecs = Post::latest('created_at')->get();
return $lastRecs->map(function ($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
Or, since this is a single record (using ->first() only ever returns 1 record), you don't need to collect() or map() at all:
$lastRec = Post::latest('created_at')->first();
return [
'id' => $lastRec->post_id,
'rec_name' => $lastRec->post_name,
'user' => $lastRec->user_id
];
Hello im new to PHPUnit with minimum knowledge in laravel.
Im trying to test this method that mass create student section
public function setStudentsSection(Request $request)
{
$enrollments = Enrollment::whereIn('student_id', $request->students)->where('session_id', $request->session_id)->get();
$program_section = ProgramSection::withCount('students')->find($request->program_section_id);
if(($program_section->students_count + count($enrollments)) <= $program_section->max_students) {
foreach($enrollments as $enrollment) {
$response = StudentSection::create([
'student_id' => $enrollment->student_id,
'enrollment_id' => $enrollment->id,
'section_id' => $request->program_section_id,
'created_at' => Carbon::now()
]);
return $response;
}
}
return response()->json(['errors' => ['message' => 'Selected Section is full.']], 405);
}
UPDATE
Here's the test case. Im trying to match the method that i've modified with my test, but im failing to do so.
public function testCanMassAssignSection()
{
$sectioning_data = $this->setMassSectioning(10);
$this->json('POST', 'api/enrollments/set-students-section', $sectioning_data['data'])
->assertStatus(201);
$student_section_data = ['student_id' => $sectioning_data['student_ids'], 'section_id' => $sectioning_data['program_section']->id];
$this->assertDatabaseHas('student.sections', $student_section_data);
}
private function setMassSectioning($max_students)
{
$session = Session::factory()->create();
$program_section = ProgramSection::factory()->create(['session_id' => $session->id, 'max_students' => $max_students]);
$enrollments = Enrollment::factory(['session_id' => $session->id])->count(3)->create();
$student_ids = array();
foreach($enrollments as $enrollment) {
array_push($student_ids, $enrollment->student_id);
}
return [
'data' => ['program_section_id' => $program_section->id, 'session_id' => $session->id, 'students' => $student_ids],
'student_ids' => $enrollment->student_id,
'program_section' => $program_section
];
}
UPDATE
Here's the error the i get.
1) Test\Feature\EnrollmentTest::testCanMassAssignSection
Failed asserting that a row in the table [student.sections] matches the attributes {
"student_id": 2765,
"section_id": 1649
}.
Found: [
{
"id": 262,
"student_id": 2763,
"section_id": 1649,
"created_at": "2022-08-24 09:32:05",
"updated_at": "2022-08-24 09:32:05",
"enrollment_id": 1740
}
].
Still can't make it to match. I do not know what im doing wrong.
Solve! I just create $student data and added to $enrollments now assert in database match. Although don't know what exactly is happening on the background.
I think when i added to enrollments variable the 'student_id' => $student->id it creates those 3 records.
private function setMassSectioning($max_students)
{
$session = Session::factory()->create();
$student = Student::factory()->create();
$program_section = ProgramSection::factory()->create(['session_id' => $session->id, 'max_students' => $max_students]);
$enrollments = Enrollment::factory(['session_id' => $session->id, 'student_id' => $student->id])->count(3)->create();
$student_ids = array();
foreach($enrollments as $enrollment) {
array_push($student_ids, $enrollment->student_id);
}
return [
'data' => ['program_section_id' => $program_section->id, 'session_id' => $session->id, 'students' => $student_ids],
'student_ids' => $enrollment->student_id,
'program_section' => $program_section
];
}
Hi all you smart individuals i'm hitting a solid wall here with someone else code that i'm trying to fix a issue.
The issue is that when this query builder has got all the results there seems to be some coming back with null values and i'm not sure how to remove them before I paginate the data, I know how to do it if it was a collection however maybe some of you might be-able to help me.
so currently the logic goes into this pagination
$return = $tld->paginate($request->get('limit'))->toArray();
$tld being the eloquent builder.
Which then gets sent into this function that was created..
$return = $this->makePagination($return);
public function makePagination($object = [], $filters = []) {
return [
'data' => [
'items' => $object['data'],
'pagination' => [
'from' => $object['from'],
'to' => $object['to'],
'total' => $object['total'],
'per_page' => $object['per_page'],
'first_page' => [
'number' => 1,
'url' => $object['first_page_url']
],
'last_page' => [
'number' => $object['last_page'],
'url' => $object['last_page_url']
],
'next_page' => [
'number' => $object['current_page'] + 1,
'url' => $object['next_page_url']
],
'prev_page' => [
'number' => $object['current_page'] - 1,
'url' => $object['prev_page_url']
]
],
'params' => $filters
]
];
}
But then i'm getting a response like this with Null values and I would like to remove them before any of this pagination happens
{
"data": {
"items": [
{
"id": 13771,
},
null,
{
"id": 4125,
},
Side note if I run $tld->get() I can see all the results and there are null values in there so if anyone can show me how to remove the null values that would be a great help <3 you all if you can help me ...
Update
Ive also tried $tld->get()->filter(); and thats also not removing the null values I still get this response
[
{
"id": 13771,
},
null,
{
"id": 789,
}
]
I think I fixed it with a little hack
$filtered = collect(array_values(array_filter($tld->get()->toArray())));
return $this->paginate($filtered, $request->get('limit') ?? 15 , $page = null, $options = []);
and then created a collection paginator
public function paginate($items, $perPage = 15, $page = null, $options = [])
{
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
#Bob Hiller Please use whereNotNull in query to remove null entries.
$tld=$query->get();
$tld->filter(function ($value) { return !is_null($value); });
$return = $tld->paginate($request->get('limit'))->toArray();
I have a ManyToMany relationship setup but need to specify a value for the key in my array to attach.
$data = request()->validate([
'homework_title' => '', // string
'homework_description' => '', // string
'group_id' => '', // array
]);
$homework = request()->user()->homeworks()->create([
'homework_title' => $data['homework_title'],
'homework_description' => $data['homework_description'],
]);
$homework->groups()->attach($data['group_id'][key]);
group_id is an array and looks like the following:
[
{
"group_id": 1,
"group_name": "8x/En2"
},
{
"group_id": 2,
"group_name": "9x/En3"
}
]
How do I specify to attach only the group_id in array?
Got it to work, with:
Arr::pluck()
First time round I forgot to import the class (stupid me)!
use Illuminate\Support\Arr;
finally looking like the following:
$homework->groups()->attach(Arr::pluck($data['group_id'], 'group_id'));
How would one do the following elegantly with laravel collections ?
Map the values of the $baseMap as keys to the collection.
The baseMap :
$baseMap = [
'name' => 'new_name',
'year' => 'new_year',
];
The collection :
$items = collect([
[
'name' => 'name1',
'year' => '1000',
'not_in_basemap' => 'foo'
],
[
'name' => 'name2',
'year' => '2000',
'not_in_basemap' => 'foo'
],
//...
]);
The end result :
$result =[
[
'new_name' => 'name1',
'new_year' => '1000',
],
[
'new_name'=> 'name2',
'new_year' => '2000',
],
];
I know how to do it in plain php , just wondering what a nice collection version would be. Thanks!
I tried to find collection methods, or php functions, but without success. Some dirty code that works with different keys from both sides (items and basemap).
$result = $items->map(function($item) use ($baseMap) {
$array = [];
foreach($baseMap as $oldKey => $newKey){
if(isset($item[$oldKey])){
$array[$newKey] = $item[$oldKey];
}
}
return $array;
});
$result = $result->toArray();
Thanks to #vivek_23 and #IndianCoding for giving me idea's I ended up with the following :
I made a small edit to make sure the mapping and the items keys lined up.
so you don't have to worry of misalignment and all in laravel collection !
$baseMap = collect($baseMap)->sortKeys();
$result = $items->map(function ($item) use ($baseMap) {
return $baseMap->values()
->combine(
collect($item)->sortKeys()->intersectByKeys($baseMap)
)
->all();
});
Use intersectByKeys to filter your baseMap keys with $items values.
$result = $items->map(function($item,$key) use ($baseMap){
return array_combine(array_values($baseMap),collect($item)->intersectByKeys($baseMap)->all());
});
dd($result);
Update:
In a pure collection way,
$baseMapCollect = collect($baseMap);
$result = $items->map(function($item,$key) use ($baseMapCollect){
return $baseMapCollect->values()->combine(collect($item)->intersectByKeys($baseMapCollect->all())->values())->all();
});
dd($result);
Here are my two cents, using map. Don't know how dynamic your collection should be, but knowing the keys I would do the following:
$baseMap = [
'name' => 'new_name',
'year' => 'new_year',
];
$items = collect([
[
'name' => 'name1',
'year' => '1000',
'not_in_basemap' => 'foo'
],
[
'name' => 'name2',
'year' => '2000',
'not_in_basemap' => 'foo'
],
])->map(function($item, $key) use ($baseMap) {
return [
$baseMap['name'] => $item['name'],
$baseMap['year'] => $item['year']
];
});