Skip to content

Field Transformers

Jean-Marc Strauven edited this page Aug 6, 2025 · 2 revisions

πŸ”„ Field Transformers

Field transformers automatically modify and clean your data when creating DTOs. They provide a powerful way to ensure data consistency and apply business rules at the DTO level.

How Transformers Work

Raw Input β†’ Transformers β†’ Validated Data β†’ DTO Creation
     ↓           ↓             ↓              ↓
"  John DOE  " β†’ trim β†’ "John DOE" β†’ title_case β†’ "John Doe"

Transformers run before validation, ensuring clean, consistent data throughout your application.

Built-in Transformers

String Transformers

fields:
  # Trim whitespace
  name:
    type: string
    transformers: [trim]
    # "  John Doe  " β†’ "John Doe"
    
  # Convert case
  email:
    type: email
    transformers: [trim, lowercase]
    # "  [email protected]  " β†’ "[email protected]"
    
  # Title case for names
  full_name:
    type: string
    transformers: [trim, title_case]
    # "john doe smith" β†’ "John Doe Smith"
    
  # Uppercase for codes
  product_code:
    type: string
    transformers: [trim, uppercase]
    # "abc123" β†’ "ABC123"

URL and Slug Transformers

fields:
  # Create URL-friendly slugs
  slug:
    type: string
    transformers: [slugify]
    # "Hello World! How are you?" β†’ "hello-world-how-are-you"
    
  # Clean URLs
  website:
    type: url
    transformers: [trim, normalize_url]
    # "  HTTPS://EXAMPLE.COM/PATH  " β†’ "https://example.com/path"
    
  # Social media handles
  twitter_handle:
    type: string
    transformers: [trim, lowercase, remove_at_symbol]
    # "@JohnDoe" β†’ "johndoe"

Numeric Transformers

fields:
  # Round decimals
  price:
    type: decimal
    precision: 2
    transformers: [round_to_precision]
    # 19.999 β†’ 19.99
    
  # Absolute values
  distance:
    type: decimal
    transformers: [absolute]
    # -15.5 β†’ 15.5
    
  # Format phone numbers
  phone:
    type: string
    transformers: [normalize_phone]
    # "(555) 123-4567" β†’ "+15551234567"

Text Transformers

fields:
  # Remove HTML tags
  description:
    type: text
    transformers: [strip_tags, trim]
    # "<p>Hello <b>world</b>!</p>" β†’ "Hello world!"
    
  # Normalize whitespace
  content:
    type: text
    transformers: [normalize_whitespace]
    # "Hello\n\n\nworld" β†’ "Hello\nworld"
    
  # Excerpt generation
  excerpt:
    type: string
    transformers: [strip_tags, truncate:150, add_ellipsis]
    # Long text β†’ "First 150 characters..."

Advanced Transformers

Custom Business Logic

fields:
  # Tax calculation
  tax_amount:
    type: decimal
    transformers: [calculate_tax]
    # Based on base_amount and tax_rate
    
  # Discount application
  final_price:
    type: decimal
    transformers: [apply_discount]
    # Original price minus discount
    
  # Generate reference numbers
  order_number:
    type: string
    transformers: [generate_order_number]
    # "ORD-2024-001234"

Data Validation and Correction

fields:
  # Validate and format credit card
  credit_card:
    type: string
    transformers: [format_credit_card, mask_credit_card]
    # "4111111111111111" β†’ "4111-****-****-1111"
    
  # Validate and format tax ID
  tax_id:
    type: string
    transformers: [format_tax_id, validate_tax_id]
    # "123456789" β†’ "123-45-6789"
    
  # Clean and validate postal codes
  postal_code:
    type: string
    transformers: [format_postal_code]
    # "k1a0a6" β†’ "K1A 0A6" (Canadian format)

Transformer Chaining

Transformers execute in the order specified:

fields:
  product_name:
    type: string
    transformers: [trim, strip_tags, title_case, truncate:100]
    # "  <b>awesome product name</b>  " 
    # β†’ "Awesome Product Name" (if under 100 chars)
    
  slug:
    type: string
    transformers: [trim, lowercase, slugify, ensure_unique]
    # "  My Awesome Product!  "
    # β†’ "my-awesome-product" or "my-awesome-product-2" if exists

Complete Transformer Reference

String Manipulation

transformers:
  - trim                    # Remove leading/trailing whitespace
  - lowercase              # Convert to lowercase
  - uppercase              # Convert to uppercase
  - title_case             # Title Case Conversion
  - snake_case             # convert_to_snake_case
  - camel_case             # convertToCamelCase
  - pascal_case            # ConvertToPascalCase
  - kebab_case             # convert-to-kebab-case

Text Processing

transformers:
  - strip_tags             # Remove HTML/XML tags
  - strip_tags:allowed     # Remove tags except allowed ones
  - normalize_whitespace   # Normalize multiple spaces/newlines
  - remove_extra_spaces    # Remove multiple consecutive spaces
  - truncate:length        # Truncate to specified length
  - pad_left:length:char   # Pad left side with character
  - pad_right:length:char  # Pad right side with character

URL and Web

transformers:
  - slugify                # Create URL-friendly slug
  - normalize_url          # Normalize URL format
  - add_http               # Add http:// if missing
  - remove_www             # Remove www. prefix
  - extract_domain         # Extract domain from URL

Numbers and Math

transformers:
  - round_to_precision     # Round to field precision
  - absolute               # Convert to absolute value
  - ceil                   # Round up to integer
  - floor                  # Round down to integer
  - format_currency        # Format as currency
  - percentage_to_decimal  # Convert 50% to 0.5

Dates and Time

transformers:
  - parse_date             # Parse various date formats
  - format_date:format     # Format date to specific format
  - timezone_convert:tz    # Convert timezone
  - relative_time          # Convert to relative time

Validation and Formatting

transformers:
  - normalize_phone        # Normalize phone number format
  - format_credit_card     # Format credit card number
  - mask_credit_card       # Mask credit card (show last 4)
  - validate_email         # Ensure valid email format
  - normalize_email        # Normalize email address

Real-World Examples

User Registration DTO

header:
  class: UserRegistrationDto
  namespace: App\DTOs\Auth

fields:
  # Clean and format name
  first_name:
    type: string
    required: true
    max_length: 50
    transformers: [trim, title_case]
    
  last_name:
    type: string
    required: true
    max_length: 50
    transformers: [trim, title_case]
    
  # Normalize email
  email:
    type: email
    required: true
    unique: true
    transformers: [trim, lowercase, normalize_email]
    
  # Format username
  username:
    type: string
    required: true
    unique: true
    min_length: 3
    max_length: 20
    transformers: [trim, lowercase, alphanumeric_only]
    
  # Clean phone number
  phone:
    type: string
    nullable: true
    transformers: [normalize_phone]

Product Data DTO

header:
  class: ProductDataDto
  namespace: App\DTOs\Catalog

fields:
  # Product name and slug
  name:
    type: string
    required: true
    max_length: 255
    transformers: [trim, title_case]
    
  slug:
    type: string
    unique: true
    transformers: [trim, lowercase, slugify, ensure_unique]
    
  # Clean description
  description:
    type: text
    max_length: 2000
    transformers: [trim, strip_tags, normalize_whitespace]
    
  # Format pricing
  price:
    type: decimal
    precision: 2
    min: 0
    transformers: [round_to_precision]
    
  # Clean and format SKU
  sku:
    type: string
    required: true
    unique: true
    transformers: [trim, uppercase, alphanumeric_dash_only]
    
  # Process tags
  tags:
    type: array
    items:
      type: string
    transformers: [trim_array_items, lowercase_array, unique_array]

Contact Form DTO

header:
  class: ContactFormDto
  namespace: App\DTOs\Contact

fields:
  # Personal information
  name:
    type: string
    required: true
    max_length: 100
    transformers: [trim, title_case]
    
  email:
    type: email
    required: true
    transformers: [trim, lowercase]
    
  company:
    type: string
    nullable: true
    max_length: 100
    transformers: [trim, title_case]
    
  # Message content
  subject:
    type: string
    required: true
    max_length: 200
    transformers: [trim, title_case]
    
  message:
    type: text
    required: true
    max_length: 2000
    transformers: [trim, strip_tags, normalize_whitespace]
    
  # Optional fields
  phone:
    type: string
    nullable: true
    transformers: [normalize_phone]
    
  website:
    type: url
    nullable: true
    transformers: [trim, lowercase, normalize_url, add_http]

Custom Transformers

Create your own transformers for specific business needs:

1. Register Custom Transformer

// In AppServiceProvider or dedicated service provider
use Grazulex\LaravelArc\Support\Transformers\TransformerRegistry;

public function boot()
{
    TransformerRegistry::register('format_tax_id', function ($value) {
        // Remove any existing formatting
        $clean = preg_replace('/[^0-9]/', '', $value);
        
        // Format as XXX-XX-XXXX
        if (strlen($clean) === 9) {
            return substr($clean, 0, 3) . '-' . 
                   substr($clean, 3, 2) . '-' . 
                   substr($clean, 5, 4);
        }
        
        return $value;
    });
}

2. Use in YAML

fields:
  tax_id:
    type: string
    required: true
    transformers: [trim, format_tax_id]
    validation: ["regex:/^\d{3}-\d{2}-\d{4}$/"]

Advanced Custom Transformer

TransformerRegistry::register('generate_customer_id', function ($value, $context) {
    // Access other field values through context
    $prefix = $context['company_type'] === 'enterprise' ? 'ENT' : 'STD';
    $timestamp = now()->format('ymd');
    $random = str_pad((string) random_int(1, 9999), 4, '0', STR_PAD_LEFT);
    
    return "{$prefix}-{$timestamp}-{$random}";
});

Transformer Performance

Efficient Chaining

# Good - logical order
transformers: [trim, lowercase, slugify]

# Avoid - redundant operations
transformers: [trim, lowercase, trim, uppercase, lowercase]

Conditional Transformers

fields:
  phone:
    type: string
    transformers: 
      - trim
      - normalize_phone:if_not_empty  # Only if value exists
      - format_phone:country={{country}}  # Dynamic based on other field

Integration with Validation

Transformers run before validation, ensuring clean data:

fields:
  email:
    type: email
    transformers: [trim, lowercase]  # Clean first
    validation: ["email:rfc,dns"]   # Then validate
    
  slug:
    type: string
    transformers: [slugify]         # Create slug
    validation: ["unique:posts,slug"] # Then check uniqueness

What's Next?

Now that you understand field transformers:


Field transformers ensure your data is clean, consistent, and ready for validation. They're the silent heroes of data integrity. 🧹

πŸš€ Laravel Arc Wiki

🏠 Home

πŸš€ Getting Started

πŸ“š Core Concepts

πŸ—οΈ Advanced Features

βš™οΈ Configuration & CLI

🌐 Real-World Examples


🎯 Key Concepts

YAML β†’ DTO β†’ Type-Safe Code

Laravel Arc transforms your YAML definitions into powerful PHP DTOs with automatic validation, field transformers, and behavioral traits.

πŸ”— Quick Links

Clone this wiki locally