Weave 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

Ares Laravel Package

h4kuna/ares

h4kuna/ares is a PHP client for the Czech ARES business registry. Look up companies by IČO and retrieve structured details such as name, address, legal form, and registration data. Lightweight, framework-agnostic, and easy to integrate into Laravel or any PHP app.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package:

composer require h4kuna/ares

There is no Laravel service provider, facade, or config file — this is a framework-agnostic library. First thing to do is open the README on GitHub and look at how the current major version constructs Ares / AresFactory, because the constructor changed between v2 and v3 (v3 requires you to pass a PSR-18 HTTP client and PSR-17 request factory, v2 used its own client). That one detail determines how you wire it up.

The minimal wiring in a Laravel app — a singleton in AppServiceProvider:

// app/Providers/AppServiceProvider.php
use h4kuna\Ares\Ares;

public function register(): void
{
    $this->app->singleton(Ares::class, function () {
        return new Ares(); // or new AresFactory()->create() depending on version
    });
}

First use case: company auto-fill on registration. A Czech user types their IČO (8-digit company ID), your controller calls ARES, and populates name, address, and DIČ:

public function lookup(Ares $ares, Request $request)
{
    $ico = preg_replace('/\D/', '', $request->input('ico'));

    $subject = $ares->find($ico);

    return response()->json([
        'name'    => $subject->getName(),
        'vat_id'  => $subject->getVatId(),   // null for non-VAT-payers
        'address' => (string) $subject->getAddress(),
    ]);
}

Treat that as a starting skeleton and verify method names against the class you installed — AresData/Subject/Address are the DTO types that come back, but property names have shifted across versions (getLegalForm, getRegistrationDate, getAddress()->getCity(), etc.).

Implementation Patterns

Wrap it, don't sprinkle it. Because there's no facade, build one thin service in your app (App\Services\CompanyRegistry) that owns the ARES call plus validation, caching, and error normalization. Controllers, form requests, and Livewire components then depend on your class, which is swappable for a fake in tests. This is the single most valuable step for a package this small and version-churny.

Cache aggressively by IČO. ARES is a government SOAP/REST endpoint: it can take 1–3 seconds, occasionally times out, and returns identical data for the same IČO most days. Wrap the call:

return Cache::remember("ares:{$ico}", now()->addDay(), fn () => $this->ares->find($ico));

Company registry data doesn't need sub-hour freshness. A 6-hour or 24-hour TTL is standard.

Validate before you call. IČO is 8 digits with a weighted checksum. A local validator saves a round-trip and lets you reject junk input before hitting a public API:

// Roughly: last digit == 11 - ((sum of first 7 digits weighted 8..2) % 11) % 10
// Prefer a tested rule; e.g. composer require jakubboucek/lorem-ipsum? no — write it once and unit-test it.

Also normalize: strip spaces, zero-pad 7-digit historical IČOs to 8.

Use it as a Job, not a synchronous call in a form flow. When you need to refresh the ARES fields for stored customers (a nightly sync), push it to a queue. A single 500 ms call is fine in a request; 50 calls for a batch import will melt the request timeout. Rate-limit the queue (Bus::batch()->allowFailures()) and back off on failures.

Persist a snapshot, not a reference. ARES is the source of truth, but the response shape changes. When a user registers via your app, copy the relevant fields into your companies table alongside the IČO and a fetched_at column. Don't re-fetch on every page render, and don't store the returned DTO — it isn't a persisted value object.

Testing pattern. Never call ARES in CI. Bind a fake Ares implementation (or Mockery with a canned AresData) in the test setup. If you need realistic fixtures, capture responses from real IČOs like 27082440 (Alza.cz) and 45274649 (Seznam.cz) once and store them as fixtures.

Gotchas and Tips

  • No Laravel package, no auto-discovery. If you're used to dropping in a package and getting a facade, you will be confused for five minutes. There's no config/ares.php to publish. Bind it yourself.
  • DIČ is not always present. getVatId() returns null for non-registered VAT payers (many sole traders). Don't call ->getVatId() in a string concatenation without a null check, and don't use VAT lookup as your primary identity — IČO is.
  • Address fields can be null. The address DTO is flat and untyped-by-contract; a foreign-registered branch may have a country but no street. Guard each getter, or cast the whole thing to a string with a fallback.
  • Sole traders (fyzická osoba) are hit-or-miss. Some individuals with an IČO do not have an ARES record worth using (no trade name, no getLegalForm). If your product needs to support them, provide a manual-entry fallback rather than blocking registration on a lookup failure.
  • Version churn in the constructor. v3 moved to PSR-18 HTTP clients. If you see "too few arguments to Ares::__construct", you installed v3 and need to pass a client — (new AresFactory())->create() is the quick fix, or bind a Guzzle/php-http adapter. Pin the version in composer.json and read the CHANGELOG before upgrading.
  • Exceptions are not Laravel-shaped. Network failures come out as raw Guzzle / Http\Client\Exception (or AresException for API-level errors). Wrap the call in a try/catch inside your service and convert to your own domain exception or null. Otherwise a transient ARES outage turns into a 500 on your signup form.
  • Czech-only data. Names, legal forms, and street names come back in Czech. If you need localized display, that's on your side. Also expect historical names to differ from the current trade name — ARES reflects register state, not marketing.
  • Data lag for new companies. A company registered today may not be queryable in ARES for days. Your signup flow should not treat "not found" as "invalid IČO."
  • Extension point: swap the HTTP client. Since the package is a thin wrapper around an HTTP call, the easiest way to add tracing, retries, or metrics is to hand it a client configured the way you want (Guzzle with RetryMiddleware, a logged psr18 client, etc.) rather than patching the library.
  • 51 stars, 0 known dependents. That's not disqualifying for a small, single-purpose lib — but it means you should pin your version, vendor your own integration tests, and expect to read the source rather than find a StackOverflow answer when the DTO shape surprises you.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console