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

String Formatter Laravel Package

respect/string-formatter

Flexible PHP string formatting library with chainable formatters and templated placeholders. Mask, pattern, date, number, and more to transform/format values (e.g., credit cards, phones, amounts) via FormatterBuilder or PlaceholderFormatter modifiers.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require respect/string-formatter
    
  2. Basic Usage:

    use Respect\StringFormatter\FormatterBuilder as f;
    
    // Mask a credit card number
    echo f::create()->mask('1234567890123456')->format('1234567890123456');
    // Output: 1234 56** **** 3456
    
    // Format a phone number
    echo f::create()->pattern('###-###-####')->format('1234567890');
    // Output: 123-456-7890
    
  3. PlaceholderFormatter for Templates:

    use Respect\StringFormatter\PlaceholderFormatter;
    
    $formatter = new PlaceholderFormatter([
        'name' => 'John Doe',
        'email' => 'john@example.com',
    ]);
    
    echo $formatter->format('Hello {{name|uppercase}}, your email is {{email}}');
    // Output: Hello JOHN DOE, your email is john@example.com
    

First Use Case: Masking Sensitive Data

// In a Laravel controller or service
use Respect\StringFormatter\FormatterBuilder as f;

public function showUserProfile(User $user) {
    $maskedPhone = f::create()->mask('###-###-####')->format($user->phone);
    $maskedEmail = f::create()->mask('*@*')->format($user->email);

    return view('profile', [
        'phone' => $maskedPhone,
        'email' => $maskedEmail,
    ]);
}

Implementation Patterns

1. Formatter Chaining

Leverage FormatterBuilder to chain multiple formatters for complex transformations:

// In a Laravel request handler
use Respect\StringFormatter\FormatterBuilder as f;

public function processInput(Request $request) {
    $cleanedInput = f::create()
        ->trim()
        ->lowercase()
        ->pattern('###-###-####')
        ->format($request->input('phone'));

    return response()->json(['phone' => $cleanedInput]);
}

2. Service Container Integration

Register formatters as Laravel services for dependency injection:

// In AppServiceProvider
public function register() {
    $this->app->singleton(FormatterBuilder::class, function () {
        return f::create();
    });
}

// Usage in a controller
public function __construct(private FormatterBuilder $formatter) {}

public function updateProfile(Request $request) {
    $formattedName = $this->formatter
        ->trim()
        ->uppercase()
        ->format($request->input('name'));

    // ...
}

3. Validation Rules

Create custom validation rules using formatters:

// app/Rules/MaskedCreditCard.php
use Respect\StringFormatter\CreditCardFormatter;
use Illuminate\Contracts\Validation\Rule;

class MaskedCreditCard implements Rule {
    public function passes($attribute, $value) {
        $formatter = new CreditCardFormatter();
        return $formatter->format($value) !== $value;
    }

    public function message() {
        return 'The :attribute must be a valid credit card number.';
    }
}

// Usage in FormRequest
public function rules() {
    return [
        'credit_card' => ['required', new MaskedCreditCard],
    ];
}

4. Dynamic Template Rendering

Use PlaceholderFormatter for dynamic content in Blade templates:

// In a controller
public function generateInvoice(User $user, Order $order) {
    $formatter = new PlaceholderFormatter([
        'user' => $user,
        'order' => $order,
        'date' => now()->format('Y-m-d'),
    ]);

    return view('invoice', [
        'content' => $formatter->format(file_get_contents('invoice_template.txt')),
    ]);
}

// invoice_template.txt
Invoice Number: {{order->id|pattern:####-####}}
Date: {{date|date:Y/m/d}}
Customer: {{user->name|uppercase}}

5. API Response Transformation

Apply formatters in Laravel API resources:

// app/Http/Resources/UserResource.php
public function toArray($request) {
    return [
        'name' => $this->formatter
            ->trim()
            ->uppercase()
            ->format($this->name),
        'phone' => $this->formatter
            ->pattern('(###) ###-####')
            ->format($this->phone),
        'email' => $this->formatter
            ->mask('*@*')
            ->format($this->email),
    ];
}

6. Middleware for Global Formatting

Create middleware to format request/response data globally:

// app/Http/Middleware/FormatStrings.php
public function handle($request, Closure $next) {
    $response = $next($request);

    if ($response->isJson()) {
        $data = $response->getData(true);
        $formatter = f::create();

        foreach ($data as &$value) {
            if (is_string($value)) {
                $value = $formatter->mask('*')->format($value);
            }
        }

        $response->setData($data);
    }

    return $response;
}

Gotchas and Tips

Common Pitfalls

  1. PatternFormatter Regex Limitations:

    • Avoid overly complex regex patterns that may cause performance issues.
    • Test with edge cases like Unicode characters or special regex metacharacters.
    • Example of a problematic pattern:
      // This may fail with Unicode or special characters
      f::create()->pattern('/[^a-zA-Z0-9]/')->format('Hello! 世界');
      
  2. PlaceholderFormatter Scope:

    • Placeholders are resolved case-sensitively by default. Use modifiers like |lowercase to normalize case.
    • Nested placeholders (e.g., {{user.address.city}}) require the full path to be defined in the formatter’s data.
  3. Credit Card Formatting Quirks:

    • CreditCardFormatter auto-detects card types but may misclassify some numbers. Validate with a dedicated library (e.g., bknock/luhn) if strict compliance is needed.
    • Masking rules vary by region (e.g., EU vs. US). Customize with SecureCreditCardFormatter for specific requirements.
  4. Unicode Handling:

    • Some formatters (e.g., TrimFormatter) may not handle Unicode whitespace correctly. Use mb_* functions explicitly if needed:
      f::create()->trim()->format('  Hello  ');
      // May not trim all Unicode spaces. Use:
      mb_trim($string, ' \t\n\r\0\x0B', 'UTF-8');
      
  5. Modifier Order Matters:

    • The order of modifiers in PlaceholderFormatter templates affects the result:
      // Different from:
      {{value|uppercase|trim}}  // Trims after uppercasing
      {{value|trim|uppercase}}  // Uppercases after trimming
      

Debugging Tips

  1. Inspect Formatter Chains:

    • Use FormatterBuilder::getFormatters() to debug the chain:
      $formatter = f::create()->trim()->uppercase();
      dd($formatter->getFormatters()); // Array of applied formatters
      
  2. PlaceholderFormatter Debugging:

    • Enable debug mode to see unresolved placeholders:
      $formatter = new PlaceholderFormatter([], [], true); // Third param: debug mode
      echo $formatter->format('{{undefined}}'); // Outputs: {{undefined}}
      
  3. PatternFormatter Validation:

    • Test patterns with preg_last_error() to catch regex issues:
      $pattern = '/[invalid[regex/';
      $formatter = f::create()->pattern($pattern);
      try {
          $formatter->format('test');
      } catch (\Exception $e) {
          dd(preg_last_error(), $pattern);
      }
      
  4. Performance Bottlenecks:

    • Avoid chaining too many formatters in loops. Cache results or use a single formatter where possible.
    • For bulk operations, use array mapping with array_map():
      $formatter = f::create()->trim();
      $cleaned = array_map([$formatter, 'format'], $dirtyArray);
      

Extension Points

  1. Custom Formatters:

    • Extend Respect\StringFormatter\Formatter for domain-specific logic:
      class CustomFormatter implements Formatter {
          public function format(string $string): string {
              // Custom logic
              return strtoupper($string) . '!';
          }
      }
      
    • Register with FormatterBuilder:
      $builder = f::create();
      $builder->addFormatter(new CustomFormatter());
      
  2. Custom Modifiers:

    • Implement Respect\StringFormatter\Modifier for PlaceholderFormatter:
      class ReverseModifier implements Modifier {
          public function modify(string $value):
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
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
spatie/mailcoach-vapor