Skip to content

Commit

Permalink
Add whereHas support for one to many relation
Browse files Browse the repository at this point in the history
  • Loading branch information
imanghafoori1 committed Sep 6, 2023
1 parent 7617448 commit f0c2aeb
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/FakeDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ public static function applyWheres($query, Collection $collection)
}
$collection = self::applyBasicWhere($where, $table, $query, $collection);
} elseif ($type === 'Column' && $where['boolean'] === 'and') {
if (strpos($where['first'], '.') && strpos($where['second'], '.')) {
return self::applyWhereColumns($where);
}

$collection = $collection->filter(function ($row) use ($where, $table) {
return self::whereColumn($where, $row[$table]);
});
Expand All @@ -340,6 +344,8 @@ public static function applyWheres($query, Collection $collection)
$method = $where['not'] ? 'whereNotBetween' : 'whereBetween';
}
$collection = $collection->$method($column, $value);
} elseif ($type === 'Exists') {
$collection = self::applyWheres($where['query'], $collection);
}
}

Expand Down Expand Up @@ -734,4 +740,26 @@ private static function aggregate($columns, $builder, $function)

return [0 => $result];
}

private static function applyWhereColumns($where): Collection
{
[$table1, $column1] = explode('.', $where['first']);
[$table2, $column2] = explode('.', $where['second']);
$op = $where['operator'];
if ($op === '=' || $op === '==') {
$op = '===';
}

$result = array_filter(self::$fakeRows[$table1], function ($row) use ($table1, $table2, $column1, $column2, $op) {
foreach (self::$fakeRows[$table2] as $row2) {
if (eval('return $row[$table1][$column1] '.$op.' $row2[$table2][$column2];')) {
return true;
}
}

return false;
});

return new Collection($result);
}
}
76 changes: 76 additions & 0 deletions tests/Wheres/WhereHasTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace Imanghafoori\EloquentMockery\Tests\Wheres;

use Illuminate\Database\Eloquent\Model;
use Imanghafoori\EloquentMockery\FakeDB;
use PHPUnit\Framework\TestCase;

class WhereHasUser extends Model
{
protected $table = 'users';

public $fillable = ['name'];

public function comments()
{
return $this->hasMany(WhereHasComment::class, 'user_id');
}
}

class WhereHasComment extends Model
{
protected $table = 'comments';

public $fillable = ['comment'];

public function user()
{
return $this->belongsTo(WhereHasUser::class);
}
}

class WhereHasTest extends TestCase
{
public function tearDown(): void
{
FakeDB::dontMockQueryBuilder();
}

public function setUp(): void
{
FakeDB::mockQueryBuilder();
}

/**
* @test
*/
public function whereHas()
{
FakeDB::addRow('users', ['id' => 1, 'name' => 'Iman 1']);
FakeDB::addRow('users', ['id' => 2, 'name' => 'Iman 2']);
FakeDB::addRow('users', ['id' => 3, 'name' => 'Iman 3']);
FakeDB::addRow('users', ['id' => 4, 'name' => 'Iman 4']);

FakeDB::addRow('comments', ['id' => 3, 'user_id' => 2]);

$users = WhereHasUser::query()->whereHas('comments')->get();
$this->assertEquals(1, $users->count());
$this->assertEquals(2, $users[0]->id);

FakeDB::addRow('comments', ['id' => 1, 'user_id' => 1]);

$users = WhereHasUser::query()->whereHas('comments')->get();
$this->assertEquals(2, $users->count());
$this->assertEquals(1, $users[0]->id);
$this->assertEquals(2, $users[1]->id);

FakeDB::addRow('comments', ['id' => 1, 'user_id' => 4]);

$users = WhereHasUser::query()->whereHas('comments')->get();
$this->assertEquals(3, $users->count());
$this->assertEquals(1, $users[0]->id);
$this->assertEquals(2, $users[1]->id);
$this->assertEquals(4, $users[2]->id);
}
}

0 comments on commit f0c2aeb

Please sign in to comment.