The Error
PHP Fatal error: Uncaught Error: Call to undefined method App\Models\User::findByEmail() in /var/www/app/controllers/AuthController.php:45
Stack trace:
#0 /var/www/app/controllers/AuthController.php(45): App\Models\User::findByEmail('admin@example.com')
#1 /var/www/app/index.php(12): AuthController->login()
#2 {main}
thrown in /var/www/app/controllers/AuthController.php on line 45
It's 2 AM. Deployment just went out. Users can't log in. The logs are screaming this. Here's how to kill it fast.
Root Causes
PHP found the class (App\Models\User) but couldn't find findByEmail() on it. Six things cause this โ and each one has a different fix, so pinning the right cause first saves you 30 minutes of blind thrashing.
- The method was never defined โ you're calling something that simply doesn't exist yet.
- Typo in method name โ
findByEmailvsfindByMailvsgetByEmail. - Wrong class being resolved โ your autoloader is pulling in a different
Userclass from a vendor package or a cached DI binding. - Method lives in a trait or parent class that wasn't included or extended.
- Static vs instance mismatch โ calling
User::findByEmail()statically when the method is defined aspublic function(non-static), or vice versa. - Stale compiled cache โ Laravel and Symfony cache class definitions in
bootstrap/cache/. A stale cache serves the old class before your new method existed.
Step 1 โ Confirm What Class You're Actually Using
Don't touch a line of code yet. First, dump the resolved class right at the call site:
// In AuthController.php, right before line 45:
var_dump(get_class($user)); // if instance
// or for static:
var_dump(User::class);
exit;
You might be surprised. A namespace collision or a misconfigured DI container can silently swap in the wrong class โ one from a vendor package that never had findByEmail to begin with.
Then confirm exactly which file PHP loaded:
$ref = new ReflectionClass(App\Models\User::class);
var_dump($ref->getFileName());
exit;
Step 2 โ Check the Class Definition
Open the file reported by getFileName() and search for the method:
grep -n 'findByEmail' /var/www/app/Models/User.php
No results? Pick one of the fixes below based on why it's missing.
Fix A โ Add the Missing Method
The simplest case: the method was never written. Add it:
// app/Models/User.php
namespace App\Models;
class User
{
public static function findByEmail(string $email): ?self
{
global $pdo;
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? LIMIT 1');
$stmt->execute([$email]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$row) return null;
$user = new self();
foreach ($row as $key => $value) {
$user->$key = $value;
}
return $user;
}
}
Laravel note: findByEmail is not a built-in Eloquent method. The idiomatic equivalent is:
// Instead of User::findByEmail($email)
$user = User::where('email', $email)->first();
Or add it as a proper static method on the model:
// app/Models/User.php (Laravel Eloquent)
public static function findByEmail(string $email): ?static
{
return static::where('email', $email)->first();
}
Fix B โ Correct a Typo
The method exists โ just under a slightly different name. Check first:
php -r "print_r(get_class_methods('App\\Models\\User'));"
This dumps every public method on the class. Scan the list for the closest match to findByEmail. Then update the call site:
// Wrong
$user = User::findByEmail($email);
// Right (match whatever the definition actually says)
$user = User::findByMail($email);
// or
$user = User::getByEmail($email);
Your IDE's autocomplete catches this before you even run the code. PhpStorm and VS Code with Intelephense both flag undefined method calls inline โ worth enabling if you haven't.
Fix C โ Include the Trait or Extend the Right Parent
The method is defined โ just somewhere the class can't see it. Two common variants:
Missing trait:
// app/Traits/FindableByEmail.php
trait FindableByEmail
{
public static function findByEmail(string $email): ?static
{
return static::where('email', $email)->first();
}
}
// app/Models/User.php
class User extends Model
{
use FindableByEmail; // create(['email' => 'test@example.com']);
$found = User::findByEmail('test@example.com');
$this->assertNotNull($found);
$this->assertEquals($user->id, $found->id);
}

