Feature Implementation Plan: Save Product Images¶
📋 Todo Checklist¶
- [ ] Install
league/flysystem-bundleand a storage adapter (e.g.,league/flysystem-aws-s3-v3). - [ ] Configure the Flysystem bundle for configurable storage (local and S3).
- [ ] Create a new
Imageentity and repository. - [ ] Update the
CoffeeBeanentity to have a one-to-many relationship with theImageentity. - [ ] Create a new
ImageControllerto handle image uploads and adding images by URL. - [ ] Implement a background job (Symfony Messenger) for processing images added by URL.
- [ ] Update
CoffeeBeanCrudControllerto manage the new image relationship. - [ ] Update the API serialization to include the array of images.
- [ ] Write unit and integration tests for the new functionality.
- [ ] Final Review and Testing
🔍 Analysis & Investigation¶
Codebase Structure¶
- Entities: A new
Imageentity is required. TheCoffeeBeanentity will be modified to replace theimageUrlfield with a collection ofImageentities. - Admin: The admin panel is built with
easycorp/easyadmin-bundle. The configuration is insrc/Controller/Admin/DashboardController.php, and there is a correspondingCoffeeBeanCrudController.phpthat will need to be updated. - Dependencies: The project is missing a filesystem abstraction layer.
league/flysystem-bundlewill be added to handle this.
Current Architecture¶
The application uses a standard Symfony architecture. The plan is to introduce a new Image entity and manage it through a dedicated controller and an updated admin interface. For adding images via URL, a message-based approach with Symfony Messenger will be used to avoid blocking API requests and to handle potential download failures gracefully.
Dependencies & Integration Points¶
- league/flysystem-bundle: This will be a new dependency to abstract the filesystem. It will be configured to allow switching between local storage and S3-compatible services via environment variables.
- EasyAdminBundle: The
CoffeeBeanCrudControllerwill be updated to use EasyAdmin'sCollectionFieldand a custom form type to manage the images, providing a user-friendly grid layout in the admin panel. - Symfony Messenger: Will be used to process image downloads from URLs in the background.
Considerations & Challenges¶
- Database Migration: The change from a simple
imageUrlstring to a one-to-many relationship requires a carefully written database migration to preserve existing image URLs. - File Uploads vs. URL Processing: The system needs to handle both direct file uploads and asynchronous URL fetching. The implementation must be robust to handle both cases.
- Configuration: The storage solution needs to be easily configurable for different environments (development, staging, production). This will be handled through Symfony's environment variable system.
- Admin UI: The admin interface for managing images should be intuitive. A grid layout with previews and options to add/remove images is desired.
📝 Implementation Plan¶
Prerequisites¶
- Add
league/flysystem-bundleand the required adapters tocomposer.json.
Step-by-Step Implementation¶
-
Configure Flysystem
- Files to create:
config/packages/flysystem.yaml - Changes needed:
- Configure two storage adapters: one for local storage (
default.storage) and one for S3 (aws.storage). - Use an environment variable (
STORAGE_ADAPTER) to determine which storage to use as the default.
- Configure two storage adapters: one for local storage (
- Files to create:
-
Create the
ImageEntity- Files to create:
src/Entity/Image.php,src/Repository/ImageRepository.php - Changes needed:
- Create an
Imageentity with fields:id(UUID),coffeeBean(ManyToOne),path(string),originalUrl(string, nullable),createdAt. - Generate the corresponding repository.
- Create an
- Files to create:
-
Update
CoffeeBeanEntity and Create Migration- Files to modify:
src/Entity/CoffeeBean.php - Changes needed:
- Remove the
imageUrlproperty. - Add a new
imagesproperty with aOneToManyrelationship to theImageentity. - Add the
#[Groups(['coffee:read'])]annotation to theimagescollection. - Generate a database migration. Manually edit the migration to move the data from the old
imageUrlcolumn to the newimagestable for existing records.
- Remove the
- Files to modify:
-
Implement Image Upload and URL Processing
- Files to create:
src/Controller/Api/ImageController.php,src/Message/ProcessImageUrlMessage.php,src/MessageHandler/ProcessImageUrlMessageHandler.php,src/Form/ImageType.php - Changes needed:
- Create an
ImageControllerwith two endpoints:POST /api/images/upload: Handles direct file uploads, saves the file to the configured storage, and creates anImageentity.POST /api/images/add-by-url: Takes a URL, dispatches aProcessImageUrlMessageto the messenger bus, and returns an initial response.
- Create the
ProcessImageUrlMessageHandlerto consume the message, download the image, save it to storage, and update theImageentity.
- Create an
- Files to create:
-
Update Admin Interface
- Files to modify:
src/Controller/Admin/CoffeeBeanCrudController.php - Changes needed:
- In
CoffeeBeanCrudController, replace theTextFieldforimageUrlwith aCollectionFieldfor theimagescollection. - Use
setEntryType(ImageType::class)for theCollectionFieldto provide a custom form for each image. - The
ImageTypeform will include fields for file upload and to display the image preview. - This will result in the desired grid layout for managing images.
- In
- Files to modify:
Testing Strategy¶
- Unit Tests:
- Write a unit test for the
ProcessImageUrlMessageHandlerto ensure it correctly processes image URLs. - Write unit tests for the
Imageentity and its relationship withCoffeeBean.
- Write a unit test for the
- Integration Tests:
- Write integration tests for the new endpoints in
ImageController. - Update the integration tests for the
/api/coffee-beansendpoint to verify that theimagesarray is present and contains the correct data. - Test the admin interface manually to ensure the image management UI works as expected.
- Write integration tests for the new endpoints in
🎯 Success Criteria¶
- Images can be uploaded and associated with a coffee bean via the admin panel and the API.
- Images can be added by providing a URL, and they are processed in the background.
- The storage location is configurable via an environment variable.
- The
/api/coffee-beansendpoint returns an array of image URLs for each bean. - The admin panel displays a grid of images for each coffee bean, with options to add and remove them.
- All new functionality is covered by tests.