Codeskill

Learn to code, step by step

Mini project: CRUD app with login

This mini project pulls these tutorials together: a notes CRUD app with registration, login, and authorisation. One user sees their notes; an admin can manage users. Plain PHP, no framework.

What you are building

  • Register, login, logout
  • List, create, edit, delete notes (owner only, admin override)
  • Flash messages and validated forms
  • Prepared statements throughout
  • Router + controllers + templates

Suggested schema

CREATE TABLE users (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(190) NOT NULL UNIQUE,
  password_hash VARCHAR(255) NOT NULL,
  role VARCHAR(20) NOT NULL DEFAULT 'user',
  created_at DATETIME NOT NULL
);

CREATE TABLE notes (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  user_id INT UNSIGNED NOT NULL,
  title VARCHAR(120) NOT NULL,
  body TEXT NOT NULL,
  created_at DATETIME NOT NULL,
  updated_at DATETIME NOT NULL,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

Routes

GET  /              home
GET  /register         register form
POST /register         create account
GET  /login            login form
POST /login            authenticate
POST /logout           logout
GET  /notes            list notes (auth)
GET  /notes/create     create form (auth)
POST /notes            store (auth)
GET  /notes/{id}/edit  edit form (auth, owner)
POST /notes/{id}       update (auth, owner)
POST /notes/{id}/delete delete (auth, owner or admin)

Build order

  • 1. Project layout, Composer, PDO connection from config
  • 2. Router and a hello-world home page
  • 3. Auth (register, login, session helpers)
  • 4. NoteRepository with prepared statements
  • 5. CRUD controllers with validation and flash
  • 6. Templates with layout and escaped output
  • 7. Admin-only user list (optional stretch)

Checklist before you call it done

  • CSRF tokens on all POST forms
  • Passwords hashed, sessions regenerated on login
  • Users cannot edit another user’s notes by guessing IDs
  • Errors logged, not dumped to the browser in production mode
  • Upload directory not used unless you added attachments

This is a portfolio-sized app. It is small on purpose – but it uses the same patterns as larger PHP codebases. Finish it, then read your own code critically: what would you extract next if the app grew?

PreviousConfig, environments, and secrets