-
Notifications
You must be signed in to change notification settings - Fork 41
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
Support for Join conditions #122
Conversation
*/ | ||
public function __construct($field, $newAlias, $dqlAlias = null) | ||
public function __construct($field, $newAlias, $dqlAlias = null, $condition = null, $conditionType = null) |
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.
Shouldn't it be the other way around? The signature of the QueryBuilder::join
is:
public function join($join, $alias, $conditionType = null, $condition = null, $indexBy = null);
I think we should have it in the same order.
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.
I chose this order because 90% of the time I don't need to change the default ON clause.
It makes the api less verbose, but on the other hand it's not as expressive and diverges from Doctrine, so it might be confusing...
Maybe we should keep it the doctrine way, and add a new method to the builder, like
Spec::with($field, $newAlias, $joinType, $joinCondition);
While we're at it we could also solve the problem that it's currently impossible to do fetch joins with the spec builder:
namespace Happyr\DoctrineSpecification\Query;
class With extends AbstractJoin
{
protected $joinType;
public function __construct ($field, $newAlias, $joinType='join', $condition=null)
{
$parentAlias = substr($field, 0, strpos($field, '.'));
$this->joinType = $joinType;
parent::__construct($field, $newAlias, $parentAlias ?: null, 'WITH', $condition);
}
public function modify(QueryBuilder $qb, $dqlAlias)
{
$dqlAlias = $this->dqlAlias ?: $dqlAlias;
$join = $this->joinType;
$condition = $this->getJoinCondition($this->condition, $qb);
$qb
->addSelect($this->newAlias) // FETCH THAT JOIN !!!
->$join("{$dqlAlias}.{$this->field}", $this->newAlias, 'WITH', $condition)
;
}
}
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.
I agree what the order doctrine uses is verbose. But it makes sense because it is easier to read and understand.
I don't really like the idea with new With
, those kind of shortcuts should be in the factory. I suggest changing the constructor to be the same as Doctrine and then add a factory method which covers the 90% of the use cases:
public static function joinWith($field, $newAlias, $condition, $dqlAlias = null, $conditionType = null)
{
return new Join($field, $newAlias, $dqlAlias, $conditionType, $condition);
}
What do you think about that?
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.
There is no need for the condition type.
For using conditions in join you can use only WITH
. If you try use ON
you get the error:
An exception has been thrown during the rendering of a template ("[Syntax Error] line 0, col 137: Error: Expected Doctrine\ORM\Query\Lexer::T_WITH, got 'ON'").
See this doctrine/orm#7193 issue for more detales.
Thank you for this PR. This sure is a missing features. I just hade some minor comments. |
if (!$this->conditionType) { | ||
return DoctrineJoin::WITH; | ||
} | ||
if (!in_array($this->conditionType, [DoctrineJoin::ON, DoctrineJoin::WITH])) { |
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.
We should define our own ON and WITH constants. We don't want to be dependent on Doctrine.
Hey. I would really like to merge this? Any estimates when an update to this PR can be made? |
I consider this change to be unnecessary. This method mixes the level of business logic and persistence level. The same result can be achieved easier: Spec::andX(
Spec::join('users', 'u'),
Spec::eq('active', true, 'u'),
Spec::eq('status', 'somestatus', 'u')
) I prefer not to use the library directly, but i create specifications, the name of which describes the business rule: Spec::andX(
new JoinCommentUser('u'),
new PublishedUser('u'),
new UserWithStatus('somestatus', 'u')
) |
The new context system added in version 2 makes using relationships even easier. Spec::andX(
Spec::eq('active', true, 'users'),
Spec::eq('status', 'somestatus', 'users')
) |
This:
Will be equivalent to: