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

Regex Value Objects Laravel Package

apie/regex-value-objects

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package:

    composer require apie/regex-value-objects
    

    Ensure your composer.json includes PHP 8.3+ and apie/core (version-matched).

  2. First Use Case: Create a value object for a specific validation need (e.g., email):

    use Apie\RegexValueObjects\RegexValueObject;
    
    class EmailAddress extends RegexValueObject
    {
        public function __construct(string $value)
        {
            parent::__construct($value, '/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/');
        }
    }
    

    Use it in a Laravel controller or service:

    $email = new EmailAddress(request('email')); // Throws InvalidArgumentException if invalid
    
  3. Where to Look First:

    • Source Code: Monorepo Structure.
    • Core Class: RegexValueObject (abstract base class with validation logic).
    • Tests: Check the monorepo for RegexValueObjectTest.php to understand edge cases (e.g., regex failures, empty inputs).

Implementation Patterns

Usage Patterns

  1. Value Object Creation: Extend RegexValueObject for domain-specific rules:

    class PhoneNumber extends RegexValueObject
    {
        public function __construct(string $value)
        {
            parent::__construct($value, '/^\+?[0-9\s\-\(\)]{10,}$/');
        }
    }
    
  2. Integration with Laravel Validation: Create a custom validation rule:

    use Apie\RegexValueObjects\RegexValueObject;
    use Illuminate\Validation\Rule;
    
    class RegexRule extends Rule
    {
        protected $pattern;
    
        public function __construct(string $pattern)
        {
            $this->pattern = $pattern;
        }
    
        public function validate($attribute, $value, $fail)
        {
            try {
                new RegexValueObject($value, $this->pattern);
            } catch (\InvalidArgumentException $e) {
                $fail($e->getMessage());
            }
        }
    }
    

    Use in FormRequest:

    public function rules()
    {
        return [
            'email' => ['required', new RegexRule('/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/')],
        ];
    }
    
  3. Domain-Driven Design (DDD) Workflow: Use value objects in domain services:

    class UserService
    {
        public function createUser(array $data)
        {
            $email = new EmailAddress($data['email']);
            $phone = new PhoneNumber($data['phone']);
    
            // Proceed with business logic...
        }
    }
    
  4. Model Casting: Cast attributes to value objects in Eloquent models:

    use Illuminate\Database\Eloquent\Casts\Attribute;
    
    protected function email(): Attribute
    {
        return Attribute::make(
            get: fn ($value) => $value,
            set: fn ($value) => new EmailAddress($value)
        );
    }
    

Workflows

  1. Input Sanitization Pipeline:

    • Use value objects in middleware or AppServiceProvider to validate incoming requests early.
    • Example middleware:
      public function handle(Request $request, Closure $next)
      {
          $request->merge([
              'email' => new EmailAddress($request->email),
          ]);
          return $next($request);
      }
      
  2. API Contracts:

    • Integrate with OpenAPI/Swagger by documenting value object constraints in schema definitions.
  3. Testing:

    • Test value objects with PHPUnit:
      public function testValidEmail()
      {
          $email = new EmailAddress('test@example.com');
          $this->assertEquals('test@example.com', $email->value());
      }
      
      public function testInvalidEmail()
      {
          $this->expectException(InvalidArgumentException::class);
          new EmailAddress('invalid-email');
      }
      

Integration Tips

  1. Performance Optimization:

    • Pre-compile regex patterns in a static method:
      class EmailAddress extends RegexValueObject
      {
          private static $pattern;
      
          public function __construct(string $value)
          {
              if (self::$pattern === null) {
                  self::$pattern = '/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/';
              }
              parent::__construct($value, self::$pattern);
          }
      }
      
  2. Error Handling:

    • Customize error messages by extending the constructor:
      public function __construct(string $value)
      {
          parent::__construct($value, '/pattern/', 'Invalid email format. Use format: user@example.com');
      }
      
  3. Laravel Service Providers:

    • Register value objects as singletons or bindings:
      $this->app->bind(EmailAddress::class, function () {
          return new EmailAddress(request('email'));
      });
      
  4. Localization:

    • Support multilingual regex patterns (e.g., international phone numbers) by parameterizing patterns:
      class PhoneNumber extends RegexValueObject
      {
          public function __construct(string $value, string $countryCode = 'US')
          {
              $pattern = $this->getPatternForCountry($countryCode);
              parent::__construct($value, $pattern);
          }
      }
      

Gotchas and Tips

Pitfalls

  1. Regex Complexity:

    • Avoid overly complex patterns (e.g., nested quantifiers, backreferences) to prevent catastrophic backtracking, which can hang PHP.
    • Tip: Use tools like Regex101 to test patterns before implementation.
  2. Immutability:

    • Value objects are immutable; modifying the $value property after instantiation will not update validation.
    • Tip: Use getter methods to access the validated value:
      public function value(): string { return $this->value; }
      
  3. Laravel Validation Integration:

    • Custom validation rules (RegexRule) do not automatically integrate with Laravel’s validation error formatting.
    • Tip: Extend Illuminate\Validation\Validator to customize error messages:
      Validator::extend('regex', function ($attribute, $value, $parameters, $validator) {
          try {
              new RegexValueObject($value, $parameters[0]);
              return true;
          } catch (\InvalidArgumentException $e) {
              $validator->errors()->add($attribute, $e->getMessage());
              return false;
          }
      });
      
  4. Dependency Isolation:

    • The package depends on apie/core, which may pull in unrelated functionality.
    • Tip: Use Composer’s replace directive to isolate dependencies:
      "replacements": {
          "apie/core": "self.version"
      }
      
  5. PHP 8.3+ Requirement:

    • If your Laravel app uses PHP <8.3, you’ll need to upgrade or fork the package.
    • Tip: Check Laravel’s PHP version requirements for compatibility.
  6. No Native Laravel Support:

    • The package lacks built-in Laravel integrations (e.g., FormRequest rules, API resource validation).
    • Tip: Create a package wrapper (e.g., laravel-regex-value-objects) to abstract Laravel-specific logic.

Debugging

  1. Regex Failures:

    • Use preg_last_error() to diagnose regex issues:
      try {
          $email = new EmailAddress($input);
      } catch (\InvalidArgumentException $e) {
          error_log('Regex error: ' . preg_last_error());
          throw $e;
      }
      
  2. Performance Bottlenecks:

    • Profile regex validation with Xdebug or Blackfire to identify slow patterns.
    • Tip: Cache compiled patterns or use simpler regex where possible.
  3. Unexpected Behavior:

    • If a value object accepts invalid input silently, check for:
      • Incorrect regex patterns.
      • Overridden validation logic in child classes.
      • Tip: Add a isValid() method to explicitly check validity:
        public function isValid(): bool
        {
            return $this->validate();
        }
        

Configuration Quirks

  1. Default Patterns:

    • The package does not provide default patterns (e.g., for emails, UUIDs). You must define them manually.
    • Tip: Create a base class with common patterns:
      abstract class BaseValueObject extends RegexValueObject
      {
          protected function getEmailPattern(): string { return '/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/'; }
      }
      
  2. Case Sensitivity:

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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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