LEARN TO CODE | PHP | 04 MINI PROJECTS AND NEXT STEPS
04 Mini projects and next steps: challenges
Demonstrate the complete project flow and prove that invalid or forbidden requests leave stored data unchanged.
START HERE | PLAN YOUR EVIDENCE
Use PHP 8.1 or later with PDO MySQL and a running local MariaDB/MySQL server. The PHP built-in server does not install or start the database. Download the complete Section 04 example files , extract them and open the php04-examples folder in VS Code.
The public folder contains browser-facing pages. The private and tools folders are siblings outside that document root. Keep the complete folder structure: copying individual PHP pages without their shared files will not work.
Attempt each task before opening guidance. Work with fictional accounts and enquiries. Record the request, signed-in account, expected result, actual response and stored data before/after. Ticks last while this page is open.
CHALLENGE 01 | CLASSIFY THE FAILURE
Explain the difference between a missing semicolon, a blank contact name and an unavailable database.
Need a hint?
Consider when PHP can parse the program, when validation runs and when a service is needed.
Reveal guidance
Fix syntax in source, return useful validation for expected input errors, and report operational failure without claiming success. Inspect local logs for service failures.
CHALLENGE 02 | SEPARATE SETTINGS FROM SOURCE
Configure the project without placing a database password in a public PHP page.
Need a hint?
Use the example config and serve only public.
Reveal guidance
Copy private/config.example.php to private/config.php, fill it locally and start with -t public. Keep filled configuration out of the shared ZIP or repository. Confirm /private/config.php is not served.
CHALLENGE 03 | HASH AND VERIFY
Create three fictional accounts, then explain why comparing two new password_hash results is the wrong login check.
Need a hint?
Salts are part of the stored verifier.
Reveal guidance
Use password_verify against the stored hash. The CLI creates Alex and Sam as editors and Robin as a reader. Do not store the plaintext password or pass it in the URL.
CHALLENGE 04 | FOLLOW THE SESSION
Describe the browser-to-server journey after a successful login, including identifier rotation and user lookup.
Need a hint?
Distinguish the session cookie from server-side user_id.
Reveal guidance
The browser carries an opaque ID; the server stores user_id. Login rotates the ID before setting authenticated identity. Each protected request retrieves current account data and permissions. The local demo has no expiry strategy beyond its session lifetime behaviour.
CHALLENGE 05 | REJECT A FALSE LOGIN
Test an unknown name and an incorrect password.
Need a hint?
Neither should create an authenticated session.
Reveal guidance
Both return the generic credentials message. A protected request still redirects to login. The generic message does not itself supply login rate limiting.
CHALLENGE 06 | SAVE ONE ENQUIRY
Submit a valid fictional message, inspect Messages, then refresh the redirected page.
Need a hint?
Check database row counts, not only the screen.
Reveal guidance
Exactly one normal submission adds a row; refreshing the resulting GET does not add another. Say “saved”, not “emailed”. This is not a guarantee against repeated simultaneous POSTs.
CHALLENGE 07 | VALIDATE AND PRESERVE
Test blank text, malformed email, array-shaped input and angle brackets in a message.
Need a hint?
Browser validation can be bypassed.
Reveal guidance
Invalid input leaves the database unchanged and displays errors. Previously entered values are escaped when redisplayed. Angle brackets are plain text, not executable markup. Byte limits are the explicit server rule.
CHALLENGE 08 | CHECK LINKS AND CATEGORIES
Try to save an unsafe URL scheme and an invented category. Then save a valid PHP manual link.
Need a hint?
URL validation and HTML escaping solve different problems.
Reveal guidance
Reject non-HTTP(S) schemes and categories outside PHP, SQL, HTML. The valid link is stored, then escaped for HTML when displayed. A valid scheme does not guarantee content suitability.
CHALLENGE 09 | ATTACK THE HIDDEN ID
As Sam, submit an update or deletion targeting Alex’s resource ID.
Need a hint?
A hidden field can be edited.
Reveal guidance
Expect 403 and no mutation. Reuse Sam’s valid token to show that CSRF and authorisation are separate checks. The SQL also targets both resource_id and owner_id.
CHALLENGE 10 | TEST READER PERMISSIONS
As Robin, request the edit page directly and attempt a POST.
Need a hint?
Hiding Add is not enforcement.
Reveal guidance
Both must be rejected by the server with 403. Robin may read and search. An unauthenticated request instead redirects to login.
CHALLENGE 11 | TOKEN AND LOGOUT BOUNDARIES
Try a missing-token contact POST, a GET deletion, and a valid logout followed by a fresh protected request.
Need a hint?
Record status and stored effects separately.
Reveal guidance
Missing token receives 403 without a save; GET delete receives 405 without deleting. Valid POST logout clears session and cookie; the next protected request requires sign-in.
CHALLENGE 12 | CAPSTONE: A REVIEWED LOCAL DIRECTORY
Demonstrate contact storage and all directory CRUD actions with three accounts. Add an allow-listed category filter and submit a test log.
Need a hint?
Reuse the complete examples, then extend one requirement deliberately.
Reveal guidance
Include successful and rejected requests, expected/actual row changes, invalid URLs, other-owner IDs, missing tokens and recovery from database failure. Your write-up must name the local limitations: no public signup, password recovery, rate limiting, deliberate expiry or concurrency controls. Do not label it production-ready.
FINISH | CHOOSE A NEXT STEP
Choose one focused improvement: category filtering, pagination, a protected staff enquiry inbox or automated ownership tests. Write its permission rules before coding. An inbox needs separate access control because contact messages are not public directory records.
Explain what remains a local teaching assumption. A clear account of limits is stronger project evidence than a claim that every security problem has been solved.
KEEP LEARNING
Previous page PHP course overview
Download complete Section 04 example files
Official references: PHP error configuration · Password hashing · Password verification · Session identifier rotation