I have a User class, this class handles things like:
- login (UserAuthenticateModel)
- Handle user sessions: user login tokens, fetching user from session if set in session, ect' (UserSessionsModel)
- Fetch & Set user data to populate $this user object. (UserFetchModel)
- Update & change my user data (to this user object - and in the database) (UserUpdateModel)
I'm asking out loud and please correct me if I'm wrong:
- Is every point a single responsibility of some sort of "something that handle only one thing" inside the "User" class and needs a different class?
- Does my User class need to be under "classes" folder, since it's just an object of "something", and my other classes like "UserSessions" and "UserAuthenticate" should be considered as a model?
I'll describe 2 examples with some code:
- Setting sessios: Insead of just pasting a whole bunch of code in my construct that "does something with sessions", I use a UserSessionsModel specifically with the method that does whatever it has to do - get data from session if exist. single responability - Setting/changing my user sessions, and populating my user object. and some of this session handling methods might be used elsewhere (example 2).
Code ex:
User class
{
public function __construct()
{
# look for a user in the session if set
$this->getFromSession();
}
public function getFromSession()
{
# Create UserSession obj
if ( !$this->UserSessions instanceof UserSessions )
$this->UserSessions = new \myapp\Models\User\UserSessionsModel();
$this->UserSessions->getUserFromSession($this);
}
}
class UserSessionsModel {
public function getUserFromSession(User $User)
{
if (Session::exists(Config::$user)) {
$session = unserialize(Session::get(Config::$user));
$User->id = $session->id;
$User->firstName = $session->firstName;
$User->lastName = $session->lastName;
$User->userName = $session->userName;
$User->email = $session->email;
$User->lastLogin = $session->lastLogin;
$User->password = $session->password;
$User->ip = $session->ip;
$User->loginTimestamp = $session->loginTimestamp;
$User->isLoggedIn = $session->isLoggedIn;
return $User;
}
}
public function setUserToSession(User $User)
{
Session::set(Config::$user, serialize($User));
}
}
- Logging in:
This has 2 parts:
- First to authenticate the user credentials
- Set security sessions (token, loggedin flag, ect'.) - using the UserSessionModel from example 1 - since it handles the same "subject". So both are under the login method (one insice an other or separately - this example handles them the first way) and both are 2 different responsibilities - one is checking a user authentication, the second is handeling the sessions/tokens.
code ex:
User class {
// after setting $this->username & $this->password to this object
public function login()
{
if ( !$this->UserAuthenticator instanceof \myapp\Models\User\UserAuthenticatorModel )
$this->UserAuthenticatorModel = new \myapp\Models\User\UserAuthenticatorModel();
return $this->UserAuthenticatorModel->login($this);
}
}
class UserAuthenticatorModel extends Model
{
public function login(User $User)
{
try {
# Connect to new database with $User->username & $User->password
...
# If status is connected
if ($newConnection) {
# Check for user credentials data
$userData = $this->UserLoginValidation($User->userName, $User->password);
# If the result isn't a valid array - EXEPTION
if ( (!is_array($userData)) || (empty($userData)) )
throw new LoginException("Invalid username ({$User->userName}) or password ({$User->password})");
if ($userData["require_password_change"] === 1) {
$this->set($User, $userData);
return true;
}
$this->set($User, $userData);
# Set logged-in security sessions
$User->UserSessions = new UserSessionsModel();
$User->UserSessions->setSecuritySession($User);
# Set User obj to session
$User->UserSessions->UserToSession($User);
# Update last_login for this user
$this->updateLastLogin($User->id, $User->loginTimestamp);
return true;
} else {
throw new LoginException('User does not exist');
return false;
}
} catch (LoginException $e) {
$e->log($e);
return false;
}
}
Using PHP here btw.