-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[Clock] Add Clock class and now() function
#48642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
2a6c3d7 to
9e7bd07
Compare
9e7bd07 to
1cc21b7
Compare
be99e56 to
e2e654f
Compare
chalasr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure that hijacked enum is better than a regular class with private+final construct, but it works and made me laugh :)
|
Less boilerplate FTW (+ newInstanceWithoutConstructor won't allow bypassing ;) ) |
e2e654f to
73474b7
Compare
|
Thanks to various comments, I figured out a better API for this global clock.
|
|
Do not add it to the API, please! I'm begging you! 🙏 It is easy to achieve by simple wrapper when it is really needed. Static calls to some global state can be useful in some code, but most of the time it leads to maintenance problems and bugs. People would use it without reason if that was in the API. The feature looks like Laravels Facades. Every time I've seen them used, they are used wrong. Not because the Facades are something bad, but because developers (especially not very experienced) do bad things with them. Facades are constantly overused/abused just because it is convenient, they are described in guides, and "they all do that, why I shouldn't?" The good answer to how to inject time (and other dependencies) into Doctrines' entities is repository. Repositories are the best place to provide entities, including new ones. If it's difficult in your case or doesn't suit your needs, there are many other options #48564 (comment) But... Please, do not add static calls to the API. |
|
I plead guilty to having a With this implementation, I don't see how I could override the current time for functional testing. I can redefine the $client = static::createClient();
$crawler = Clock::with($mockClock, fn() => $client->request('GET', '/')); |
|
@GromNaN you nailed it :) |
73474b7 to
d660ee7
Compare
|
|
d660ee7 to
4795584
Compare
6ef4125 to
20ca626
Compare
20ca626 to
09acb88
Compare
Clock class and now() function
|
Thanks for the feedback. PR updated. It now provides integration with services + phpunit. PR description updated. |
09acb88 to
ab6b038
Compare
| true === $when => new MockClock(), | ||
| $when instanceof ClockInterface => $when, | ||
| $when instanceof \DateTimeImmutable => new MockClock($when), | ||
| default => new MockClock(now()->modify($when)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't this be confusing if now() is not a native clock currently ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not a native clock, it's usually a mock clock. This behavior is desired to me, to do eg:
self::mockTime(); // freeze
//...
self::mockTime('+1 days'); // frozen time + 1 dayab6b038 to
43d3143
Compare
43d3143 to
1eb775b
Compare
1eb775b to
aaad65c
Compare
| * Note that you should prefer injecting a ClockInterface or using | ||
| * ClockAwareTrait when possible instead of using this function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…lt (nicolas-grekas) This PR was merged into the 6.3 branch. Discussion ---------- [Clock] Make ClockAwareTrait use the global clock by default | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Let's make `ClockAwareTrait` compatible with `Clock::now()` from #48642 by default. Commits ------- ec60013 [Clock] Make ClockAwareTrait use the global clock by default
|
Why is there a |

See discussion on #48564.
This PR adds 2 static methods and one function:
It also wires this global clock as a service so that injecting the
ClockInterfaceor usingnow/Clock::get()returns the same time.Last but not least, this PR also provides a
ClockSensitiveTraitto help write test cases that rely on the clock. This trait provides oneself::mockTime()method and it restores the global clock after each test case.mockTime()accepts either a string (eg'+1 days'or'2022-12-22'), a DTI instance, or a boolean (to freeze/restore the global clock).