Intereting Posts
Vimeo Advanced API – Как подключиться через Oauth? Использование переменной в качестве оператора Отправка строки на страницу PHP и отображение страницы PHP. Строка Где находится таблица, которая содержит «Специальную цену» в Magento? Получить данные от Json через php в android? Codeigniter, создающий новый сеанс при каждой загрузке страницы php-скрипт анализирует контент из RTE (tt_news), но внутренние ссылки не отображаются как говорящий URL-адрес Интеграция jQuery fullcalendar в PHP-сайт Установите PECL на Mac OS X 10.6 Отключить сообщение об ошибке проверки Yii на фокусе / клавише вверх – Yii2 Почему я не могу получить идентификатор альбома в facebook? Как установить значение по умолчанию в поле выбора symfony2 с данными из базы данных Как получить разрешение экрана посетителя в javascript и / или php? mysql разделяет строку поиска пробелом и вставляет запрос Использование флажков ввода с базой данных

Laravel – Относящиеся отношения

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

$factory->define(App\User::class, function (Faker\Generator $faker) { return [ 'name' => $faker->name, 'email' => $faker->email, 'password' => bcrypt(str_random(10)), 'remember_token' => str_random(10), ]; }); $user = factory(App\User::class, 50)->create(); 

Однако, скажем, ваша модель пользователя имеет отношения hasMany со многими другими моделями, например модель Post :

 Post: id name body user_id 

Поэтому в этой ситуации вы хотите засеять свою таблицу сообщений фактическими пользователями, которые были засеяны в вашей таблице «Пользователи». Это явно не обсуждается, но в документах Laravel я нашел следующее:

 $users = factory(App\User::class, 3) ->create() ->each(function($u) { $u->posts()->save(factory(App\Post::class)->make()); }); 

Итак, на вашей фабрике пользователей вы создаете X количество сообщений для каждого созданного вами пользователя. Однако в большом приложении, где, возможно, 50 – 75 моделей разделяют отношения с пользовательской моделью, ваш пользовательский сеятель, по сути, в конечном итоге высевает всю базу данных со всеми ее отношениями.

Мой вопрос: это лучший способ справиться с этим? Единственное, что я могу придумать, это сначала Seed the Users (без посева каких-либо отношений), а затем вытащить случайных пользователей из БД по мере необходимости, пока вы высеиваете другие Модели. Однако в тех случаях, когда они должны быть уникальными, вам нужно будет отслеживать, какие пользователи были использованы. Кроме того, похоже, это добавит много дополнительных запросов к процессу посева.

Related of "Laravel – Относящиеся отношения"

Вы также можете использовать saveMany. Например:

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

Лично я считаю, что один класс Seeder для управления этими отношениями лучше разделяет классы сеялок, потому что у вас есть вся логика в одном месте, поэтому в одном взгляде вы можете видеть, что происходит. (Любой, кто знает лучший подход: пожалуйста, поделитесь) 🙂

Решением может быть: один DatabaseSeeder и частные методы внутри класса, чтобы сохранить метод «run» немного чище. У меня есть этот пример ниже, в котором есть User, Link, LinkUser (многие-ко-многим) и заметки (много-к-одному).

Для отношений «многие ко многим» я сначала создаю все ссылки и получаю вставленные идентификаторы. (поскольку идентификаторы являются auto-inc, я думаю, что идентификаторы можно было бы получить легче (получить max), но в данном примере это не имеет значения). Затем создайте пользователей и присоедините некоторые случайные ссылки каждому пользователю (многие-ко-многим). Он также создает случайные заметки для каждого пользователя (пример много-к-одному). Он использует «заводские» методы.

Если вы замените ссылку «Ссылка» для своей «Почты», это должно сработать. (Вы можете удалить раздел «Примечание», затем …)

(Существует также способ убедиться, что у вас есть 1 действительный пользователь с вашими учетными данными).

 <?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // Create random links factory(App\Link::class, 100)->create(); // Fetch the link ids $link_ids = App\Link::all('id')->pluck('id')->toArray(); // Create random users factory(App\User::class, 50)->create()->each(function ($user) use ($link_ids) { // Example: Many-to-many relations $this->attachRandomLinksToUser($user->id, $link_ids); // Example: Many-to-one relations $this->createNotesForUserId( $user->id ); }); // Make sure you have a user to login with (your own email, name and password) $this->updateCredentialsForTestLogin('john@doe.com', 'John Doe', 'my-password'); } /** * @param $user_id * @param $link_ids * @return void */ private function attachRandomLinksToUser($user_id, $link_ids) { $amount = random_int( 0, count($link_ids) ); // The amount of links for this user echo "Attach " . $amount . " link(s) to user " . $user_id . "\n"; if($amount > 0) { $keys = (array)array_rand($link_ids, $amount); // Random links foreach($keys as $key) { DB::table('link_user')->insert([ 'link_id' => $link_ids[$key], 'user_id' => $user_id, ]); } } } /** * @param $user_id * @return void */ private function createNotesForUserId($user_id) { $amount = random_int(10, 50); factory(App\Note::class, $amount)->create([ 'user_id' => $user_id ]); } /** * @param $email * @param $name * @param $password * @return void */ private function updateCredentialsForTestLogin($email, $name, $password) { $user = App\User::where('email', $email)->first(); if(!$user) { $user = App\User::find(1); } $user->name = $name; $user->email = $email; $user->password = bcrypt($password); // Or whatever you use for password encryption $user->save(); } } 

Вы можете сделать это, используя закрытие в ModelFactory, как описано здесь .

Это решение работает чисто и элегантно с сеятелями.

 $factory->define(App\User::class, function (Faker\Generator $faker) { return [ 'name' => $faker->name, 'email' => $faker->email, 'password' => bcrypt(str_random(10)), 'remember_token' => str_random(10), ]; }); $factory->define(App\Post::class, function (Faker\Generator $faker) { return [ 'name' => $faker->name, 'body' => $faker->paragraph(1), 'user_id' => function() { return factory(App\User::class)->create()->id; }, ]; }); 

Для вашей сеялки используйте что-то простое:

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

ПРИМЕЧАНИЕ. Этот метод не создает ненужные записи в базе данных, вместо этого переданные атрибуты назначаются ПЕРЕД созданием связанных записей.

 $factory->define(App\User::class, function (Faker\Generator $faker) { return [ 'name' => $faker->name, 'email' => $faker->email, 'password' => bcrypt(str_random(10)), 'remember_token' => str_random(10), ]; }); $factory->define(App\Post::class, function (Faker\Generator $faker) { return [ 'name' => $faker->name, 'body' => $faker->paragraph(1), 'user_id' => factory(App\User::class)->create()->id, ]; }); 

Итак, если вы сделаете эту factory(App\Post::class, 4)->create() она создаст 4 разных сообщения и в этом процессе также создаст 4 разных пользователя.

Если вы хотите, чтобы тот же пользователь для всех сообщений, что я обычно делаю, это:

 $user = factory(App\User::class)->create(); $posts = factory(App\Posts::class, 40)->create(['user_id' => $user->id]);