Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Api Resource Mapper Laravel Package

zingle/api-resource-mapper

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require zingle/api-resource-mapper
    

    Register ApiResourceMapperProvider in config/app.php under providers.

  2. Define Mapping Configuration Create a mapping file (e.g., Resources/config/mapping/foo_module.json) in your module:

    {
        "FooModel": {
            "source": ["id", "name", "api_field"],
            "target": ["id", "name", "custom_name"],
            "transform": {
                "custom_name": "strtoupper"
            }
        }
    }
    
  3. Register Mapper in Module Provider Add the registerMapper() method to your module’s service provider:

    private function registerMapper()
    {
        $this->app->bind('zingle.foo_module.meta_loader', function ($app) {
            $module = $app->make('laravel_modules.repository')->find('FooModule');
            return new \Zingle\ApiResourceMapper\Loader($module->getExtraPath('Resources/config/mapping'));
        });
        $this->app->bind('zingle.foo_module.model_meta_factory', function ($app) {
            return new \Zingle\ApiResourceMapper\ModelMetaFactory($app->make('zingle.foo_module.meta_loader'));
        });
    }
    
  4. First Use Case Extend AbstractResource and inject the mapper in the constructor:

    use Zingle\ApiResourceMapper\AbstractResource;
    
    class FooResource extends AbstractResource
    {
        public function __construct($mapperFactory)
        {
            $this->mapper = $mapperFactory->getMapper(app('zingle.foo_module.model_meta_factory'));
        }
    
        public function toArray($request)
        {
            return $this->mapper->map($this->resource);
        }
    }
    

Implementation Patterns

Core Workflow

  1. Mapping Definition Define mappings in JSON files under Resources/config/mapping/ for each module. Example:

    {
        "User": {
            "source": ["api_id", "email", "created_at"],
            "target": ["id", "email", "created_at"],
            "transform": {
                "email": "strtolower"
            }
        }
    }
    
  2. Dynamic Resource Mapping Use the mapper in toArray() or toResponse() methods:

    public function toArray($request)
    {
        return $this->mapper->map($this->resource, 'User'); // 'User' is the model key in mapping
    }
    
  3. Collection Handling Map collections by leveraging the mapCollection method:

    public function toArray($request)
    {
        return $this->mapper->mapCollection($this->resource->all(), 'User');
    }
    
  4. Conditional Mapping Use the conditionalMap method for runtime logic:

    $this->mapper->conditionalMap($resource, 'User', function ($item) {
        return $item->isActive();
    });
    
  5. Integration with API Clients Combine with HTTP clients (e.g., Guzzle) to fetch and map data:

    $response = $client->get('api/users');
    $users = json_decode($response->getBody(), true);
    return $this->mapper->mapCollection($users, 'User');
    

Gotchas and Tips

Pitfalls

  1. Missing Mapping Files Ensure Resources/config/mapping/ exists and is accessible. Double-check paths in Loader initialization.

  2. Case Sensitivity Model keys in JSON mappings must match the class name exactly (e.g., User, not user).

  3. Circular Dependencies Avoid binding the mapper factory to the same module’s provider if the module depends on the mapper during bootstrapping.

  4. Transform Functions Custom transform functions (e.g., "transform": {"field": "myFunction"}) must be globally available or autoloaded. Use fully qualified namespaces if needed:

    "transform": {
        "field": "\\App\\Transformers::customTransform"
    }
    
  5. Performance with Large Collections For large datasets, cache the ModelMetaFactory instance to avoid reloading mappings:

    $this->app->singleton('zingle.foo_module.model_meta_factory', function ($app) {
        return new ModelMetaFactory($app->make('zingle.foo_module.meta_loader'));
    });
    

Debugging Tips

  1. Validate Mappings Use php artisan tinker to test mappings interactively:

    $mapper = app('zingle.foo_module.model_meta_factory')->getMapper();
    $mapper->map($rawData, 'User'); // Check output for errors
    
  2. Logging Enable Laravel’s debug mode (APP_DEBUG=true) to log missing mappings or transform errors.

  3. Fallback Handling Implement a fallback in AbstractResource for unmapped fields:

    public function toArray($request)
    {
        $mapped = $this->mapper->map($this->resource, 'User');
        return array_merge($mapped, $this->resource->toArray()); // Fallback to raw data
    }
    

Extension Points

  1. Custom Mappers Extend AbstractMapper to add logic (e.g., nested resource handling):

    class NestedMapper extends AbstractMapper
    {
        public function map($resource, $modelKey)
        {
            // Custom logic
            return parent::map($resource, $modelKey);
        }
    }
    
  2. Dynamic JSON Loading Override the Loader class to fetch mappings from a database or external API:

    class DatabaseLoader extends Loader
    {
        public function load($path)
        {
            return json_decode($this->fetchFromDatabase($path), true);
        }
    }
    
  3. Event-Based Mapping Dispatch events before/after mapping (e.g., MappingStarted, MappingCompleted):

    use Illuminate\Support\Facades\Event;
    
    Event::listen('zingle.mapping.started', function ($resource, $modelKey) {
        // Pre-process resource
    });
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
babenkoivan/elastic-client
innmind/static-analysis
innmind/coding-standard
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme
agtp/agtp-php
agtp/mod-php
centraldesktop/protobuf-php