answear/econt-pickup-point-bundle
Econt pickup point integration for Symfony: fetch offices and cities from the Econt nomenclatures API via simple command classes. Install with Composer, add credentials in config, and query offices or cities in a few lines of PHP.
Architecture fit. The first thing to flag: despite the framing, this is a Symfony bundle, not a Laravel package. It ships an AnswearEcontBundle registered via Symfony Flex, depends on symfony/http-kernel and symfony/serializer, and exposes its API through DI-injected command objects (GetOffices, GetCities). The functional surface is deliberately narrow — it is a thin, read-only client over Econt's Nomenclatures REST API (offices and cities), with DTO hydration via Symfony Serializer and HTTP via Guzzle. There is no shipping, label, tracking, or pricing logic. That narrowness is a strength for evaluation: the blast radius is small and the package is easy to reason about, fork, or replace.
Integration feasibility. Straightforward for a Symfony 7 / PHP 8.4 estate: composer require, Flex registers the bundle, two config keys (user, password) feed ConfigProvider, done. For Laravel it is not a drop-in: bundles do not auto-register, and symfony/http-kernel is dead weight in a Laravel app. The realistic path is to consume the underlying classes as a plain library (skip bundle registration, bind ConfigProvider and the command classes in a small service provider) — feasible, but it requires reading source because the README documents only the Symfony-Flex path and never shows constructor signatures.
Technical risk.
user/password) to Econt. Anyone who integrated before this patch has been transmitting carrier credentials in the clear. This is the single most important finding in the new release: it is a security fix shipped as an unremarkable patch note, with no CVE, no security advisory, and no version constraint guidance. Treat 4.2.1 as a minimum version floor, not an optional bump, and audit any pre-existing deployments.php: ^8.4 and symfony/*: ^7.0.3 are hard constraints. Many production Laravel/Symfony estates still sit on 8.2/8.3 and Symfony 6, so this may be a non-starter before anything else is evaluated.openingHours in 1.2.1, a parameter rename in 3.0.0).Key questions to resolve before committing.
Stack fit. For a Symfony target: install as designed, accept the Flex wiring, and treat it as a reference-data adapter. For a Laravel target: do not install-and-hope. Either (a) require the package but bypass the bundle — bind ConfigProvider, GetOffices, and GetCities in a service provider and inject them — or (b) fork into an app-local namespace if we need to patch DTOs. Given the surface is two endpoints, a hand-rolled ~200-line Guzzle client is a legitimate third option and may be cheaper to own than a dependency with zero dependents — and it lets you bake in HTTPS-by-default, timeouts, and retry from day one rather than inheriting them release by release.
Migration path. This is greenfield — there is no incumbent integration to displace. The correct shape is not live API calls from checkout. Fetch cities and offices on a schedule, persist locally, and serve the picker from our own tables. That converts a third-party availability dependency into a batch job. If any prototype or spike already exists against <4.2.1, treat its stored config as compromised: rotate the Econt credentials and repoint to 4.2.1 before further testing.
Compatibility. Concrete checks before anything else: PHP version pin (must be 8.4), symfony/serializer major (7.x only — collides with any app pinned to 6.x), guzzlehttp/guzzle ^7.8.2, and the ext-json requirement. In Laravel, symfony/http-kernel will be installed but unused; confirm it does not conflict with framework constraints. Constrain the requirement to ^4.2.1 explicitly — do not allow ^4.0, which would let a fresh install resolve to a plaintext-HTTP version in any lockfile rebuild.
Sequencing.
^4.2.1 immediately and grep committed lockfiles and CI images for any resolved 4.x < 4.2.1.https:// back to http://.getCities() and getOffices() from a console command; dump raw payloads and compare against the DTOs to surface mapping gaps early. Assert in the spike that the request URI scheme is https.econt_cities, econt_offices tables with an upstream-id key and a synced_at column.Maintenance. Code churn is low between releases, but every release has tended to be a major with compatibility drops. Budget an upgrade task per major rather than assuming patch-level safety. Vendor-backed (Answear) with a small contributor pool — reasonable activity, thin bus factor, now with a new external contributor. MIT means we can pin a fork if needed; decide the fork trigger in advance (e.g. upstream inactive >6 months or a blocking BC break).
Support. No community to lean on: no Stack Overflow corpus, no third-party tutorials, minimal README. Support is GitHub issues plus source reading. There is no vendor SLA for the package itself, only whatever Econt offers for the API. The 4.2.1 release is a case study in why this matters: a security-relevant fix with no advisory means you cannot rely on being told — subscribe to GitHub releases, or pin and diff on a schedule.
Scaling. Effectively a non-issue if architected as recommended. Nomenclature data is small, slow-changing, and read-mostly. A daily sync plus indexed local tables handles any realistic order volume. The only scaling mistake would be per-request calls to Econt from checkout — that introduces Econt's latency and availability into our conversion funnel for no benefit, and (pre-4.2.1) into our credential-exposure surface as well.
Failure modes.
user/password) passed to ConfigProvider; ensure these go through a secret manager, not committed config, and define a rotation runbook.Ramp-up. Roughly half a day for a PHP developer comfortable with Symfony DI and Guzzle. For a Laravel-only developer, budget a full day: the bundle-registration model is unfamiliar, the README does not show how to instantiate the command classes outside a container, and they will need to read the source to discover constructor dependencies. Add a short orientation note on the version floor and its reason — a new joiner seeing ^4.2.1 pinned should understand it is a security constraint, not arbitrary strictness, so nobody "helpfully" relaxes it. The documentation gap, not the technical complexity, is the dominant onboarding cost — worth capturing in an internal README we own on day one.
How can I help you explore Laravel packages today?