Skip to content

Commit dbb44d5

Browse files
committed
add dedicated exceptions
1 parent f8917ff commit dbb44d5

File tree

11 files changed

+112
-18
lines changed

11 files changed

+112
-18
lines changed

docs/relations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class PostModel extends Model
9393

9494
public function user(): Relation
9595
{
96-
return $this->belongTo(UserModel::class);
96+
return $this->belongsTo(UserModel::class);
9797
}
9898
}
9999
```

src/Enums/RelationTypes.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ enum RelationTypes
88
{
99
case hasOne;
1010
case hasMany;
11-
case belongTo;
11+
case belongsTo;
1212
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Michalsn\CodeIgniterNestedModel\Exceptions;
4+
5+
use RuntimeException;
6+
7+
final class NestedModelException extends RuntimeException
8+
{
9+
public static function forMethodNotSupported(string $name): static
10+
{
11+
return new self(lang('NestedModel.methodNotSupported', [$name]));
12+
}
13+
14+
public static function forParentRelationNotDeclared(string $name): static
15+
{
16+
return new self(lang('NestedModel.parentRelationNotDeclared', [$name]));
17+
}
18+
19+
public static function forRelationNotDefined(string $name): static
20+
{
21+
return new self(lang('NestedModel.relationNotDefined', [$name]));
22+
}
23+
24+
public static function forMissingReturnType(string $name): static
25+
{
26+
return new self(lang('NestedModel.missingReturnType', [$name]));
27+
}
28+
29+
public static function forIncorrectReturnType(string $name): static
30+
{
31+
return new self(lang('NestedModel.incorrectReturnType', [$name]));
32+
}
33+
}

src/Language/en/NestedModel.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
return [
4+
'methodNotSupported' => 'This method is not supported for the "{0}" relation.',
5+
'parentRelationNotDeclared' => 'Parent relation "{0}" has not been declared yet.',
6+
'relationNotDefined' => 'Relation "{0}" is not defined.',
7+
'missingReturnType' => 'Method "{0}()" is missing a required return type declaration.',
8+
'incorrectReturnType' => 'Method "{0}()" returned an incorrect type.'
9+
];

src/Relation.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use CodeIgniter\Model;
1111
use Michalsn\CodeIgniterNestedModel\Enums\OrderTypes;
1212
use Michalsn\CodeIgniterNestedModel\Enums\RelationTypes;
13+
use Michalsn\CodeIgniterNestedModel\Exceptions\NestedModelException;
1314
use ReflectionObject;
1415

1516
class Relation
@@ -126,7 +127,7 @@ public function ofMany(string $field, OrderTypes $order): static
126127
private function setOrder(string $field, OrderTypes $order): void
127128
{
128129
if ($this->type !== RelationTypes::hasOne) {
129-
throw new BadMethodCallException("This method is not supported for the '{$this->type->name}' relation.");
130+
throw NestedModelException::forMethodNotSupported($this->type->name);
130131
}
131132

132133
$this->model->orderBy($field, $order->value);

src/Traits/HasLazyRelations.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ private function handleRelation(string $name)
4141

4242
$relation->model->where($relation->foreignKey, $this->attributes[$relation->primaryKey]);
4343

44-
if (in_array($relation->type, [RelationTypes::hasOne, RelationTypes::belongTo], true)) {
44+
if (in_array($relation->type, [RelationTypes::hasOne, RelationTypes::belongsTo], true)) {
4545
$this->attributes[$name] = $relation->model->first();
4646
} else {
4747
$this->attributes[$name] = $relation->model->findAll();

src/Traits/HasRelations.php

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use InvalidArgumentException;
1010
use LogicException;
1111
use Michalsn\CodeIgniterNestedModel\Enums\RelationTypes;
12+
use Michalsn\CodeIgniterNestedModel\Exceptions\NestedModelException;
1213
use Michalsn\CodeIgniterNestedModel\Relation;
1314
use Michalsn\CodeIgniterNestedModel\With;
1415
use ReflectionClass;
@@ -43,7 +44,7 @@ public function with(string $relation, ?Closure $closure = null): static
4344
[$relation, $name] = explode('.', $relation, 2);
4445

4546
if (! isset($this->relations[$relation])) {
46-
throw new InvalidArgumentException(sprintf('Parent relation "%s" has not been declared yet.', $relation));
47+
throw NestedModelException::forParentRelationNotDeclared($relation);
4748
}
4849

4950
$this->relations[$relation]->setWith(new With($name, $closure));
@@ -65,18 +66,18 @@ public function with(string $relation, ?Closure $closure = null): static
6566
private function checkReturnType(string $methodName): bool
6667
{
6768
if (! method_exists($this, $methodName)) {
68-
throw new InvalidArgumentException(sprintf('Relation "%s" is not defined.', $methodName));
69+
throw NestedModelException::forRelationNotDefined($methodName);
6970
}
7071

7172
$reflectionMethod = new ReflectionMethod($this, $methodName);
7273
$returnType = $reflectionMethod->getReturnType();
7374

7475
if (! $returnType instanceof ReflectionNamedType) {
75-
throw new LogicException(sprintf('Method "%s()" is missing a required return type declaration.', $methodName));
76+
throw NestedModelException::forMissingReturnType($methodName);
7677
}
7778

7879
if ($returnType->getName() !== Relation::class) {
79-
throw new UnexpectedValueException(sprintf('Method "%s()" returned an incorrect type.', $methodName));
80+
throw NestedModelException::forIncorrectReturnType($methodName);
8081
}
8182

8283
return true;
@@ -97,8 +98,8 @@ private function addRelation(Model|string $model, RelationTypes $relationType, ?
9798
$this->relations[$relation] = new Relation(
9899
$relationType,
99100
$model,
100-
$foreignKey ?? ($relationType === RelationTypes::belongTo ? $this->relationsGetBelongForeignKey($model) : $this->relationsGetHasForeignKey()),
101-
$primaryKey ?? ($relationType === RelationTypes::belongTo ? $this->relationsGetBelongPrimaryKey($model) : $this->relationsGetHasPrimaryKey())
101+
$foreignKey ?? ($relationType === RelationTypes::belongsTo ? $this->relationsGetBelongForeignKey($model) : $this->relationsGetHasForeignKey()),
102+
$primaryKey ?? ($relationType === RelationTypes::belongsTo ? $this->relationsGetBelongPrimaryKey($model) : $this->relationsGetHasPrimaryKey())
102103
);
103104

104105
return $this->relations[$relation];
@@ -123,9 +124,9 @@ protected function hasMany(Model|string $model, ?string $foreignKey = null, ?str
123124
/**
124125
* @throws ReflectionException
125126
*/
126-
protected function belongTo(Model|string $model, ?string $primaryKey = null, ?string $foreignKey = null): Relation
127+
protected function belongsTo(Model|string $model, ?string $primaryKey = null, ?string $foreignKey = null): Relation
127128
{
128-
return $this->addRelation($model, RelationTypes::belongTo, $foreignKey, $primaryKey);
129+
return $this->addRelation($model, RelationTypes::belongsTo, $foreignKey, $primaryKey);
129130
}
130131

131132
/*
@@ -177,6 +178,7 @@ protected function belongsToMany(Model|string $model, Model|string $through, ?st
177178
$this->relations[$relation]->setThrough($through, $throughForeignKey, $throughPrimaryKey);
178179
}
179180
*/
181+
180182
/**
181183
* @throws ReflectionException
182184
*/
@@ -387,7 +389,7 @@ protected function getDataForRelationById(int|string $id, Relation $relation)
387389

388390
$relation->applyConditions();
389391

390-
return in_array($relation->type, [RelationTypes::hasOne, RelationTypes::belongTo], true) ?
392+
return in_array($relation->type, [RelationTypes::hasOne, RelationTypes::belongsTo], true) ?
391393
$query->first() :
392394
$query->findAll();
393395
}
@@ -431,7 +433,7 @@ protected function getDataForRelationByIds(array $id, Relation $relation): array
431433

432434
$relationData = [];
433435

434-
if (in_array($relation->type, [RelationTypes::hasOne, RelationTypes::belongTo], true)) {
436+
if (in_array($relation->type, [RelationTypes::hasOne, RelationTypes::belongsTo], true)) {
435437
foreach ($results as $row) {
436438
$relationData[$this->tempReturnType === 'array' ? $row[$relation->foreignKey] : $row->{$relation->foreignKey}] = $row;
437439
}

tests/ModelTest.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use CodeIgniter\Model;
99
use CodeIgniter\Test\CIUnitTestCase;
1010
use CodeIgniter\Test\DatabaseTestTrait;
11+
use Michalsn\CodeIgniterNestedModel\Exceptions\NestedModelException;
1112
use Tests\Support\Database\Seeds\SeedTests;
1213
use Tests\Support\Entities\Post;
1314
use Tests\Support\Entities\Profile;
@@ -32,6 +33,46 @@ public function testModelInstance(): void
3233
$this->assertInstanceOf(UserModel::class, $model);
3334
}
3435

36+
public function testRelationNotDefined(): void
37+
{
38+
$this->expectException(NestedModelException::class);
39+
$this->expectExceptionMessage('Relation "notExist" is not defined.');
40+
41+
model(UserModel::class)->with('notExist')->find(1);
42+
}
43+
44+
public function testMissingReturnType(): void
45+
{
46+
$this->expectException(NestedModelException::class);
47+
$this->expectExceptionMessage('Method "missingReturnType()" is missing a required return type declaration.');
48+
49+
model(UserModel::class)->with('missingReturnType')->find(1);
50+
}
51+
52+
public function testIncorrectReturnType(): void
53+
{
54+
$this->expectException(NestedModelException::class);
55+
$this->expectExceptionMessage('Method "incorrectReturnType()" returned an incorrect type.');
56+
57+
model(UserModel::class)->with('incorrectReturnType')->find(1);
58+
}
59+
60+
public function testParentRelationNotDeclared(): void
61+
{
62+
$this->expectException(NestedModelException::class);
63+
$this->expectExceptionMessage('Parent relation "posts" has not been declared yet.');
64+
65+
model(UserModel::class)->with('posts.something')->find(1);
66+
}
67+
68+
public function testMethodNotSupported(): void
69+
{
70+
$this->expectException(NestedModelException::class);
71+
$this->expectExceptionMessage('This method is not supported for the "hasMany" relation.');
72+
73+
model(UserModel::class)->posts()->latestOfMany();
74+
}
75+
3576
public function testFindHasOne()
3677
{
3778
// Load normal model
@@ -135,7 +176,7 @@ public function testFindHasManyAsArray()
135176
$this->assertSame('Title 1', $user->posts[0]['title']);
136177
}
137178

138-
public function testFindBelongTo()
179+
public function testFindbelongsTo()
139180
{
140181
// Load normal model
141182
$post = model(PostModel::class)->find(1);

tests/_support/Models/CommentModel.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ protected function initialize(): void
5656

5757
public function user(): Relation
5858
{
59-
return $this->belongTo(UserModel::class);
59+
return $this->belongsTo(UserModel::class);
6060
}
6161

6262
public function post(): Relation
6363
{
64-
return $this->belongTo(PostModel::class);
64+
return $this->belongsTo(PostModel::class);
6565
}
6666
}

tests/_support/Models/PostModel.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ protected function initialize(): void
5656

5757
public function user(): Relation
5858
{
59-
return $this->belongTo(UserModel::class);
59+
return $this->belongsTo(UserModel::class);
6060
}
6161

6262
public function comments(): Relation

0 commit comments

Comments
 (0)