First, I would try to find two numbers using non-regex (or preg_match_all('[0-9]', ...) >= 2 , and then checking for:
^[ !@ #$%*a-zA-Z0-9]{8,}$
It should be faster and more understandable. To do this using only regular expression sounds, you need a lookahead that basically scans the expression twice afaik, although I am not sure about the internal functions of PHP on this.
Be prepared for many complaints that passwords are not accepted. I personally have a large subset of passwords that do not confirm these restrictions. Also meaningless passwords, such as 12345678 , will check or even 11111111 , but not f4# f@faASvCXZr $%%zcorrecthorsebatterystaple .
sapht source share