fabic/nql

NQL 不是 GraphQL,但为其他人提供了一种类似 GraphQL 的实现。

v0.0.4 2018-06-11 17:48 UTC

This package is not auto-updated.

Last update: 2024-09-29 05:32:32 UTC


README

也许它就像是“为我们其余人的 GraphQL”;-

编辑/2018-06-10/v0.0.1: 尽管还处于非常初级的开发阶段,但已发布到 Packagist。

用例

  • 作为“扩展”的 Symfony 属性路径语法?
  • 作为 GraphQL 的替代品?
  • 至少对于客户端 JS 的快速原型设计。
  • ...

入门

$ composer require fabic/nql

可能无需进一步配置即可工作。

应该存在一个名为 /api/nql/query 的路由,该路由接受作为 POST 体的查询。

使用 Curl 测试

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

Laravel 5.4.x : 声明服务提供者。

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

可选:发布 config/nql.php 文件

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

可选:针对具有子域的 app 设置 CORS

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

并且也允许带有凭据(即经过身份验证)接收 XHR/Ajax 请求

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

例如,使用 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 路由声明。

通过在 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;
});

尝试使用它

$ curl -D /dev/stderr \
    -H "Content-Type: application/not+graphql" \
    -H "Accept: application/json" \
    --cookie "XDEBUG_SESSION=PHPSTORM; path=/; domain=.localdomain;" \
    -X POST https:///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 '.'

变更日志

  • 0.0.1 / 2018-06-10 : 实验性实现。

感谢 & 信用

  • 感谢 \Doctrine\Common\Annotations 的人们,该实现被用作 Lexer 和 Parser 类的起点。

自我备注

开发环境

伙计,你通过在该项目中创建一个子目录 fabic/nql 来创建这个库...

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

然后

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

确保 Composer 如期创建符号链接

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

并且你可能需要偶尔运行

$ composer update -vv fabic/nql

每次更改 composer.json 时。

EOF