Laravel 5.8 - Посеять отношения ManyToOne - PullRequest
0 голосов
/ 08 июля 2019

Вечер всех,

Я с нетерпением жду, чтобы заполнить мою таблицу сообщений внутри моей таблицы категорий через внешний ключ, category_id , внутри моей таблицы сообщений.

Но, к сожалению, я столкнулся с проблемой, с которой мне не удалось справиться, и именно поэтому я прошу вашей помощи


Вот мои модели :

Пост :

<?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()
];
});

My Seeder

<?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 - Отношения посева


Я также знаю, что если вы добавите это:

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

На вашем заводе будут генерироваться поля category_id в соответствии с количеством сообщений, которые вы запросили.

Таким образом, это означает, что если вы запросите 5 сообщений, то сгенерирует вам 5 номеров category_id от 1 до 5: это также означает 5 новых категорий в вашей базе данных.

Тогда, если вы попросите 50 сообщений, вы получите 50 новых категорий ..

Это не то, что я ищу.


Так что мой вопрос такой,

Как сделать так, чтобы я мог добавить желаемый номер категории, которую я хочу, наряду с желаемым количеством сообщений, которые я хочу?

Так что обе таблицы все еще связаны в базе данных.

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

Если вы посмотрите на мою Почтовую фабрику , вы увидите следующее:

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

Я знаю, что таким образом, генерируя случайное число с максимальным значением равным количеству категорий, которые я хочу :

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

Это даст мне случайное число от 1 до 5 для моего category_id и в то же время даст мне желаемое количество категорий, которые я запросил.

Так что мои посты не будут иметь линейный category_id (1,2,3,4,5), но они будут перетасованы случайным образом.

Это то, что я тоже ищу.

Есть ли лучший способ сделать это?

1 Ответ

1 голос
/ 08 июля 2019

Я думаю, у вас есть ответ на свой вопрос. Я бы просто создал желаемое количество Category объектов (скажем, 5). Сделай это первым.

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

Теперь, когда они у вас есть, если это ваша первая миграция, вы можете просто добавить их случайным образом, как если бы они были в вашей фабричной модели Post:

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

Однако, если у вас уже есть значения для идентификаторов Category , или вы можете добавить или изменить их позже, и хотите использовать фабрику для будущих Сообщений вне оригинала В процессе миграции вы можете получить идентификаторы текущей категории, а затем вставить их случайным образом в поле post category_id на той же фабрике:

$cat_ids = Category::pluck('id', 'id')->toArray();

 return [
    'title' => 'hello',
    // .. etc.
    'category_id' => array_rand($cat_ids, 1)
];
...