php - Laravel 工厂关联只关联最后的数据。如何解决这个问题?
问题描述
创建数据后,我有 2 个模型需要关联。我已经在这里问过了并得到了答案。我实现了它并进行了一些修改,因为它没有正确关联数据。现在我的协会有问题。它仅与最后一个数据相关联。
我期待的是从工厂创建的所有数据都是相互关联的。
当我执行php artisan tinker
并运行App\App::first()->load('menus', 'menus.page')
命令时,它没有给我正确的数据。请在此处查看结果。
如您所见,正确的数据仅显示在最后一个对象上。剩下的就是null
。我怎样才能解决这个问题?请看下面我的播种机文件,我犯了什么错误吗?
<?php
use App\App;
use App\Component;
use App\Menu;
use App\Page;
use App\Role;
use App\Submenu;
use App\User;
use Illuminate\Database\Seeder;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$superadmin = Role::whereName('superadmin')->first();
$tester = new User();
$tester->name = "Tester";
$tester->email = "test@appbuilder.com";
$tester->password = bcrypt('password');
$tester->save();
$tester->roles()->attach($superadmin);
// Create 5 apps for each user
$tester->apps()->saveMany(factory(App::class, 5)->make())->each(function ($app) {
$menus = factory(Menu::class, 5)->make();
$pages = factory(Page::class, 5)->make();
// Create 5 menus for each app and 5 submenus for each menu
$app->menus()->saveMany($menus)->each(function ($menu) use ($pages) {
// Associate page with each menu
$pages->each(function ($page) use ($menu) {
$page->menu()->associate($menu);
});
// Create 5 submenus for each menu
$menu->submenus()->saveMany(factory(Submenu::class, 5)->make())->each(function ($submenu) use ($pages) {
// Associate page with each submenu
$pages->each(function ($page) use ($submenu) {
$page->submenu()->associate($submenu);
});
});
});
// Create 5 pages for each app and 5 components for each page
$app->pages()->saveMany($pages)->each(function ($page) {
$page->components()->saveMany(factory(Component::class, 5)->make());
});
});
}
}
更新
这是我的模型文件,请看一下:
App.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class App extends Model
{
/**
* The attributes that should not be mass assignable.
*
* @var array
*/
protected $guarded = ['id'];
/**
* Each app belongs to a user.
*
* @return \Illuminate\Database\Eloquent\Relationship\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Each app has many pages.
*
* @return \Illuminate\Database\Eloquent\Relationship\HasMany
*/
public function pages()
{
return $this->hasMany(Page::class);
}
/**
* Each app has many menus.
*
* @return \Illuminate\Database\Eloquent\Relationship\HasMany
*/
public function menus()
{
return $this->hasMany(Menu::class);
}
}
Menu.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Menu extends Model
{
/**
* The attributes that should not be mass assignable.
*
* @var array
*/
protected $guarded = ['id'];
/**
* Each menu belongs to a app.
*
* @return \Illuminate\Database\Eloquent\Relationship\BelongsTo
*/
public function app()
{
return $this->belongsTo(App::class);
}
/**
* Each menu has one page.
*
* @return \Illuminate\Database\Eloquent\Relationship\HasOne
*/
public function page()
{
return $this->hasOne(Page::class);
}
/**
* Each menu has many submenus.
*
* @return \Illuminate\Database\Eloquent\Relationship\HasMany
*/
public function submenus()
{
return $this->hasMany(Submenu::class);
}
/**
* Each menu belongs to many roles.
*
* @return \Illuminate\Database\Eloquent\Relationship\BelongsToMany
*/
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
Page.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Page extends Model
{
/**
* The attributes that should not be mass assignable.
*
* @var array
*/
protected $guarded = ['id'];
/**
* Each page belongs to an app.
*
* @return \Illuminate\Database\Eloquent\Relationship\BelongsTo
*/
public function app()
{
return $this->belongsTo(App::class);
}
/**
* Each page has many components.
*
* @return \Illuminate\Database\Eloquent\Relationship\HasMany
*/
public function components()
{
return $this->hasMany(Component::class);
}
/**
* Each page belongs to a menu.
*
* @return \Illuminate\Database\Eloquent\Relationship\BelongsTo
*/
public function menu()
{
return $this->belongsTo(Menu::class);
}
/**
* Each page belongs to a submenu.
*
* @return \Illuminate\Database\Eloquent\Relationship\BelongsTo
*/
public function submenu()
{
return $this->belongsTo(Submenu::class);
}
}
解决方案
那么事实上你确实犯了一个错误。通过遍历菜单循环内的每一页。因此,在第一次运行中,每个页面都会与第一个菜单条目相关联。在第二次运行时,每个页面都有第二个菜单项,依此类推。最终导致这样一个事实,即每个页面都与最后一个菜单条目相关联。
为了保持结构像你有一个可以做这样的事情:
$tester = new \App\User();
$tester->name = "Tester";
$tester->email = "test@appbuilder.com";
$tester->password = bcrypt('password');
$tester->save();
// Create 5 apps for each user
$tester->apps()->saveMany(factory(\App\App::class, 5)->make())->each(function ($app) {
$menus = factory(\App\Menu::class, 5)->make();
$pages = factory(\App\Page::class, 5)->make();
$pagesIterator = $pages->getIterator();
// Create 5 menus for each app and 5 submenus for each menu
$app->menus()->saveMany($menus)->each(function ($menu) use ($pagesIterator) {
$page = current($pagesIterator);
$page->menu()->associate($menu);
// Create 5 submenus for each menu
$menu->submenus()->saveMany(factory(\App\Submenu::class, 5)->make())->each(function ($submenu) use ($page) {
// Associate page with each submenu
$page->submenu()->associate($submenu);
});
next($pagesIterator);
});
// Create 5 pages for each app and 5 components for each page
$app->pages()->saveMany($pages)->each(function ($page) {
$page->components()->saveMany(factory(\App\Component::class, 5)->make());
});
});
因此,我们只需通过迭代器从循环内的集合中获取下一页,并将每个菜单与集合中的下一页相关联。(请注意,如果您希望每个子菜单关联不同的页面,则需要创建更多页面......)
题外话:
$page->menu()->associate($menu);
通常需要一个$page->save()
后跟,因为 associate() 方法不会自动保存。在您的情况下, $pages 通过在最后调用来持久化到数据库$app->pages()->saveMany($pages)
中。
推荐阅读
- ios - 如何转换 UITextField 中的数字并将其传递给 UITableViewCell 中的 UILabel?
- java - 如何在 mongodb Spring Boot 中持久化嵌套文档?
- node.js - 登录表单未正确发布
- javascript - Greasemonkey - 集成滚动和鼠标点击动作
- python - django.core 序列化器和 Django Rest Framework 序列化器之间的区别
- javascript - 如何在给定时区的情况下将时间转换为 UTC?
- c# - 访问时填充数据集表
- java - 我正在尝试在播放声音时显示暂停图标,然后在声音播放完毕时显示播放图标
- vb.net - 如何克服“数组范围外的索引”?
- c# - 如何从命令行使用 msbuild 编译我的 c# 解决方案