【发布时间】:2021-02-22 21:52:39
【问题描述】:
我有一个项目,我正在从 Rails REST API 转换为 Laravel GraphQL API(我是 Laravel 的新手),并且正在设置模型和关系。
我有一个categories、category_items 和items 表。
category_items 表包含 category_id、item_id 和 position 的列。
items 表有一列用于category_id。
当我打开 artisan tinker 并运行 App\Models\Category::find(1)->items()->get(); 时,它会返回所有预期的内容(包括嵌套在 Item 对象下方的数据透视表)。但是,当我在 graphql-playground 中运行它时,我得到了错误:
"debugMessage": "SQLSTATE[42S02]: Base table or view not found: 1146 Table 'my_project.category_item' doesn't exist (SQL: select * from `category_item` where 0 = 1)",
我有一种感觉,我忽略了一些微小的东西,就像我不知道的错字或命名约定一样。
我还想做的是在项目对象中包含来自数据透视表的position 列。本质上,我不想将“位置”列嵌套在项目的枢轴内,而是希望将“位置”作为项目对象的一部分包含在内,但是我不确定这是否可能。
Schema.graphql
type Query {
categories: [Category!]! @field(resolver: "CategoriesQuery@find_by_user")
items: [Item!]! @field(resolver: "ItemsQuery@find_by_user")
notifications: [Notification!]! @field(resolver: "NotificationQuery@find_by_user")
}
type Category {
id: ID!
name: String!
created_at: DateTime!
updated_at: DateTime!
category_items: [CategoryItem!]! @hasMany
items: [Item!]! @belongsToMany
}
type CategoryItem {
id: ID!
position: Int!
created_at: DateTime!
updated_at: DateTime!
categories: [Category!]! @hasMany
items: [Item!]! @hasMany
}
type Item {
id: ID!
name: String
quantity: Int
created_at: DateTime!
updated_at: DateTime!
categories: [Category]! @belongsToMany
category_item: CategoryItem! @belongsTo
}
Category.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Category extends Model
{
protected $fillable = [
'name'
];
// automatically eager load items of a category
protected $with = ['items'];
// define relationships
public function category_items(): HasMany
{
return $this->hasMany(CategoryItem::class);
}
public function items(): BelongsToMany
{
return $this
->belongsToMany('App\Models\Item', 'category_items', 'item_id', 'category_id')
->using('App\Models\CategoryItem')
->withPivot(['position'])
->withTimestamps();
}
}
CategoryItem.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\Relations\HasMany;
class CategoryItem extends Pivot
{
protected $fillable = [
'category_id', 'item_id', 'position'
];
// public function category(): HasMany
// {
// return $this->hasMany(Category::class);
// }
// public function item(): HasMany
// {
// return $this->hasMany(Item::class);
// }
}
Item.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Item extends Model
{
protected $fillable = [
'name', 'price', 'category_id', 'quantity'
];
// define relationships
public function categories(): BelongsToMany
{
return $this
->belongsToMany('App\Models\Category', 'category_items', 'item_id', 'category_id')
->using('App\Models\CategoryItem')
->withPivot(['position'])
->withTimestamps();
}
public function category_item(): BelongsTo
{
return $this->belongsTo('App\Models\CategoryItem');
}
}
总结一下,我的问题是:
- 是什么导致了 Playground 中的 GraphQL 错误?
- 是否可以将透视表属性附加到其直接父对象?
【问题讨论】:
-
您通常不需要为数据透视表创建模型,但如果您愿意,您需要指定表名,因为您使用的是非标准名称。
protected $table = 'category_items';数据透视表应该按字母顺序用单数命名,所以category_item. -
你知道,我实际上是在文档中读到的,它导致了其他错误,所以我保留了它。我可以开始沿着这条路线再次测试它。不过以防万一,我会将
protected $table应用于哪个模型?另外,您是说表名本身应该是“category_item”而不是“category_items”?因为我所有的表都是复数形式的:“categories”、“category_items”、“items”....这只是 Rails 命名约定,而在 Laravel 中这些都应该是单数形式吗? -
好的,只需仔细检查源代码,是的,数据透视模型确实需要一个单数表名,因此您应该将该属性放入您的
CategoryItem模型定义中。抱歉编辑混乱,我不应该怀疑自己! -
一切都好,感谢您的帮助!它修复了原来的错误,但是现在我得到了
Cannot return null for non-nullable field Item.category_item
标签: laravel eloquent graphql laravel-lighthouse