Free tools Windows power users keep installed
One-click scans. No signup required.
If password_verify($password, $hash) returns false, PHP did not find a match between the password string supplied and that hash. The call’s parameter order is correct when the submitted password comes first and the complete stored hash comes second, but that does not prove the values belong together. Trace the exact password and hash from registration through storage and login before changing the verification code. The 2018 SitePoint thread that prompted this question does not establish a confirmed cause. Read the original discussion.
First, confirm the password-hashing API works
PHP documents password_verify($password, $hash) as checking whether a given hash matches a given password. It returns a boolean. A hash produced by password_hash() includes the algorithm, cost, and salt information needed for verification, so you do not need to retrieve or supply a separate salt. See the PHP password_verify() manual.
As an Amazon Associate I earn from qualifying purchases.
Run a temporary, isolated check with a known test value. Keep the string unchanged between hashing and verification:
$testPassword = 'temporary test password';
$testHash = password_hash($testPassword, PASSWORD_DEFAULT);
var_dump(password_verify($testPassword, $testHash)); // true
This checks the API in isolation; it does not test your application’s database row or form handling. Do not use a real user password for debugging, and remove temporary diagnostic code when finished. PHP recommends using password_verify() rather than hashing the submitted password again and comparing hash strings, because password hashes use salts. See the verification manual and the PHP password hashing overview.
#1 Best Overall
Check the selected account and its stored hash
When the isolated check succeeds but your login fails, determine whether the email lookup returns the intended account and whether the selected password field contains that account’s complete hash. A query can run successfully and still select a different row or retrieve a value other than the one created at registration.
- Confirm the lookup condition uses the submitted email and returns the expected account.
- Check that the fetched password field is the stored hash, not an empty value, another column, or a stale variable.
- Inspect diagnostics without exposing real passwords or full hashes in browser output, logs, screenshots, or public help requests.
The SitePoint poster showed a query selecting email, password, and status, but the thread does not provide enough evidence to confirm which row or hash was actually used in the failing request.
Rank #2
Trace password handling from registration to login
Compare the value passed to password_hash() at registration with the value passed as the first argument to password_verify() at login. Check each step for transformations: trimming whitespace, filtering, stripping characters, encoding, escaping, or otherwise changing the string.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Do not silently sanitize or remove characters from a password. If registration and login treat the same typed password differently, verification can fail even when the user believes they entered the right password. Keep password handling consistent. SQL safety should come from parameterized queries, not from mutating the password string before verification.
Check that the database kept the complete hash
PHP recommends a width of 255 bytes for storing hashes created with PASSWORD_DEFAULT, because the default algorithm can change and the resulting hash length may vary. A 255-byte column is suitable, but its declared width does not prove the stored value is complete or unchanged. Check for truncation, a mismatched schema, a faulty insert or update, or retrieval of a different value. See the PHP password_hash() manual.
A hash beginning with $2y$ is consistent with bcrypt, but that prefix alone cannot show that the password matches or that the hash was stored intact. If bcrypt is in use, PHP documents a 72-byte limit for the password input; consider this only when diagnosing unusually long passwords, not as an assumed explanation for every mismatch. The thread does not establish truncation, a bcrypt length issue, or any other specific cause.
Rank #4
Separate password failure from later login logic
Confirm that the branch you are debugging is reached because password_verify() returned false. In the code shown in the SitePoint thread, a successful password check could still lead to a redirect based on account status. If verification returns true, trace that status condition and the redirect separately rather than treating every failed login outcome as a password mismatch.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Quick Recap
Diagnostic checklist
- Verify a known, unchanged test string against a hash created from that same string.
- Confirm the email query selects the intended account and that the fetched field is its complete password hash.
- Compare registration and login handling to find any transformation of the password string.
- Inspect storage and retrieval for truncation, failed updates, or a different value; do not share real credentials or hashes.
- Check account-status and redirect logic only after establishing whether verification returned true or false.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




