为什么PHP / Laravel没有增加这个值?

时间:2016-10-28 20:31:34

标签: php sqlite laravel reference phpunit

使用Laravel 5和sqlite进行单元测试。我有一个简单的测试,其中User创建了Post

/** @test */
public function it_should_increment_post_count_when_a_user_makes_a_post()
{
    // Given
    $u = User::first();
    $count1 = $u->posts->count();
    var_dump($count1);

    // When
    $p = new Post();
    $p->title = 'My Title';
    $p->content = 'This is the content';
    $p->user_id = $u->id;
    $p->save(); // This is definitely saving
    $count2 = $u->posts->count();
    var_dump($count2);

    // Then
    $this->assertEquals($count1+1, $count2);
}

结果如下:

root@7053bd7f558c:/var/www/laravel# phpunit
PHPUnit 5.5.7 by Sebastian Bergmann and contributors.

.....Fint(11)
int(11)
.                                                             7 / 7 (100%)

Time: 1.98 seconds, Memory: 12.00MB

There was 1 failure:

1) BasicUserTest::it_should_increment_post_count_when_a_user_makes_a_post
Failed asserting that 11 matches expected 12.

/var/www/laravel/tests/BasicUserTest.php:96

FAILURES!
Tests: 7, Assertions: 11, Failures: 1.

当然可以保存到数据库中(如果我在没有use DatabaseTransactions;的情况下运行它,它每次都会递增)。 $count1是否以某种方式引用$u->posts->count()

编辑: 类似的变化产生了一个奇怪的属性:

/** @test */
public function it_should_increment_post_count_when_a_user_makes_a_post()
{
    // Given
    $p = new Post([
        'title' => 'tha title',
        'content' => 'tha content',
    ]);
    $u_old = User::first();
    var_dump($u_old->posts->count());

    // When
    $u_old->posts()->save($p);

    // Then
    $u_new = User::first();
    $this->assertEquals($u_old->posts->count()+1, $u_new->posts->count());
}

这样可行,但如果我注释掉var_dump($u_old->posts->count());行,则会失败。

3 个答案:

答案 0 :(得分:3)

当你这样写:

$u->posts->count();

不是模型中缓存的count()。这是posts关系。您将所有用户的帖子作为Collection(基本上是一个美化的数组),然后count集合中的项目数量

如果您只需要帖子数量,则加载完整集合。您只应在实际需要有关每个帖子的详细信息时加载该集合。

相反,这样做:

$u->posts()->count();

在帖子后注意()。这意味着您实际上正在构建一个查询以选择发布的总数。这样:

  1. 需要更少的内存(Eloquent对象很大)
  2. 将更容易在您的数据库上(从表中选择计数而不是*)
  3. 将从数据库中提取新内容并在每次调用时准确无误

答案 1 :(得分:2)

count保持相同的值,因为该值存储在Eloquent模型中。 这是保留在记忆中的值。

因此,插入后,您需要发出新请求。 例如: <?php DB::table('name')->count(); ?>

或者只是真正的计数:<?php $count2 = count($y->posts); ?>

(我不记得是否有重新加载计数器值的提示......)

答案 2 :(得分:2)

所选答案是正确的,但我想我会为另一个选项提供输入。它在插入后保存第二个查询。

插入后,您可以刷新User模型上的关系数据。

// Get fresh data for posts relationship
$u = $u->fresh();

来自API docs

  

从数据库重新加载新模型实例。