public function Join()
{
// Check Join type
$joinType = AST\Join::JOIN_TYPE_INNER;
if ($this->_lexer->isNextToken(Lexer::T_LEFT)) {
$this->match(Lexer::T_LEFT);
// Possible LEFT OUTER join
if ($this->_lexer->isNextToken(Lexer::T_OUTER)) {
$this->match(Lexer::T_OUTER);
$joinType = AST\Join::JOIN_TYPE_LEFTOUTER;
} else {
$joinType = AST\Join::JOIN_TYPE_LEFT;
}
} else if ($this->_lexer->isNextToken(Lexer::T_INNER)) {
$this->match(Lexer::T_INNER);
}
$this->match(Lexer::T_JOIN);
$joinPathExpression = $this->JoinAssociationPathExpression();
if ($this->_lexer->isNextToken(Lexer::T_AS)) {
$this->match(Lexer::T_AS);
}
$token = $this->_lexer->lookahead;
$aliasIdentificationVariable = $this->AliasIdentificationVariable();
// Verify that the association exists.
$parentClass = $this->_queryComponents[$joinPathExpression->identificationVariable]['metadata'];
$assocField = $joinPathExpression->associationField;
if ( ! $parentClass->hasAssociation($assocField)) {
$this->semanticalError(
"Class " . $parentClass->name . " has no association named '$assocField'."
);
}
$targetClassName = $parentClass->associationMappings[$assocField]['targetEntity'];
// Building queryComponent
$joinQueryComponent = array(
'metadata' => $this->_em->getClassMetadata($targetClassName),
'parent' => $joinPathExpression->identificationVariable,
'relation' => $parentClass->getAssociationMapping($assocField),
'map' => null,
'nestingLevel' => $this->_nestingLevel,
'token' => $token
);
$this->_queryComponents[$aliasIdentificationVariable] = $joinQueryComponent;
// Create AST node
$join = new AST\Join($joinType, $joinPathExpression, $aliasIdentificationVariable);
// Check for ad-hoc Join conditions
if ($this->_lexer->isNextToken(Lexer::T_WITH)) {
$this->match(Lexer::T_WITH);
$join->conditionalExpression = $this->ConditionalExpression();
}
return $join;
}