【问题标题】:Laravel Eloquent - For loop inside seeder file is behaving in a strange wayLaravel Eloquent - 种子文件中的 For 循环表现得很奇怪
【发布时间】:2019-04-17 18:18:23
【问题描述】:

我有两个模型,文章和项目。 project 可以有很多相关的文章,一篇文章可以属于一个项目,也可以不属于一个项目。我有两个播种机 projectseeder 和 articleseeder。文章播种器首先被调用并且运行良好,然后我尝试在项目播种器中运行一个 for 循环来关联一些随机文章,结果只有一篇文章被添加到集合中。奇怪的是,添加的文章与项目具有相同的 ID,即如果项目 ID 为 1,则关联的文章 ID 也是 1。我不知道为什么项目播种器中的 for 循环没有按预期工作。

   class Article extends Model{
    //An Article can only belong to one project or it could be independent of project
    public function project()
    {
        return $this->belongsToMany('App\Models\Project', 'id');
    }
class Project extends Model
{

    public function articles()
    {
        return $this->hasMany('App\Models\Article', 'id', 'id');
    }
}

还有我的工厂和播种机

$factory->define(Article::class, function (Faker $faker) {
    return [
        'title'         => $faker->sentence(rand(1,2)),
        'short_text'    => $faker->sentence(rand(3,5)),
        'content'       => $faker->paragraph(10),
        'is_featured'   => $faker->randomElement(['Y','N']),
        'posted_by'     =>'John Smith'

    ];
});


class ProjectTableSeeder extends Seeder
{
    public function run()
    {

        Eloquent::unguard();

        //select  random articles for project
        factory(App\Models\Project::class, 10)->create()
            ->each(function($project){
                //associate 3 random article with this project
                for ($i=0; $i <4 ; $i++) {
                    $project->articles->add(Article::find(rand(1,50))->get());
                }//end for
        }//end each function
        );


        Eloquent::reguard();

    }
}

我死掉了关系,但我只得到一个文章实例。请帮我找出我做错了什么!提前感谢您的帮助。

更新#1: 这些是模型的迁移文件

Schema::create('articles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->string('title');
            $table->text('short_text'); // Mandetory first 150 chars of content
            $table->text('content');
            $table->char('is_featured'); // Y for N for No
            $table->string('posted_by'); // Auth user
        });

Schema::create('projects', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->text('title');
        });

更新#2:

非常感谢您的回答。我很惊讶您实际上创建了一个完整的项目来回答我的问题!!!你真好,我真的很欣赏你的精神。您的解决方案就像一个魅力。

我不知道这是否会要求太多,但这是我要求的最后帮助。 所有 10 个项目都有相同的相关文章,即从文章 0 到 5。我希望选择随机文章,而不是所有项目都有相同的文章。

更新#3 我想出了一个不同的方法并改变了工厂方法

    $factory->define(Article::class, function (Faker $faker) {
    return [
        'title'         => $faker->sentence(rand(1,2)),
        'short_text'    => $faker->sentence(rand(3,5)),
        'content'       => $faker->paragraph(10),
        'is_featured'   => $faker->randomElement(['Y','N']),
        'posted_by'     =>'John Smith',
        'project_id'    =>$faker->randomElement([null,rand(1,10)]),
    ];
});

现在文章要么将项目的空值或随机 ID 作为项目 ID,而且文章现在自动与项目相关联。尽管如此,还是非常感谢您宝贵的时间。祝你有美好的一天。

【问题讨论】:

  • 两张表中的每一个都有哪些列?最相关的是键列和外键列。

标签: laravel


【解决方案1】:

第一次发布答案。 :)

您的文章()关系正在使用两个表中的 id 列来获取文章。这将导致您仅检索一篇文章。如果您将“projects_id”列添加到您的文章表并将该列设置为项目的 id,然后修改您的关系以使用该列,您将能够获得多篇文章。

希望这会有所帮助。

更新: 将 ->nullable() 添加到迁移列允许您将其保留为空或将其设置为特定项目。

迁移:

Schema::create('articles', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedInteger('projects_id')->nullable(); 
            // Add column that specifies what project this belongs to
            $table->timestamps();
            $table->string('title');
            $table->text('short_text'); // Mandetory first 150 chars of content
            $table->text('content');
            $table->char('is_featured'); // Y for N for No
            $table->string('posted_by'); // Auth user
        });

关系:

public function articles()
{
    return $this->hasMany('App\Models\Article', 'projects_id', 'id');
    // Use the projects_id we just added to get all 
    // articles for that project
}

我建议通读 Laravel 文档,特别是迁移和关系。

https://laravel.com/docs/5.8/eloquent-relationships

https://laravel.com/docs/5.8/migrations

更新#2:

文章迁移:https://pastebin.com/QaDUzG9x

项目迁移:https://pastebin.com/4i9Bg5vQ

文章&项目模型:https://pastebin.com/8GWmcx7U

播种者:https://pastebin.com/MDi2nW5N

文章和项目工厂:https://pastebin.com/BUFfP7iv

下载项目:http://www.mediafire.com/file/wv5188frvd0k9m0/devtest.zip/file

使用php artisan tinkerApp\Project::first()-&gt;articles,我能够在数据库中获取第一个项目及其所有文章。

【讨论】:

  • 感谢您的回答。文章可以独立于项目。它们可能属于也可能不属于某个项目。因此,我不能在文章表中使用项目 ID,因为它可能保持为空。
  • 您可以通过在迁移中添加 ->nullable() 来使 projects_id 为空。这将允许您将它们保留为空或将它们设置为特定项目。我将更新我的答案以反映这一点。
  • @Johnny 我希望这对您有所帮助,如果您还有任何问题,请随时提问!使用 projects_id 列和列上的 nullable() 属性应该可以满足您的需求,因为它允许您为一个项目获取多篇文章拥有不属于某个项目的独立文章。跨度>
  • 嗨 ImJT,再次感谢,在更改外键后播种现在可以工作,但这次没有文章被添加到集合中!
  • 当我今天有机会时,我会继续按照您正在寻找的内容写一些东西并用它修改我的答案。您的文章现在是否获得了项目 ID?如果没有项目 ID,您将不会收到任何与该项目相关的文章。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
相关资源
最近更新 更多