code-rhapsodie/ezdataflow-bundle
## Getting Started
### Minimal Steps to Begin
1. **Installation**:
```bash
composer require code-rhapsodie/ibexa-dataflow-bundle
Ensure CodeRhapsodie\DataflowBundle\CodeRhapsodieDataflowBundle and CodeRhapsodie\EzDataflowBundle\CodeRhapsodieEzDataflowBundle are enabled in config/bundles.php (Dataflow first).
Routing & DB Schema:
Import routing in config/routing/ezdataflow.yaml:
_cr.dataflow:
resource: '@CodeRhapsodieEzDataflowBundle/Resources/config/routing.yaml'
Run migrations as per DataflowBundle docs.
First Use Case:
Define a DataflowType (e.g., ArticleImportDataflowType) tagged with coderhapsodie.dataflow.type:
use CodeRhapsodie\DataflowBundle\DataflowType\AbstractDataflowType;
use CodeRhapsodie\EzDataflowBundle\Writer\ContentWriter;
class ArticleImportDataflowType extends AbstractDataflowType {
public function __construct(ContentWriter $contentWriter) {
$this->contentWriter = $contentWriter;
}
protected function buildDataflow(DataflowBuilder $builder, array $options) {
$builder->addWriter($this->contentWriter);
}
}
Tag it in services.yaml:
App\Dataflow\ArticleImportDataflowType:
tags: ['coderhapsodie.dataflow.type']
Access UI: Navigate to Admin > Ibexa Dataflow in the Ibexa backoffice to create schedules.
Content Import/Update:
Use ContentWriter + ContentStructureFactory to transform data into ContentCreateStructure/ContentUpdateStructure:
$builder->addStep(function ($data) {
return $this->contentStructureFactory->transform(
$data,
'remote-id-' . $data['id'],
'eng-GB',
'article',
123, // Parent location ID
ContentStructureFactoryInterface::MODE_INSERT_OR_UPDATE
);
});
Scheduled Jobs:
+1 day) and first run time in the UI.Data Validation:
Use NotModifiedContentFilter to skip unchanged updates:
$builder->addStep($this->notModifiedContentFilter);
.env.local (e.g., PARENT_ARTICLE_FOLDER=123).ContentStructureFactory to map external fields to Ibexa field types (e.g., ezstring, ezrichtext).setLogger():
$this->contentWriter->setLogger($this->logger);
Custom Field Comparators:
Extend AbstractFieldComparator for unsupported field types (e.g., ezmatrix):
class MatrixFieldComparator extends AbstractFieldComparator {
protected function compareValues(Value $current, Value $new): bool {
return $current->value === $new->value;
}
}
Register it in services.yaml:
App\Comparator\MatrixFieldComparator:
tags: ['coderhapsodie.ezdataflow.field_comparator', { fieldType: 'ezmatrix' }]
Dynamic Options: Pass runtime options via the UI (YAML format):
api_url: https://example.com/data
batch_size: 100
Queue Integration:
Configure the dataflow_runner queue worker (e.g., Symfony Messenger or Supervisor):
# config/packages/messenger.yaml
framework:
messenger:
transports:
dataflow: '%env(MESSENGER_TRANSPORT_DSN)%'
routing:
'CodeRhapsodie\DataflowBundle\Message\RunDataflowMessage': dataflow
Bundle Loading Order:
ClassNotFoundException for ContentWriter.CodeRhapsodieDataflowBundle is loaded before CodeRhapsodieEzDataflowBundle in bundles.php.Remote ID Conflicts:
remote_id values cause updates to fail.article-{id}) and validate in your DataflowType:
if ($this->contentService->loadContentByRemoteId($remoteId)) {
throw new \RuntimeException("Duplicate remote ID: $remoteId");
}
Field Type Mismatches:
InvalidArgumentException when mapping unsupported field types.transform().Queue Stuck Jobs:
pending state.dataflow_runner is running:
php bin/console messenger:consume dataflow -vv
Permission Issues:
Setup / Administrate and Ibexa Dataflow / View policies to the user role.Enable Logging:
Configure Monolog in config/packages/monolog.yaml:
handlers:
dataflow:
type: stream
path: '%kernel.logs_dir%/dataflow.log'
level: debug
Dump Dataflow Schema:
Use the CLI command to inspect your DataflowType:
php bin/console code-rhapsodie:dataflow:dump-schema --siteaccess=admin
Test Locally:
--dry-run to simulate jobs:
php bin/console code-rhapsodie:dataflow:run --siteaccess=admin --dry-run
ContentCreateStructure objects with:
$this->contentStructureFactory->validate($structure);
Custom Writers:
Extend AbstractWriter to support non-content operations (e.g., sending emails):
class EmailWriter extends AbstractWriter {
public function write(array $data) {
// Send email logic
}
}
Register it in your DataflowType:
$builder->addWriter(new EmailWriter());
Pre/Post-Processing: Add steps for data enrichment or validation:
$builder->addStep(function ($data) {
$data['processed_at'] = new \DateTime();
return $data;
});
UI Customization:
Override Twig templates in templates/bundles/CodeRhapsodieEzDataflowBundle/ to modify the admin interface.
Performance:
Reader\BatchReader to limit memory usage:
$builder->addReader(new BatchReader($reader, 50));
ezsearch fields to ContentUpdateStructure for faster lookups:
$structure->setField('search_keyword', $data['keyword']);
Admin User:
admin user. Override in config/packages/code_rhapsodie_ez_dataflow.yaml:
code_rhapsodie_ez_dataflow:
admin_login_or_id: webmaster
Siteaccess Awareness:
--siteaccess (not --connection) for CLI commands:
php bin/console code-rhapsodie:dataflow:run --siteaccess=admin
YAML Options:
options:
filters:
- { field: status, value: published }
- { field: date, operator: '>', value: '2023-01-01' }
Environment-Specific Configs:
Use parameters.yaml for environment-specific settings (e.g., API keys):
parameters:
dataflow:
api_key: '%env(APP_API_KEY)%'
Reusable DataflowTypes:
Share DataflowType classes across projects via Composer packages.
How can I help you explore Laravel packages today?