Skip to content

Conversation

@binaryfire
Copy link
Contributor

Ports Laravel's #[UseResource] and #[UseResourceCollection] attributes to Hypervel, enabling declarative resource binding for models and collections.

Summary

  • Add #[UseResource] attribute for declaratively binding a JsonResource to a model
  • Add #[UseResourceCollection] attribute for declaratively binding a ResourceCollection to a model
  • Add TransformsToResource trait providing toResource() method on models
  • Add TransformsToResourceCollection trait providing toResourceCollection() method on collections
  • Fix AnonymousResourceCollection inheritance to properly extend Hypervel's ResourceCollection

Usage

Model to Resource

use Hypervel\Database\Eloquent\Attributes\UseResource;
use Hypervel\Database\Eloquent\Model;

#[UseResource(PostResource::class)]
class Post extends Model {}

// Transform model to resource
$post->toResource(); // Returns PostResource instance

// Or explicitly specify a resource class
$post->toResource(AlternativeResource::class);

Collection to Resource Collection

use Hypervel\Database\Eloquent\Attributes\UseResourceCollection;
use Hypervel\Database\Eloquent\Model;

#[UseResourceCollection(PostCollection::class)]
class Post extends Model {}

// Transform collection to resource collection
Post::all()->toResourceCollection(); // Returns PostCollection instance

// Or use #[UseResource] - will use ::collection() method
#[UseResource(PostResource::class)]
class Post extends Model {}

Post::all()->toResourceCollection(); // Returns AnonymousResourceCollection of PostResource

Resolution Order

toResource() on Model:

  1. Explicit class parameter
  2. #[UseResource] attribute
  3. Convention-based guessing (App\Http\Resources\{ModelName}Resource)

toResourceCollection() on Collection:

  1. Explicit class parameter
  2. #[UseResourceCollection] attribute (returns new instance)
  3. #[UseResource] attribute (uses ::collection() method)
  4. Convention-based guessing

Files Changed

New Files

  • src/core/src/Database/Eloquent/Attributes/UseResource.php
  • src/core/src/Database/Eloquent/Attributes/UseResourceCollection.php
  • src/core/src/Database/Eloquent/Concerns/TransformsToResource.php
  • src/support/src/Traits/TransformsToResourceCollection.php

Modified Files

  • src/core/src/Database/Eloquent/Model.php - Added TransformsToResource trait
  • src/core/src/Database/Eloquent/Collection.php - Added TransformsToResourceCollection trait
  • src/support/src/Collection.php - Added TransformsToResourceCollection trait
  • src/http/src/Resources/Json/AnonymousResourceCollection.php - Fixed inheritance hierarchy

Test Files

  • tests/Core/Database/Eloquent/Concerns/TransformsToResourceTest.php
  • tests/Core/Database/Eloquent/Models/TransformsToResourceTestModelInModelsNamespace.php
  • tests/Support/Traits/TransformsToResourceCollectionTest.php

AnonymousResourceCollection Fix

As part of this PR, AnonymousResourceCollection was updated to properly extend Hypervel\Http\Resources\Json\ResourceCollection instead of Hyperf\Resource\Json\AnonymousResourceCollection.

Before: The class extended Hyperf's version, which meant it wasn't a subtype of Hypervel's ResourceCollection.

After: The class now extends Hypervel's ResourceCollection, ensuring proper type hierarchy and allowing toResourceCollection() to return the correct type.

Test Plan

  • toResource() transforms model with explicit class
  • toResource() uses #[UseResource] attribute
  • toResource() throws when resource cannot be found
  • guessResourceName() returns correct names for \Models\ namespace
  • guessResourceName() returns empty for non-Models namespace
  • Explicit resource takes precedence over attribute
  • toResourceCollection() transforms collection with explicit class
  • toResourceCollection() returns empty collection for empty input
  • toResourceCollection() uses #[UseResourceCollection] attribute
  • toResourceCollection() uses #[UseResource] with ::collection()
  • #[UseResourceCollection] takes precedence over #[UseResource]
  • Works on both Hypervel\Support\Collection and Hypervel\Database\Eloquent\Collection
  • Throws for non-object items
  • Throws for items without guessResourceName method

Port Laravel's resource attributes for declarative model-to-resource binding:

- Add #[UseResource] attribute for binding JsonResource to models
- Add #[UseResourceCollection] attribute for binding ResourceCollection to models
- Add TransformsToResource trait providing toResource() on models
- Add TransformsToResourceCollection trait providing toResourceCollection() on collections
- Fix AnonymousResourceCollection to properly extend Hypervel's ResourceCollection
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.

1 participant