Code Monkey home page Code Monkey logo

php-rql-parser's Introduction

php-rql-parser - Query MongoDB using RQL in PHP

This is a wrapper around libgraviton/rql-parser that combines that parser with a small layer of mongodb integration.

This package adheres to SemVer versioning.

It uses a github version of git-flow in which new features and bugfixes must be merged to develop using a github pull request. It uses the standard git-flow naming conventions with the addition of a 'v' prefix to version tags.

Installation

Install it using composer.

composer require graviton/php-rql-parser

Usage

<?php

require 'vendor/autoload.php';

$rql = 'or(eq(name,foo)&eq(name,bar))';

/** @var \Doctrine\ODM\MongoDB\Query\Builder $builder */
$visitor = new \Graviton\Rql\Visitor\MongoOdm();
$visitor->setBuilder($builder);
$lexer = new \Graviton\RqlParser\Lexer;
$parser = \Graviton\RqlParser\Parser::createDefault();

// parse some Resource Query Language 
$rqlQuery = $parser->parse($lexer->tokenize($rql));

// get query
$query = $visitor->visit($rqlQuery)->getQuery();

// ...

Development

We welcome contributions on the develop branch.

php-rql-parser's People

Contributors

clementedalmagro avatar gfellerleonard avatar hairmare avatar lapistano avatar mrix avatar narcoticfresh avatar phil2211 avatar tobster67 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-rql-parser's Issues

Encoding special chars with URL encoding

Lexer ignores rules written in RQL documentation:

The RQL grammar is based around standard URI delimiters. The standard rules for encoding strings with URL encoding (%xx) are observed.

For example RQL eq(id,a%20b) is parsed as:

Graviton\Rql\AST\EqOperation {
  -property: "id"
  -value: "a%20b"
}

Expected result:

Graviton\Rql\AST\EqOperation {
  -property: "id"
  -value: "a b"
}

String values with a space

I get the following error:

Invalid character \" \" at position 14

when executing the following query:

(eq(field,some value with spaces))

I have got around this by amending the REGEX_VALUE const in the Lexer class to:

const REGEX_VALUE = '/(\s|\w|\-|\+|\*|\?|\:|\.|\%[0-9a-f]{2})+/Ai';

MongoOdm constructor

From README:Usage section:

/** @var \Doctrine\ODM\MongoDB\Query\Builder $builder */
$visitor = new \Graviton\Rql\Visitor\MongoOdm($builder);

MongoOdm doesn't have constructor and so it cannot set builder from constructor.

Add return $this; to setters.

Why is class MongoOdm final??

sorting is ignored when combined with lt()

This is from GRV-1497 and pertains to 2.0.0-alpha1.

Sorting seems to not work in combination with lt(). The following example is how this was reproduced.

lt(id,3),sort(-group)
  • check if this was fixed in 2.0.0-alpha7
  • add test cases to MongoDbVisitor
  • fix bug

print visitor

We need a small visitor implementation for pretty printing of parsed rql. I assume we'll be adding a rql:debug command in graviton/rql-parser-bundle so devs can debug snippets of rql using this visitor.

After we remove the mongodb visitor in #16 this will also be the reference implementation of a visitor.

sort(<+|-><property>) vs. sort(<property>,<direction>)

According to the RQL specification, sort() requires a list of properties prepended with a + or -, not a property followed by a direction. The current parser does a great job of allowing this functionality, no complaints there, but the sort() description in QueryInterface.php is misleading. Something akin to the following might be better:

/**
 * @param string $fields,... List of fields, each prefixed with <+|->
 *
 * @return mixed
 */
public function sort(/* ... */);

...and here is one possible implementation:

/**
 * {@inheritdoc}
 */
public function sort(/* ... */)
{

    $fields = func_get_args();
    $out = array();

    // Note that + must be URL encoded as %2B
    foreach( $fields as $field ) {
        switch( $field[0] ) {
            case '+' : array_push($out, substr($field, 1) . ' ASC' ); break;
            case '-' : array_push($out, substr($field, 1) . ' DESC' ); break;
            default: throw new \Exception("Must specify valid sort order for field {$field}"); break;
        }
    }

    $out = implode( ', ', $out );

    // And just for debugging...
    print_r( $out );
    exit;

}

Personally, I like implementing sorting as sort($field, $direction = false), where $direction indicates whether the sorting should be reversed (i.e. DESC). This works great with the pipe/ajax functionality of the SmartTable module for AngularJS. (However, much like the suggested implementation described in QueryInterface.php, my implementation does not follow RQL spec.)

Here it is, if anyone out there is looking for more examples:

public function sort($field, $direction = false)
{
    // protected function wrapTable() turns objects.title into `objects`.title
    // It is meant for resolving ambiguity in joins by verifying against a list of allowed tables
    // e.g. foobar.title would not be allowed, b/c table `foobar` is not assoc. with the current entity
    $field = $this->wrapTable( $field );
    $direction = filter_var($direction, FILTER_VALIDATE_BOOLEAN);
    $direction = $direction ? 'DESC' : 'ASC';
    array_push( $this->order, "{$field} {$direction}" );
    // ...and then I retrieve the order with $queriable->get_order();
    // Of course, currently, I'm limited to sorting by one field at a time
}

I'm using PHP ActiveRecord in my project. I've written a QueryInterface implementation for it, which generates an $options['conditions'] array. I'd be happy to add it to the project as an example. I've never done a pull request before, but let me know if you are interested, and I'll figure out how to do it. Cheers!

expose proper error handling api

This should be simple. We just need to add some classes based off Exception document them and throw them at the right places. This will also need some kind of example in the docs and it should be built in a way that it interacts nicely with symfonys expection stuff.

Some nodes are missing in AST after parsing

No limit in AST eq(id,1),sort(+a,-b),limit(1,2):

Graviton\Rql\AST\QueryOperation {#148
  -queries: array:2 [
    0 => Graviton\Rql\AST\EqOperation {#147
      -property: "id"
      -value: 1
    }
    1 => Graviton\Rql\AST\SortOperation {#149
      -fields: array:2 [
        0 => array:2 [
          0 => "a"
          1 => "asc"
        ]
        1 => array:2 [
          0 => "b"
          1 => "desc"
        ]
      ]
    }
  ]
}

No sort in AST eq(id,1),limit(1,2),sort(+a,-b):

Graviton\Rql\AST\QueryOperation {#162
  -queries: array:2 [
    0 => Graviton\Rql\AST\EqOperation {#161
      -property: "id"
      -value: 1
    }
    1 => Graviton\Rql\AST\LimitOperation {#163
      -limit: "1"
      -skip: "2"
    }
  ]
}

No eq in AST sort(+a,-b),eq(id,1):

Graviton\Rql\AST\SortOperation {#175
  -fields: array:2 [
    0 => array:2 [
      0 => "a"
      1 => "asc"
    ]
    1 => array:2 [
      0 => "b"
      1 => "desc"
    ]
  ]
}

make parser strategies configurable

it should be possible to configure the set of RQL-Parser-Strategies to be able to influence the parsing process.
It would further open the parser to other strategies without the need to change the implementation.

implement sugar syntax handling

We need the parser to implement at least some of the sugar syntax variants. In some areas this will need quite some refactoring of the existing parsers but other areas should be easy.

  • & instead of and() (maybe , should do this as per spec as well)
  • | instead of or()
  • name=val instead of eq(name,val)
  • count=lt=10 instead of lt(count,10)
  • name=val&count=1 instead of eq(name,val),eq(count,1)
  • () based arrays (ie. foo=in=(3,bar,true,2000-01-01T00:00:00Z)
  • typecasting (ie foo=string:3)
  • array nesting: (foo,bar)=3 instead of eq(foo.bar,3)
  • array nesting: foo/bar=3 instead of eq(foo.bar,3)

This listing is neither complete neither do I expect us to implement all of it. We'll close this as soon as we reach some kind of consensus that what's implemented is easy enough.

add logging

Lots of it! We need to be able to pass a PSR\Log\LoggerInterface to the parser and visitor structures so they can do heaps of logging.

Fixing this should add a lot of log calls throughout the codebase and make debugging this when it is embedded in your code base possible.

The logger part should be injectable using constructor injection making it optional by passing an included dummy logger.

An idea is to add monolog/monolog to "dev" in composer.json so we can have a nice embedded example of how it all really works in test/.

Rewrite Parser approach

I was trying to implement them by my self but I could not get the regex working. I'm not so good at regex :D

What I was trying to do is parsing a query like this "(eq(foo,3)&lt(price,10))|eq(bar,5)" and I was expecting to get it parsed according to what you written in the README but actually it is not.

Could you please help me parsing this query so then I can fix my Queriable class to handle it?

Thanks a lot

Numerical values in array operators

RQL in(id,[1,2,3]) cannot be parsed:

Graviton\Rql\Exceptions\SyntaxErrorException {#92
   #message: "no string found"
   #code: 0
   #file: "vendor/graviton/php-rql-parser/src/Parser/ParserUtil.p"…2
   #line: 155
}

But in(id,[a,b,c]) is parsed correctly:

Graviton\Rql\AST\InOperation {#106
   -property: "id"
   -array: array:3 [
     0 => "a"
     1 => "b"
     2 => "c"
   ]
}

And eq(id,1):

Graviton\Rql\AST\EqOperation {#64
   -property: "id"
   -value: 1
}

and() and or() only work with eq() and ne()

This is from GRV-1497 and pertains to 2.0.0-alpha1.

Only eq() and ne() seem to be supported as <query> in and() and or() operators. The following example is how this was reproduced.

and(eq(name,foo),lt(count,3))
  • check if this was fixed in 2.0.0-alpha2 v2.0.0-alpha7
  • add test cases to MongoDbVisitor
  • fix bug

test dues are overdue

This module needs acceptance, unit testing as well as some basic qa. For starters I believe we will need to implement the following.

  • Unit tests that tests the parser agains a mocked instance of Graviton\Rql\QueryInterface. This should cover all the code except Graviton\Rql\Queriable\MongoOdm.
  • Acceptance tests that test Graviton\Rql\Queriable\MongoOdm mocked (or even faked) data.
  • CodeSniffer and PMD reports that are run on build with sensible error/warn conditions.

implement more features in parser and ast

This issues tracks new features we should add to the AST.

  • select(<property>,<property>,...) - Trims each object down to the set of properties defined in the arguments
  • first() - Returns the first record of the query's result set
  • one() - Returns the first and only record of the query's result set, or produces an error if the query's result set has more or less than one record in it
  • count() - Returns the count of the number of records in the query's result set

I copied those that I think look handy :) Feel free to just add more if you have edit right or ping us with you needs if you need anything not on the list.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.