Home > Mobile >  How to format collections to object with arrays using Laravel
How to format collections to object with arrays using Laravel

Time:10-26

Every row in my schedules table has start_time and end_time. I can get and map them by using the code below.

My question is how can I deliver an object with moments as an array of arrays, containing the intervals start_time, end_time of every row I get from my schedules table?

Below is the format I want to achieve, you can see there are two arrays inside of moments they are the two rows that came from my schedules table.

{
    moments: [ 
        [ { hour: 6, minute: 45 }, { hour: 7, minute: 45 }, ],
        [ { hour: 10, minute: 30 }, { hour: 11, minute: 30 }, ]  
    ]
}

Here are my schedules table and sample records.

 ---------- ------------------ ---------------- ------------- 
|    id    |    start_time    |    end_time    |   user_id   |
 ---------- ------------------ ---------------- ------------- 
|    1     |       6:45       |      7:45      |      1      |
|    2     |       10:30      |      11:30     |      1      |
 ---------- ------------------ ---------------- ------------- 

Code

$user = User::find(1);

$schedules = Schedule::select('start_time', 'end_time')
  ->whereBelongsTo($user)
  ->get();

$collection = $schedules->map(function ($time) {
  return [date("g:i", strtotime($time['start_time'])), date("g:i", strtotime($time['end_time']))];
});

$data = $collection->values()->all();

// result
[
  [
    "6:45",
    "7:45",
  ],
  [
    "10:30",
    "11:30",
  ],
]

Q: Why do I need that specific format?

A: Because I will use that on the client side's DateTimePicker to disable time intervals - https://getdatepicker.com/4/Options/#disabledtimeintervals

Client side code

Here I will access the formatted response from my backend by passing it inside JSON.stringify().

const timeIntervalsData = JSON.stringify( { moments: [ 
    [ { hour: 6, minute: 45 }, { hour: 7, minute: 45 }, ],
    [ { hour: 10, minute: 30 }, { hour: 11, minute: 30 }, ]  
  ]
});

let options = {
    format: 'hh:mm A',
    disabledTimeIntervals: JSON.parse(timeIntervalsData)
      .moments
      .map( ([start, end]) => [ moment(start), moment(end) ] )
}

$('.datetimepicker').datetimepicker(options)

CodePudding user response:

Providing my own answer to this question from SO, proving our only ally is ourselves.

in my controller method

$user = User::find(1);
$schedules = Schedule::select('start_time', 'end_time')
    ->whereBelongsTo($user)
    ->get();

$collection = $schedules->map(function ($time) {
    return [
        date("H:i", strtotime($time['start_time'])),
        date("H:i", strtotime($time['end_time'])),
    ];
});

return response()->json([
    'status' => true,
    'time' => $collection->all(),
], 200);

client side

<input type="text" name="time"  required>

// From AJAX response.
const time = data.time

// Format the times into moment.js instances.
const timeIntervalsData = time.map(function(schedule) {
    return [
        moment(schedule[0], 'H:mm'), // Start time
        moment(schedule[1], 'H:mm') // End time
    ]
})

let options = {
    format: 'hh:mm A',
    disabledTimeIntervals: timeIntervalsData
}

$('.datetimepicker').datetimepicker(options)

Hope this helps anyone with the same problem in the future.

CodePudding user response:

You can map over all the items in the collection and then use something like

$collection = collect($schedules)->map(function ($time) {
  // your logic
return [
'hour' => $time->start_time->diff($time->end_time)->format('%H'),
'minute' => $time->start_time->diff($time->end_time)->format('%I'),
],
});

And in your model make sure you cast them to Carbon instances, that makes it easier.

  • Related