Comments (9)
Hi @AndyBursh
Thank you for this issue. It is a valid problem you are raising. I have not considered that one before.
I like that you provided clear code examples.
I have one question in mind. What if we added a LogicX::Append(Specification) method? I think that would solve your problem as well, wouldn't it?
public function search($parameters)
{
$spec = new Spec::andX();
// ... If foo is set
$spec->append(Spec::eq("foo", $parameters["foo"]));
// ... If bar ir set
$spec->append(Spec::eq("bar", $parameters["bar"]));
$finalSpec = Spec::orX(
$spec,
Spec::andX(Spec::lt("fizz", 4), Spec::eq("bing", false)),
Spec::gt("buzz", 99)
);
$results = $repo->match($finalSpec);
}
from doctrine-specification.
@Nyholm I think adding an append
spec solves the problem on at a technical level, but I'm not so sure about solving it at a usability level.
My mental model when working with specifications is of combining logical statements together, so I don't feel that appending one specification to another is a natural fit here. I think a better form of your solution might be to have correpsonding methods on the logic specifications
public function search($parameters)
{
$spec = Spec::andX();
// ... If foo is set
$spec->andX(Spec::eq("foo", $parameters["foo"]);
// ... If bar is set
$spec->andX(Spec::eq("bar", $parameters["bar"]);
$finalSpec = Spec::orX(
$spec,
Spec::andX(Spec::lt("fizz", 4), Spec:: eq("bing",
);
$finalSpec->orX(Spec::gt("buzz", 99));
}
However, this then precludes me from writing something as simple as below. I'm not sure that's a bad thing, necessarily, but I think it's something worth considering.
$spec = Spec::eq("foo", $parameters["foo"]);
$spec->andX(Spec::eq("bar", $parameters["bar"]));
I could prepare implementations of both versions (fluent, and correpsonding methods) if that would help.
from doctrine-specification.
Hm. I see you point and I do think the code you supplied looks better.
Me and @cakper did some work and had a long discussion about #39 yesterday. He is going to provide a PR with some refactoring. Maybe an other solution will be more obvious by that PR.
I suggest we reconsider this issue after we see the result of that PR. Because I do think you raise an important issue here.
from doctrine-specification.
I really do want to tackle this problem now.
Consider the following scenario:
$spec = // Some spec object
$spec->andX(A);
$spec->andX(B);
$spec->orX(C);
How should the spec tree be built?
1) (A && B) || C
2) A && (B || C)
What if we use multiple arguments?
$spec = // Some spec object
$spec->andX(A, B);
$spec->orX(C);
How should the spec tree be built?
1) (A && B) || C
2) A && (B || C)
Suggestion
We add AndX::andX
that will take one Specification as argument. Likewise we add OrX::orX
.
$spec = Spec::andX(A, B)
$spec->andX(C);
// $spec will be the same as Spec::andX(A, B, C);
$spec = Spec::andX(A, B)
$spec->andX(Spec::orX(C, D));
// $spec will be the same as Spec::andX(A, B, Spec::orX(C, D));
You could now do...
public function search($parameters)
{
$spec = Spec::andX();
// ... If foo is set
$spec->andX(Spec::eq("foo", $parameters["foo"]);
// ... If bar is set
$spec->andX(Spec::eq("bar", $parameters["bar"]);
$finalSpec = Spec::orX(
$spec,
Spec::andX(Spec::lt("fizz", 4), Spec:: eq("bing",
);
$finalSpec->orX(Spec::gt("buzz", 99));
}
But you can't do
$spec = Spec::andX(A);
$spec->andX(B);
$spec->orX(C); //orX is not defined on class AndX.
What do you think. Will it be more fluent? Will it be clear how the logic tree is build?
from doctrine-specification.
I think, in your first example, the first tree construct is right. The second tree would be constructed with something like:
$spec = // Some spec object
$spec->andX(A);
$spec->andX(Spec::orX(B, C));
I like the solution you've proposed with AndX::andX
and OrX::orX
. However, I don't think what you say about your last example is worth much worry. The tree you're attempting to construct there is still feasible to construct, it's just a bit more circuitous.
$spec = Spec::orX(
C,
Spec::andX(A, B) // or some previously constructed spec
);
To clarify, your proposal allows usage to be less verbose than your examples too? For example
$spec = (Spec::AndX(A))->andX(B)->andX(C);
I forget if calling members on the result of something in parentheses is allowed in PHP, but you get the gist.
from doctrine-specification.
To clarify, your proposal allows usage to be less verbose than your examples too? For example
That is the plan. I'll submit a PR and we can evaluate.
from doctrine-specification.
The PR is merged. I consider this issue to be closed.
from doctrine-specification.
Thank you @AndyBursh for you comments! I really think it is an improvement.
from doctrine-specification.
You're welcome, @Nyholm. Thanks for taking it in to account.
from doctrine-specification.
Related Issues (20)
- Need remove not used vars in RoundDateTimeSpec
- Add createQueryBuilder() abstract method in EntitySpecificationRepositoryTrait HOT 1
- Remove AbstractJoin::getJoinType() method HOT 1
- [Syntax Error] line 0, col -1: Error: Expected Literal, got end of string. HOT 1
- Mysql substring function bug HOT 1
- Disable Style CI HOT 3
- Release 2.0.0 HOT 1
- Check single entity satisfiability HOT 8
- DATE_ADD() and DATE_SUB() platform functions does not work HOT 1
- TRIM() platform functions does not support options HOT 1
- Best practices and architectural decissions HOT 5
- Use defaultRepositoryClassName instead of the RepositoryFactory HOT 4
- Using subqueries HOT 5
- Always use a unique aliases to prevent cases in which we have auto-joining and reserved keywords as context HOT 4
- Psalm annotations HOT 5
- A bit confused about the proper use of `$context` HOT 2
- Customize JOIN HOT 1
- Auto-joins with dot notation HOT 7
- Symfony 6 HOT 1
- How to set Query::HINT? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from doctrine-specification.