Scheduling ElePHPants (DateTime math is HARD)

      No Comments on Scheduling ElePHPants (DateTime math is HARD)

1200401259_aff9b29113_mIt was while I was creating the 100th or so cronjob to do some very similar to the other 99 that I thought, “Hey! Why not just put all this in a database and check it once a minute instead?” I mean c’mon, working with MySQL is soooooo much easier than working with cron. Besides, a lot of these jobs are “sit and wait a random amount of time before doing something” type of jobs. It would be so much easier to deal with in PHP. Also, cron does not scale well at all either in performance or management.

The problem is that cron is an elegant solution for “Do this at that time” type of problems. Every solution I came up with was basically re-creating cron. That in itself isn’t a bad thing, but the logic involved in doing what cron does is mind-melting. In mapping out the decision tree alone, I was indenting so many levels that I could feel Rafael Dohms queuing up to slap me.

Then it hit me, I am probably not the first person that has had this need. There have probably been other people who needed to implement “Do this at that time” within a PHP application. So I started looking around. What I found was encouraging. Yes, there were a lot of solutions out there that do what I need to do. Both Google and Packagist returned a solid number of prospects. However, after whittling them down using my own convoluted criteria that included things like “has it been updated this year” I settled on two candidates, Laravel Task Scheduling, and cron-expression.

Honorable Mention

Both of these solutions fit all the criteria I needed. In the end, the Laravel solution lost because I was already well down the road of developing my API using Slim Framework. If I had not already started coding, I would have probably selected Laravel Task Scheduling. As it was, it was not clear how much of Lumen I would have to bring into my project to get this one piece. I did not want two complete frameworks installed in this project if I could help it.

The one I selected

The other problem I had with Laravel Task Scheduling was that i really only wanted something to handle the scheduling. I already had my logical unit of work defined – the task that needed to be completed – and I didn’t want to have to rebuild it. Thankfully, that is all that cron-expression brings to the table. It literally takes a string that is the first 5 arguments of a cron task and parses them. it will tell you if it’s due to run, it will tell you when it will run next and when it ran last.

Most of the solutions I threw out, I did so because they were either unmaintained or they did too much. cron-expression is a discrete piece of code that does a single test.

Really, the only problem I ran into was the almost nonexistent documentation. The Readme on the project gives you the basics but the examples are pretty simple and not always useful. Thankfully, Michael Dowling, the author, wrote a great article about WHY he built it and also shows a lot of examples on HOW to use it. If you are going to use this code, make sure you read “Cron Expression Parsing in PHP”. Not only is Michael a good writer, it is very informative.


If you are looking for “Do this at that time” there are a lot of PHP based solutions available for you. If you are early enough in your design process to make framework choices, look seriously at the larval solution, although there are others that are framework agnostic also.

Side Note

I ad spent countless hours trying to create the solution myself. Since everything I was working with will be inside a MySQL database, I envisioned a convoluted and ultimately beautiful SQL statement that would do all of the calculations for me and tell me exactly when something was to run. I got so lost in solving the problem, I forgot to look to see if someone had already solved it.

After I finally came to my senses, I tweeted that out to remind myself to “Use the Source”.

Photo Credit: The hi-tech scheduling board By Terry Chay (YES! THAT TERRY CHAY!) :)