Logo of php-etl
Getting Started
🐘 Standalone šŸŽµ Symfony 🦢 Sylius
Core Concepts
The Concept Execution Context Item Types Custom Operations Glossary FAQ
ā›“ļø Operations
Building Blocks
Split Merge Repeat Safe
Extract
File Finder CSV JSON
Transform
External File Processor Filter Data Rule Transformer Split Item HTTP Client Log Callback
Aggregation
Simple Grouping
Load
CSV JSON
šŸ§‘ā€šŸ³ Cookbook
Without Context
Grouping / Aggregation Filtering Splitting/Forking Making your chains configurable Complex data to csv / Flatten Data Api to CSV N°1 Api to CSV N°2 Sub chains
With Context
Api to CSV Import external file
Custom Operations

PHP-ETL - Cook Books
Complex data to csv / Flatten Data

Complex json files/api responses can be flattened and have multiple columns using the rule engine. In our example we have a list of products with their name, their skus etc. The name of the product is different for each locale.

We could manually create a list of columns for each locale using the rule engine, but this will not be very generic, and if we have a lot of locales & a lot of translatable fields on our products this will be complicated to maintain.

Example products file

[
  {
    "productId": 1,
    "sku": "sku1",
    "name": {
      "fr_FR": "Mon Produit 1",
      "en_US": "My Product 1"
    }
  },
  {
    "productId": 2,
    "sku": "sku2",
    "name": {
      "fr_FR": "Mon Produit 2",
      "en_US": "My Product 2"
    }
  },
  {
    "productId": 3,
    "sku": "sku3",
    "name": {
      "fr_FR": "Mon Produit 3",
      "en_US": "My Product 3"
    }
  }
]

We can use dynamic columns for this purpose. To use this we will need to list locales when starting the process:

$chainProcessor->process(
    new ArrayIterator([__DIR__ . "/products.json"]),
    [
        'locales' => ['fr_FR', 'en_US']
    ]
);

Then we will use the following rule to read the name for each of the given locales:

As you can see the {@context/locales} part of the columns name is dynamic. We can use then the get rule to read the data from that product. We could also have used symfony expression language but both behaves differently if the given locale is missing. get will simply return an empty column, symfony expression language rule will fail.

        'name-{@context/locales}':
          rules:
            - get : {field: ['name', '@context/locales']}

Complete Code

chain:
  read-file:
    operation: json-read
    options: []

  flatten:
    operation: rule-engine-transformer
    options:
      add: false # We want to replace all existing columns with our new columns.
      columns:
        productId:
          rules:
            - get: {field: 'productId'}
        sku:
          rules:
            - get: {field: 'sku'}
        'name-{@context/locales}':
          rules:
            - get : {field: ['name', '@context/locales']}

  write-new-file:
    operation: csv-write
    options:
      file: "output.csv"

Network

GitHub Repo Issues Good First Issues

Help Preserve This Project

Support for the continued development of php ETL. I maintain this project in my free time.

Support
Free & Open Source (MIT)