为什么 PHP/Laravel 不增加这个值?
Why isn't PHP/Laravel incrementing this value?
使用 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());
,它就会失败。
count
保持相同的值,因为该值存储在 Eloquent 模型上。
这是一个保存在内存中的值。
因此,插入后,您需要进行新的请求。
例如:
<?php DB::table('name')->count(); ?>
或者可能只是一个真实的计数:<?php $count2 = count($y->posts); ?>
(不记得有没有提示重新加载计数器值了。。。)
选择的答案是正确的,但我想我会为另一个选项提供输入。它在插入后保存第二个查询。
插入后,您可以在 User
模型上刷新关系数据。
// Get fresh data for posts relationship
$u = $u->fresh();
来自API docs:
Reload a fresh model instance from the database.
当你这样写的时候:
$u->posts->count();
模型中缓存的不是count()
。就是posts
关系。您正在获取 该用户的所有 posts 作为 Collection
(这基本上是一个美化的数组),然后 count
ing 的数量集合中的项目。
如果您只需要 post 的数量,您应该 而不是 加载完整的集合。仅当您确实需要有关每个 post.
的详细信息时,才应加载集合
相反,这样做:
$u->posts()->count();
注意 post 秒后的 ()
。这意味着您实际上是在构建一个查询 select 到 post 的总数。这个:
- 需要更少的内存(Eloquent 对象很大)
- 你的数据库会更容易(selecting 计数而不是 * 来自 table)
- 每次调用时都会从数据库中重新提取并准确
使用 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());
,它就会失败。
count
保持相同的值,因为该值存储在 Eloquent 模型上。
这是一个保存在内存中的值。
因此,插入后,您需要进行新的请求。
例如:
<?php DB::table('name')->count(); ?>
或者可能只是一个真实的计数:<?php $count2 = count($y->posts); ?>
(不记得有没有提示重新加载计数器值了。。。)
选择的答案是正确的,但我想我会为另一个选项提供输入。它在插入后保存第二个查询。
插入后,您可以在 User
模型上刷新关系数据。
// Get fresh data for posts relationship
$u = $u->fresh();
来自API docs:
Reload a fresh model instance from the database.
当你这样写的时候:
$u->posts->count();
模型中缓存的不是count()
。就是posts
关系。您正在获取 该用户的所有 posts 作为 Collection
(这基本上是一个美化的数组),然后 count
ing 的数量集合中的项目。
如果您只需要 post 的数量,您应该 而不是 加载完整的集合。仅当您确实需要有关每个 post.
的详细信息时,才应加载集合相反,这样做:
$u->posts()->count();
注意 post 秒后的 ()
。这意味着您实际上是在构建一个查询 select 到 post 的总数。这个:
- 需要更少的内存(Eloquent 对象很大)
- 你的数据库会更容易(selecting 计数而不是 * 来自 table)
- 每次调用时都会从数据库中重新提取并准确