Lighthouse GraphQL 将 ID 转换为字符串而不是整数?
Posted
技术标签:
【中文标题】Lighthouse GraphQL 将 ID 转换为字符串而不是整数?【英文标题】:Lighthouse GraphQL casts ID to string instead of Integer? 【发布时间】:2021-03-20 08:32:15 【问题描述】:我有一个应用程序,在后端使用 Laravel 和 Lighthouse,在前端使用 Nuxt 和 Vuex-ORM/graphql-plugin。我很难进行比较,因为无论出于何种原因,有时数据会被查询或变异,并且 ID 似乎是整数或字符串的混合体。
我正在努力确保每个 ID 实际上都是一个整数。每当我在前端 console.log 一个 Trip 时,那个 Trip 的 ID 仍然是一个字符串。当我在 graphql-playground 中运行查询时,它以字符串形式返回,但我认为这更多是因为它是一个“ID”标量类型,可以是 int 或字符串。或者其他的东西。我不知道,我还是很喜欢这个。
Trip.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Trip extends Model
protected $fillable = [
'name', 'description', 'user_id'
];
// automatically eager load todos and shopping_list_items
protected $with = [
'items', 'users'
];
// define relationships
public function users(): BelongsToMany
return $this->belongsToMany(User::class);
trip.graphql:
extend type Query @guard(with: ["api"])
trip(id: ID! @eq): Trip! @find
trips: [Trip]! @field(resolver: "TripsQuery@find_by_user")
extend type Mutation @guard(with: ["api"])
updateTrip(id: ID! trip: TripInput! @spread): Trip @update
type Trip
id: ID!
name: String
description: String
created_at: DateTime!
updated_at: DateTime!
user_id: ID
items: [Item]! @hasMany
users: [User]! @hasMany
input TripInput
name: String
description: String
user_id: ID
trip.js:
import Model from '@vuex-orm/core';
import Item from './item';
import TripUser from './tripUser';
import User from './user';
export default class Trip extends Model
static entity = 'trips';
static eagerLoad = ['items', 'users'];
static fields ()
return
id: this.number(0),
name: this.string(''),
description: this.string(''),
user_id: this.number(0),
// relationships
items: this.hasMany(Item, 'trip_id'),
users: this.belongsToMany(User, TripUser, 'trip_id', 'user_id')
;
;
planning.vue:
<script>
import currentUser from '~/mixins/currentUser';
import Trip from '~/data/models/trip';
import tripsQuery from '~/apollo/queries/content/trips.gql';
export default
name: 'Planning',
middleware: 'authenticated',
mixins: [currentUser],
data: () => (
loading: 1,
),
computed:
trips ()
return Trip.query().where('owner_id', this.currentUser.id).all();
,
async mounted ()
const trips = await this.$store.dispatch('entities/simpleQuery',
query: tripsQuery,
variables: ,
bypassCache: false
);
console.log(typeof trips[0].id); // <--- returns 'string';
Trip.insert( data: [...trips] );
this.selectedTrip = trips.length ? trips[0] : null;
this.loading = 0;
,
head ()
return
title: 'Planning'
;
;
</script>
您可以在 Vue 文件中 mounted
函数的 console.log 中看到,id 仍然以字符串而不是整数的形式返回。如何确保它始终是整数?
更新: 我想我已经使用我正在使用的@vuex-orm/plugin-graphql 库将其缩小到一个更大的问题。我试图恢复一点,以便所有内容都使用字符串 id,但是我发现当我调度突变时,由于某种原因,有代码将 id 转换为整数。我将向该库提交错误报告,然后关闭此问题。
【问题讨论】:
【参考方案1】:我想在这里插话并指出 ID 被设计为字符串,而不是错误。你在这个 SO 答案中看到了更多关于它的信息:https://***.com/a/47888604/11678503
简而言之,ID 是在GraphQL specification(2018 年 6 月工作规范)中定义的标量类型:
ID 标量类型表示唯一标识符,通常用于重新获取对象或作为缓存的键。 ID类型的序列化方式与String相同;但是,它并不适合人类阅读。虽然它通常是数字,但它应该始终序列化为字符串。
虽然数据库中的 ID 通常是自动递增的数字键,但这绝不是标准。许多 API 使用哈希和 UUID,因为它取决于用例。因此,ID 始终可以是字符串,但不能始终是数字——因此为什么转换为字符串是更安全的选择。
所以我希望能弄清楚为什么 Lighthouse 以及 graphql-php library 将 ID 转换为字符串。他们符合规范。
希望这有助于解决问题!
【讨论】:
一点额外的一点是,当您知道您的 id 是整数时,您当然可以将类型更改为Int
而不是 ID
。这样,它们在返回时将始终转换为整数。
完全理解,你会看到我在第二段中提到了关于 ID 标量类型的内容。同样在帖子底部的更新中,我解释说我在@vuex-orm/plugin-graphql 库中发现了一个错误/功能,当调度突变时,ID 会转换为整数,所以不管我更喜欢以哪种方式开始,无论哪种方式我都搞砸了。最后我决定放弃那个库,因为它还不够成熟,这很遗憾,因为我喜欢这个想法。感谢您的 cmets!以上是关于Lighthouse GraphQL 将 ID 转换为字符串而不是整数?的主要内容,如果未能解决你的问题,请参考以下文章
Laravel Lighthouse Graphql HasOne 嵌套关系不起作用
在 Laravel/Lighthouse GraphQL API 中实现搜索功能
如何在lighthouse graphql laravel中获取自定义指令参数?
Laravel Lighthouse GraphQL - 在服务器端排序