A small PHP application built for the Sweetwater web programmer test. It works with a table of order comments and does two things:
- Comments report (
public/index.php) - a web page that lists every comment, grouped under its best-match topic (candy, call me / don't call me, who referred me, signature on delivery, miscellaneous), tags each comment with every topic it matches, and offers category and ship-date filters. - Ship-date fill - parses the "Expected Ship Date" out of each comment and
writes it into the
shipdate_expectedcolumn. This runs automatically when the report loads and is also available as commands:bin/backfill_shipdates.phpto fill andbin/reset_shipdates.phpto revert to the original zeros for re-testing.
Built with plain PHP 8.3 and PDO. No frameworks, no Composer packages, and vanilla JavaScript only (no libraries).
Status: Complete.
The original test brief is preserved in TEST_INSTRUCTIONS.md.
One command brings up PHP and MySQL, imports the supplied data, and serves the report. Nothing to configure.
docker compose up --buildThen open http://localhost:8080. The ship dates (task 2) fill in automatically on that first load.
Optional dev commands once the stack is up:
docker compose exec app php bin/reset_shipdates.php # revert to the original zeros
docker compose exec app php bin/backfill_shipdates.php # fill the ship dates by handStop everything with docker compose down.
Requirements: PHP 8.1+ and a MySQL 8 server.
-
Create the database and import the supplied table. The dump stores empty ship dates as
0000-00-00, which MySQL 8 rejects under strict mode, so the import relaxessql_mode:mysql -u root -e "CREATE DATABASE IF NOT EXISTS sweetwater_test" mysql -u root --init-command="SET SESSION sql_mode=''" sweetwater_test < data/sweetwater_test.sql
-
Serve the report:
php -S localhost:8000 -t public
Then open http://localhost:8000. The ship dates (task 2) fill in automatically on load.
Optional dev commands:
php bin/reset_shipdates.php # revert to the original zeros
php bin/backfill_shipdates.php # fill the ship dates by handConnection settings default to a stock local MySQL (127.0.0.1, user root,
empty password, database sweetwater_test). If yours differ, copy
.env.example to .env and adjust.
I've added a small dependency-free test suite. Run it locally:
php tests/run.phpOr inside the Docker container:
docker compose exec app php tests/run.phpIt prints each result and exits non-zero if anything fails. The suite covers the ship-date parser and the comment classifier (common and edge cases for both.)
- On load,
public/index.phpfills any outstanding ship dates from the comment text (viaShipDate\ShipDateBackfiller), then reads the table to render the report. - The supplied dump (
data/sweetwater_test.sql) is never modified, so the original data is always recoverable and a freshdocker compose uprestores it. We do actually make an update, to meet the criteria of the instructions/business needs. src/holds the pieces:Config(env-based settings),Database\Connection(PDO),Comments\*(the category model, classifier, and repository), andShipDate\*(the date parser and the backfiller).
- Categorization is best-match. A comment is placed under the single category it best fits (the one with the most keyword matches); ties fall back to a fixed priority order. Every category a comment matches is still shown as a tag, with the best match emphasized.
- Ship dates are read from the explicit "Expected Ship Date:" label only,
formatted
M/D/YY(US month/day/year). Other dates that appear in comment text (for example a "9/11/2018 memorial" reference) are intentionally ignored so they are not mistaken for ship dates. - Rows with no parseable ship date keep their original
0000-00-00and are shown as "Date Missing" in the report so they can be followed up, as they are exceptions. - The schema is left as provided.
shipdate_expectedstaysNOT NULL; the zero value is the indicator to the front to flag as exception.