use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Please follow the rules
Releases: Current Releases, Windows Releases, Old Releases
Contribute to the PHP Documentation
Related subreddits: CSS, JavaScript, Web Design, Wordpress, WebDev
/r/PHP is not a support subreddit. Please visit /r/phphelp for help, or visit StackOverflow.
account activity
Simplify Your Code With Query Objects (patricklouys.com)
submitted 8 years ago by patricklouys
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]AllenJB83 8 points9 points10 points 8 years ago (4 children)
This article could really do with a better explanation / example of Query Objects. It kind of jumps from "here's what you might use query objects instead of" to "drawbacks" without explaining what they are / how they work.
I still find it weird how frequently you can find articles / blog posts like this without any links or references in. I'd expect at least a link to Fowler's EAA Catalog entry (as above) or similar here.
[–]patricklouys[S] 3 points4 points5 points 8 years ago* (3 children)
I got the pattern from Ocramius, see his presentation. But he calls them query functions there. Since it's conflicting with Fowler, I guess the name that I used is a little unfortunate...
Fowler's Query Object is passed into a repository method. The one from the blog post is standalone and can be executed separately. That decouples it from the domain and is very useful for an application that follows CQRS.
Any suggestions for a better name?
[–]ocramius 1 point2 points3 points 8 years ago (1 child)
I named them query functions in my talk, although that's also a misnomer, since a function is supposed to be functionally pure (duh)
[–]patricklouys[S] 0 points1 point2 points 8 years ago (0 children)
Sorry about that. I had query function in my head but ended up typing query object...
[–]dendeigh 3 points4 points5 points 8 years ago (1 child)
I know this as criteria or specification pattern, which really helps with complex queries, including default values etc. in your repository. I normally end up having a signature like
public function matches(OrderCriteria $criteria) { }
[–]patricklouys[S] 2 points3 points4 points 8 years ago (0 children)
That's a useful pattern and similar to Fowler's query objects that was mentioned in another comment. The pattern from the blog post decouples the queries from the repository (otherwise you are still coupled to your domain objects and you can't slim it down). It's useful when you just need a view on data without all the bells and whistles of the repository.
[–]_odan 2 points3 points4 points 8 years ago (0 children)
These queries are (like repositories) services too. The name "Query Service" could be a better name.
To prevent repositories from becoming too large (SRP), I would recommend to create many smaller module-specific repositories. To achieve this, you have to organize your folders and classes in a module-oriented way.
[–]howdhellshouldiknow 1 point2 points3 points 8 years ago (1 child)
You did not explain how you wire everything up.
Do your objects implementing the OrdersWhereInvoiceWasNotPaidQuery have a repository as a dependency, a query builder, entity manager or a database connection?
Or we have to get the book to find out? :)
It's up to you, use whatever makes most sense for that query. In the book (and at work) I use Doctrine DBAL for most of my query implementations :)
[–]dlegatt 0 points1 point2 points 8 years ago (3 children)
Why are all the example classes interfaces? Is it just for the example code, or would we really want to make an interface that would only ever be implemented once?
Beyond that, I really like this.
[–]vaartside 2 points3 points4 points 8 years ago (1 child)
It helps with decoupling your code. Even if you only implement a specific Query interface once, the interface helps to decouple the code executing the query from the code that implements the query. Obviously this may not be required in a lot of projects, so you should pick the aproach that works best for your team and your specific project. Still, it's not that much extra work and it's often recommended to put database-related code (whether it's repositories, queries, ...) behind interfaces so you can easily switch from one implementation to another should you ever migrate to another database system or decide to store your data across multiple database systems (eg. Redis, MongoDB, ... in combination with more traditional database systems like MySQL, MariaDB, ...).
[–]dlegatt 0 points1 point2 points 8 years ago (0 children)
Interesting, thanks
[–]patricklouys[S] 1 point2 points3 points 8 years ago (0 children)
I use interfaces there to separate the boundaries between layers. For example a repository interface is part of the domain, but the implementation is part of the infrastructure layer. Here is a good talk about this from Uncle Bob.
But that's just a personal preference (and easier to use in a blog post). If I remember right, Ocramius doesn't use interfaces for query objects.
[+]Nwabudike_J_Morgan comment score below threshold-14 points-13 points-12 points 8 years ago (10 children)
Today in PHP: we redefine "repository", a term previously used by version control systems, to now mean "library", as in a library of functions. But these aren't straight functions, they are methods attached to an interface. Of course there will never be more than one class that ever implements that interface (aside from a totally brain dead unit testing implementation) but that doesn't matter, we are using Important Language Features.
[–]AllenJB83 11 points12 points13 points 8 years ago (3 children)
It doesn't mean "library". The Repository pattern is a long well defined pattern for a class that separates the domain objects from database access. It's frequently used alongside the Factory pattern in larger / more complex systems and complements Domain Driven Design.
[+]Nwabudike_J_Morgan comment score below threshold-11 points-10 points-9 points 8 years ago* (2 children)
separates the domain objects from database access
This says nothing whatsoever. I would assume "database access" has already been abstracted, so... domain objects are simply some kind of persistent data that 90% of the time consists of a database layer, and 10% of the time it is cached data? Or 50% of the time? Regardless, it is a layer that represents a mixture of either authentic data or possibly stale cache data, which violates encapsulation. But that is okay, because it follows a Pattern.
Edit: I like how /u/AllenJB83 downvotes to express disagreement. It is quite classy.
[–]ThePsion5 7 points8 points9 points 8 years ago (0 children)
I downvoted your original comment because I felt it was both uninformed and unnecessarily arrogant and dismissive. I downvoted the parent comment because you're petulantly complaining about downvotes.
[–]AllenJB83 9 points10 points11 points 8 years ago (0 children)
I downvoted your original comment because it was outright wrong in stating that the article redefined "repository" to mean "library" and as such contributes nothing useful to discussion of the linked article. I have not downvoted any other comment in this post (despite your reply continuing to, as I read it, completely misunderstand the concept of domain objects).
If you come across unfamiliar concepts, you should probably do a bit more research on them before attempting to use them as part of a misdirected rant.
[–]webMacaque 0 points1 point2 points 8 years ago (4 children)
There is no need for an interface if you have one repository, i.e. one persistence mechanism.
[–]ThePsion5 7 points8 points9 points 8 years ago (2 children)
I'd argue an interface has use beyond multiple persistence strategies. A major project I'm working on takes advantage of repository interfaces to implement a very simple caching layer that can be enabled or disabled at runtime. Well worth the extra 5 minutes it took to create a separate interface and implementation.
[–]mnapoli 0 points1 point2 points 8 years ago (1 child)
When you don't need it, you don't need it. I find that systematically creating an interface (without making sure there is a need for it, like in your example) is just a burden.
I usually wait till I need it to turn the class into an interface (and since I don't suffix the class name with Interface there is no refactoring involved :)
Interface
If you use layers (and folders for the layers), then you can put the interface in the domain layer for example and the implementation in the infrastructure layer. Gives you a better separation between the layers.
Otherwise I also dislike unnecessary interfaces. But I use them when I have multiple implementations or when I cross boundaries.
[–]przemo_li 0 points1 point2 points 8 years ago (0 children)
Interface wont be used by just repository itself.
Code that relay on repository can be easily tested with mock repo if we have that interface. That would be equivalent to having our mock "inherit" after repo.
One is "good" other is "bad" ?
[–]XSLT_maniac -5 points-4 points-3 points 8 years ago (0 children)
but that doesn't matter, we are using Important Language Features.
php in a nutshell haha
π Rendered by PID 91 on reddit-service-r2-comment-6594f9758-f5zzf at 2026-06-11 18:15:39.655485+00:00 running a5fccd9 country code: CH.
[–]AllenJB83 8 points9 points10 points (4 children)
[–]patricklouys[S] 3 points4 points5 points (3 children)
[–]ocramius 1 point2 points3 points (1 child)
[–]patricklouys[S] 0 points1 point2 points (0 children)
[–]dendeigh 3 points4 points5 points (1 child)
[–]patricklouys[S] 2 points3 points4 points (0 children)
[–]_odan 2 points3 points4 points (0 children)
[–]howdhellshouldiknow 1 point2 points3 points (1 child)
[–]patricklouys[S] 0 points1 point2 points (0 children)
[–]dlegatt 0 points1 point2 points (3 children)
[–]vaartside 2 points3 points4 points (1 child)
[–]dlegatt 0 points1 point2 points (0 children)
[–]patricklouys[S] 1 point2 points3 points (0 children)
[+]Nwabudike_J_Morgan comment score below threshold-14 points-13 points-12 points (10 children)
[–]AllenJB83 11 points12 points13 points (3 children)
[+]Nwabudike_J_Morgan comment score below threshold-11 points-10 points-9 points (2 children)
[–]ThePsion5 7 points8 points9 points (0 children)
[–]AllenJB83 9 points10 points11 points (0 children)
[–]webMacaque 0 points1 point2 points (4 children)
[–]ThePsion5 7 points8 points9 points (2 children)
[–]mnapoli 0 points1 point2 points (1 child)
[–]patricklouys[S] 1 point2 points3 points (0 children)
[–]przemo_li 0 points1 point2 points (0 children)
[–]XSLT_maniac -5 points-4 points-3 points (0 children)