#laravel #eloquent #graphql #laravel-lighthouse
#laravel #красноречивый #graphql #laravel-lighthouse
Вопрос:
У меня есть проект, который я конвертирую из Rails REST API в Laravel GraphQL API (я новичок в Laravel), и я работаю над настройкой моделей и отношений.
У меня есть categories
, category_items
, и items
таблица.
В category_items
таблице есть столбцы для category_id
, item_id
и position
.
В items
таблице есть столбец для category_id
.
Когда я открываю artisan tinker и запускаю AppModelsCategory::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
столбец из сводной таблицы в объект item. По сути, вместо того, чтобы иметь столбец «позиция», вложенный внутри оси элемента, я бы хотел, чтобы «позиция» была включена как часть объекта Item, однако я не уверен, возможно ли это.
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 AppModels;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsBelongsTo;
use IlluminateDatabaseEloquentRelationsHasMany;
use IlluminateDatabaseEloquentRelationsBelongsToMany;
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('AppModelsItem', 'category_items', 'item_id', 'category_id')
->using('AppModelsCategoryItem')
->withPivot(['position'])
->withTimestamps();
}
}
CategoryItem.php
<?php
namespace AppModels;
use IlluminateDatabaseEloquentRelationsPivot;
use IlluminateDatabaseEloquentRelationsHasMany;
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 AppModels;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsBelongsTo;
use IlluminateDatabaseEloquentRelationsBelongsToMany;
class Item extends Model
{
protected $fillable = [
'name', 'price', 'category_id', 'quantity'
];
// define relationships
public function categories(): BelongsToMany
{
return $this
->belongsToMany('AppModelsCategory', 'category_items', 'item_id', 'category_id')
->using('AppModelsCategoryItem')
->withPivot(['position'])
->withTimestamps();
}
public function category_item(): BelongsTo
{
return $this->belongsTo('AppModelsCategoryItem');
}
}
Итак, в заключение, мои вопросы:
- Что вызывает ошибку GraphQL на игровой площадке?
- Можно ли добавить свойство сводной таблицы к ее непосредственному родительскому объекту?
Комментарии:
1. Обычно вам не нужно создавать модель для вашей сводной таблицы, но если вы хотите, вам нужно указать имя таблицы, поскольку вы используете нестандартное имя.
protected $table = 'category_items';
Сводная таблица должна быть названа с помощью символов в алфавитном порядке, такcategory_item
что .2. Вы знаете, я действительно прочитал это в документах, и это вызвало другие ошибки, поэтому я сохранил это. Я могу начать идти по этому маршруту, чтобы снова его протестировать. На всякий случай, к какой модели я бы применил
protected $table
? Кроме того, вы хотите сказать, что само имя таблицы должно быть «category_item» вместо «category_items»? Потому что все мои таблицы множественны: «категории», «category_items», «элементы» …. это просто соглашение об именовании Rails, и в Laravel все они должны быть разделены?3. Хорошо, просто дважды проверил источник, и да, сводные модели ожидают единственное имя таблицы, поэтому вам следует включить это свойство в
CategoryItem
определение вашей модели. Извините за беспорядок при редактировании, я не должен был сомневаться в себе!4. Все хорошо, я ценю помощь! Исправлена исходная ошибка, однако теперь я получаю
Cannot return null for non-nullable field Item.category_item
Ответ №1:
@miken32 очень помог с этим. Я удалил ненужные CategoryItem.php модель, переименовал таблицу БД из category_items
в category_item
, и в моем schema.graphql
переопределил типы следующим образом:
type Category {
id: ID!
name: String!
created_at: DateTime!
updated_at: DateTime!
pivot: CategoryItemPivot
items: [Item!]! @belongsToMany
}
type CategoryItemPivot {
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
pivot: CategoryItemPivot
}