A full-stack PHP matchmaking platform — registration, secure authentication, and a recommendation engine, built solo and deployed to production. This is also the story of the bug that quietly broke it.
Every new user who registered disappeared. Not an error — silence. They could log in, but they'd never show up in search, browse, or anyone's match results.
The cause was one missing row. register.php created the account, but never created the matching stub row in user_profiles. Every browse, search, and match query joined the two tables with an INNER JOIN — which meant any user without a profile row was silently excluded from the result set entirely. No error thrown, nothing to log. The site just quietly stopped showing people who'd just joined it.
Switched the join type everywhere a newly registered user could be affected — profiles.php, the public profile viewer, and getRecommendedMatches() — plus a related issue where zero-score matches were being filtered out of recommendations instead of shown at the bottom.
-- Before: profile-less users vanish SELECT u.*, p.* FROM users u INNER JOIN user_profiles p ON u.id = p.user_id WHERE u.status = 'active'; -- After: every user returned, profile fields fill in as completed SELECT u.*, p.* FROM users u LEFT JOIN user_profiles p ON u.id = p.user_id WHERE u.status = 'active';
Root cause stayed in register.php too — it now creates the user_profiles stub at signup, so the gap can't reopen for the next user.
getRecommendedMatches(), a scored recommendation function rather than a static browse list.config.example.php pattern so real credentials never touch the repo.