Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[11.x] Allow easier overriding of the exception thrown by invalid ID in route binding #53944

Conversation

cosmastech
Copy link
Contributor

@cosmastech cosmastech commented Dec 17, 2024

This is to make it easier to handle invalid route keys without having to override HasUniqueStringIds@resolveRouteBindingQuery() method (which would be a lot of duplication and create maintenance overhead).

This consolidates code a little bit into a common method handleInvalidUniqueId which should throw an exception. There is no breaking change here, as we're still throwing the same ModelNotFoundException. For a team that wishes to customize their return type (such as indicating this is a 422 response, not a 404), they can easily do that as follows:

// custom exception
class InvalidTwrnException extends \RuntimeException implements Responsable
{
    public $key;

    public function setTwrn($key)
    {
        $this->key = $key;

        return $this;
    }

    public function toResponse($request)
    {
        return response()->json(['message' => 'invalid twrn', 'twrn' => $this->key], 422);
    }
}

// the trait
trait HasTwrnsTrait
{
    use HasUniqueStringIds;

    public function newUniqueId()
    {
        return (string) Twrn::new();
    }
  
    protected function isValidUniqueId($value): bool
    {
        return Twrn::isValid($value);
    }

    protected function handleInvalidUniqueId($value, $field): never
    {
        throw (new InvalidTwrnException)->setTwrn($value);
    }
}

*/
protected function handleInvalidUniqueId($value, $field)
{
throw (new ModelNotFoundException)->setModel(get_class($this), $value);
Copy link
Contributor

@shaedrich shaedrich Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could even put the exception name as static property on the model so ModelNotFoundException is taken as a default but can be overwritten without overwriting handleInvalidUniqueId() when one just wants to change the class name

Suggested change
throw (new ModelNotFoundException)->setModel(get_class($this), $value);
throw (new $notFoundException)->setModel(get_class($this), $value);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea, but I think it would require the class to implement setModel() which isn't enforced by an interface.

Copy link
Contributor

@shaedrich shaedrich Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point 👍🏻 Maybe this can be implemented via an interface then 🤔

 trait HasUniqueStringIds
 {
+    private ModelException $notFoundException = ModelNotFoundException
interface ModelException
{
    /**
     * Set the affected Eloquent model and instance ids.
     *
     * @param  class-string<TModel>  $model
     * @param  array<int, int|string>|int|string  $ids
     * @return $this
     */
    public function setModel($model, $ids = []);
}

@taylorotwell taylorotwell merged commit b6f5f02 into laravel:11.x Dec 17, 2024
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants