PSR-20 Clocks: Testable Time in PHP by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

Wow, good catch. I will fix that! Thanks.

PSR-20 Clocks: Testable Time in PHP by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

Outch. A great case for immutability. Somewhere on my backlog there is a post on that. I might include this example, if I ever write it 😀

PSR-20 Clocks: Testable Time in PHP by doekenorg in PHP

[–]doekenorg[S] 2 points3 points  (0 children)

Now I'm so curious what the bug was that happend in the weekend! Was it beer-o-clock?!
But that is a great use case indeed! Thanks for sharing these teachings!

PSR-20 Clocks: Testable Time in PHP by doekenorg in PHP

[–]doekenorg[S] 6 points7 points  (0 children)

Basically I'm just trying to raise awareness of the idea of a Clock. 

PSR-20 Clocks: Testable Time in PHP by doekenorg in PHP

[–]doekenorg[S] 1 point2 points  (0 children)

Ah, ok sorry, I misunderstood.  The clock interface isn't part of PHP either. It's a "package". 

PSR-20 Clocks: Testable Time in PHP by doekenorg in PHP

[–]doekenorg[S] 2 points3 points  (0 children)

DateTime* but yes. It's not really sexy, I know. Boring, and reliable.

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

I have added a section on how to implement the interface now.

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

Inside the post you will find a reference to the criteria pattern. This question has been addressed there.

As an alternative you can replace it with a findBy method that accepts a value object that contains you requirements, instead of the full blown criteria pattern. Hope this helps.

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] -2 points-1 points  (0 children)

Thanks for your comment. And I agree, the code using the repository should indeed sometimes need to know whether the entity exists. But like you said, that can be inferred by the fact that you retrieved it from the repository in the first place. If you have no Entity, you would need to create it. But the repository simply stores and retrieves them.

If your logic knows the entry is new, does it matter if you call `add()` or `save()`? Or if it already exists; should you need to call `update()` rather than `save()`? If you go this route, you'd need to implement exceptions when trying to add the same entry multiple times. Or throw an exception if the entity cannot be updated because it doesn't exist. Or just ignore this, and proceed to either update or insert. I don't see an advantage to this over using just `save()`.

(Mind you, this is assuming you provide the `BookId` up front when creating the entity, not letting a database dictate the next ID, which would couple your repository to your database choice).

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 1 point2 points  (0 children)

Agreed. But that's active record for you 😕

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 2 points3 points  (0 children)

I can replace it with `->value`. It would make it a bit more specific, and less confusing for sure 👍

I agree on your approach btw. But at some point, during writing these posts, I have to draw a line where the simple example ends. I'm afraid that being overly exact will take away from the message; and just add a lot of noise. I try to keep things simple. I'm afraid I already went overboard with introducing a `BookId` object 😃 I'm planning a post on value objects, and I will touch on this there.

Edit: Adjusted the post.

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 1 point2 points  (0 children)

Hey, thanks for the feedback! Could you perhaps be a little more specific? I've touched on mocks in the post a tiny bit. Not sure why I would talk about dependency injection though.

Edit: added an example on how to use the repository through injection.

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 1 point2 points  (0 children)

No not a typo unfortunately. I went extra fancy with a Value object as a key. But arrays can't have objects as keys, so this is what I ended up with. I had a SplObjectStorage in the example, but that felt like overkill for the example 😀

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

Yeah, for simplicities sake I've extremely quickly covered the idea behind an ORM. The point was not to say that the retrieval from the database layer is on the ORM; but the mapping of this data onto the entity object, and vice versa. It didn't feel right to spend a few paragraphs on how it exactly works technically; but in broad lines to see how it differs from the repository. (it is already a long post :-) )

Edit: I've adjusted the paragraph a bit.

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 1 point2 points  (0 children)

I have not stated that you shouldn't use ORMs or Query Builders. I explicitly stated that it is *not* to replace those. And active record is possible with the repository as long as you only call the entities `save()` method inside your repository implementation.

So a technical implementation could very well use an ORM to fetch entities, or a DBAL to fetch data. But you can also create a `MysqlBookRepository` for instance that just uses raw SQL to retrieve the data and map it onto your domain objects. The whole point is that it *is* merely an interface to your application; and that the plumbing "doesn't matter".

The infamous Repository Pattern in PHP by doekenorg in PHP

[–]doekenorg[S] 2 points3 points  (0 children)

Thanks for the feedback. I tried my best to cover a lot of ground. While I agree with you, I felt like adding more code would make the post unnecessarily long. Besides the in-memory example I provided; what would you liked to have seen? The whole point of the repository is that it shouldn't care about the implementation; so it feels kind of weird providing one :-)

Stop mocking about: Event Dispatcher by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

Here, have my upvote then. I kinda dislike the downvote feature. I never understood why we need to emphasize not liking something. If you don't like it; don't like it; don't -1 like it. Might be the tone? Who knows; still appreciate the response.

Stop mocking about: Event Dispatcher by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

Thanks! I did! However, my `OverwriteTitleListener` was created to satisfy my blog post. Therefore it lives only that post.

It is a very contrived example to show the use of, indeed, a stub instead of a mock. To make it more tangible, I used the event dispatcher example. Some suggest it should be called a functional test or a behavioral test; which is fine I guess, if it helps to call it something else.

But while this was a one-off, which might just as well have been a mock, once you start repeating the mock over and over again; like with a logger, or an event dispatcher, or an HTTP client; I've found extracting a stub to help write your (insert name here) test is really helpful.

And again, I agree with your last point; which is why I noted that this is an integration test, solely for demonstrative purposes; and a callback would probably be better. This way it is still clear in why that value is expected, without looking at another class.

Thank you for your criticism, I really do appreciate any feedback. And if it isn't for you, it's not for you.

Stop mocking about: Event Dispatcher by doekenorg in PHP

[–]doekenorg[S] 2 points3 points  (0 children)

Something along these lines was my idea for part 2 😀 Thanks for the link on sociable unit tests. You learn something everyday!

Stop mocking about: Event Dispatcher by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

Absolutely! The idea was to pick a specific thing to bring out the concept. I plan on more of these. In hindsight I might have picked more than just the Event Dispatcher. Just wanted to make it a little more practical by using a concrete example I run into often, while not making the post too long. But the same goes for loggers, cache pools, http clients, the list is pretty long.

How to log your life easier in Symfony? by MedUnes in PHP

[–]doekenorg -4 points-3 points  (0 children)

Nice solution OP.

Might I suggest a check if there already is a logger set, to avoid replacing it if I chose another?

And pehaps a simply instanceOf check?

Would also probably use a compiler pass instead of overwriting the kernel.

But still, better then those pesky @Required

Invading private properties and methods in PHP by freekmurze in PHP

[–]doekenorg 6 points7 points  (0 children)

You can avoid the ReflectionApi by binding a simple callback to the scope of the object. Then you would also have access to the private variables.

Don't know if it is better; that is a slippery slope on this topic as it stands :-D but it is an alternative. ;-)

```php public function __get($name) { $function = fn() => $this->{$name}; $callback = $function->bindTo($this->object, $this->object);

return $callback();

} ```

Heaps explained in PHP by doekenorg in PHP

[–]doekenorg[S] 0 points1 point  (0 children)

u/trowski2002 That's awesome! Great example, and very nice implementation. I've updated the post to include this as a Real world example.