PHPackages                             fabic/nql - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. fabic/nql

ActiveLibrary[HTTP &amp; Networking](/categories/http)

fabic/nql
=========

NQL is not GraphQL, but some sort of GraphQL-like impl. for the Rest of us.

v0.0.4(7y ago)314MITPHPPHP &gt;=7.0

Since Jun 10Pushed 7y ago1 watchersCompare

[ Source](https://github.com/fabic/nql)[ Packagist](https://packagist.org/packages/fabic/nql)[ Docs](http://fabic.net)[ RSS](/packages/fabic-nql/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependencies (1)Versions (6)Used By (0)

NQL is not GraphQL, at all.
===========================

[](#nql-is-not-graphql-at-all)

*Or maybe it is something like “GraphQL for the rest of us” ;-*

**EDIT/2018-06-10/v0.0.1:** publishing to packagist, even though it's in very early stages of development.

Use cases
---------

[](#use-cases)

- as an “extended” Symfony Property Path grammar ?.
- as an alternative to GraphQL ?
- at least for rapid prototyping client-side JS.
- ...

Getting started
---------------

[](#getting-started)

```
$ composer require fabic/nql
```

It might work without further configuration
-------------------------------------------

[](#it-might-work-without-further-configuration)

A route for `/api/nql/query` should exists that accepts a query as POST body.

Test with Curl:

```
$ curl -D /dev/stderr \
    -H "Content-Type: application/not+graphql" \
    -H "Accept: application/json" \
    -X POST http://localhost/api/nql/query \
    -d '\App\User { id, email, username, created_at, updated_at, roles }
'
```

### Laravel 5.4.x : Declare the service provider.

[](#laravel-54x--declare-the-service-provider)

```
// config/app.php
return [
    // ...
    'providers' => [
        // ...
        Fabic\Nql\Laravel\NqlServiceProvider::class,
    ]
    // ...
];
```

### Optional: Publish config/nql.php file

[](#optional-publish-confignqlphp-file)

```
$ ./artisan vendor:publish -v --provider="Fabic\Nql\Laravel\NqlServiceProvider"
```

### Optional: Setup CORS wrt. app that serves subdomains.

[](#optional-setup-cors-wrt-app-that-serves-subdomains)

```
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, X-Custom-Header"
Header always set "Access-Control-Allow-Methods" "GET, POST, OPTIONS, PUT, DELETE"

#Header always set Access-Control-Allow-Origin "*"
SetEnvIf Origin ^(https?://(?:.+\.)?(example.net|elsewhere.org|whatever.com)(?::\d{1,5})?)$  CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin  %{CORS_ALLOW_ORIGIN}e  env=CORS_ALLOW_ORIGIN

# This one is recommanded too, why? I can't remember.
Header merge  Vary "Origin"

```

#### Access-Control-Allow-Credentials true

[](#access-control-allow-credentials-true)

And also for XHR/Ajax requests to be received with credentials (i.e. authenticated) :

```
Header append Access-Control-Allow-Credentials true  env=CORS_ALLOW_ORIGIN

```

So that one would for ex. with jQuery :

```
$.ajax({
	type: 'POST',
	url: 'http://hyperion.example.net',
	data: $('form#nql-query').serialize(),
	xhrFields: { withCredentials: true },   //< (!)
	success: function (data) {
		console.log("RESPONSE", data);
	}
});
```

### Laravel API route decl.

[](#laravel-api-route-decl)

By means of a closure, directely in `routes/api.php` :

```
/* routes/api.php */
Route::post('/dude', function (Request $request) {

    $query = $request->getContent();

    \Log::debug("NQL: Query: $query");

    $parser = new \Fabic\Nql\Parser();

    $entities = $parser->parse($query);

    $result = $parser->apply($entities, [

        'users' => function(array &$meta, PropertyAccessorInterface $pa) {
            if (! empty($meta['identifier'])) {
                $user = \App\User::find($meta['identifier']);
                return $user;
            }
            else {
                $users = \App\User::all($columns);
                return $users;
            }
        },

        'orders' => \App\Order::all(),

        'order:states' => function(array &$meta, PropertyAccessorInterface $pa) {
            $states = \DB::table('orders')->groupBy('state')->get(['state'])->pluck('state');
            return $states;
        }

    ]);

    return $result;
});
```

### Experimenting with it

[](#experimenting-with-it)

```
$ curl -D /dev/stderr \
    -H "Content-Type: application/not+graphql" \
    -H "Accept: application/json" \
    --cookie "XDEBUG_SESSION=PHPSTORM; path=/; domain=.localdomain;" \
    -X POST http://localhost/api/nql/query \
    -d '
users | randomize | sort: updated_at | limit: 25 {
    id, name, surname, email,
    country {
        id,
        name,
        iso_code
    },
    created_at, updated_at
},
order:states
' \
  | jq -rC '.'
```

ChangeLog
---------

[](#changelog)

- 0.0.1 / 2018-06-10 : proof-of-concept impl.

Thanks &amp; Credits
--------------------

[](#thanks--credits)

- Thanks to the folks of `\Doctrine\Common\Annotations` which implementation was used as a starting point for the Lexer and Parser classes.

Notes to self
-------------

[](#notes-to-self)

### Development setup

[](#development-setup)

Dude, you did develop this one thing by creating a subdir. `fabic/nql` for that library into that fellow project...

```
/* composer.json of top-level project */
{
    "repositories": [
        {
            "type": "path",
            "url": "fabic/nql",
            "options": {
                "symlink": true
            }
        }
    ]
}
```

Then:

```
$ composer require --dev -vv fabic/nql:dev-master
```

Ensure Composer did symlink it as expected:

```
ls -ld vendor/fabic/nql
lrwxrwxrwx 1 fabi fabi 15 Jun 10 10:07 vendor/fabic/nql -> ../../fabic/nql
```

And you may have to run:

```
$ composer update -vv fabic/nql
```

once in a while when you change `composer.json`.

**EOF**

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity9

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

4

Last Release

2894d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/d59ccc40b330e253b10f65bac1113e3d72025be9f533146a09e8f559eca925e8?d=identicon)[fabic](/maintainers/fabic)

---

Top Contributors

[![fabic](https://avatars.githubusercontent.com/u/211503?v=4)](https://github.com/fabic "fabic (9 commits)")

---

Tags

composerlaravelrestgraphqlpackage

### Embed Badge

![Health badge](/badges/fabic-nql/health.svg)

```
[![Health](https://phpackages.com/badges/fabic-nql/health.svg)](https://phpackages.com/packages/fabic-nql)
```

###  Alternatives

[api-platform/core

Build a fully-featured hypermedia or GraphQL API in minutes!

2.6k48.1M236](/packages/api-platform-core)[lomkit/laravel-rest-api

A package to build quick and robust rest api for the Laravel framework.

59152.2k](/packages/lomkit-laravel-rest-api)[api-platform/laravel

API Platform support for Laravel

59126.4k6](/packages/api-platform-laravel)[threesquared/laravel-wp-api

Laravel package for the Wordpress JSON REST API

1310.3k](/packages/threesquared-laravel-wp-api)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
