Feature Implementation Plan: top-level-countries-endpoint¶
📋 Todo Checklist¶
- [ ] Create a new
CountryControllerfor the top-level endpoint. - [ ] Create a new
CountryCsvReaderServicefor reading country data from CSV. - [ ] Add OpenAPI documentation for the new endpoint.
- [ ] Implement caching for the country data.
- [ ] Write integration tests for the new endpoint.
- [ ] Final Review and Testing.
🔍 Analysis & Investigation¶
Codebase Structure¶
The project is a Symfony application. The feature requires a new controller in src/Controller/Api/ and a new service in src/Service/. The data source is the CSV file located at resources/countries-en.csv.
Current Architecture¶
The application follows a standard Symfony architecture. By creating a new CountryController, we are introducing a new top-level resource, /api/countries, which is distinct from the existing /api/locations resource. This aligns with REST principles by separating the resource of "all countries in the world" from the more specific resource of "coffee-producing locations." This approach promotes a clean separation of concerns.
Dependencies & Integration Points¶
- Symfony Framework: The core of the application. We will use the
AbstractController'sjson()method. - NelmioApiDocBundle: For documenting the new API endpoint using OpenAPI annotations.
- CSV File: The
resources/countries-en.csvfile is the data source.
Considerations & Challenges¶
- Performance: Reading and parsing the CSV file on every request is inefficient. A caching mechanism is essential.
- Error Handling: The implementation must gracefully handle cases where the CSV file is missing or unreadable.
- Data Structure: The frontend needs a simple list of countries for a dropdown or selector. The response should be filtered to include only the necessary fields (
country_iso_codeandcountry_name) to minimize payload size. - Code Reusability: The logic for reading and parsing the CSV should be encapsulated in a dedicated service (
CountryCsvReaderService) to promote reusability and a clean separation of concerns.
📝 Implementation Plan¶
Prerequisites¶
- Ensure the
resources/countries-en.csvfile is present and readable.
Step-by-Step Implementation¶
-
Create
CountryCsvReaderService:- Files to modify:
src/Service/CountryCsvReaderService.php(new file) - Changes needed:
- Create a new service class
CountryCsvReaderService. - Inject Symfony's
ParameterBagInterfaceto get the project directory path. - Implement a public method
getCountries()that reads, parses, and caches the country data fromresources/countries-en.csv. - The method should return an array of countries, where each country is an associative array containing only
country_iso_codeandcountry_name. - Implement simple in-memory caching (e.g., using a static property) to avoid file I/O on subsequent requests within the same process.
- Create a new service class
- Files to modify:
-
Register the Service:
- Files to modify:
config/services.php - Changes needed:
- Ensure the new
CountryCsvReaderServiceis registered for autowiring. Symfony's default service configuration should handle this automatically.
- Ensure the new
- Files to modify:
-
Create
CountryController:- Files to modify:
src/Controller/Api/CountryController.php(new file) - Changes needed:
- Create a new controller class
CountryControllerthat extendsAbstractController. - Define a top-level route for the controller:
#[Route('/api/countries', name: 'api_countries_')]. - Inject the new
CountryCsvReaderServiceinto the controller's constructor. - Create a new public method
getAllCountries(). - Add the
#[Route('', name: 'list', methods: ['GET'])]attribute to the method. - Implement the method to call
getCountries()from theCountryCsvReaderServiceand return the data as aJsonResponse. - Include a try-catch block for robust error handling.
- Create a new controller class
- Files to modify:
-
Add OpenAPI Documentation:
- Files to modify:
src/Controller/Api/CountryController.php - Changes needed:
- Add
#[OA\Get]and#[OA\Response]annotations to thegetAllCountries()method. - The documentation should define the path as
/api/countries, provide a clear summary and description, and assign it to a "Locations" or a new "Countries" tag. - The response schema should reflect the filtered array of countries (
country_iso_code,country_name).
- Add
- Files to modify:
Testing Strategy¶
- Integration Test:
- Create a new test file
tests/Controller/Api/CountryControllerTest.php. - Write a test case for the
/api/countriesendpoint. - The test should:
- Make a GET request to the endpoint.
- Assert that the response has a 200 OK status code.
- Assert that the response content is valid JSON.
- Assert that the returned JSON contains an array of countries with the expected keys (
country_iso_code,country_name). - Assert that a known country (e.g., "United States") is present in the response.
- Create a new test file
- Manual Testing:
- Run the application locally.
- Access the endpoint
http://localhost/api/countriesusing a browser or API client. - Verify that the response is correct and matches the documentation.
🎯 Success Criteria¶
- A GET request to
/api/countriesreturns a JSON array of all countries from the CSV file. - The response is cached to ensure good performance.
- The endpoint is clearly documented in the OpenAPI specification.
- The implementation includes passing integration tests.