Improving Cron expression DX to reduce cron expression generation errors and typo - #217
Improving Cron expression DX to reduce cron expression generation errors and typo#217nyamsprod wants to merge 2 commits into
Conversation
|
While I appreciate the work, please investigate how this library is already constructed. A lot of this PR has the bones of good ideas, but ends up duplicating a ton of exisiting code and existing classes. A quick glance shows that a lof of these ideas could probably be done in a backwards compatible way. I'm not closing this PR fully out to give you a chance to better implement these ideas. |
|
@dragonmantank thanks for the quick answer. But I believe, you may prove me wrong, that the named constructors and the mutators like Again this is but a proposal I could rewrite it to include those methods in the CronExpression class directly if needed. But I wanted first to show the full scope of the PR and its implementation and start a discussion. Hence why I have added some open question. I probably should have added should those mutators or named constructors be added to the CronExpression class directly. |
|
@dragonmantank What do you think if I update the PR do the following echo CronExpression::daily()
->every(step: 5, position: CronExpression::WEEKDAY)
->list([8, 12, 15], CronExpression::HOUR)
->everyInRange(start: 12, end: 30, step:3, position: CronExpression::DAY), PHP_EOL;
// returns '0 8,12,15 12-30/3 * */5'
echo CronExpression::midnight(), PHP_EOL;
// returns '0 0 * * *'which can even be rewritten using the echo CronExpression::daily()
->everyDaysOfWeek(step: 5)
->listHours([8, 12, 15])
->everyInRangeDaysOfMonth(start: 12, end: 30, step:3), PHP_EOL;
// returns '0 8,12,15 12-30/3 * */5'
echo CronExpression::midnight(), PHP_EOL;
// returns '0 0 * * *'TL;DR:
|
1ad27e4 to
ef1ab69
Compare
|
@dragonmantank I have updated the PR. It is now in a stable state that you can review. Looking forward for your review and remarks. |
ba52055 to
d54205f
Compare
d54205f to
2eab047
Compare
2eab047 to
43aaaee
Compare
Cron Expression Building
Introduction
Currently, to create a CronExpression we must use the CronExpression constructor
and provide a valid cron expression string. On error an exception is thrown.
The issue is that even if we can find online some CRON syntax validator and even
if the syntax is well documented in the package README file, making typo while
building a new CronExpression is one of the most common mistake when dealing
with Cron expressions.
Proposal
In order to provide a more ergonomic and efficient solution for CRON expression
building, a fluent API is added to the current
CronExpressionclass to improveCRON expression building.
Added Methods
The complete new methods signature to be added are the following:
Design consideration
Constructors
Named constructors
CronExpressionprovides named constructors to create common cron expressions through explicit, type-safe entry points:minutely(): selfdailyAt(string|int $hour, string|int $minute): selfweeklyOn(string|int $dayOfWeek, string|int $hour, string|int $minute): selfmonthlyOn(string|int $dayOfMonth, string|int $hour, string|int $minute): selfyearlyOn(string|int $month, string|int $dayOfMonth, string|int $hour = 0, string|int $minute = 0): selfThese methods provide a safer and more predictable alternative to directly instantiating the class by making the intent explicit at the call site.
Like the constructor, each named constructor accepts an optional
FieldFactoryInterfaceimplementation as its final argument. When omitted, the default field factory implementation is used.__callStatic()to access aliasesThe
__callStatic()magic method provides a convenient way to create expressions from registered cron aliases using an expressive API.For example:
Because
daily()maps to the registered@dailycron alias, it provides a more discoverable alternative to passing the alias string directly.Like the named constructors, alias methods accept an optional
FieldFactoryInterfaceimplementation as their only argument.For example:
can be rewritten as:
Mutators
The following mutators are introduced:
every(int $step, int $position): selfrange(string|int $start, string|int $end, int $position): selflist(iterable<string|int> $list, int $position): selfeveryInRange(string|int $start, string|int $end, int $step, int $position): selfThe methods allow updating the
CronExpressionin a more secure and predicable way bysupported basic CRON field grammar.
__callto improve DXThe
__call()magic method provides a more developer-friendly API by generating expressive methods dynamically.For example:
can be rewritten as
Both snippets produce the same cron expression:
The same applies to retrieving individual cron fields:
can be rewritten as
This allows developers to interact with cron fields using meaningful names instead of having to remember the
CronExpressionposition constants and their values.The following dynamic methods are supported:
everyeveryrangerangelistlisteveryInRangeeveryInRangesetsetPartgetgetExpressionEach method prefix can be combined with one of the following suffixes:
MinutesCronExpression::MINUTEHoursCronExpression::HOURMonthsCronExpression::MONTHDaysOfWeekCronExpression::WEEKDAYDaysOfMonthCronExpression::DAY