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

Util Transformer Laravel Package

phrity/util-transformer

Lightweight PHP utility for transforming values between types. Provides transformers with canTransform()/transform(), plus resolvers to chain and recurse converters. Includes JSON/flatten decoders and converters for basic types, DateTime, enums, Stringable, Throwable and more.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require phrity/util-transformer
    
  2. First Use Case: Transform a simple value (e.g., DateTime to string):

    use Phrity\Util\Transformer\Converters\DateTimeConverter;
    use Phrity\Util\Transformer\Types;
    
    $dateTime = new \DateTime('2025-07-29 14:13');
    $converter = new DateTimeConverter();
    
    if ($converter->canTransform($dateTime, Types::STRING)) {
        $result = $converter->transform($dateTime, Types::STRING);
        // $result = "2025-07-29T14:13:00+00:00" (default ISO 8601 format)
    }
    
  3. Where to Look First:

    • Documentation: Start with the README and Types for type definitions.
    • Transformers List: Review the transformers list to identify the most relevant one for your use case.
    • Resolvers: For complex transformations, explore resolvers like FirstMatchResolver or RecursionResolver.

Implementation Patterns

Core Workflow

  1. Check Compatibility: Always use canTransform($subject, $targetType = null) before calling transform() to avoid runtime errors.

    if ($transformer->canTransform($data, Types::ARRAY)) {
        $arrayData = $transformer->transform($data, Types::ARRAY);
    }
    
  2. Chaining Transformers: Use FirstMatchResolver to chain transformers for fallback behavior:

    use Phrity\Util\Transformer\Resolvers\FirstMatchResolver;
    
    $resolver = new FirstMatchResolver([
        new DateTimeConverter(),
        new EnumConverter(),
        new BasicTypeConverter(), // Fallback
    ]);
    
  3. Recursive Transformations: Apply transformations recursively to nested structures (arrays/objects) using RecursionResolver:

    use Phrity\Util\Transformer\Resolvers\RecursionResolver;
    
    $recursiveTransformer = new RecursionResolver(new BasicTypeConverter());
    $result = $recursiveTransformer->transform($nestedData);
    
  4. String Conversion: For universal string conversion, use StringResolver:

    use Phrity\Util\Transformer\Resolvers\StringResolver;
    
    $stringResolver = new StringResolver();
    $stringOutput = $stringResolver->transform($anything);
    

Integration Tips

  • Laravel Service Providers: Register transformers as singletons in AppServiceProvider for reuse:

    public function register()
    {
        $this->app->singleton(DateTimeConverter::class, fn() => new DateTimeConverter());
    }
    
  • API Responses: Use RecursionResolver with BasicTypeConverter to normalize Eloquent models:

    $modelTransformer = new RecursionResolver(new BasicTypeConverter());
    return response()->json($modelTransformer->transform($user));
    
  • Form Request Validation: Decode flattened arrays (e.g., from API payloads) with FlattenDecoder:

    $decoder = new FlattenDecoder('_');
    $nestedData = $decoder->transform($request->all());
    
  • Error Handling: Wrap throwables in ThrowableConverter for debugging:

    $errorTransformer = new ThrowableConverter();
    $errorMessage = $errorTransformer->transform($exception, Types::STRING);
    
  • Symfony Normalizers: Integrate with Symfony’s NormalizerInterface via SymfonyNormalizerWrapper:

    $normalizer = new \Symfony\Component\Serializer\Normalizer\PropertyNormalizer();
    $wrapper = new SymfonyNormalizerWrapper($normalizer);
    $arrayData = $wrapper->transform($object);
    

Gotchas and Tips

Pitfalls

  1. Type Mismatches:

    • canTransform() may return true for a target type, but transform() might fail if the input cannot logically be converted (e.g., converting a DateTime to Types::INTEGER).
    • Fix: Handle exceptions or validate output post-transformation.
  2. Recursion Depth:

    • RecursionResolver may hit PHP’s recursion limit for deeply nested structures.
    • Fix: Use setMaxDepth() or limit recursion manually:
      $recursiveTransformer->setMaxDepth(10);
      
  3. JSON Decoding:

    • JsonDecoder defaults to decoding objects as stdClass. To force associative arrays, pass true:
      $decoder = new JsonDecoder(true); // Decodes to array
      
  4. Symfony Dependencies:

    • SymfonyNormalizerWrapper requires symfony/serializer and optionally symfony/property-access. Install manually:
      composer require symfony/serializer symfony/property-access
      
  5. Custom Types:

    • Extending Type constants requires defining new constants in your codebase. Ensure consistency across transformers.

Debugging

  • Log Transformations: Override transform() in a custom transformer to log inputs/outputs:

    class DebugTransformer extends BasicTypeConverter {
        public function transform($subject, $targetType = null) {
            \Log::debug("Transforming: " . print_r($subject, true));
            return parent::transform($subject, $targetType);
        }
    }
    
  • Check canTransform(): Always verify compatibility before transformation to avoid silent failures.

Extension Points

  1. Custom Transformers: Implement the TransformerInterface to create domain-specific transformers:

    class MyCustomTransformer implements TransformerInterface {
        public function canTransform($subject, $targetType = null): bool {
            return is_a($subject, MyClass::class);
        }
    
        public function transform($subject, $targetType = null) {
            return $subject->toArray();
        }
    }
    
  2. Override Defaults: Customize BasicTypeConverter defaults (e.g., force OBJECT to ARRAY):

    $converter = new BasicTypeConverter([
        Types::OBJECT => Types::ARRAY,
    ]);
    
  3. Resolver Strategies: Combine resolvers for complex pipelines:

    $pipeline = new ChainedResolver([
        new FlattenDecoder('_'),
        new RecursionResolver(new FirstMatchResolver([
            new DateTimeConverter(),
            new BasicTypeConverter(),
        ])),
    ]);
    
  4. Performance: Cache transformers for repeated use (e.g., in Laravel’s service container):

    $this->app->singleton(RecursionResolver::class, fn() => new RecursionResolver(new BasicTypeConverter()));
    

Quirks

  • Empty Strings: BasicTypeConverter converts empty strings to false for booleans and 0 for integers/numbers. Handle edge cases explicitly if needed.

  • Null Handling: canTransform(null) may return true for some transformers (e.g., BasicTypeConverter), but transform(null) will return null or an empty structure. Validate outputs for null inputs.

  • DateTime Formatting: DateTimeConverter uses ISO 8601 (c) by default. Customize with dateTimeFormat:

    new DateTimeConverter(dateTimeFormat: 'Y-m-d H:i:s');
    
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.
cadot.eu/make
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky