PHPackages                             fogswimmer/data-migration - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. fogswimmer/data-migration

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

fogswimmer/data-migration
=========================

Declarative data migration between legacy databases and Symfony entities.

1.2.3(4mo ago)01MITPHPPHP ^8.2

Since Dec 19Pushed 4mo agoCompare

[ Source](https://github.com/Fogswimmer/data-migration-bundle)[ Packagist](https://packagist.org/packages/fogswimmer/data-migration)[ RSS](/packages/fogswimmer-data-migration/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (15)Versions (8)Used By (0)

Data Migration Bundle for Symfony
=================================

[](#data-migration-bundle-for-symfony)

A declarative, config-driven data migration tool for Symfony applications.
Designed to migrate data from legacy sources (databases, JSON, CSV\*) into modern Doctrine entities with transformations, post-processing and ID mapping.

---

Overview
--------

[](#overview)

This bundle provides a structured way to migrate data from an old system into a new Symfony project:

- maps legacy rows to Doctrine entities
- applies transformation pipelines to field values
- supports custom post-processors for complex logic
- keeps track of old → new ID mappings
- works with different data sources (database, JSON, CSV\*)

The entire migration process is described declaratively in a single YAML configuration file.

\*Under development in the current version

---

Intallation
-----------

[](#intallation)

```
  composer require --dev fogswimmer/data-migration
```

Commands
--------

[](#commands)

1. Initialize:

```
  bin/console data-migration:init
```

2. Launch data migration:

```
  bin/console data-migration:migrate
```

How It Works
------------

[](#how-it-works)

For each configured entity, the migration process follows these steps:

1. **Fetches data** from the configured data source (database, JSON, CSV).
2. **Creates a new entity instance** for each source row.
3. **Maps fields** from the source to entity properties.
4. **Applies transformation chains** (e.g. `strip_tags`, `truncate`, custom transformers).
5. **Persists the entity** and stores the old → new ID mapping.
6. **Executes post-processors**, allowing to:
    - create related entities
    - attach media
    - restore relations
    - perform any custom logic

Configuration lives in `config/packages/data_migration.yaml`.

---

Data Sources
------------

[](#data-sources)

Currently supported data sources:

- **Database** (via Doctrine DBAL connection)
- **JSON files**

The data source is defined globally and reused across tables.

Example:

```
data_source:
  type: database
  connection: old
```

or

```
data_source:
  type: json
```

Database Connection (Legacy DB)
-------------------------------

[](#database-connection-legacy-db)

This bundle does not manage connections itself — you are responsible for configuring access to the legacy database.

### Option 1: SSH Tunnel (Port Forwarding)

[](#option-1-ssh-tunnel-port-forwarding)

If the legacy database is accessible only via SSH:

```
ssh -L 0.0.0.0:3307:127.0.0.1:3306 user@remote-host
```

Then configure the connection using host.docker.internal so Docker containers can access the host:

```
OLD_DATABASE_URL=mysql://db_user:db_password@host.docker.internal:3307/db_name
```

> Important: host.docker.internal allows Docker containers to reach services running on the host machine.

### Option 2: Temporary Database Container

[](#option-2-temporary-database-container)

You may also spin up a temporary container with the legacy database:

```
old-db:
  image: mariadb:10.11
  ports:
    - "3312:3306"
  environment:
    MYSQL_DATABASE: ${OLD_DB_NAME}
    MYSQL_USER: ${OLD_DB_USER}
    MYSQL_PASSWORD: ${OLD_DB_PASSWORD}
    MARIADB_ROOT_PASSWORD: root
```

Then connect normally:

```
OLD_DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3312/db_name
```

Migration Configuration Example
-------------------------------

[](#migration-configuration-example)

```
data_migration:
  data_source:
    type: database
    connection: old

  tables:
    App\Entity\Doctor:
      source: doctor

      map:
        fullName:
          - surname
          - name
          - patronymic
        description: desc

      transform:
        description:
          - strip_tags
          - truncate: 255

      post_process:
        - doctor_media
        - education_media
```

Field Mapping
-------------

[](#field-mapping)

- A single column:

```
description: desc
```

- Multiple columns (concatenated with space):

```
fullName:
  - surname
  - name
  - patronymic
```

Transformers
------------

[](#transformers)

Transformers modify field values during migration.

### Transformer Interface

[](#transformer-interface)

```
interface DataMigrationTransformerInterface
{
    public function getName(): string;

    public function transform(mixed $value, mixed $params = null): mixed;
}
```

### Example Transformer

[](#example-transformer)

```
final class TruncateTransformer implements DataMigrationTransformerInterface
{
    public function getName(): string
    {
        return 'truncate';
    }

    public function transform(mixed $value, mixed $params = null): mixed
    {
        return mb_substr((string) $value, 0, (int) $params);
    }
}
```

**Usage in YAML**

```
transform:
  description:
    - strip_tags
    - truncate: 255
```

Transformers are automatically discovered via Symfony autowiring.

Post Processors
---------------

[](#post-processors)

Post-processors are executed after an entity is persisted. They are intended for complex logic such as:

- creating related entities
- restoring relations
- attaching media
- working with legacy auxiliary tables

### Post Processor Interface

[](#post-processor-interface)

```
interface DataMigrationPostProcessorInterface
{
    public function getName(): string;

    public function process(
        array $oldRow,
        object $entity,
        DataSourceInterface $dataSource,
        mixed $params = null
    ): void;
}
```

### Example Post Processor

[](#example-post-processor)

1. Simple Data Source (e.h. json)

```
final class DoctorMediaProcessor implements DataMigrationPostProcessorInterface
{
    public function getName(): string
    {
        return 'doctor_media';
    }

    public function process(
        array $oldRow,
        object $entity,
        DataSourceInterface $dataSource
    ): void {
        // custom logic here
    }
}
```

2.When usign database as source, please use RequiresAdvancedQuerySourceInterface to be able to use such methods as **fetchColumn**, **fetchOne**, **fetchAllByQuery** from **AdvancedQueryDataSourceInterface**

```
final class DoctorMediaPostProcessor
    implements DataMigrationPostProcessorInterface, RequiresAdvancedQuerySourceInterface
{
    public function getName(): string
    {
        return 'doctor_media';
    }

    public function process(
        array $oldRow,
        object $entity,
        DataSourceInterface $source,
        ?array $params = null,
    ): void {

    }
}

interface AdvancedQueryDataSourceInterface extends DataSourceInterface
{
    public function fetchColumn(
        string $resource,
        string $column,
        array $criteria = [],
    ): array;

    public function fetchOne(
        string $resource,
        string $column,
        array $criteria = [],
    ): mixed;

    public function fetchAllByQuery(
        string $sql,
        array $params = [],
    ): iterable;
}
```

**Usage in YAML**

```
post_process:
  - doctor_media
```

ID Mapping
----------

[](#id-mapping)

The migration engine automatically stores old → new ID mappings.

This allows post-processors to:

- resolve relations between migrated entities
- restore foreign keys correctly

Extending the Bundle
--------------------

[](#extending-the-bundle)

You can freely extend the migration by adding:

- custom transformers
- custom post-processors
- custom data sources

All custom logic stays inside your project, the bundle only provides the infrastructure.

Notes
-----

[](#notes)

- The bundle intentionally does not manage Doctrine ORM configuration.
- Database connectivity must be handled by the host project.
- Docker users must explicitly expose host services if required.

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance74

Regular maintenance activity

Popularity1

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

7

Last Release

148d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/babbf693180f04b8febd8bf9b16179152839f8794b348baac3564164a71395f5?d=identicon)[Fogswimmer](/maintainers/Fogswimmer)

---

Tags

phpsymfonydata migration

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/fogswimmer-data-migration/health.svg)

```
[![Health](https://phpackages.com/badges/fogswimmer-data-migration/health.svg)](https://phpackages.com/packages/fogswimmer-data-migration)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

7310.3k29](/packages/open-dxp-opendxp)[netgen/layouts-core

Netgen Layouts enables you to build and manage complex web pages in a simpler way and with less coding. This is the core of Netgen Layouts, its heart and soul.

3689.4k10](/packages/netgen-layouts-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
