A containerized PHP CLI application for importing CSV data into MongoDB. Built with Symfony Console, Doctrine ODM, and designed to run across all platforms using Docker.
- Docker & Docker Compose
- Make (for using Makefile commands)
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ CSV Files │ │ PHP CLI App │ │ MongoDB │
│ (data/*.csv) │───▶│ (Symfony) │───▶│ (Database) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
The application processes CSV files containing product data and imports them into MongoDB using batched operations for optimal performance.
# Setup the project from scratch
make setup
# Import sample CSV data
make import
# Run all tests
make test
# Inspect database data
make mongosh
# Run static analysis
make analyze
The application uses a Symfony Console Command architecture:
- Entry Point:
bin/csv-importer
- The main CLI executable - Command:
ImportCsvCommand
- Registered asimport:csv
command - Handler: Uses SOLID principles with dependency injection
- Architecture: Domain/Application/Infrastructure layers with proper separation of concerns
The ImportCsvCommand
provides a clean interface for processing CSV files with configurable batch sizes and error handling.
The application expects CSV files with the following structure:
gtin,language,title,picture,description,price,stock
7034621736823,it,Product 1,http://example.com/image1.jpg,Description text,738.7,99
2306833701228,es,Product 2,http://example.com/image2.jpg,Description text,127.81,87
Required Fields:
gtin
: Product identifier (string)language
: Language code (en, es, it, fr, de)title
: Product title (string)picture
: Image URL (string)description
: Product description (string)price
: Product price (decimal, supports different formats)stock
: Stock quantity (integer)
Command | Description |
---|---|
make setup |
Complete project setup from scratch |
make start |
Start application containers |
make stop |
Stop application containers |
make restart |
Restart application containers |
make import |
Import sample CSV data |
make test |
Run all tests (unit + integration) |
make test-unit |
Run unit tests only |
make test-integration |
Run integration tests only |
make shell |
Open shell in app container |
make mongosh |
Open MongoDB shell with quick hints |
make logs |
Show application logs |
make logs-mongo |
Show database logs |
make analyze |
Run PHPStan static analysis |
make fix |
Fix code style with PHP-CS-Fixer |
make fix-dry |
Check code style without fixing |
make clean |
Clean up containers and volumes |
The project includes comprehensive quality assurance:
- PHPStan: Level 5 static analysis for type safety
- PHP-CS-Fixer: Automatic code style formatting
- PHPUnit: Unit and integration tests
# Run static analysis
make analyze
# Fix code style
make fix
# Run comprehensive test suite
make test
The application uses multi-stage Docker builds with BuildKit caching for fast setup:
services:
app: PHP 8.1 with MongoDB extension
mongodb: MongoDB 7.0 with automatic initialization
Volumes are configured for persistent data storage and development convenience.
# Basic import
docker-compose exec app php bin/csv-importer import:csv data/products.csv products
# With custom batch size
docker-compose exec app php bin/csv-importer import:csv data/products.csv products --batch-size=500
# With custom delimiter
docker-compose exec app php bin/csv-importer import:csv data/custom.csv products --delimiter=";"
# Help and options
docker-compose exec app php bin/csv-importer import:csv --help
Default configuration values:
Setting | Default Value | Description |
---|---|---|
MongoDB Host | mongodb |
Container hostname |
MongoDB Port | 27017 |
Standard MongoDB port |
Database Name | csv_data |
Target database |
Collection | products |
Target collection |
Batch Size | 1000 |
Records per batch |
CSV Delimiter | , |
Field separator |
Configuration is handled through Symfony's dependency injection container and can be customized in config/services.yaml
.
Quick Database Inspection:
make mongosh
# Then run: db.products.countDocuments()
# Or: db.products.find().limit(10).pretty()