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

Connector Mapping Bundle Laravel Package

akeneo/connector-mapping-bundle

Akeneo Connector Mapping Bundle provides configurable mapping infrastructure for Akeneo import/export connectors, letting developers define how source fields map to target fields and reuse mapping logic across jobs.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: akeneo/connector-mapping-bundle is a Symfony bundle from the Akeneo PIM ecosystem, not a Laravel package. There is no service provider, no facade, no config file to publish, no Artisan command. Any day-to-day leverage you get from it comes from calling its plain PHP classes directly, or — more realistically — from treating it as a reference implementation of column-to-attribute mapping while you write your own transform code.

So the first decision is a fork in the road:

Your situation What to do
You run Akeneo PIM and are extending/debugging a connector Work inside Akeneo's Symfony app; use the bundle natively via its DI wiring.
You have a Laravel app and want "map vendor CSV columns to our attribute model" Do not install this. Read its converters as a spec, then write ~100 lines of your own mapping layer.
You are pulling Akeneo data into Laravel over HTTP Use Akeneo's REST API + a thin Laravel client. This bundle does not help you here.

If you have decided to install it anyway (e.g. you genuinely need Akeneo's exact value-conversion semantics in a Laravel ETL job):

composer require akeneo/connector-mapping-bundle

Expect the install itself to be the first real test. Akeneo components pin symfony/* and PHP versions tightly; a Laravel app already carrying symfony/console, symfony/process, and symfony/http-foundation through its own dependency tree is a likely conflict. Verify with composer why-not akeneo/connector-mapping-bundle before you invest time.

Where to look first, in order:

  1. src/ArrayConverter/ — the ArrayConverterInterface and its concrete implementations. The contract is effectively convert(array $item, array $options = []): array. This is the only surface you should call.
  2. The *ConverterRegistry class (if present in your version) — how converters are looked up by name/type. This tells you whether you can resolve one by string key or must construct it.
  3. Resources/config/ — the service definitions. This is your copy-paste source. Laravel will not auto-discover these; you will manually re-declare the subset you need in a ServiceProvider, including constructor arguments.
  4. composer.json — PHP constraint, Symfony constraint, and whether it drags in akeneo/pim-community-dev or Oro packages. If it pulls Oro, stop: you are about to install a platform, not a library.

Your first use case should be embarrassingly small: take one representative raw row (a supplier CSV line with locale/channel-suffixed columns) and pass it through one converter, dumping input and output. If you cannot get a single row through in an afternoon, the dependency is wrong for your project and the correct move is to reimplement the 60–100 lines of logic you actually need. That is a genuinely common outcome here and not a failure.

// tinker / a throwaway route / a test — anywhere you can dump
$converter = app(\App\Support\Mapping\ProductRowMapper::class);
dump($rawRow);            // e.g. ['sku' => 'ABC', 'price-ecommerce-en_US' => '19.99', ...]
dump($converter->map($rawRow));

Implementation Patterns

Wrap it immediately, expose nothing. The single most important pattern: no controller, job, or Blade-adjacent code should ever reference an Akeneo class. Put one thin class in app/Support/Mapping/ behind an interface you own, and let the bundle's converter be a private implementation detail. When the package rots (it will), you replace one constructor.

namespace App\Support\Mapping;

interface RowMapper
{
    public function map(array $rawRow): array;
}

final class ConverterRowMapper implements RowMapper
{
    public function __construct(
        private \Akeneo\Tool\Component\Connector\ArrayConverter\ArrayConverterInterface $converter
    ) {}

    public function map(array $rawRow): array
    {
        return $this->converter->convert($rawRow, [
            'with_associations' => false,
            'case_insensitive_keys' => true,
        ]);
    }
}

Bind converters manually in a service provider. Laravel will not read Resources/config/*.yml. Translate the definitions you need by hand, and keep them in a dedicated provider (MappingServiceProvider) so the foreign wiring is isolated and greppable.

// app/Providers/MappingServiceProvider.php
public function register(): void
{
    // Only bind what you actually use. Copy constructor args from Resources/config/.
    $this->app->bind(ArrayConverterInterface::class, function ($app) {
        return new \Akeneo\Component\Connector\ArrayConverter\StandardConverter(
            $app->make(SomeFieldMapper::class),   // ← verify against the real signature
        );
    });

    $this->app->bind(RowMapper::class, ConverterRowMapper::class);
}

If the constructor signature is long or unstable, bind a pre-built singleton instead and treat it as immutable.

Compose a pipeline instead of hunting for one fat converter. Akeneo's idiom is small, single-purpose converters chained together. Mirror that in your code, where it is testable and visible:

final class ImportPipeline
{
    /** @param RowMapper[] $steps */
    public function __construct(private array $steps) {}

    public function __invoke(array $row): array
    {
        foreach ($this->steps as $step) {
            $row = $step->map($row);
        }
        return $row;
    }
}

Typical order for a supplier-feed transform: normalise keys → split locale/channel-suffixed columns into proper scope structure → coerce units/booleans → validate required attributes → emit canonical array. The bundle helps most in the middle of that chain (scope splitting, value conversion), least at the ends.

Run it in queued jobs, on chunks, never in a request cycle. Converters are stateless and CPU-bound on array walks; a 50k-row supplier file will time out a web request. Chunk at the job level, resolve the mapper from the container per job, and hand output to a persistence step.

final class ImportProductChunk implements ShouldQueue
{
    public function __construct(private array $rows) {}

    public function handle(RowMapper $mapper, ProductWriter $writer): void
    {
        foreach ($this->rows as $row) {
            $writer->upsert($mapper->map($row));   // or collect + bulk upsert
        }
    }
}

Test as a black box against fixtures. Golden-file testing is the right shape here: a fixture row in, an expected canonical array out, asserted with assertSame. Never assert on converter internals — you did not write them and they change on Akeneo's schedule. Include nasty fixtures up front: empty strings, 0 vs null, metric values with units, multi-select columns with , delimiters, and rows with a locale/channel column that is missing entirely.

If you are customising inside Akeneo (the one context where this package is genuinely first-class), the extension point is implementing ArrayConverterInterface and registering it in the bundle's DI config or converter registry — then referencing it from a job profile. Do not subclass an existing Akeneo converter.

Gotchas and Tips

  • There is no Laravel integration, and there won't be. Missing Kernel, unresolved compiler passes, @service references that mean nothing in Laravel, Oro/Doctrine entity metadata assumed present. Budget a day for "make it instantiate" and be prepared to abandon it. The pragmatic fallback — copying the two or three converters whose behaviour you need into app/Support/Mapping/ — is often the correct engineering call, not a cop-out.

  • Fail at composer require, not in production. Akeneo pins PHP minors and Symfony ranges aggressively. Run the install on a branch, read every conflict message, and check whether the package drags akeneo/pim-community-dev or Oro transitively. If it does, the dependency is a platform and you should not proceed.

  • Silent wrongness is the real risk, not exceptions. Mapping bugs do not throw — they write wrong attribute values at scale. The three classics to test explicitly:

    • Scope collapse: price-ecommerce-en_US and price-mobile-en_US both landing in one field, last-write-wins.
    • Unit mistakes: metric attributes (12.5 KG vs 12500 G) converted or not converted depending on a flag you did not pass.
    • Silent drops: unmapped source columns disappear with no warning. Add an explicit assertion on your side that every source column is either mapped or on an allowlist of ignored columns.
  • $options is loosely typed and fails silently. Converters read it with isset() and fall back to defaults — a missing or misspelled key produces wrong-shaped output, not an error. Pass options explicitly, define them in one constants class, and never rely on defaults you have not verified in source.

  • No logging hooks, so debug by dumping between steps. dump($item) after each pipeline stage is genuinely the fastest path to the problem. Do not step-debug into vendored Akeneo code; you will burn an hour in a call stack that belongs to a different framework.

  • Pin the exact version. Zero stars, zero dependents, zero score. Upstream will not fix bugs or patch for new Symfony/PHP releases. Use "akeneo/connector-mapping-bundle": "x.y.z" with no caret, commit the lock file, and treat any upgrade as a scheduled task with regression tests rather than a routine composer update.

  • Check whether you even need it. Later Akeneo majors absorbed connector-mapping functionality into core; on a legacy 2.x-era PIM the bundle may be redundant or actively conflicting with the native mapping step. Also confirm CE vs EE: some mapping surface was Enterprise-only in this era, so a CE instance may not expose what you are reading about.

  • Never fork it to add features. Forking a platform-internal bundle turns every Akeneo upgrade into a rebase exercise. The escalation ladder is: configuration → pre-processing outside the PIM (a Laravel job that normalises the file before it ever reaches Akeneo) → a custom converter registered via the interface → fork, costed as a recurring maintenance line.

  • Extension point is the interface, not inheritance. Implement ArrayConverterInterface yourself for custom behaviour. Subclassing Akeneo's converters couples you to internals with no semver stability and no upstream triage.

  • When the mapping requirement outgrows this — reusable templates, per-supplier saved mappings, richer transformation rules — that is a product/roadmap item, not a code patch. The realistic answers are configuration on top of the bundle, a normalisation step in your own Laravel pipeline, or a managed ETL (Airbyte/dbt) for the general case. This package is only the right tool when the target is Akeneo and the flow is a bulk connector profile.

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.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table