-
-
Save dantleech/6098615 to your computer and use it in GitHub Desktop.
<?php | |
// ******** ODM Iteration 4 - Proposed ******** | |
// Fluid interface. | |
// | |
// This illustrates the "broken" style, you could equally do | |
// the entire thing fluently using "end()" methods. | |
// | |
// 20 lines | |
$qb->select() | |
->column('foobar', null, 'a') | |
->column('barfoo', null, 'a'); | |
$qb->from() | |
->join() | |
->left()->document('Doctrine\Fqn\Foobar', 'a') | |
->right()->document('Doctrine\Fqn\Foobar', 'b') | |
->condition()->equi('a', 'foobar', 'b', 'barfoo'); | |
$qb->where() | |
->and() | |
->descendantNode('/foobar') | |
->equals() | |
->nodeLocalName('a') | |
->bindVariable('test_bar'); | |
$qb->orderBy() | |
->ascending()->propertyValue('foobar', 'a') | |
->descending()->nodeLocalName('a'); | |
$q = $qb->getQuery(); | |
$q->setParameter('test_bar'); | |
$q->execute(); | |
// *********************************** | |
// ***** Original PHPCR method ******* | |
// 27 lines | |
$q = $qom->createQuery( | |
// SourceInterface | |
$qom->join( | |
$qom->selector('nt:unstructured', 'a'), | |
$qom->selector('nt:unstructured', 'b'), | |
$qom->equiJoinCondition( | |
'a', 'foobar', | |
'b', 'barfoo' | |
) | |
), | |
// ConstraintInterface | |
$qom->andConstraint( | |
$qom->descendantNode('/foobar'), | |
$qom->comparison( | |
$qom->nodeLocalName('a'), | |
$qom->bindVariable('test_var'), | |
QueryObjectModelInterface::JCR_OPERATOR_EQUAL_TO | |
) | |
), | |
// Array of OrderingInterfaces | |
array( | |
$qom->ascending($qom->propertyValue('foobar', 'a')), | |
$qom->descending($qom->nodeLocalName('a')), | |
), | |
// Array of ColumnInterfaces | |
array( | |
$qom->column('foobar', null, 'a'), | |
$qom->column('barfoo', 'custom_column_name', 'a'), | |
) | |
); | |
$q->bindValue('test_var', 'moobar'); | |
$q->execute(); | |
// ********************************* | |
// ******** Iteration 1 ************ | |
// Factory is built into query builder | |
// - slt|selectFactory: return SelectorInterface | |
// - src|sourceFactory: return SourceInterface | |
// - cns|constraintFactory: return ConstraintInterface | |
// - opr|operandFactory: return OperandInterface | |
// - ord|orderingFactory: return OrderingInterface | |
// - jCn|joinConstraint: return JoinConstraintInterface | |
// | |
// 30 lines | |
$qb->select(array( | |
$qb->slt()->column('foobar', null, 'a'), | |
$qb->slt()->column('barfoo', null, 'a') | |
)); | |
$qb->from( | |
$qb->src()->join( | |
$qb->src()->document('Doctrine\Fqn\Foobar', 'a'), // | |
$qb->src()->document('Doctrine\Fqn\Foobar', 'b'), // | |
$qb->jCn()->equi( // eqJoinCon | |
'a', 'foobar', | |
'b', 'barfoo' | |
) | |
) | |
); | |
$qb->where( | |
$qb->cns()->and( | |
$qb->cns()->descendantNode('/foobar'), | |
$qb->cns()->comparison( | |
$qb->opr()->nodeLocalName('a'), | |
$qb->opr()->bindVariable('test_bar'), | |
'EQUAL_TO' | |
) | |
) | |
); | |
$qb->orderBy(array( | |
$qb->ord()->ascending($qb->opr()->propertyValue('foobar', 'a')), | |
$qb->ord()->descending($qb->opr()->nodeLocalName('a')) | |
)); | |
$q = $qb->getQuery(); | |
$q->setParameter('test_bar', 'bar'); | |
$q->execute(); | |
// ********************************* | |
// ******** Iteration 2 ************ | |
// 24 lines | |
// | |
// Compatible with above, adds: | |
// | |
// - andWhere | |
// - explicit method for each operator (eq, neq, gt, gte, etc) | |
// - fromJoin | |
$qb->select(array( | |
$qb->slt()->column('foobar', null, 'a'), | |
$qb->slt()->column('barfoo', null, 'a') | |
)); | |
$qb->fromJoin( | |
$qb->src()->document('Doctrine\Fqn\Foobar', 'a'), | |
$qb->src()->document('Doctrine\Fqn\Foobar', 'b'), | |
$qb->jcn()->equi( | |
'a', 'foobar', | |
'b', 'barfoo' | |
) | |
); | |
$qb->where($qb->cns()->descendantNode('/foobar')); | |
$qb->andWhere($qb->cns()->eq( | |
$qb->opr()->nodeLocalName('a'), | |
$qb->opr()->bindVariable('test_bar') | |
)); | |
$qb->orderBy(array( | |
$qb->ord()->ascending($qb->opr()->propertyValue('foobar', 'a')), | |
$qb->ord()->descending($qb->opr()->nodeLocalName('a')) | |
)); | |
$q = $qb->getQuery(); | |
$q->setParameter('test_bar', 'bar'); | |
$q->execute(); | |
// ******** ODM Iteration 3 ******** | |
// Factory f() uses same methods as PHPCR interface | |
// The object can either be specified with a method or as | |
// a magic string followed by its arguments. | |
$qb->select(array( | |
$qb->f('column', 'foobar', null, 'a'), | |
$qb->f('column', 'barfoo', null, 'a') | |
)); | |
$qb->from( | |
$qb->f('join', | |
$qb->f('documentSelector', 'Doctrine\Fqn\Foobar', 'a'), | |
$qb->f('documentSelector', 'Doctrine\Fqn\Foobar', 'b'), | |
$qb->f('equiJoinCon', | |
'a', 'foobar', | |
'b', 'barfoo' | |
) | |
) | |
); | |
$qb->where( | |
$qb->obj()->and( | |
$qb->f()->descendantNode('/foobar'), | |
$qb->f()->comparison( | |
$qb->f()->nodeLocalName('a'), | |
$qb->f()->bindVariable('test_bar'), | |
'EQUAL_TO' | |
) | |
) | |
); | |
$qb->orderBy(array( | |
$qb->f()->ascending($qb->opr()->propertyValue('foobar', 'a')), | |
$qb->f()->descending($qb->opr()->nodeLocalName('a')) | |
)); | |
$q = $qb->getQuery(); | |
$q->setParameter('test_bar', 'bar'); | |
$q->execute(); | |
I think you simply add a join as an argument to join. We shouldn't lose any functionality, this is almost like a proxy for the PHPCR builder.
The short names borrow from doctrine (eq, expr, neq, GT, etc) although I made the factory methods 3 chars so things align, but yeah that introduces problems with names like "CNS".
We could have just one factory, like QOMF, so jCon->equi might become fac()->equiJoinCondition
ok, updated this with a much better (in my opinion) interface. which I have put at the top of this gist.
//cc @lsmith77, @dbu, @wjzijderveld
I am a bit unsure here.
You are proposing "ODM Iteration 3"?
I do not like a method name "f" .. the method names need to be more verbose.
I would also like to see how it would work for simpler non join cases. Finally I think it should be possible to add a join to an existing query by simply adding additional method calls, rather than having to modify existing ones which seems to be necessary in your proposal.
no no no.. the first one, Iteration 4 :) (intuitive no?)
looks interesting.
slt
orord
, select and order are not so long that its a problem. if we provide full alternatives, reading the method names or using code completion will start to look overloaded.