Skip to content

Commit b905597

Browse files
authored
[10.x] Added eachById and chunkByIdDesc to BelongsToMany (#50991)
* Added failing test * Added eachById and chunkByIdDesc to BelongsToMany * Removed extra namespace
1 parent cc039d5 commit b905597

File tree

3 files changed

+208
-12
lines changed

3 files changed

+208
-12
lines changed

src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -997,19 +997,66 @@ public function chunk($count, callable $callback)
997997
*/
998998
public function chunkById($count, callable $callback, $column = null, $alias = null)
999999
{
1000-
$this->prepareQueryBuilder();
1000+
return $this->orderedChunkById($count, $callback, $column, $alias);
1001+
}
1002+
1003+
/**
1004+
* Chunk the results of a query by comparing IDs in descending order.
1005+
*
1006+
* @param int $count
1007+
* @param callable $callback
1008+
* @param string|null $column
1009+
* @param string|null $alias
1010+
* @return bool
1011+
*/
1012+
public function chunkByIdDesc($count, callable $callback, $column = null, $alias = null)
1013+
{
1014+
return $this->orderedChunkById($count, $callback, $column, $alias, descending: true);
1015+
}
10011016

1017+
/**
1018+
* Execute a callback over each item while chunking by ID.
1019+
*
1020+
* @param callable $callback
1021+
* @param int $count
1022+
* @param string|null $column
1023+
* @param string|null $alias
1024+
* @return bool
1025+
*/
1026+
public function eachById(callable $callback, $count = 1000, $column = null, $alias = null)
1027+
{
1028+
return $this->chunkById($count, function ($results, $page) use ($callback, $count) {
1029+
foreach ($results as $key => $value) {
1030+
if ($callback($value, (($page - 1) * $count) + $key) === false) {
1031+
return false;
1032+
}
1033+
}
1034+
}, $column, $alias);
1035+
}
1036+
1037+
/**
1038+
* Chunk the results of a query by comparing IDs in a given order.
1039+
*
1040+
* @param int $count
1041+
* @param callable $callback
1042+
* @param string|null $column
1043+
* @param string|null $alias
1044+
* @param bool $descending
1045+
* @return bool
1046+
*/
1047+
public function orderedChunkById($count, callable $callback, $column = null, $alias = null, $descending = false)
1048+
{
10021049
$column ??= $this->getRelated()->qualifyColumn(
10031050
$this->getRelatedKeyName()
10041051
);
10051052

10061053
$alias ??= $this->getRelatedKeyName();
10071054

1008-
return $this->query->chunkById($count, function ($results) use ($callback) {
1055+
return $this->prepareQueryBuilder()->orderedChunkById($count, function ($results, $page) use ($callback) {
10091056
$this->hydratePivotRelation($results->all());
10101057

1011-
return $callback($results);
1012-
}, $column, $alias);
1058+
return $callback($results, $page);
1059+
}, $column, $alias, $descending);
10131060
}
10141061

10151062
/**

tests/Database/DatabaseEloquentBelongsToManyChunkByIdTest.php

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,14 @@ public function createSchema()
3737
});
3838

3939
$this->schema()->create('articles', function ($table) {
40-
$table->increments('aid');
40+
$table->increments('id');
4141
$table->string('title');
4242
});
4343

4444
$this->schema()->create('article_user', function ($table) {
45+
$table->increments('id');
4546
$table->integer('article_id')->unsigned();
46-
$table->foreign('article_id')->references('aid')->on('articles');
47+
$table->foreign('article_id')->references('id')->on('articles');
4748
$table->integer('user_id')->unsigned();
4849
$table->foreign('user_id')->references('id')->on('users');
4950
});
@@ -58,7 +59,22 @@ public function testBelongsToChunkById()
5859

5960
$user->articles()->chunkById(1, function (Collection $collection) use (&$i) {
6061
$i++;
61-
$this->assertEquals($i, $collection->first()->aid);
62+
$this->assertEquals($i, $collection->first()->id);
63+
});
64+
65+
$this->assertSame(3, $i);
66+
}
67+
68+
public function testBelongsToChunkByIdDesc()
69+
{
70+
$this->seedData();
71+
72+
$user = BelongsToManyChunkByIdTestTestUser::query()->first();
73+
$i = 0;
74+
75+
$user->articles()->chunkByIdDesc(1, function (Collection $collection) use (&$i) {
76+
$this->assertEquals(3 - $i, $collection->first()->id);
77+
$i++;
6278
});
6379

6480
$this->assertSame(3, $i);
@@ -83,9 +99,9 @@ protected function seedData()
8399
{
84100
$user = BelongsToManyChunkByIdTestTestUser::create(['id' => 1, 'email' => '[email protected]']);
85101
BelongsToManyChunkByIdTestTestArticle::query()->insert([
86-
['aid' => 1, 'title' => 'Another title'],
87-
['aid' => 2, 'title' => 'Another title'],
88-
['aid' => 3, 'title' => 'Another title'],
102+
['id' => 1, 'title' => 'Another title'],
103+
['id' => 2, 'title' => 'Another title'],
104+
['id' => 3, 'title' => 'Another title'],
89105
]);
90106

91107
$user->articles()->sync([3, 1, 2]);
@@ -126,10 +142,9 @@ public function articles()
126142

127143
class BelongsToManyChunkByIdTestTestArticle extends Eloquent
128144
{
129-
protected $primaryKey = 'aid';
130145
protected $table = 'articles';
131146
protected $keyType = 'string';
132147
public $incrementing = false;
133148
public $timestamps = false;
134-
protected $fillable = ['aid', 'title'];
149+
protected $fillable = ['id', 'title'];
135150
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Database;
4+
5+
use Illuminate\Database\Capsule\Manager as DB;
6+
use Illuminate\Database\Eloquent\Model as Eloquent;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class DatabaseEloquentBelongsToManyEachByIdTest extends TestCase
10+
{
11+
protected function setUp(): void
12+
{
13+
$db = new DB;
14+
15+
$db->addConnection([
16+
'driver' => 'sqlite',
17+
'database' => ':memory:',
18+
]);
19+
20+
$db->bootEloquent();
21+
$db->setAsGlobal();
22+
23+
$this->createSchema();
24+
}
25+
26+
/**
27+
* Setup the database schema.
28+
*
29+
* @return void
30+
*/
31+
public function createSchema()
32+
{
33+
$this->schema()->create('users', function ($table) {
34+
$table->increments('id');
35+
$table->string('email')->unique();
36+
});
37+
38+
$this->schema()->create('articles', function ($table) {
39+
$table->increments('id');
40+
$table->string('title');
41+
});
42+
43+
$this->schema()->create('article_user', function ($table) {
44+
$table->increments('id');
45+
$table->integer('article_id')->unsigned();
46+
$table->foreign('article_id')->references('id')->on('articles');
47+
$table->integer('user_id')->unsigned();
48+
$table->foreign('user_id')->references('id')->on('users');
49+
});
50+
}
51+
52+
public function testBelongsToEachById()
53+
{
54+
$this->seedData();
55+
56+
$user = BelongsToManyEachByIdTestTestUser::query()->first();
57+
$i = 0;
58+
59+
$user->articles()->eachById(function (BelongsToManyEachByIdTestTestArticle $model) use (&$i) {
60+
$i++;
61+
$this->assertEquals($i, $model->id);
62+
});
63+
64+
$this->assertSame(3, $i);
65+
}
66+
67+
/**
68+
* Tear down the database schema.
69+
*
70+
* @return void
71+
*/
72+
protected function tearDown(): void
73+
{
74+
$this->schema()->drop('users');
75+
$this->schema()->drop('articles');
76+
$this->schema()->drop('article_user');
77+
}
78+
79+
/**
80+
* Helpers...
81+
*/
82+
protected function seedData()
83+
{
84+
$user = BelongsToManyEachByIdTestTestUser::create(['id' => 1, 'email' => '[email protected]']);
85+
BelongsToManyEachByIdTestTestArticle::query()->insert([
86+
['id' => 1, 'title' => 'Another title'],
87+
['id' => 2, 'title' => 'Another title'],
88+
['id' => 3, 'title' => 'Another title'],
89+
]);
90+
91+
$user->articles()->sync([3, 1, 2]);
92+
}
93+
94+
/**
95+
* Get a database connection instance.
96+
*
97+
* @return \Illuminate\Database\ConnectionInterface
98+
*/
99+
protected function connection()
100+
{
101+
return Eloquent::getConnectionResolver()->connection();
102+
}
103+
104+
/**
105+
* Get a schema builder instance.
106+
*
107+
* @return \Illuminate\Database\Schema\Builder
108+
*/
109+
protected function schema()
110+
{
111+
return $this->connection()->getSchemaBuilder();
112+
}
113+
}
114+
115+
class BelongsToManyEachByIdTestTestUser extends Eloquent
116+
{
117+
protected $table = 'users';
118+
protected $fillable = ['id', 'email'];
119+
public $timestamps = false;
120+
121+
public function articles()
122+
{
123+
return $this->belongsToMany(BelongsToManyEachByIdTestTestArticle::class, 'article_user', 'user_id', 'article_id');
124+
}
125+
}
126+
127+
class BelongsToManyEachByIdTestTestArticle extends Eloquent
128+
{
129+
protected $table = 'articles';
130+
protected $keyType = 'string';
131+
public $incrementing = false;
132+
public $timestamps = false;
133+
protected $fillable = ['id', 'title'];
134+
}

0 commit comments

Comments
 (0)