I'm fairly new to PHP and am very interested in learning best practices, etc. I have just created a user registration system mostly in OOP that will dump user info into a database I've created. This is nothing revolutionary, but can you all tell me if my code is sound and clean? I want to be sure I'm on track for using best practices.
INDEX
<?php
require('./includes/functions.php');
require('./classes/usernameAuth.php');
require('./classes/checkPassword.php');
require('./classes/insertUser.php');
require('./classes/checkEmail.php');
if (isset($_POST['register'])) {
$conn = dbConnect('localhost', 'db_admin', 'kfor.com', 'bobs_auto_parts');
$checkUsername = new usernameAuth($_POST['username'], 6);
$checkPassword = new checkPassword($_POST['password'], $_POST['confirmPassword'], 8);
$checkPassword->reTyped();
$checkPassword->requireMixedCase();
$checkPassword->requireNumbers(2);
$checkPassword->requireSymbols(2);
$passwordOK = $checkPassword->check();
$emailCheck = new checkEmail($_POST['email']);
$emailCheck->validEmail($_POST['email']);
$statusOK = $emailCheck->getStatus();
if ($statusOK && $passwordOK) {
$insertUser = new insertUser($_POST['username'], $_POST['password'], $_POST['email'], $conn);
$success = $insertUser->checkSuccess();
}
$errors = array_merge($checkPassword->getErrors(), $checkUsername->getErrors(), $insertUser->getErrors());
}
?>
usernameAuth.php
<?php
class usernameAuth
{
protected $username;
protected $minUsernameChars;
protected $errors = array();
public function __construct($username, $minUsernameChars = 6)
{
$this->username = $username;
$this->minUsernameChars = $minUsernameChars;
if (strlen($this->username) < $this->minUsernameChars) {
$this->errors[] = "Username must be at least $minUsernameChars characters.";
}
if (preg_match_all('/\s/', $this->username)) {
$this->errors[] = "Username should not contain any spaces";
}
return $this->errors;
}
public function getErrors()
{
return $this->errors;
}
}
checkPassword.php
<?php
class checkPassword
{
protected $password;
protected $reTyped;
protected $minPasswordChars;
protected $minNumbers = 0;
protected $minSymbols = 0;
protected $mixedCase = false;
protected $errors = array();
public function __construct($password, $confirmPassword, $minPasswordChars = 8)
{
$this->password = $password;
$this->reTyped = $confirmPassword;
$this->minPasswordChars = $minPasswordChars;
}
public function reTyped() {
if ($this->password != $this->reTyped) {
$this->errors[] = "Passwords don't match.";
}
}
public function requireMixedCase()
{
$this->mixedCase = true;
}
public function requireNumbers($num = 1)
{
if (is_numeric($num) && $num > 0) {
$this->minNumbers = (int)$num;
}
}
public function requireSymbols($num = 1)
{
if (is_numeric($num) && $num > 0) {
$this->minSymbols = (int)$num;
}
}
public function check()
{
if (preg_match('/\s/', $this->password)) {
$this->errors[] = "Password cannot contain spaces.";
}
if (strlen($this->password) < $this->minPasswordChars) {
$this->errors[] = "Password must be at least $this->minPasswordChars characters.";
}
if ($this->mixedCase) {
$pattern = '/(?=.*[a-z])(?=.*[A-Z])/';
if (!preg_match($pattern, $this->password)) {
$this->errors[] = "Password should include uppercase and lowercase characters.";
}
}
if ($this->minNumbers) {
$pattern = '/\d/';
$found = preg_match_all($pattern, $this->password, $matches);
if ($found < $this->minNumbers) {
$this->errors[] = "Password should contain at least $this->minNumbers number(s).";
}
}
if ($this->minSymbols) {
$pattern = "/[-!$%^&*(){}<>[\]'" . '"|#@:;.,?+=_\/\~]/';
$found = preg_match_all($pattern, $this->password, $matches);
if ($found < $this->minSymbols) {
$this->errors[] = "Password should contain at least $this->minSymbols non-alphanumeric character(s).";
}
}
return $this->errors ? false : true;
}
public function getErrors()
{
return $this->errors;
}
}
insertUser.php
<?php
class insertUser
{
protected $password;
protected $username;
protected $email;
protected $errors = array();
protected $success;
public function __construct($username, $password, $email, $conn)
{
$this->username = $username;
$this->password = $password;
$this->email = $email;
$salt = time();
$pwd = sha1($this->password . $salt);
$sql = 'INSERT into users (username, password, salt, email) VALUES (?, ?, ?, ?)';
$stmt = $conn->stmt_init();
$stmt = $conn->prepare($sql);
$stmt->bind_param('ssis', $this->username, $pwd, $salt, $this->email);
$stmt->execute();
if ($stmt->affected_rows == 1) {
$this->success = "$this->username has registered. You can now log in.";
} elseif ($stmt->errno == 1062) {
$this->errors[] = "$this->username or $this->email is already in use. Please redo.";
} else {
$this->errors[] = 'Sorry, there was an issue with the database.';
}
return $this->success;
}
public function getErrors()
{
return $this->errors;
}
public function checkSuccess() {
return $this->success;
}
}
checkEmail.php
class checkEmail {
protected $email;
protected $status;
public function __construct($email) {
$this->email = $email;
if (empty($this->email) || !$this->validEmail($email)) {
$this->status = "Please provide a name and a valid email address.";
} else {
$this->status = 'Great Email!';
}
}
public function validEmail($email) {
return filter_var($this->email, FILTER_VALIDATE_EMAIL);
}
public function getStatus() {
return $this->status;
}
}