The refresh_token is only returned on the first request. When you refresh the access token a second time it returns everything except the refresh_token and the file_put_contents removes the refresh_token when this happens the second time.
Modifying the code as following will merge in the original access token with the new one (see: array_merge). This way you will be able to preserve your refresh_token for future requests. I have submitted the following fix to Google, hope they update it at some point.
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$newAccessToken = $client->getAccessToken();
$accessToken = array_merge($accessToken, $newAccessToken);
file_put_contents($credentialsPath, json_encode($accessToken));
}