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

Dto Bundle Laravel Package

antonchernik/dto-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle

    composer require antonchernik/dto-bundle
    

    Register the bundle in config/bundles.php:

    return [
        // ...
        AntonChernik\DtoBundle\AntonChernikDtoBundle::class => ['all' => true],
    ];
    
  2. Configure AutoMapper+ Update config/packages/automapper_plus.yaml (or create it):

    automapper_plus:
        sources:
            - '%kernel.project_dir%/config/automapper'
        mapping_paths:
            - '%kernel.project_dir%/config/automapper'
    
  3. Define a DTO Create a DTO class (e.g., src/Dto/UserDto.php):

    namespace App\Dto;
    
    class UserDto
    {
        public string $name;
        public int $age;
    }
    
  4. Map an Entity to DTO Create a mapping file (config/automapper/UserMapping.php):

    use App\Entity\User;
    use App\Dto\UserDto;
    use AutoMapperPlus\AutoMapper\Configuration\MappingConfiguration;
    
    return function (MappingConfiguration $config) {
        $config->newMapping()
            ->forSource(User::class)
            ->forDestination(UserDto::class)
            ->constructBy('name', 'age');
    };
    
  5. Use in Controller

    use App\Dto\UserDto;
    use App\Entity\User;
    use AutoMapperPlus\AutoMapper\AutoMapperInterface;
    
    class UserController
    {
        public function __construct(private AutoMapperInterface $mapper) {}
    
        public function show(User $user): UserDto
        {
            return $this->mapper->map(UserDto::class, $user);
        }
    }
    

Implementation Patterns

Common Workflows

  1. DTO Creation

    • Use DTOs for API responses, form submissions, or service layer contracts.
    • Example: Convert a User entity to UserDto for JSON responses.
  2. Nested Mappings

    • Map complex relationships (e.g., UserUserDto with embedded AddressDto):
      $config->newMapping()
          ->forSource(User::class)
          ->forDestination(UserDto::class)
          ->constructBy('name', 'age')
          ->forMember('address', fn($src) => $this->mapper->map(AddressDto::class, $src->address));
      
  3. Conditional Logic

    • Use forMember with closures for dynamic transformations:
      ->forMember('fullName', fn($src) => $src->firstName . ' ' . $src->lastName)
      
  4. Validation Integration

    • Combine with Symfony Validator for DTO validation:
      use Symfony\Component\Validator\Constraints as Assert;
      
      class UserDto
      {
          #[Assert\NotBlank]
          public string $name;
      }
      
  5. Service Layer Abstraction

    • Use DTOs to decouple controllers from entities:
      // Controller
      $dto = $this->mapper->map(UserDto::class, $request->all());
      $this->userService->create($dto);
      
      // Service
      public function create(UserDto $dto): User
      {
          $user = new User();
          $this->mapper->map($user, $dto);
          $entityManager->persist($user);
      }
      
  6. Batch Processing

    • Map collections efficiently:
      $users = $this->userRepository->findAll();
      $dtos = $this->mapper->map(UserDto::class, $users, true); // true = batch mode
      

Gotchas and Tips

Pitfalls

  1. Circular References

    • AutoMapper+ may fail on bidirectional relationships (e.g., UserAddress).
    • Fix: Use ->ignore() or custom logic:
      ->ignore('addresses') // Skip circular references
      
  2. Mapping Paths

    • Forgetting to configure mapping_paths in automapper_plus.yaml will break mappings.
    • Fix: Ensure paths are correct and files are autoloaded.
  3. Type Mismatches

    • AutoMapper+ is strict about types. Mismatches (e.g., stringint) will throw errors.
    • Fix: Use explicit type casting in mappings:
      ->forMember('age', fn($src) => (int) $src->age)
      
  4. Caching Issues

    • Mappings are cached. Changes to mapping configurations require cache clearing:
      php bin/console cache:clear
      
  5. Overwriting Default Mappings

    • If multiple mappings exist for the same source/destination, the last one wins.
    • Tip: Use ->override() to explicitly replace mappings.

Debugging Tips

  1. Enable AutoMapper+ Debugging Add to config/packages/dev/automapper_plus.yaml:

    automapper_plus:
        debug: true
    

    Check logs for mapping execution details.

  2. Inspect Mappings Dump registered mappings:

    $this->mapper->getConfiguration()->getMappings();
    
  3. Use constructBy Carefully

    • constructBy requires exact property names. Typos will cause silent failures.
    • Tip: Use IDE autocompletion for property names.

Extension Points

  1. Custom Value Resolvers Extend AutoMapperPlus\AutoMapper\ValueResolver\ValueResolverInterface for complex logic:

    class CustomResolver implements ValueResolverInterface
    {
        public function resolve($source, $destination, $propertyPath, MappingContext $context)
        {
            return strtoupper($source->name);
        }
    }
    

    Register in a mapping:

    ->forMember('name', fn($src) => $this->mapper->resolve('CustomResolver', $src))
    
  2. Event Listeners Use Symfony events to pre/post-process mappings:

    // src/EventListener/MappingListener.php
    public function onKernelRequest(GetResponseEvent $event)
    {
        $this->mapper->addValueResolver(new CustomResolver());
    }
    
  3. Custom Naming Conventions Override AutoMapper+'s default naming strategies (e.g., for snake_case ↔ camelCase):

    automapper_plus:
        naming_convention: snake_case
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui