Skip to content

Instantly share code, notes, and snippets.

@dantleech
Last active December 20, 2015 08:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dantleech/6098615 to your computer and use it in GitHub Desktop.
Save dantleech/6098615 to your computer and use it in GitHub Desktop.
Example of advanced phpcr query
<?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();
@dbu
Copy link

dbu commented Jul 28, 2013

looks interesting.

  • how do joins work in the last version when i would join more than 2 classes?
  • i am not too fond of the super short names like slt or ord, 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.

@dantleech
Copy link
Author

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

@dantleech
Copy link
Author

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

@lsmith77
Copy link

lsmith77 commented Aug 7, 2013

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.

@dantleech
Copy link
Author

no no no.. the first one, Iteration 4 :) (intuitive no?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment