Weave 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

Mapping Bundle Laravel Package

ehyiah/mapping-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require ehyiah/mapping-bundle
    

    For non-Flex projects, manually add to composer.json:

    "require": {
        "ehyiah/mapping-bundle": "^1.0"
    }
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        Ehyiah\MappingBundle\MappingBundle::class => ['all' => true],
    ];
    
  2. First Use Case: Map a DTO to an Entity for form handling:

    use Ehyiah\MappingBundle\Mapper\MapperAwareInterface;
    use Ehyiah\MappingBundle\Mapper\MapperAwareTrait;
    
    class UserDto implements MapperAwareInterface
    {
        use MapperAwareTrait;
    
        private string $name;
        private string $email;
    
        // Getters/setters...
    }
    
    class User // Entity
    {
        private string $name;
        private string $email;
    
        // Getters/setters...
    }
    
    // In a controller/service:
    $mapper = $this->get('ehyiah_mapping.mapper');
    $userDto = new UserDto();
    $userDto->setName('John');
    $userDto->setEmail('[email protected]');
    
    $user = $mapper->mapToTarget($userDto, new User());
    

Where to Look First

  • Core Service: ehyiah_mapping.mapper (autowired or via DI container).
  • Documentation: Bundle’s README.md for method signatures and basic examples.
  • Tests: Check tests/ for edge cases (e.g., nested objects, type mismatches).

Implementation Patterns

Core Workflows

1. Form Data Mapping

  • Problem: Avoid passing full entities to forms (e.g., User with sensitive fields).
  • Solution: Create a DTO (e.g., UserEditDto) and map to/from the entity.
    // Controller
    $form = $this->createForm(UserEditDtoType::class, $dto);
    $form->handleRequest($request);
    
    if ($form->isSubmitted() && $form->isValid()) {
        $mapper->mapToTarget($dto, $userEntity); // Sync DTO → Entity
        $entityManager->flush();
    }
    

2. Bidirectional Sync

  • Use mapFromTarget to update a DTO from an entity (e.g., after DB fetch):
    $userEntity = $entityManager->find(User::class, $id);
    $mapper->mapFromTarget($userEntity, $userDto);
    

3. Custom Mappings

  • Override default property mapping via setMapping():
    $mapper->setMapping($sourceClass, $targetClass, [
        'sourceProperty' => 'targetProperty',
        // Custom logic via callables:
        'sourceMethod' => function ($source) {
            return strtoupper($source->getName());
        },
    ]);
    

4. Integration with Symfony Forms

  • Use MapperAwareInterface in DTOs to auto-configure form fields:
    class UserEditDto implements MapperAwareInterface
    {
        use MapperAwareTrait;
    
        // ...
    }
    
    // FormType
    $builder->add('name', TextType::class, [
        'mapped' => false, // Manually map via MapperBundle
    ]);
    

Advanced Patterns

Nested Object Mapping

  • Map complex objects (e.g., User with Address):
    $mapper->mapToTarget($userDto, $userEntity);
    // Address is auto-mapped if both DTO/Entity implement MapperAwareInterface.
    

Event Listeners

  • Extend mapping logic via events (e.g., pre/post-map hooks):
    $mapper->addListener(new class implements MappingListenerInterface {
        public function onPreMap($source, $target, MappingEvent $event) {
            // Modify $target before mapping.
        }
    });
    

Batch Processing

  • Map collections efficiently:
    $users = $mapper->mapToTargetCollection($userDtos, [], User::class);
    

Gotchas and Tips

Pitfalls

  1. Circular References

    • Issue: Mapping bidirectional relationships (e.g., User ↔ Profile) may cause infinite loops.
    • Fix: Explicitly exclude properties or use ignoreProperties:
      $mapper->mapToTarget($source, $target, [], ['ignoredProperty']);
      
  2. Type Mismatches

    • Issue: Silent failures if property types don’t align (e.g., string ↔ int).
    • Fix: Enable strict mode or validate manually:
      $mapper->setStrictMode(true); // Throws exceptions on type errors.
      
  3. Lazy-Loaded Entities

    • Issue: Proxy entities (e.g., Doctrine) may not have loaded properties.
    • Fix: Use mapFromTarget after fetching all required data:
      $entityManager->refresh($entity); // Ensure data is loaded.
      
  4. Overwriting Data

    • Issue: mapToTarget overwrites existing target properties.
    • Fix: Use partial mapping or merge strategies:
      $mapper->setMergeMode(true); // Preserve existing values.
      

Debugging Tips

  • Enable Logging:
    # config/packages/ehyiah_mapping.yaml
    ehyiah_mapping:
        debug: true # Logs mapping operations.
    
  • Inspect Mappings:
    $mapper->getMappings(); // View registered mappings.
    
  • Test Edge Cases:
    • Null values, empty collections, and nested objects.

Extension Points

  1. Custom Mappers

    • Implement MapperInterface for domain-specific logic:
      class CustomMapper implements MapperInterface {
          public function map($source, $target, array $options = []) {
              // Custom logic.
          }
      }
      
    • Register via:
      services:
          App\Mapper\CustomMapper:
              tags: ['ehyiah_mapping.mapper']
      
  2. Property Transformers

    • Use callables in mappings for dynamic transformations:
      $mapper->setMapping(UserDto::class, User::class, [
          'rawName' => function ($value) {
              return trim($value); // Sanitize input.
          },
      ]);
      
  3. Event-Driven Extensions

    • Listen to MappingEvent for pre/post-processing:
      $mapper->addListener(new class implements MappingListenerInterface {
          public function onPostMap($source, $target, MappingEvent $event) {
              if ($target instanceof User) {
                  $target->setUpdatedAt(new \DateTime());
              }
          }
      });
      

Configuration Quirks

  • Default Mappings: The bundle auto-detects properties with matching names, but explicit mappings override defaults.
  • Performance: For large datasets, batch processing (mapToTargetCollection) is more efficient than looping.
  • Symfony Flex: If using Flex, ensure config/bundles.php is updated post-install.
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels