Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

So I am working on a LMS project and I have a User class that will handle everything about the user such as registration, login, showing list of courses that they are subscribed to, etc.

User.class.php

class User {
    protected $_firstName;
    protected $_lastName;
    protected $_email;
    protected $_username;
    protected $_password;
    protected $_createdOn;
    protected $_userLevel;
    protected $_salt = '}$YY lGC6&wib=w{dpqgzXv>{)A3w)5@mi`/Q7HK|/GwZ6)K<4I~Ey-bQ';

    public function getFirstName() { return $this->_firstName; }

    public function setFirstName($value) { 
            $this->_firstName = $value;
            if (empty($value)) {
                    setError('firstName', 'Enter your first name.');
            } else if (strlen($value) < 2) {
                    setError('firstName', 'The name you provided is too short.');
            } else if (!ctype_alpha(str_replace(array('-',' '), '', $value))) {
                    setError('firstName', 'The name you provided can only contain letters.');
            }
    }

    public function getLastName() { return $this->_lastName; }

    public function setLastName($value) { 
            $this->_lastName = $value;
            if (empty($value)) {
                    setError('lastName', 'Enter your last name.');
            } else if (strlen($value) < 2) {
                    setError('lastName', 'The name you provided is too short.');
            } else if (!ctype_alpha(str_replace(array('-',' '), '', $value))) {
                    setError('lastName', 'The name you provided can only contain letters.');
            }
    }

    public function getEmail() { return $this->_email; }

    public function setEmail($value) {
            $this->_email = $value;
            $pattern = '!^.{1,}@.{2,}$!i';
            if (empty($value)) {
                    setError('email', 'Enter your email.');
            } else if (substr_count($value, '@') != 1 and !preg_match($pattern, $value)) {
                    setError('email', 'The email you provided is not valid.');
            }
    }

    public function getUsername() { return $this->_username; }

    public function setUsername($value) { 
            $this->_username = strtolower($value);
            if (empty($value)) {
                    setError('username', 'Enter your username.');
            } else if (strlen($value) < 6) {
                    setError('username', 'The username you provided must have at least 6 characters.');
            } else if (!ctype_alnum(str_replace('_', '', $value))) {
                    setError('username', 'The username you provided can only contain letters, numbers, and underscores.');
            }
    }

    public function getPassword() { return $this->_password; }

    public function setPassword($value) { 
            $this->_password = $value;
            if (empty($value)) {
                    setError('password', 'Enter a password.');
            } else if (strlen($value) < 6) {
                    setError('password', 'The password you provided must have at least 6 characters.');
            }
    }

    public function setConfirmPassword($value) {
            if (empty($value)) {
                    setError('confirmPassword', 'Re-enter your password again.');
            } else if ($this->_password != $value) {
                    setError('confirmPassword', 'This does not match your password.');
            }
    }

    private function _encrypt($value) {
            return sha1(md5($this->_salt.md5($value)));
    }

    public function register() {
            if (!hasErrors()) {
                    try {
                            $core = Core::getInstance();
                            $sth = $core->dbh->prepare(<<<SQL
INSERT IGNORE INTO `users` SET 
`first_name` = :first_name, `last_name` = :last_name, `email` = LOWER(:email), 
`username` = LOWER(:username), `password` = :password, 
`created_on` = NOW()
SQL
                            );
                            $sth->bindValue(':first_name', propercase($this->_firstName), PDO::PARAM_STR);
                            $sth->bindValue(':last_name', propercase($this->_lastName), PDO::PARAM_STR);
                            $sth->bindValue(':email', $this->_email, PDO::PARAM_STR);
                            $sth->bindValue(':username', $this->_username, PDO::PARAM_STR);
                            $sth->bindValue(':password', $this->_encrypt($this->_password), PDO::PARAM_STR);
                            $sth->execute();
                    } catch (Exception $e) {
                            // print $e->getMessage();
                    }      
            }
    }

    public function login() {
            if (!hasErrors()) {
                    try {
                            $core = Core::getInstance(); 
                            $sth = $core->dbh->prepare(<<<SQL
SELECT * 
FROM `users`
WHERE `username` = :username
LIMIT 1     
SQL
                            );
                            $sth->bindValue(':username', $this->_username, PDO::PARAM_STR);
                            $sth->execute();
                            $row = $sth->fetch();
                            $sth->closeCursor();

                            if ($row and $row->password == $this->_encrypt($this->_password)) {
                                    $_SESSION['uid'] = $row->id;
                                    $_SESSION['user'] = $row->username;
                                    $_SESSION['pass'] = $row->password;
                                    $_SESSION['level'] = $row->user_level;
                            }
                    } catch (Exception $e) {
                            // print $e->getMessage();
                    }
            }
    }

    private function _destroySession() {
            session_unset();
            session_destroy();
    }

    public function logout() {
            $this->_destroySession();
            redirect('index.php');
    }

    public function check() {
            if (isset($_SESSION['pass'])) {
                    try {       
                            $core = Core::getInstance(); 
                            $sth = $core->dbh->prepare(<<<SQL
SELECT * FROM `users` WHERE `username` = :username
LIMIT 1
SQL
                            );
                            $sth->bindValue(':username', $_SESSION['user'], PDO::PARAM_STR);
                            $sth->execute();
                            $row = $sth->fetch();
                            $sth->closeCursor();
                            if (!$row or $row->password != $_SESSION['pass']) {
                                    $this->logout();
                            }
                    } catch (Exception $e) {
                            // print $e->getMessage();
                    }
            }
    }

    public function isLoggedIn() {
            return (isset($_SESSION['pass']));
    }

    public function getCourseSubscriptions() {
            $rows = array();
            try {
                    $core = Core::getInstance();
                    $sth = $core->dbh->prepare(<<<SQL
SELECT c.`id` AS id, c.`code` AS code, c.`name` AS name, 
IF(`u_id` IS NULL, 0, 1) AS subscribed
FROM `courses` c
LEFT JOIN `course_subscriptions` s 
ON c.id = s.`c_id` AND s.`u_id` = :u_id
ORDER BY `code`
SQL
                    );
                    $sth->bindValue(':u_id', $_SESSION['uid'], PDO::PARAM_INT);
                    $sth->execute();
                    $rows = $sth->fetchAll();
                    $sth->closeCursor();
            } catch (PDOException $e) {
                    // print $e->getMessage();
            }
            return $rows;
    }

    public function addCourseSubscription($c_id) {
            try {
                    $core = Core::getInstance();
                    $sth = $core->dbh->prepare(<<<SQL
INSERT IGNORE INTO `course_subscriptions`(c_id, u_id) 
VALUES(:c_id, :u_id)
SQL
                    );
                    $sth->bindValue(':c_id', $c_id, PDO::PARAM_INT);
                    $sth->bindValue(':u_id', $_SESSION['uid'], PDO::PARAM_INT);
                    $sth->execute();
                    return true;
            } catch (PDOException $e) {
                    // print $e->getMessage();
            }
            return false;
    }
}

Everything is working fine but I feel.. stuck with how to use this object properly with a session. Below is an example on how I am currently using my class.

course_catalog.php

$userObj = new User();
$userObj->check();
$list = $userObj->getCourseSubscriptions();

Any suggestions on how I can improve any of this?

share|improve this question
add comment

1 Answer

up vote 1 down vote accepted

First of all I would split the User class in 2 or 3 classes User, Authentication and Registration. The setter error could easily become Exceptions, which you could collect in you Registration class.

At the end you will have a smaller User object you can attach to the session.

Please also check http://www.phpbuilder.com/columns/validating_php_user_sessions.php3 for some hint regarding session validation.

share|improve this answer
    
Thanks for the suggestion about splitting the class. That really helped me. I don't quite understand though when you say change the setter error to Exceptions. Should I be creating a custom exception for each property that I'm trying to set e.g. throw InvalidFirstNameException()? Though, if I am calling the setters one after the other, wouldn't throwing an exception cause not all setters to be called. –  Mikey Feb 16 '13 at 19:19
    
I think the is something like an InvalidParameterException. You would catch this exception in you Registration class and transform them to an error message for the user. –  mnhg Feb 16 '13 at 20:22
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.