Skip to content

Commit

Permalink
Throw exception when cast class is not existed. (#6010)
Browse files Browse the repository at this point in the history
Co-authored-by: 李铭昕 <715557344@qq.com>
  • Loading branch information
her-cat and limingxinleo committed Aug 9, 2023
1 parent bcc5cf3 commit 7c4c00e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
27 changes: 27 additions & 0 deletions src/Exception/InvalidCastException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Database\Exception;

use RuntimeException;

class InvalidCastException extends RuntimeException
{
/**
* @param string $model the name of the affected model
* @param string $column the name of the column
* @param string $castType the name of the cast type
*/
public function __construct(public string $model, public string $column, public string $castType)
{
parent::__construct("Call to undefined cast [{$castType}] on column [{$column}] in model [{$model}].");
}
}
21 changes: 18 additions & 3 deletions src/Model/Concerns/HasAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Hyperf\Contract\CastsAttributes;
use Hyperf\Contract\CastsInboundAttributes;
use Hyperf\Contract\Synchronized;
use Hyperf\Database\Exception\InvalidCastException;
use Hyperf\Database\Model\EnumCollector;
use Hyperf\Database\Model\JsonEncodingException;
use Hyperf\Database\Model\Relations\Relation;
Expand Down Expand Up @@ -1264,9 +1265,23 @@ protected function isJsonCastable(string $key): bool
*/
protected function isClassCastable(string $key): bool
{
return array_key_exists($key, $this->getCasts())
&& class_exists($class = $this->parseCasterClass($this->getCasts()[$key]))
&& ! in_array($class, static::$primitiveCastTypes);
$casts = $this->getCasts();

if (! array_key_exists($key, $casts)) {
return false;
}

$castType = $this->parseCasterClass($casts[$key]);

if (in_array($castType, static::$primitiveCastTypes)) {
return false;
}

if (class_exists($castType)) {
return true;
}

throw new InvalidCastException($this::class, $key, $castType);
}

/**
Expand Down
10 changes: 10 additions & 0 deletions tests/DatabaseModelCustomCastingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Hyperf\Contract\Castable;
use Hyperf\Contract\CastsAttributes;
use Hyperf\Contract\CastsInboundAttributes;
use Hyperf\Database\Exception\InvalidCastException;
use Hyperf\Database\Model\CastsValue;
use Hyperf\Database\Model\Model;
use Mockery;
Expand Down Expand Up @@ -251,6 +252,14 @@ public function testCastsValueSupportNull()
unset($user->not_found);
$this->assertSame(['name' => 'Hyperf', 'gender' => 1, 'role_id' => null], $model->getAttributes());
}

public function testThrowExceptionWhenCastClassNotExist()
{
$this->expectException(InvalidCastException::class);
$this->expectExceptionMessage('Call to undefined cast [HyperfTest\Database\InvalidCaster] on column [invalid_caster] in model [HyperfTest\Database\TestModelWithCustomCast].');
$model = new TestModelWithCustomCast();
$model->invalid_caster = 'foo';
}
}

class TestModelWithCustomCast extends Model
Expand All @@ -274,6 +283,7 @@ class TestModelWithCustomCast extends Model
'value_object_caster_with_argument' => ValueObject::class . ':argument',
'value_object_caster_with_caster_instance' => ValueObjectWithCasterInstance::class,
'cast_using' => CastUsing::class,
'invalid_caster' => InvalidCaster::class,
];
}

Expand Down

0 comments on commit 7c4c00e

Please sign in to comment.