My lost password function
This seems quite fine. It's good that you are using prepared statements for all database queries.

What bugs me the most is that the users table is reused for multiple purposes:


Store essential user information such as email and password
Store information about tracking reset password requests


It would be better to use another table for the 2nd purpose.
The reason is that the users table is an essential piece of your site and you wouldn't want anything to happen to it by accident.
So the less you touch that table, the better.
Besides, for most users the new_password_key and new_password_requested fields will be blank / unused most of the time.



The variable names are sometimes not so great. For example:


$value = isset($_GET['key']) ? $_GET['key'] : null;



$value is a key, so I suggest to name it accordingly.



One last small thing, I recommend to use braces with all if, else if statements.