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

Vatin Bundle Laravel Package

becklyn/vatin-bundle

Symfony bundle integrating the VATIN library to validate EU VAT numbers. Provides a @Vatin constraint for format checks and optional VIES existence validation, plus services to validate VATINs and query the VIES SOAP web service directly.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require ddeboer/vatin-bundle
    

    Add the bundle to config/app.php under providers:

    Ddeboer\VatinBundle\DdeboerVatinBundle::class,
    
  2. First Use Case: Validate a VAT number format in a Laravel model using annotations:

    use Ddeboer\VatinBundle\Validator\Constraints\Vatin;
    
    class Company
    {
        /**
         * @Vatin
         */
        public $vatNumber;
    }
    

    Laravel’s validator will automatically check the VAT format during form submissions or model validation.


Where to Look First


Implementation Patterns

Usage Patterns

  1. Annotation-Based Validation (Recommended for Forms/Models):

    use Ddeboer\VatinBundle\Validator\Constraints\Vatin;
    
    class UserRequest extends FormRequest
    {
        /**
         * @Vatin(checkExistence=true)
         */
        public $vatNumber;
    }
    
    • Use checkExistence=true to validate against the VIES service (requires internet access).
  2. Manual Validation in Controllers/Commands:

    use Ddeboer\VatinBundle\Validator\VatinValidator;
    
    public function store(Request $request)
    {
        $validator = app(VatinValidator::class);
        $isValid = $validator->isValid($request->vat_number, false); // false = format only
        if (!$isValid) {
            return back()->withErrors(['vat_number' => 'Invalid VAT format.']);
        }
    }
    
  3. VIES Service Integration:

    use Ddeboer\VatinBundle\Client\ViesClient;
    
    public function checkVatExistence(string $vatNumber)
    {
        $vies = app(ViesClient::class);
        try {
            $response = $vies->checkVat(explode(' ', $vatNumber)[0], explode(' ', $vatNumber)[1]);
            return $response->isValid();
        } catch (\Exception $e) {
            // Handle VIES service unavailability
            return false;
        }
    }
    

Workflows

  1. Form Handling:

    • Use annotations in request classes or model fields.
    • Handle ValidatorException for VIES service failures gracefully:
      try {
          $validator->validate($entity);
      } catch (ValidatorException $e) {
          // Log or notify admin about VIES service issues
          return back()->withErrors(['vat_number' => 'Unable to verify VAT. Please try again later.']);
      }
      
  2. API Validation:

    • Create a custom validator or use Laravel’s ValidatesWhenResolved trait to integrate with API requests:
      use Illuminate\Validation\ValidatesWhenResolved;
      
      class CreateCompanyRequest extends FormRequest
      {
          use ValidatesWhenResolved;
      
          public function rules()
          {
              return [
                  'vat_number' => ['required', new Vatin(['checkExistence' => true])],
              ];
          }
      }
      
  3. Batch Processing:

    • Validate VAT numbers in bulk (e.g., during data migration):
      $validator = app(VatinValidator::class);
      $companies = Company::all();
      foreach ($companies as $company) {
          if (!$validator->isValid($company->vat_number)) {
              $company->markAsInvalid();
          }
      }
      

Integration Tips

  1. Laravel Service Container:

    • Bind the validator manually if not using Symfony’s container:
      $this->app->bind(VatinValidator::class, function ($app) {
          return new VatinValidator();
      });
      
  2. Custom Validation Logic:

    • Extend the validator for business-specific rules:
      class CustomVatinValidator extends VatinValidator
      {
          public function isValidForBusiness(string $vatNumber): bool
          {
              $isValid = parent::isValid($vatNumber);
              return $isValid && $this->isApprovedCountry($vatNumber);
          }
      }
      
  3. Caching VIES Responses:

    • Cache responses from the VIES service to reduce API calls (e.g., using Laravel’s cache):
      $cacheKey = 'vies_' . md5($vatNumber);
      $response = Cache::remember($cacheKey, now()->addHours(1), function () use ($vies, $vatNumber) {
          return $vies->checkVat(...);
      });
      
  4. Fallback for Offline Use:

    • Implement a fallback mechanism when the VIES service is unavailable:
      try {
          $response = $vies->checkVat(...);
      } catch (\Exception $e) {
          $response = Cache::get('vies_fallback_' . $vatNumber, false);
      }
      

Gotchas and Tips

Pitfalls

  1. VIES Service Unavailability:

    • The VIES service is unreliable. Always wrap calls in a try-catch block and handle failures gracefully.
    • Tip: Implement a retry mechanism or fallback to cached/offline data.
  2. Symfony Dependency:

    • The bundle relies on Symfony’s validator component. If you’re not using Symfony, ensure compatibility by manually binding the validator:
      $this->app->bind('validator', function () {
          return Validation::makeValidator();
      });
      
  3. Annotation Parsing:

    • Laravel’s validator may not automatically parse annotations in all contexts (e.g., API resources). Use explicit validation rules or custom validators:
      // Instead of annotations:
      $validator = Validator::make($data, [
          'vat_number' => [new Vatin(['checkExistence' => true])],
      ]);
      
  4. VAT Number Format:

    • The validator expects the VAT number in the format COUNTRYCODE123456789B01 (e.g., NL123456789B01). Ensure your input matches this format before validation.
    • Tip: Preprocess the input to standardize the format:
      $vatNumber = strtoupper(trim($request->vat_number));
      
  5. Testing:

    • The VIES service may block or throttle requests during testing. Use mocks or stubs:
      $this->mock(ViesClient::class)->shouldReceive('checkVat')->andReturn((object) ['isValid' => true]);
      

Debugging

  1. Validator Errors:

    • Check the error messages returned by the validator. For example:
      $errors = $validator->getErrors();
      // Handle errors like 'Invalid VAT format' or 'VAT number not found in VIES'.
      
  2. VIES Service Issues:

    • Log the raw response from the VIES service for debugging:
      try {
          $response = $vies->checkVat(...);
          \Log::debug('VIES Response', ['data' => $response]);
      } catch (\Exception $e) {
          \Log::error('VIES Error', ['error' => $e->getMessage()]);
      }
      
  3. Performance Bottlenecks:

    • The VIES service can be slow. Profile your application to identify delays:
      $start = microtime(true);
      $response = $vies->checkVat(...);
      $duration = microtime(true) - $start;
      \Log::info('VIES Request Duration', ['duration' => $duration]);
      

Config Quirks

  1. Customizing the VIES Client:

    • The VIES client uses default SOAP options. Customize it by binding a new instance:
      $this->app->bind(ViesClient::class, function ($app) {
          $client = new ViesClient();
          $client->setOptions(['timeout' => 10]); // Custom timeout
          return $client;
      });
      
  2. Validator Configuration:

    • The checkExistence option enables VIES validation. Disable it for offline use or when the service is unreliable:
      $validator->isValid($vatNumber, false); // false = format only
      
  3. Supported Countries:

    • The validator supports EU VAT numbers. Non-EU numbers may not validate correctly.
    • Tip: Extend the validator to support additional countries if needed.

Extension Points

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