Skip to content

Commit c8a624b

Browse files
authored
Merge pull request #2580 from warlof/polymorphic-search
feat(relations): add partial polymorphic support
2 parents 4974f6e + 4f4b72b commit c8a624b

File tree

6 files changed

+211
-4
lines changed

6 files changed

+211
-4
lines changed

src/EloquentDataTable.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
88
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
99
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
10+
use Illuminate\Database\Eloquent\Relations\MorphTo;
1011
use Illuminate\Database\Eloquent\Relations\Relation;
1112
use Yajra\DataTables\Exceptions\Exception;
1213

@@ -91,9 +92,15 @@ protected function compileQuerySearch($query, $columnName, $keyword, $boolean =
9192
return parent::compileQuerySearch($query, $columnName, $keyword, $boolean);
9293
}
9394

94-
$query->{$boolean . 'WhereHas'}($relation, function (Builder $query) use ($column, $keyword) {
95-
parent::compileQuerySearch($query, $column, $keyword, '');
96-
});
95+
if ($this->query->getModel()->$relation() instanceof MorphTo) {
96+
$query->{$boolean . 'WhereHasMorph'}($relation, '*', function (Builder $query) use ($column, $keyword) {
97+
parent::compileQuerySearch($query, $column, $keyword, '');
98+
});
99+
} else {
100+
$query->{$boolean . 'WhereHas'}($relation, function (Builder $query) use ($column, $keyword) {
101+
parent::compileQuerySearch($query, $column, $keyword, '');
102+
});
103+
}
97104
}
98105

99106
/**
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
3+
namespace Yajra\DataTables\Tests\Integration;
4+
5+
use Illuminate\Foundation\Testing\DatabaseTransactions;
6+
use Yajra\DataTables\DataTables;
7+
use Yajra\DataTables\Tests\Models\HumanUser;
8+
use Yajra\DataTables\Tests\Models\User;
9+
use Yajra\DataTables\Tests\TestCase;
10+
11+
/**
12+
* Class MorphToRelationTest.
13+
*/
14+
class MorphToRelationTest extends TestCase
15+
{
16+
use DatabaseTransactions;
17+
18+
/** @test */
19+
public function it_returns_all_records_with_the_relation_when_called_without_parameters()
20+
{
21+
$response = $this->call('GET', '/relations/morphTo');
22+
$response->assertJson([
23+
'draw' => 0,
24+
'recordsTotal' => 20,
25+
'recordsFiltered' => 20,
26+
]);
27+
28+
$this->assertArrayHasKey('user', $response->json()['data'][0]);
29+
$this->assertCount(20, $response->json()['data']);
30+
}
31+
32+
/** @test */
33+
public function it_returns_all_records_with_the_deleted_relation_when_called_with_withtrashed_parameter()
34+
{
35+
HumanUser::find(1)->delete();
36+
37+
$response = $this->call('GET', '/relations/morphToWithTrashed');
38+
$response->assertJson([
39+
'draw' => 0,
40+
'recordsTotal' => 20,
41+
'recordsFiltered' => 20,
42+
]);
43+
44+
$this->assertArrayHasKey('user', $response->json()['data'][0]);
45+
$this->assertArrayHasKey('user', $response->json()['data'][1]);
46+
$this->assertNotEmpty($response->json()['data'][0]['user']);
47+
$this->assertNotEmpty($response->json()['data'][1]['user']);
48+
}
49+
50+
/** @test */
51+
public function it_returns_all_records_with_the_only_deleted_relation_when_called_with_onlytrashed_parameter()
52+
{
53+
HumanUser::find(1)->delete();
54+
55+
$response = $this->call('GET', '/relations/morphToOnlyTrashed');
56+
$response->assertJson([
57+
'draw' => 0,
58+
'recordsTotal' => 20,
59+
'recordsFiltered' => 20,
60+
]);
61+
62+
$this->assertArrayHasKey('user', $response->json()['data'][0]);
63+
$this->assertArrayHasKey('user', $response->json()['data'][1]);
64+
$this->assertNotEmpty($response->json()['data'][0]['user']);
65+
$this->assertEmpty($response->json()['data'][1]['user']);
66+
}
67+
68+
/** @test */
69+
public function it_can_perform_global_search_on_the_relation()
70+
{
71+
$response = $this->getJsonResponse([
72+
'search' => ['value' => 'Animal'],
73+
]);
74+
75+
$response->assertJson([
76+
'draw' => 0,
77+
'recordsTotal' => 20,
78+
'recordsFiltered' => 10,
79+
]);
80+
81+
$this->assertCount(10, $response->json()['data']);
82+
}
83+
84+
protected function getJsonResponse(array $params = [])
85+
{
86+
$data = [
87+
'columns' => [
88+
['data' => 'user.name', 'name' => 'user.name', 'searchable' => 'true', 'orderable' => 'false'],
89+
['data' => 'name', 'name' => 'name', 'searchable' => 'true', 'orderable' => 'true'],
90+
['data' => 'email', 'name' => 'email', 'searchable' => 'true', 'orderable' => 'true'],
91+
],
92+
];
93+
94+
return $this->call('GET', '/relations/morphTo', array_merge($data, $params));
95+
}
96+
97+
protected function setUp(): void
98+
{
99+
parent::setUp();
100+
101+
$this->app['router']->get('/relations/morphTo', function (DataTables $datatables) {
102+
return $datatables->eloquent(User::with('user')->select('users.*'))->toJson();
103+
});
104+
105+
$this->app['router']->get('/relations/morphToWithTrashed', function (DataTables $datatables) {
106+
return $datatables->eloquent(User::with(['user' => function ($query) {
107+
$query->withTrashed();
108+
}])->select('users.*'))->toJson();
109+
});
110+
111+
$this->app['router']->get('/relations/morphToOnlyTrashed', function (DataTables $datatables) {
112+
return $datatables->eloquent(User::with(['user' => function ($query) {
113+
$query->onlyTrashed();
114+
}])->select('users.*'))->toJson();
115+
});
116+
}
117+
}

tests/Models/AnimalUser.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Yajra\DataTables\Tests\Models;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Database\Eloquent\SoftDeletes;
7+
8+
/**
9+
* Class AnimalUser.
10+
*/
11+
class AnimalUser extends Model
12+
{
13+
use SoftDeletes;
14+
15+
/**
16+
* @var array
17+
*/
18+
protected $guarded = [];
19+
20+
/**
21+
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
22+
*/
23+
public function users()
24+
{
25+
return $this->morphMany(User::class, 'user');
26+
}
27+
}

tests/Models/HumanUser.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Yajra\DataTables\Tests\Models;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Database\Eloquent\SoftDeletes;
7+
8+
/**
9+
* Class HumanUser.
10+
*/
11+
class HumanUser extends Model
12+
{
13+
use SoftDeletes;
14+
15+
/**
16+
* @var array
17+
*/
18+
protected $guarded = [];
19+
20+
/**
21+
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
22+
*/
23+
public function users()
24+
{
25+
return $this->morphMany(User::class, 'user');
26+
}
27+
}

tests/Models/User.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@ public function roles()
2222
{
2323
return $this->belongsToMany(Role::class);
2424
}
25+
26+
public function user()
27+
{
28+
return $this->morphTo();
29+
}
2530
}

tests/TestCase.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use Illuminate\Database\Schema\Blueprint;
66
use Orchestra\Testbench\TestCase as BaseTestCase;
7+
use Yajra\DataTables\Tests\Models\AnimalUser;
8+
use Yajra\DataTables\Tests\Models\HumanUser;
79
use Yajra\DataTables\Tests\Models\Role;
810
use Yajra\DataTables\Tests\Models\User;
911

@@ -27,6 +29,8 @@ protected function migrateDatabase()
2729
$table->increments('id');
2830
$table->string('name');
2931
$table->string('email');
32+
$table->string('user_type')->nullable();
33+
$table->unsignedInteger('user_id')->nullable();
3034
$table->timestamps();
3135
});
3236
}
@@ -62,14 +66,32 @@ protected function migrateDatabase()
6266
$table->timestamps();
6367
});
6468
}
69+
if (! $schemaBuilder->hasTable('animal_users')) {
70+
$schemaBuilder->create('animal_users', function (Blueprint $table) {
71+
$table->increments('id');
72+
$table->string('name');
73+
$table->timestamps();
74+
$table->softDeletes();
75+
});
76+
}
77+
if (! $schemaBuilder->hasTable('human_users')) {
78+
$schemaBuilder->create('human_users', function (Blueprint $table) {
79+
$table->increments('id');
80+
$table->string('name');
81+
$table->timestamps();
82+
$table->softDeletes();
83+
});
84+
}
6585
}
6686

6787
protected function seedDatabase()
6888
{
6989
$adminRole = Role::create(['role' => 'Administrator']);
7090
$userRole = Role::create(['role' => 'User']);
91+
$animal = AnimalUser::create(['name' => 'Animal']);
92+
$human = HumanUser::create(['name' => 'Human']);
7193

72-
collect(range(1, 20))->each(function ($i) use ($userRole) {
94+
collect(range(1, 20))->each(function ($i) use ($userRole, $animal, $human) {
7395
/** @var User $user */
7496
$user = User::query()->create([
7597
'name' => 'Record-' . $i,
@@ -88,8 +110,10 @@ protected function seedDatabase()
88110

89111
if ($i % 2) {
90112
$user->roles()->attach(Role::all());
113+
$human->users()->save($user);
91114
} else {
92115
$user->roles()->attach($userRole);
116+
$animal->users()->save($user);
93117
}
94118
});
95119
}

0 commit comments

Comments
 (0)