我正在尝试创建我的第一个多态关系,并遵循了网站上的文档,并查看了几个在线教程,这些教程都遵循了类似的主题。我有三张桌子,页面,菜单和菜单项。菜单项将始终是菜单的子项,并且将是一个页面(在链接的情况下)或另一个菜单(在子菜单的情况下,)。我的桌子是:
页面
+----+------+----------+------+--------+-----------+-----------------+------------+------------+------------+
| id | name | url_slug | file | layout | seo_title | seo_description | created_at | updated_at | deleted_at |
+----+------+----------+------+--------+-----------+-----------------+------------+------------+------------+
菜单
+----+------+------------+------------+
| id | name | created_at | updated_at |
+----+------+------------+------------+
菜单项
+----+---------+-------------+---------------+-------+------+-------+------------+------------+
| id | menu_id | itemable_id | itemable_type | label | left | right | created_at | updated_at |
+----+---------+-------------+---------------+-------+------+-------+------------+------------+
因此,对于菜单项表,menu_id
是菜单项的父项,它与菜单表具有一对多关系。itemable_id
和itemable_type
用于复数关系,itemable_id
应参考菜单或页面中的id
列,这取决于itemable_type
是什么,它将是菜单或页面模型。
为了创建这种关系,我在模型中添加了如下方法:
页面
/**
* Fetch the menu items this page is linked to.
*
* @return 'Illuminate'Database'Eloquent'Relations'MorphMany
*/
public function menuItems()
{
return $this->morphMany('App'Modules'Menu'Models'MenuItem', 'itemable');
}
菜单
/**
* Fetch all child menu items belonging to this menu.
*
* @return 'Illuminate'Database'Eloquent'Relations'HasMany
*/
public function childItems()
{
return $this->hasMany('App'Modules'Menu'Models'MenuItem');
}
/**
* Fetch all menu items linked to this menu.
*
* @return 'Illuminate'Database'Eloquent'Relations'MorphMany
*/
public function menuItems()
{
return $this->morphMany('App'Modules'Menu'Models'MenuItem', 'itemable');
}
菜单项
/**
* Fetch the menu this item belongs to.
*
* @return 'Illuminate'Database'Eloquent'Relations'BelongsTo
*/
public function menu()
{
return $this->belongsTo('App'Modules'Menu'Models'Menu');
}
/**
* Fetch the models this menu item links to.
*
* @return 'Illuminate'Database'Eloquent'Relations'MorphTo
*/
public function itemable()
{
return $this->morphTo();
}
我已经创建了所有的表,现在我正在尝试为它们播种。我的种子是这样的:
public function run()
{
$menu = Menu::create([
'name' => 'Main'
]);
foreach ( [
[
'page_id' => 1,
'label' => 'Home',
'left' => 1,
'right' => 2
],
[
'page_id' => 2,
'label' => 'About Us',
'left' => 3,
'right' => 4
]
] as $arr )
{
/* @var $page Page */
$page = Page::findOrFail($arr['page_id']);
$item = new MenuItem($arr);
$page->menuItems()->save($item);
$item->menu()->associate($menu);
}
}
但是,当我在page_id
列不存在的情况下运行它时,我总是会遇到错误。准确的错误是
[Illuminate'Database'QueryException]
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'page_id' in 'field list' (SQL: insert into `menu_items` (`page_id`, `label`, `left`, `right`, `itemable_type`, `itemable_id`, `updated_at`, `created_at`) values (1, Home, 1, 2, App'Models'Page, 1, 2016-08-03 12:32:21, 2016-08-03 12:32:21))
除了尝试填充page_id
和itemable列之外,查询的所有内容都很好。它为什么要这么做?我该如何避开它?
尝试将page_id
更改为itemable_id
[
'page_id' => 1, //change this to itemable_id
'label' => 'Home',
'left' => 1,
'right' => 2
],
[
'page_id' => 2, //change this to itemable_id
'label' => 'About Us',
'left' => 3,
'right' => 4
]
因为在下面的行中,
$item = new MenuItem($arr);
当您试图在MenuItem中插入$arr
时,它应该是itemable_id
,而不是page_id
因此,您更新的代码如下所示:
public function run()
{
$menu = Menu::create([
'name' => 'Main'
]);
foreach ( [
[
'itemable_id' => 1,
'label' => 'Home',
'left' => 1,
'right' => 2
],
[
'itemable_id' => 2,
'label' => 'About Us',
'left' => 3,
'right' => 4
]
] as $arr )
{
/* @var $page Page */
$page = Page::findOrFail($arr['itemable_id']);
$item = new MenuItem($arr);
$page->menuItems()->save($item);
$item->menu()->associate($menu);
}
}
您的menu_items
列不包含任何page_id
列,当您尝试种子时,您尝试将新数据存储到menu_items
中,它将用您的目标表检查file_list
中的每一列,该表在这里是menu_items
,它包含
菜单项
+----+---------+-------------+---------------+-------+------+-------+------------+------------+
| id | menu_id | itemable_id | itemable_type | label | left | right | created_at | updated_at |
+----+---------+-------------+---------------+-------+------+-------+------------+--
所以像一样将列重命名为itemable_id
foreach ( [
[
'itemable_id' => 1,
'label' => 'Home',
'left' => 1,
'right' => 2
],
[
'itemable_id' => 2,
'label' => 'About Us',
'left' => 3,
'right' => 4
]
] as $arr )
{
/* @var $page Page */
$page = Page::findOrFail($arr['itemable_id']);