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

Partita Iva Laravel Package

fdisotto/partita-iva

Laravel/PHP package to validate EU VAT numbers via the EU VIES service (checkVatService). Performs a remote lookup against the official EC endpoint to confirm whether a VAT number exists across EU Member States.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require fdisotto/partita-iva:^3.0
    
    • No additional configuration is required. The package now supports both Italian Partita IVA and EU VAT number validation via remote API calls.
  2. Basic Usage Validate an Italian VAT number (Partita IVA) or EU VAT number:

    use Fdisotto\PartitaIva\PartitaIva;
    
    $validator = new PartitaIva();
    $isValid = $validator->isValid('12345678901'); // Italian Partita IVA (bool)
    $isEuValid = $validator->isValid('IT12345678901'); // EU VAT (bool, remote check)
    
  3. First Use Case

    • Form Validation (Italian + EU):
      use Illuminate\Support\Facades\Validator;
      
      $validator = Validator::make(['vat' => 'IT12345678901'], [
          'vat' => ['required', function ($attribute, $value, $fail) {
              if (!app(\Fdisotto\PartitaIva\PartitaIva::class)->isValid($value)) {
                  $fail('The :attribute is invalid.');
              }
          }]
      ]);
      

Implementation Patterns

Core Workflows

  1. Validation in Requests Extend Laravel’s FormRequest for both local and remote validation:

    use Fdisotto\PartitaIva\PartitaIva;
    
    public function rules()
    {
        return [
            'vat_number' => ['required', 'string', function ($attribute, $value, $fail) {
                if (!app(PartitaIva::class)->isValid($value)) {
                    $fail('Invalid VAT number.');
                }
            }]
        ];
    }
    
  2. Service Layer Integration Create a dedicated service for VAT logic (now supporting EU checks):

    namespace App\Services;
    
    use Fdisotto\PartitaIva\PartitaIva;
    
    class VatService {
        protected $validator;
    
        public function __construct(PartitaIva $validator) {
            $this->validator = $validator;
        }
    
        public function validateVat(string $vat): bool {
            return $this->validator->isValid($vat);
        }
    
        public function isEuVat(string $vat): bool {
            return $this->validator->isEuVat($vat); // New method for EU-specific checks
        }
    }
    

    Register the service in AppServiceProvider:

    $this->app->bind(VatService::class, function ($app) {
        return new VatService(new PartitaIva());
    });
    
  3. API Responses Return validation results with metadata (e.g., country code for EU VATs):

    $result = app(PartitaIva::class)->validateWithDetails($request->vat);
    return response()->json($result);
    

Advanced Patterns

  • Batch Validation (EU + Italian) Validate multiple VAT numbers with mixed formats:

    $vatNumbers = ['12345678901', 'IT12345678901', 'DE123456789'];
    $results = collect($vatNumbers)->map(fn($vat) => [
        'vat' => $vat,
        'valid' => app(PartitaIva::class)->isValid($vat),
        'is_eu' => app(PartitaIva::class)->isEuVat($vat),
    ]);
    
  • Custom Error Messages for EU VATs Differentiate between Italian and EU validation errors:

    'vat' => ['required', function ($attribute, $value, $fail) {
        $validator = app(PartitaIva::class);
        if (!$validator->isValid($value)) {
            if ($validator->isEuVat($value)) {
                $fail('The :attribute is not a valid EU VAT number.');
            } else {
                $fail('The :attribute is not a valid Italian Partita IVA.');
            }
        }
    }]
    
  • Caching Remote EU Checks Cache EU VAT responses to reduce API calls (e.g., using Laravel Cache):

    $validator = new PartitaIva();
    $validator->setCacheEnabled(true); // Enable caching (default: false)
    $validator->setCacheTTL(3600); // Cache for 1 hour
    

Gotchas and Tips

Pitfalls

  1. Remote API Dependencies

    • EU VAT validation requires network access to the European Commission API.
    • Mitigation:
      • Enable caching (setCacheEnabled(true)) to avoid repeated requests.
      • Handle exceptions for offline/rate-limited scenarios:
        try {
            $isValid = $validator->isValid('IT12345678901');
        } catch (\Exception $e) {
            \Log::error("EU VAT check failed: " . $e->getMessage());
            // Fallback to local validation or manual review
        }
        
  2. EU VAT Format Variations

    • EU VAT numbers follow the format XX123456789 (country code + digits).
    • Common Issues:
      • Missing country code (e.g., 123456789 instead of IT123456789).
      • Invalid country codes (e.g., US123456789).
    • Solution: Use isEuVat() to pre-check format before remote validation.
  3. Rate Limiting

    • The European Commission API may throttle excessive requests.
    • Workaround: Implement exponential backoff or use a queue (e.g., Laravel Queues) for bulk validations.
  4. Deprecated Methods

    • Methods like isItalianVat() are deprecated in v3.0. Use isValid() for both Italian and EU checks.
    • Migration Tip: Replace:
      $validator->isItalianVat('12345678901'); // Deprecated
      
      with:
      $validator->isValid('12345678901'); // Works for both
      

Debugging Tips

  • Log Remote API Responses Enable debug mode to log EU VAT API responses:

    $validator = new PartitaIva();
    $validator->setDebugMode(true); // Logs API calls/responses
    
  • Test EU VAT Formats Validate known EU VAT numbers (e.g., DE123456789, FR123456789012):

    $validator = new PartitaIva();
    $validator->isValid('DE123456789'); // Should return true/false
    
  • Fallback for Offline Mode Implement a fallback for when remote checks fail:

    public function safeValidate(string $vat): bool {
        try {
            return app(PartitaIva::class)->isValid($vat);
        } catch (\Exception $e) {
            // Fallback: Validate as Italian Partita IVA only
            return app(PartitaIva::class)->isItalianVat($vat);
        }
    }
    

Extension Points

  1. Custom EU VAT Whitelisting Override EU validation logic to whitelist specific VATs:

    class CustomPartitaIva extends PartitaIva {
        protected $whitelist = ['IT12345678901', 'DE987654321'];
    
        public function isValid(string $vat): bool {
            if (in_array($vat, $this->whitelist)) {
                return true;
            }
            return parent::isValid($vat);
        }
    }
    
  2. Integration with Laravel Notifications Notify users of invalid VATs via email:

    if (!$validator->isValid($request->vat)) {
        $user->notify(new InvalidVatNotification($request->vat));
    }
    
  3. Testing Remote Calls Mock the EU VAT API in tests:

    $validator = Mockery::mock(PartitaIva::class);
    $validator->shouldReceive('isEuVat')
              ->with('IT12345678901')
              ->andReturn(true);
    $this->app->instance(PartitaIva::class, $validator);
    
  4. New Method: validateWithDetails() Retrieve structured validation results (country code, validity, etc.):

    $details = $validator->validateWithDetails('IT12345678901');
    // Returns:
    // [
    //     'valid' => true,
    //     'country_code' => 'IT',
    //     'vat_number
    
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.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours