Your approach is very fine for normal sessions. The problematic bit here is a "remember me" functionality, which needs to be handled differently than a normal session.
A common way to implement that functionality is to store a second cookie with a far expiration date and put the user ID plus a secure hash in it. You need the user id or some other identification to detect which user comes back, but you also need the secure hash to be sure that the cookie is the one that your web app set and has not been crafted manually.
If you do not have a secure hash, people can sent a self-built cookie with the user ID and automatically get logged in.
So the secure hash needs to contain information that only your web app knows about, i.e. the user creation date.
You might want to do it like this:
$cookieValue = (int)$user->id . ':' . md5($user->creationDate . '/' . $user->passwordHash);
Since neither creationDate nor passwordHash change, you can verify the validity of the secure hash when the user tries to login via cookie. When the user changed his password, the password hash changes and the user needs a new cookie - which is very fine in my eyes, since people who stole the cookie would also be logged out.
If you want additional security, use another value for hash creation, i.e. a special cookie hash that you store along with the other user data. You can create it completely randomly and should change it whenever the user logs in:
$randomValue = md5(time() . rand() . $user->passwordHash);
$user->setCookieValue($randomValue);
$cookieValue = (int)$user->id . ':' . $randomValue;
Now when logging in:
list($userId, $hash) = explode(':', $cookieValue);
$user = loadUser($userId);
if ($user instanceof User && $user->cookieValue == $hash) {
//user logged in
//generate and set new cookie value
} else {
// handle invalid persistent cookie
}