My approach is a bit different.
I maintain a table of failed attempts that contains a timestamp and ip address of the client. ( Always use $_SERVER[‘REMOTE_ADDR’], never use $_SERVER[‘HTTP_CLIENT_IP’] )
When the number of failed attempts within a (configurable) period exceeds the (configurable) maximum, my login app will issue a shell_exec() to linux to block the ip address in iptables (linux firewall).
In my experience, when somebody is trying to hack, they try several different userIDs, so tracking failed attempts by userID alone is futile, and ends up blocking too many legitimate users. It is much more appropriate to block an ip address that is perhaps trying many userID-password combinations.
If you want more specific details on how to do this, let me know and I will give more details.
Dave