Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ollie_123's avatar

Recurring Events With Task

Hi All

I have created a form that allows the user to create a task with a recurring event i.e weekly, monthly etc, however i'm having a bit of trouble in submitting on the events side when trying to create the recurring event,

I have a tasks table that hasMany('App\Event') and an events table that belongsTo('App\Task').

Upon submission the task submits but then falls over at the events part with an error of undefined index times.

Ultimately I dont think this is the best way of doing things as it doesn't account for any leap years and i havent figured out how to add the number of days on from the event (i.e if its weekly add 7 days). If someone could advise a better way to do this it would be much appreciated.

//TaskController
....
$newTask = \App\Task::create($form_data); 

        $recurrences = [
            'daily'     => [
                'times'     => 365,
            ],
            'weekly'    => [
                'times'     => 52,
            ],
            'monthly'    => [
                'times'     => 12,
            ]
        ];

        $event = array(
            'task_id'        => $newTask->id,
            'customer_id'   => $request->customer_id,
            'start_time'    => $request->start,
            'end_time'      => $request->end,
            'recurrence'    => $request->recurrence,
        );
        for($i = 0; $i < $recurrences['times']; $i++)
        {
            \App\Event::create($event); 
        }

Thank you in advance.

0 likes
43 replies
ollie_123's avatar

Hi @tinfoilman thanks for your response. i did consider task scheduling but i wasnt sure if it worked for what i was looking to do.

The user that creates the task then assigns that to the relevant person who once completes the task can update the record with "Complete". My thoughts were if i used a database entry for each event then it could be marked as complete once done?

Unless im missing something with scheduling?

tinfoilman's avatar

I see what you're saying now. I was thinking it was an automated task. Sorry.

tinfoilman's avatar

What about using Carbon? You can take the date and add days, or weeks, or months, and it should correct for leap years and all.

ollie_123's avatar

Good shout on carbon. 👍🏻

The bit I’m really stuck on/trying to figure out is how to get that foreach into the db based on the recurrence selected by the user.

Snapey's avatar

You don't have an index 'times' in the recurrences array, it is a child of daily, weekly, monthly.

You may want to consider further the effect of weekdays also?

perhaps you meant to do

for($i = 0; $i < $recurrences[$request->recurrence]['times']; $i++)

assuming $request->recurrence contains one one of 'daily', 'weekly', 'monthly'

ollie_123's avatar

Hey @snapey ah that makes sense. Thanks for pointing out.

Weekdays are currently done in the datetime picker where user selects start date & time and end date and time etc. I will be looking at more complex recurrences soon but just trying to get the form functioning initially.

As above, the bit I’m really stuck on/trying to figure out is how to get that foreach into the events table based on the recurrence selected by the user as I think I’m a bit off In my approach.

Snapey's avatar

I updated the question, but at present you will create multiple events with the same event date. Perhaps you should be incrementing the date on each pass.

ollie_123's avatar

Thanks @snapey, sorry i didn't see that the first time round.

Agreed, i definitely want to be incrementing on each pass but i'm not sure how best to do it. Any help would be much appreciated.

ollie_123's avatar

Hey @snapey. I've tried a few different ways on inserting with the start & finish date incrementing each time but have not had much joy as i am getting the same date on each record inserted X amount of times depending on the frequency chosen.

Please could you advise on where i might be going wrong, or if there is a better way of doing this?

...
$newTask = \App\Task::create($form_data); 

$recurrences = [
            'Daily'     => [
                'times'         => 364,
                'futureStart'   => Carbon::parse($request->start)->addDay(),
                'futureFinish'  => Carbon::parse($request->end)->addDay(),
            ],
            'Weekly'    => [
                'times'         => 51,
                'futureStart'   => Carbon::parse($request->start)->addWeek(),
                'futureFinish'  => Carbon::parse($request->end)->addWeek(),
            ],
            'Monthly'    => [
                'times'         => 11,
                'futureStart'   => Carbon::parse($request->start)->addMonth(),
                'futureFinish'  => Carbon::parse($request->end)->addMonth(),
            ]
        ];
        $event = array(
            'task_id'       => $newTask->id,
            'customer_id'   => $request->customer_id,
            'start_time'    => $request->start,
            'end_time'      => $request->end,
            'recurrence'    => $request->recurrence,
        );
        $newEvent = \App\Event::create($event);
        
        for($i = 0; $i < $recurrences[$request->recurrence]['times']; $i++)
        {
            $futureEvent = array(
                'task_id'       => $newTask->id,
                'customer_id'   => $request->customer_id,
                'start_time'    => $recurrences[$request->recurrence]['futureStart'],
                'end_time'      => $recurrences[$request->recurrence]['futureFinish'],
                'recurrence'    => $request->recurrence,
            );

           \App\Event::create($futureEvent);
        }

Thank you in advance.

Snapey's avatar

You need to addDay() , addWeek() oraddMonth() to the date each iteration of the loop

ollie_123's avatar

Thanks @snapey. I’ve tried a couple of different versions of the above code but can’t figure out how to add the addDay etc iteration to the loop.

Please could you advise on how to go about it.

Thanks in advance.

Snapey's avatar

I knocked this up, but then was waiting for you to say how start and end should behave...

anyway, you might find it useful unfinished

    $recurrence = strtolower($request->recurrence);

    function_exists($this->recurrence) 
        ? $this->$recurrence($newTask) 
        : return;


        private function daily($newTask)
        {   
            $at = now();

            foreach(range(1,365) as $x) {
                $at->addDay();
                $this->createEvent($at,$newTask);  
            }

        }

        private function weekly($newTask)
        {
            $at = now();

            foreach (range(1, 52) as $x) {
                $at->addDays(7);
                $this->createEvent($at, $newTask);
            }

        }

        private function monthly($newTask)
        {
            $at = now();

            foreach (range(1, 12) as $x) {
                $at->addMonth();
                $this->createEvent($at, $newTask);
            }

        }

        private function createEvent($at,$newTask)
        {
            App\Event::create([
                'task_id'       => $newTask->id,
                'customer_id'   => request()->customer_id,
                'start_time'    => $at,
                'end_time'      => $at,
                'recurrence'    => request()->recurrence,
            ]);

        }
ollie_123's avatar

Hey @snapey sorry i missed the notification that you had responded. Thank you for helping with the code.

As for your question, the start is the beginning of the task (datetime) and the end is the completion of the task (datetime), like a calendar schedule to complete tasks.

In regards to your code, would that all go inside of the model? and then i call the function from the controller? Not done schedules before so this is all new to me lol.

If it makes a helps at all, i've dropped the event table and concatenated tasks/events into one table.

This is where i'm currently at, not too dissimilar from my original post but wasnt sure on how to apply what you had suggested to mine.

//TaskController

public function store(Request $request)
{
	$recurrences = [
	...
	];

	for($i = 0; $i < $recurrences[$request->recurrence]['times']; $i++)
	{
            $event = array(
                'uuid'          => (string) \Str::uuid(),
                'ref'           => $request->ref,
                'assigned_to'   => $request->assigned_to,
                'start_time'    => $recurrences[$request->recurrence]['futureStart'],
                'end_time'      => $recurrences[$request->recurrence]['futureFinish'],
                'recurrence'    => $request->recurrence,
            );

           $tags = \App\Tag::whereIn('id', $request->tag_id)->get();
   
           $newTask = \App\Task::create($event); 
   
           $newTask->tags()->attach($tags);

        }
	
	return redirect...
}

Thank you in advance

ollie_123's avatar

Hey @snapey please could you advise following my last post.

Thank you in advance.

Snapey's avatar

did you even try to understand my approach?

You didn't explain what values you are expecting for start and end

ollie_123's avatar

Hey @snapey i did try and i followed up with a question as i wasn't completely sure where it fit in. Also i explained the values in my last post?...

The "start" field is the beginning of the task (datetime) and the end is the completion of the task (datetime), like a calendar schedule to complete tasks.

For instance, an example would be calling someone every month but have a recurring entry. i would like to insert the "start" value from the date time field and then depending on the recurrence selected (lets say monthly) enter an additional 11 x the date but incrementing by a month. i.e

21/07/2020
21/08/2020
21/09/2020
etc...

Sorry if i'm missing something obvious. I just couldn't work out where the code you suggested should go or what i needed to modify to fit it into mine.

Thank you again in advance for your help.

Snapey's avatar

i understood you needed an event at the intervals, daily, weekly or monthly. Within the event there is a start and an end date time. why?

Why not just an event date time? Why does the event need both?

The code I showed replaces your previous code.

You pass in the selected recurrence and it then calls a function with the same name as the recurrence. This sets up the number of events required and the interval between them.

ollie_123's avatar

Thanks @snapey.

The event was what i was calling the task event and not specifically an Event as built into Laravel.

However i get an syntax error, unexpected (T_RETURN) from

        ? $this->$recurrence($newTask) 
        : return;

Also as this is inside the TaskController in a public function store(Request $request) do i just omit the private part of the function from each function that follows? as currently i get a syntax error, unexpected (T_PRIVATE).

Or would it be better to just place the code inside of an actual ('App\Event') and call the event from the controller?

Thanks again.

Snapey's avatar

I don't really understand. You have changed from Event to task?

As I understand it, you want to populate the database with a number of tasks at a specific interval?

So, if the user specifies that the recurrence is monthly then after this store, there should be 12 entries in the database?

ollie_123's avatar

Hey @snapey. Originally i had two separate tables. one was task and the other was event. Event belonged to task and task had many events.

I've changed the structure slightly now to one table so that each task has a start and end date is on the task table as i think i was over complicating it previously.

And yes you're absolutely right, if the user specifies monthly there would be 12 entries in the db (adding a month to each entry). 01/01/2020, 01/02/2020 etc.

Thank you in advance.

Snapey's avatar

so back to the earlier question. We have 12 entries in the database, what are the values for start and end?

ollie_123's avatar

The values would be the task start date inputted by the user in a datetime format

The recurrence (weekly/monthly) which comes from a <select> option

and the end would be the task end date in a datetime format.

Thanks Snapey.

Snapey's avatar

and the end would be the task end date in a datetime format.

How can I show you the code when you cannot explain the requirements.

the end is the end.....

wtf

ollie_123's avatar

Hey @snapey

I'm not sure how else to explain it. Maybe we ignore the end date for now and just focus on the start date.

In my task table i have

id
start_time //datetime format
//end_time //datetime format
recurrence // varchar

The task is created by the user in this case, lets call the task "Call Company A" and he has to call a Company A every week / every month.

I'm looking for when the user creates a task he sets the first task start_date to 26/7/20, and the recurrence to monthly . Then upon submit it populates the database with 26/7/20 and adds a month onto the start of each task so that in the task table it ends up with 12 records each incremented by a month.

Thanks in advance.

Snapey's avatar
Snapey
Best Answer
Level 122

and thats what the code I posted shows.

You call a function that is named the same as the recurrence. That function creates a new task with the $at date set. It controls the number of iterations and the amount the date should be moved on at each iteration.

The createEvent function needs changing now to createTask and use the Task model, but you should be able to manage that?

    $recurrence = strtolower($request->recurrence);

    function_exists($this->recurrence) 
        ? $this->$recurrence($newTask) 
        : return;

$recurrence is the lowercase form of the recurrence field from the form

If there is a function with the same name , ie 'monthly' then call it

The monthly function

        private function monthly($newTask)
        {
            $at = now();

            foreach (range(1, 12) as $x) {
                $at->addMonth();
                $this->createEvent($at, $newTask);
            }

        }

starts with todays date (you can change this if the user is saying the start date) then does 12 iterations

In each iteration it adds a month and then creates the Event (now needs to be changed to task)

Exactly the same principle for days and weeks but with different number of iterations and the date is moved along by a different amount.

ollie_123's avatar

Thanks @snapey. I understand your code however the part that i got stuck on previously is that i get the following error in the TaskController in my public function store()

$recurrence = strtolower($request->recurrence);

    function_exists($this->recurrence) 
        ? $this->$recurrence($newTask) 
        : return; // This causes syntax error

Error: syntax error, unexpected 'return'

Please can you advise?

Next

Please or to participate in this conversation.