diff --git a/src/foundation/src/Model/Model.php b/src/foundation/src/Model/Model.php index 53c426e9..49b87685 100644 --- a/src/foundation/src/Model/Model.php +++ b/src/foundation/src/Model/Model.php @@ -5,8 +5,14 @@ namespace SwooleTW\Hyperf\Foundation\Model; use Hyperf\DbConnection\Model\Model as BaseModel; +use SwooleTW\Hyperf\Router\Contracts\UrlRoutable; -abstract class Model extends BaseModel +abstract class Model extends BaseModel implements UrlRoutable { protected ?string $connection = null; + + public function resolveRouteBinding($value) + { + return $this->where($this->getRouteKeyName(), $value)->firstOrFail(); + } } diff --git a/src/router/src/Contracts/UrlRoutable.php b/src/router/src/Contracts/UrlRoutable.php index 2bfe4d90..3b31edb2 100644 --- a/src/router/src/Contracts/UrlRoutable.php +++ b/src/router/src/Contracts/UrlRoutable.php @@ -4,22 +4,29 @@ namespace SwooleTW\Hyperf\Router\Contracts; +use Hyperf\Database\Model\Model; + interface UrlRoutable { /** * Get the value of the model's route key. + * + * @return string */ - public function getRouteKey(): string; + public function getRouteKey(); - // TODO: Route model binding - // /** - // * Get the route key for the model. - // */ - // public function getRouteKeyName(): string; + /** + * Get the route key for the model. + * + * @return string + */ + public function getRouteKeyName(); - // TODO: Route model binding - // /** - // * Retrieve the model for a bound value. - // */ - // public function resolveRouteBinding(string $value, ?string $field = null): Hyperf\Database\Model\Model; + /** + * Retrieve the model for a bound value. + * + * @param string $value + * @return null|Model + */ + public function resolveRouteBinding($value); } diff --git a/src/router/src/Exceptions/UrlRoutableNotFoundException.php b/src/router/src/Exceptions/UrlRoutableNotFoundException.php new file mode 100644 index 00000000..6352a294 --- /dev/null +++ b/src/router/src/Exceptions/UrlRoutableNotFoundException.php @@ -0,0 +1,18 @@ +getName(); + if (is_a($class, UrlRoutable::class, true)) { + return $this->resolveUrlRoutable($class, $params[$name]); + } + if (is_a($class, Model::class, true)) { return $this->resolveModel($class, $params[$name]); } @@ -118,6 +124,21 @@ protected function resolveBinding(ReflectionType $definition, array $params, str } } + /** + * @param class-string $class + * @throws ModelNotFoundException + */ + protected function resolveUrlRoutable(string $class, string $routeKey): UrlRoutable + { + $urlRoutable = make($class)->resolveRouteBinding($routeKey); + + if (is_null($urlRoutable)) { + throw new UrlRoutableNotFoundException($class, $routeKey); + } + + return $urlRoutable; + } + /** * @param class-string $class * @throws ModelNotFoundException diff --git a/tests/Router/Stub/UrlRoutableStub.php b/tests/Router/Stub/UrlRoutableStub.php index 05366fed..29b004bf 100644 --- a/tests/Router/Stub/UrlRoutableStub.php +++ b/tests/Router/Stub/UrlRoutableStub.php @@ -4,12 +4,23 @@ namespace SwooleTW\Hyperf\Tests\Router\Stub; +use Hyperf\Database\Model\Model; use SwooleTW\Hyperf\Router\Contracts\UrlRoutable; class UrlRoutableStub implements UrlRoutable { - public function getRouteKey(): string + public function getRouteKey() { return '1'; } + + public function getRouteKeyName() + { + return 'id'; + } + + public function resolveRouteBinding($value) + { + return new Model(); + } }