practical capstone projects
Capstone: Maintainable PHP App
The capstone turns the catalog increments into one portfolio application another developer can run, review, test, and deploy. Do not restart from a blank directory. Consolidate the product manager, login, templates, CLI command, and JSON API into one maintained repository.
Keep The Scope Finishable
The required application is deliberately small:
public product list and detail pages
admin login and logout
protected create, edit, and delete actions
PDO migration and product repository
escaped templates and server-side validation
CSRF protection for browser state changes
CLI product report
read-only JSON product endpoints
automated checks and deployment notes
Add a feature only when the required application is complete. A finished understandable app is stronger portfolio evidence than an unfinished list of technologies.
Use A Reviewable Repository Shape
bin/products-report.php
migrations/
public/index.php
src/Controller/
src/Repository/
src/Service/
templates/
tests/
.env.example
README.md
Keep secrets out of Git. Explain required environment variables in .env.example and the README.
Add Verification At Several Boundaries
Use the cheapest useful check for each risk:
| Risk | Minimum evidence |
|---|---|
| Product validation | focused unit test |
| PDO statements and mapping | repository integration test |
| Anonymous admin edit | HTTP-level rejected request |
| CSRF failure | HTTP-level rejected request |
| Escaping | product name containing HTML characters |
| JSON missing product | curl request returning stable 404 JSON |
| CLI report | normal and invalid command exits |
| Deployment | documented build, migration, health, and rollback steps |
Write The README For A New Developer
Start from a clean checkout and follow only the README. It should explain runtime requirements, environment setup, dependency installation, migration, local server command, test commands, CLI report usage, and deployment outline.
Record one short architecture note: where requests enter, where SQL lives, where authorization runs, and where templates escape output.
Final Review
Before calling the app portfolio-ready:
- Run from a clean checkout.
- Exercise normal and rejected browser journeys.
- Run automated checks.
- Review tracked files for secrets and runtime output.
- Explain one tradeoff you intentionally made.
Practice
Practice: Finish The Capstone App
Consolidate the guided catalog increments into one repository and prove the application from a clean checkout.
Requirements
- Implement product browsing and an authenticated admin edit flow.
- Use PDO migrations and prepared statements.
- Add escaped templates, validation, CSRF protection, and sessions.
- Provide CLI maintenance and a small JSON endpoint.
- Keep the project small enough to finish.
- Do not hide errors or commit secrets.
- Include README setup and verification steps.
Produce:
- the working repository shape from the lesson;
- a README another developer can follow without hidden setup;
- the verification evidence table completed with commands or test names;
- one short architecture note;
- one deliberate tradeoff you can explain in an interview.
Show solution
clean checkout installs dependencies and applies migrations
local server command opens the product list
anonymous admin edit is rejected
valid admin login regenerates the session ID
create, edit, and delete use validation, authorization, CSRF, and prepared statements
HTML-looking product names render as text
JSON list, found, and missing responses keep stable shapes
CLI report documents successful and failed exits
automated checks pass
deployment notes include migration, health check, and rollback
The architecture note should be brief and concrete:
Requests enter through public/index.php and the router.
Controllers translate HTTP input and call application code.
ProductRepository owns SQL.
Authorization runs before admin changes.
Templates escape untrusted values when rendering HTML.
The app is ready to discuss in an interview when another developer can reproduce those checks from the README and you can explain why each boundary exists.