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