【问题标题】:Laravel 5.8 - Seeding a ManyToOne relationshipLaravel 5.8 - 播种多对一关系
【发布时间】:2019-11-17 11:34:00
【问题描述】:

大家晚上好,

我期待通过我的 Post Table 中的外键 category_id 在我的 Category Table 中植入我的 Post Table。

但不幸的是,我遇到了一个我无法处理的问题,这就是我请求您帮助的原因


这是我的模型:

发帖:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Storage;

/**
 * @method static create(array $array)
 */
class Post extends Model
{

   use SoftDeletes;

   protected $fillable = ['title', 'description', 'contenu', 'image', 'published_at', 'category_id'];


   /**
    * Delete image from storage
    */
    public function deleteImage()
    {
      Storage::delete($this->image);
    }

    // OneToMany(Inverse)
    public function category()
    {
      return $this->belongsTo(Category::class, 'category_id', 'id');
    }

    // ManyToMany
    public function tags()
    {
      return $this->belongsToMany(Tag::class);
    }


    /**
     * Check if a post has tag.
     * tags return a collection, if we want to get the id from the array
     * we must use the pluck function
     * @param $id
     * @return bool
     */
     public function hasTag($id)
     {
       return in_array($id, $this->tags->pluck('id')->toArray());
     }
}

类别

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

/**
 * @method static create(array $all)
 */
class Category extends Model
{
  protected $fillable = ['name'];

  // OneToMany
  public function posts()
  {
    return $this->hasMany(Post::class);
  }
}

这是我的工厂:

发帖

<?php

/* @var $factory \Illuminate\Database\Eloquent\Factory */

use App\Category;
use App\Post;
use Carbon\Carbon;
use Faker\Generator as Faker;
use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;

$factory->define(Post::class, function (Faker $faker) {

$image = $faker->image();
$imageFile = new File($image);

return [
    'title' => 'hello',
    'description' => $faker->text(100),
    'contenu' => $faker->text(100),
    'image' => Storage::disk('public')->putFile('posts', $imageFile),
    'published_at' => $faker->date('Y-m-d'),
    'category_id' => factory('App\Category')->create()->id,
    // 'category_id' => $faker->numberBetween(1,5)
];
});

类别

<?php

/* @var $factory \Illuminate\Database\Eloquent\Factory */

use App\Category;
use Faker\Generator as Faker;

$factory->define(Category::class, function (Faker $faker) {
return [
    'name' => $faker->words(5, true),
    'image' => $faker->imageUrl()
];
});

我的播种机

<?php

use App\Post;
use App\Tag;
use Illuminate\Database\Seeder;

class PostTableSeeder extends Seeder
{
  /**
   * Run the database seeds.
   *
   * @return void
   */
  public function run()
  {
    /**
     * MANY TO MANY
     */
    $posts = factory(Post::class, 15)->create(); // 1.
    $tags = factory(Tag::class, 10)->create(); // 2
    $posts
        ->each(function (Post $posts) use ($tags) {
            $posts->tags()->attach(
                $tags->random(rand(1, 10))->pluck('id')->toArray() // 3.
            );
        });
   }
}

我知道通过 hasMany 关系,你可以这样做:

factory(User::class, 10)->create()->each(function ($user) {
$user->posts()->saveMany(factory(Posts::class, 5)->make());
});

或者这样:

//create 10 users
factory(User::class, 10)->create()->each(function ($user) {
//create 5 posts for each user
factory(Post::class, 5)->create(['user_id'=>$user->id]);
});

用户和帖子模型相互连接:Laravel - Seeding Relationships


我也知道,如果你加上这个:

'category_id' => factory('App\Category')->create()->id,

到你的工厂它会根据你询问的帖子数量生成 category_id 字段。

这意味着如果您要求 5 个帖子,它将为您生成 5 个从 1 到 5 的 category_id 编号:这也意味着您的数据库中有 5 个新类别。

那么如果你要求 50 个帖子,你将获得 50 个新类别..

这不是我要找的。​​p>


所以我的问题是这样的,

我怎样才能做到这一点,我可以添加所需的我想要的类别数量,以及所需的我想要的帖子数量? p>

这样两个表在数据库中仍然链接在一起。

Schema::table('posts', function (Blueprint $table) {
    $table->unsignedBigInteger('category_id');
    $table
        ->foreign('category_id')
        ->references('id')
        ->on('categories')
        ->onDelete('cascade');

如果您查看我的 Post Factory,您会看到以下评论:

 // 'category_id' => $faker->numberBetween(1,5)

我知道通过这种方式,通过生成一个随机数,最大值等于我想要的类别个数:

   factory(Category::class, 5)->create();

它会给我一个介于 1 和 5 之间的随机数作为我的 category_id,同时,我会得到我想要的我请求的类别数。

所以我的帖子不会有线性 category_id (1,2,3,4,5),但会随机排列。

这也是我想要的。

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: php laravel factory seeding faker


    【解决方案1】:

    我认为你有自己问题的答案。我只会创建你想要的 Category 对象的数量(比如 5 个)。先做这个。

    factory(Category::class, 5)->create();
    

    现在您已经有了这些,如果这是您的第一次迁移,您可以像在 Post factory 模型中一样随机添加它们:

    return [
        'title' => 'hello',
        // .. etc.
        'category_id' => $faker->numberBetween(1,5)
    ];
    

    但是,如果您已经有 Category id 的值,或者您以后可能会添加更多或更改它们,并且希望在以后的 Posts 之外使用工厂原来的迁移,可以获取当前的category id,然后随机注入到postcategory_id同厂的字段中:

    $cat_ids = Category::pluck('id', 'id')->toArray();
    
     return [
        'title' => 'hello',
        // .. etc.
        'category_id' => array_rand($cat_ids, 1)
    ];
    

    【讨论】:

    • 非常感谢。我会像你说的那样坚持下去,但是添加这个“array_rand($cat_ids,1)”提示,非常好。度过美好的一天/晚上。
    猜你喜欢
    • 2017-12-29
    • 2019-01-05
    • 2015-12-23
    • 2019-08-31
    • 2021-07-06
    • 2016-05-28
    • 2021-10-29
    • 2017-11-24
    • 1970-01-01
    相关资源
    最近更新 更多