Skip to content

Commit 797f5a9

Browse files
authored
Merge pull request #61 from zoul0813/feature/first-find-fail
Add firstOrFail, findOrFail support Close #60
2 parents cf8939a + 3860825 commit 797f5a9

File tree

5 files changed

+185
-0
lines changed

5 files changed

+185
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ vendor
22
composer.lock
33
dynamodb_local_test.db
44
/nbproject
5+
*.log

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ $model->chunk(10, function ($records) {
118118
// Use this with caution unless your limit is small.
119119
// DynamoDB has a limit of 1MB so if your limit is very big, the results will not be expected.
120120
$model->where('name', 'foo')->take(3)->get();
121+
122+
// firstOrFail
123+
$model->where('name', 'foo')->firstOrFail();
124+
// for composite key
125+
$model->where('id', 'foo')->where('id2', 'bar')->firstOrFail();
126+
127+
// findOrFail
128+
$model->findOrFail('foo');
129+
// for composite key
130+
$model->findOrFail(['id' => 'foo', 'id2' => 'bar']);
121131
```
122132
123133
* Or if you want to sync your DB table with a DynamoDb table, use trait `BaoPham\DynamoDb\ModelTrait`, it will call a `PutItem` after the model is saved.

src/DynamoDbQueryBuilder.php

+54
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Aws\DynamoDb\DynamoDbClient;
66
use Exception;
77
use Illuminate\Database\Eloquent\Collection;
8+
use \Illuminate\Database\Eloquent\ModelNotFoundException;
89
use Illuminate\Support\Facades\Log;
910

1011
class DynamoDbQueryBuilder
@@ -148,6 +149,10 @@ public function chunk($chunk_size, callable $callback)
148149

149150
public function find($id, array $columns = [])
150151
{
152+
if ($this->isMultipleIds($id)) {
153+
return $this->findMany($id, $columns);
154+
}
155+
151156
$model = $this->model;
152157

153158
$model->setId($id);
@@ -185,13 +190,44 @@ public function find($id, array $columns = [])
185190
return $model;
186191
}
187192

193+
public function findMany($ids, array $columns = [])
194+
{
195+
throw new NotSupportedException('Finding by multiple ids is not supported');
196+
}
197+
198+
public function findOrFail($id, $columns = [])
199+
{
200+
$result = $this->find($id, $columns);
201+
202+
if ($this->isMultipleIds($id)) {
203+
if (count($result) == count(array_unique($id))) {
204+
return $result;
205+
}
206+
} elseif (! is_null($result)) {
207+
return $result;
208+
}
209+
210+
throw (new ModelNotFoundException)->setModel(
211+
get_class($this->model), $id
212+
);
213+
}
214+
188215
public function first($columns = [])
189216
{
190217
$item = $this->getAll($columns, 1);
191218

192219
return $item->first();
193220
}
194221

222+
public function firstOrFail($columns = [])
223+
{
224+
if (! is_null($model = $this->first($columns))) {
225+
return $model;
226+
}
227+
228+
throw (new ModelNotFoundException)->setModel(get_class($this->model));
229+
}
230+
195231
public function get($columns = [])
196232
{
197233
return $this->getAll($columns);
@@ -457,6 +493,24 @@ protected function getSpecificDynamoDbKey($keyName, $value)
457493
return $key;
458494
}
459495

496+
protected function isMultipleIds($id)
497+
{
498+
$hasCompositeKey = $this->model->hasCompositeKey();
499+
500+
if (!$hasCompositeKey && isset($id[$this->model->getKeyName()])) {
501+
return false;
502+
}
503+
504+
if ($hasCompositeKey) {
505+
$compositeKey = $this->model->getCompositeKey();
506+
if (isset($id[$compositeKey[0]]) && isset($id[$compositeKey[1]])) {
507+
return false;
508+
}
509+
}
510+
511+
return $hasCompositeKey ? is_array(array_first($id)) : is_array($id);
512+
}
513+
460514
/**
461515
* @return DynamoDbModel
462516
*/

tests/DynamoDbCompositeModelTest.php

+63
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace BaoPham\DynamoDb\Tests;
44

5+
use BaoPham\DynamoDb\NotSupportedException;
6+
use \Illuminate\Database\Eloquent\ModelNotFoundException;
7+
58
/**
69
* Class DynamoDbCompositeModelTest
710
*
@@ -52,6 +55,66 @@ public function testFindRecord()
5255
$this->assertEquals($seedName, $item->name);
5356
}
5457

58+
public function testFindMultiple()
59+
{
60+
$this->expectException(NotSupportedException::class);
61+
$this->testModel->find([['id1' => 'bar', 'id2' => 'foo']]);
62+
}
63+
64+
public function testFindOrFailRecordPass()
65+
{
66+
$seed = $this->seed();
67+
$seedId = array_get($seed, 'id.S');
68+
$seedId2 = array_get($seed, 'id2.S');
69+
$seedName = array_get($seed, 'name.S');
70+
71+
$item = $this->testModel->findOrFail(['id' => $seedId, 'id2' => $seedId2]);
72+
73+
$this->assertNotEmpty($item);
74+
$this->assertEquals($seedId, $item->id);
75+
$this->assertEquals($seedId2, $item->id2);
76+
$this->assertEquals($seedName, $item->name);
77+
}
78+
79+
public function testFindOrFailMultiple()
80+
{
81+
$this->expectException(NotSupportedException::class);
82+
$this->testModel->findOrFail([['id' => 'bar', 'id2' => 'foo']]);
83+
}
84+
85+
public function testFirstOrFailRecordPass()
86+
{
87+
$seed = $this->seed();
88+
$seedId = array_get($seed, 'id.S');
89+
$seedId2 = array_get($seed, 'id2.S');
90+
$seedName = array_get($seed, 'name.S');
91+
92+
$first = $this->testModel
93+
->where('id', $seedId)
94+
->where('id2', $seedId2)
95+
->firstOrFail();
96+
97+
$this->assertNotEmpty($first);
98+
$this->assertEquals($seedId, $first->id);
99+
$this->assertEquals($seedId2, $first->id2);
100+
$this->assertEquals($seedName, $first->name);
101+
}
102+
103+
public function testFindOrFailRecordFail()
104+
{
105+
$this->expectException(ModelNotFoundException::class);
106+
$this->testModel->findOrFail(['id' => 'failure-expected', 'id2' => 'expected-to-fail']);
107+
}
108+
109+
public function testFirstOrFailRecordFail()
110+
{
111+
$this->expectException(ModelNotFoundException::class);
112+
$this->testModel
113+
->where('id', 'failure-expected')
114+
->where('id2', 'expected-to-fail')
115+
->firstOrFail();
116+
}
117+
55118
public function testUpdateRecord()
56119
{
57120
$seed = $this->seed();

tests/DynamoDbModelTest.php

+57
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace BaoPham\DynamoDb\Tests;
44

5+
use BaoPham\DynamoDb\NotSupportedException;
6+
use \Illuminate\Database\Eloquent\ModelNotFoundException;
7+
58
/**
69
* Class DynamoDbModelTest
710
*
@@ -47,6 +50,60 @@ public function testFindRecord()
4750
$this->assertEquals($seedName, $item->name);
4851
}
4952

53+
public function testFindMultiple()
54+
{
55+
$this->expectException(NotSupportedException::class);
56+
$this->testModel->find(['bar', 'foo']);
57+
}
58+
59+
public function testFindOrFailRecordPass()
60+
{
61+
$seed = $this->seed();
62+
$seedId = array_get($seed, 'id.S');
63+
$seedName = array_get($seed, 'name.S');
64+
65+
$item = $this->testModel->findOrFail($seedId);
66+
67+
$this->assertNotEmpty($item);
68+
$this->assertEquals($seedId, $item->id);
69+
$this->assertEquals($seedName, $item->name);
70+
}
71+
72+
public function testFindOrFailMultiple()
73+
{
74+
$this->expectException(NotSupportedException::class);
75+
$this->testModel->findOrFail(['bar', 'foo']);
76+
}
77+
78+
public function testFirstOrFailRecordPass()
79+
{
80+
$seed = $this->seed();
81+
$seedId = array_get($seed, 'id.S');
82+
$seedName = array_get($seed, 'name.S');
83+
84+
$first = $this->testModel
85+
->where('id', $seedId)
86+
->firstOrFail();
87+
88+
$this->assertNotEmpty($first);
89+
$this->assertEquals($seedId, $first->id);
90+
$this->assertEquals($seedName, $first->name);
91+
}
92+
93+
public function testFindOrFailRecordFail()
94+
{
95+
$this->expectException(ModelNotFoundException::class);
96+
$this->testModel->findOrFail('expected-to-fail');
97+
}
98+
99+
public function testFirstOrFailRecordFail()
100+
{
101+
$this->expectException(ModelNotFoundException::class);
102+
$this->testModel
103+
->where('id', 'expected-to-fail')
104+
->firstOrFail();
105+
}
106+
50107
public function testGetAllRecords()
51108
{
52109
$this->seed();

0 commit comments

Comments
 (0)