雄辩的渴望加载关系

时间:2020-08-30 05:19:56

标签: laravel eloquent eloquent-relationship

StackOverflow的朋友们大家好,希望大家度过美好的一天(˘⌣˘)♡(˘⌣˘)

我是Laravel的新手,目前正在学习雄辩的人际关系(hasMany)

很抱歉,这篇文章读得太久了,但是我想弄清楚自己遇到的每一个步骤,直到遇到问题为止,还对不起我的英语不好(⁄ ⁄•⁄ ω⁄•⁄ ⁄)

所以我们开始

在我的用户模型中

public function posts() {
    // A user can have many posts
    return $this->hasMany('App\Post');
}

在我的帖子模型中

public function owner()
{
    // A post belongs to a user
    return $this->belongsTo('App\User', 'user_id');
}

在我的帖子表中,我有3条简单记录

|----------------------------------------------------------|
| id |   user_id |   body          |    ...    |   ...     |
|  1 |   1       |   My first post |    ...    |   ...     |
|  2 |   1       |   Second post   |    ...    |   ...     |
|  3 |   1       |   Another post  |    ...    |   ...     |

然后让我们说,我们希望看到id = 1的用户及其创建的所有帖子,因此我使用以下代码:

// AccountController
public function profile($id)
{
    $user = App\User::with('posts')->findOrFail($id);
    return $user;
}

// Will return data:
{
    "id": 1,
    "name": "Prof. Angela Runte Jr.",
    "email": "mborer@example.org",
    ...
    "posts": [
        {
            "id": 1,
            "user_id": 1,
            "body": "My first post",
            ...
        },
        {
            "id": 1,
            "user_id": 1,
            "body": "Second post",
            ...
        },
        {
            "id": 1,
            "user_id": 1,
            "body": "Another post",
            ...
        }
}

在Blade视图中,我可以简单地获取如下数据:

// in profile.blade.php

$user->name
$user->...

@foreach($user->posts as $post)
// Show each post data
@endforeach

它以我想要的方式完美运行,这要感谢泰勒·奥特威尔(Taylor Otwell)创建了一个了不起的框架(´•ω•`)♡

然后我想到一个主意,让我们创建一个功能,使用户可以发布给其他用户,为什么不呢?我们开始做吧! (✧ω✧)

因此,在我的Post迁移中,我更改了表架构:

发件人:

// Before
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignBigInteger('user_id');

$table->text('body');
$table->timestamps();

收件人:

// After
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedBigInteger('user_id');

// New column: nullable()
$table->foreign('for_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedBigInteger('for_id')->nullable();

$table->text('body');
$table->timestamps();

如您所见,我将nullable()放在“ for_id”列中

换句话说,如果for_id为空,则该帖子仅属于发布该帖子的用户

否则,该帖子属于发布该帖子的用户以及目标用户(for_id)。

然后,我跑步

// I only use UserSeeder (wanna keep it simple tho)
php artisan migrate:fresh --seed

现在我们有2个ID为1和2的用户(是!)

|----------------------------------------------------------------------------------------|
| id |   name                    |   email                     |    ...     |    ...     |
|  1 |   Camden Kulas            |   lemke.fabian@example.net  |    ...     |    ...     |
|  2 |   Mrs. Roberta Stroman    |   ybartoletti@example.com   |    ...     |    ...     |

让我们使用修补程序来创建伪数据

php artisan tinker
>> $user = App\User::first();
=> App\User {#3910
       id: 1,
       name: "Camden Kulas",
       email: "lemke.fabian@example.net",
       ...
   }
>> $user->posts()->create(['body' => 'New first post']);
=> App\Post {#4120
       body: "New first post",
       user_id: 1,
       updated_at: "2020-08-30 03:42:43",
       created_at: "2020-08-30 03:42:43",
       id: 1,
   }

// we create one for Mrs. Roberta Stroman (user with id #2)
>> $user->posts()->create(['for_id' => 2, 'body' => 'Hello there']);
=> App\Post {#3912
       for_id: 2,
       body: "Hello there",
       user_id: 1,
       updated_at: "2020-08-30 03:44:18",
       created_at: "2020-08-30 03:44:18",
       id: 2,
   }

所以现在我们的帖子表中有2条记录

|--------------------------------------------------------------------|
| id |   user_id |   for_id        |   body              |   ...     |
|  1 |   1       |   NULL          |   New first post    |   ...     |
|  2 |   1       |   2             |   Hello there       |   ...     |

我们仍处于用户ID#1

>> $user->posts

=> Illuminate\Database\Eloquent\Collection {#4120
       all: [
           App\Post {#4125
               id: 1,
               user_id: 1,
               for_id: null,
               body: "New first post",
               ...
           },
           App\Post {#4128
               id: 2,
               user_id: 1,
               for_id: 2,
               body: "Hello there",
               ...
           },
       ],
   }

( ̄ω ̄)好的,到这里,一切正常,让我们尝试使用用户ID#2

在我看来,我希望获得用户ID为2,并且所有帖子都由ID为2,以及其他所有ID为2的帖子

>> $user = App\User::find(2);
=> App\User {#4121
       id: 2
       name: "Mrs. Roberta Stroman",
       email: "ybartoletti@example.com",
       ...
   }
>> $user->posts
=> Illuminate\Database\Eloquent\Collection {#4067
       all: [],
   }

Σ(°ロ°)帖子是空的,那为什么它是空的?

ఠ͟ಠ然后我尝试使用with()

>> $user = App\User::with('posts')->find(2);
=> App\User {#4120
       id: 2,
       name: "Mrs. Roberta Stroman",
       email: "ybartoletti@example.com",
       ...
       posts: Illuminate\Database\Eloquent\Collection {#4123
           all: [],
       },
   }

(ꐦ°᷄д°᷅)什么?为什么帖子仍然是空的? щ(ºДºщ)

因此,经过数天的搜索和阅读,我仍然不知道如何解决此问题(。╯︵╰。)

然后我尝试更改用户模型:posts()函数

发件人:

public function posts()
{
    // A post belongs to a user
    return $this->hasMany('App\Post');
}

收件人:

public function posts()
{
    // In my logic like:
    // Hey I want to fetch all posts that made by this user, **or where all posts that created by others for this user**
    // Make sense in human language right?
    return $this->hasMany('App\Post', 'user_id')->orWhere('posts.for_id', $this->id);
}

我退出了修补匠,然后再次进入修补匠

>> $user = App\User::first();
// return user id #1

>> $user->posts
// works fine, return all posts

(ಠ益ಠ)现在我面临其他问题

>> $user = App\User::with('posts')->first(); // notice that I'm using with()

// tinker return the desired user, and also return ONLY one post

>> App\User {#4123
       id: 1,
       name: "Camden Kulas",
       email: "lemke.fabian@example.net",
       ....
       posts: Illuminate\Database\Eloquent\Collection {#4130
           all: [
               App\Post {#4128
                   id: 1,
                   user_id: 1,
                   for_id: null,
                   body: "New first post",
                   created_at: "2020-08-30 03:42:43",
                   updated_at: "2020-08-30 03:42:43",
               },

               // where is the second post?
           ],
       },
   }

然后我尝试使用用户ID#2更改修补匠会话

>> $user = App\User::find(2);
// return user id #2

>> $user = App\User::with('posts')->find(2);
// return user id #2, but no post (only array all)

因此,我无需再提出其他问题

[#1]为什么用户#1只获取一个帖子,而他却创建了2个帖子?

一篇文章没有for_id(NULL),第二篇文章有for_id

[#2]如何使用户ID#2来获取其所有帖子,以及为其创建的帖子?

因为用户模型中的IMHO posts()函数对我来说很有意义,但这不起作用

如果有不清楚的解释,它将及时进行编辑

预先感谢

更新

我发现可以这样简单地获取用户X的所有帖子和用户X的所有帖子:

$user = App\User::find(X);
$posts = $user->posts()->orWhere('for_id', X)->get();
return [
    'user' => $user,
    'posts => $posts
];

所以现在我想到了这个问题:

如何在$ posts中使用with()?

// Like this
$user = App\User::with('allposts')->find(X);
// Return user X and all posts made by X and posted to user X

// So I can simply get data in view like this:

@foreach ($user->allposts as $post)
// Loop all posts by user X and for user X
@endforeach

0 个答案:

没有答案