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 - 在服务器端排序

变异中的 Laravel LightHouse GraphQL DateTime 输入始终为空

Lighthouse 找不到我的 Union 自定义类型