Board index   FAQ   Search  
Register  Login
Board index PHP Your Scripts

Two neat member classes

This is where you share YOUR scripts with others

Moderators: macek, egami, gesf

Two neat member classes

Postby Strider64 » Mon May 20, 2013 5:46 am

Here are two simple user registration/login classes, well at least I think they are:

First one I called: Member.php
Code: Select all
<?php

class Member extends DBConnect {
   
    // The member attributes containing required and optional information.
    // The attributes must correspond to the database table columns:
   
    private $userType=NULL; // Required (assigned)
    private $username=NULL; // Required
    private $email=NULL; // Required   
    private $pass=NULL; // Required
    private $fullName=NULL;
    private $address=NULL;
    private $city=NULL;
    private $state=NULL;
    private $zipCode=NULL;
   
    // Get the private attributes:
    public function __get($property) {
    if (property_exists($this, $property)) {      
      return $this->$property;
    }
    }
   
    // Set the private attributes:
    public function __set($property, $value) {
    if (property_exists($this, $property)) {
 
      $this->$property = $value;
    }
 
    return $this;
    }
   
   // Method returns the user ID:
   public function getId() {
      return $this->id;
   }
   
   // Method returns a Boolean if the user is an administrator:
   public function isAdmin() {
      return ($this->userType == 'admin');
   }
   
   // Method returns a Boolean indicating if the user is an administrator
   // or if the user is the original author of the provided page:
   public function canEditPage(Page $page) {
      return ($this->isAdmin() || ($this->id == $page->getCreatorId()));
   }
   
   // Method returns a Boolean indicating if the user is an administrator or an author:
   public function canCreatePage() {
      return ($this->isAdmin() || ($this->userType == 'author'));
   }
     
}


The second class I called: Registration.php:
Code: Select all
<?php
class Registration extends Member {
   
   // Make sure username isn't empty:
   public function isUsernameValid() {
      return ($this->username == NULL);   
   }
   
   // Method checks to see if username isn't already taken and returns true if it is already taken:
   public function isUsernameAvailable() {
      // Connect to PDO database:
      $pdo = parent::connect();
      
        $query = "
            SELECT
                1
            FROM users
            WHERE
                username = :username1
        ";
      
        $query_params = array(
            ':username1' => $this->username
        );   

        // These two statements run the query against your database table.
        $stmt = $pdo->prepare($query);
        $result = $stmt->execute($query_params);

        // The fetch() method returns an array representing the "next" row from
        // the selected results, or false if there are no more rows to fetch.            
        return $row = $stmt->fetch();      
        // If a row was returned, then we know a matching username was found in
        // the database already and we should return a boolean value back.      
                     
   }
   
   // Verify that password is not null:
   public function processPass($password) {   
    return ($password == NULL) ? NULL : sha1($password);   
   }
   
   public function isPassBlank() {
      return ($this->pass == null);
   }
   
   public function isPassLongEnough($pass) {
      return (strlen($pass) < 6);
   }
   
   // Method returns a Boolean if the user's email is valid:
   public function hasValidEmail() {
      return (!filter_var($this->email, FILTER_VALIDATE_EMAIL));      
   
   }
     
   public function isEmailUsed() {
      
      $pdo = parent::connect();
      
        $query = "
            SELECT
                1
            FROM users
            WHERE
                email = :email1
        ";
      
        $query_params = array(
            ':email1' => $this->email
        );   
      
        // These two statements run the query against your database table.
        $stmt = $pdo->prepare($query);
        $result = $stmt->execute($query_params);

        // The fetch() method returns an array representing the "next" row from
        // the selected results, or false if there are no more rows to fetch.            
        return $row = $stmt->fetch();      
        // If a row was returned, then we know a matching email was found in
        // the database already and we should return a boolean value back.                   
   }
      
}


The reason I didn't have this in one class is that I don't want the user getting the chance to know about the member class. You will still need to validate the data that comes into the Member class somehow, but I'll leave that up to you to figure out. 8)

Then all you would have to do is something like the following:

Code: Select all
<?php #register.php
// Need the utilities file:
require('includes/utilities.inc.php');
// Process form once user clicks on Register:
if (isset($_POST['action']) && $_POST['action'] == 'register') {
   
    $guest = new Registration();   // Registration Class extends Members Class.      
      $errorMsg = NULL;
   
    $data['userType']  = 'public'; // User has no rights to add or edit pages.
    $data['username']  = htmlspecialchars($_POST['username']); // Required
    $data['email']     = htmlspecialchars($_POST['email']); // Required
    $password['pass']  = htmlspecialchars($_POST['pass']); // Do Not Store
    $data['pass']      = $guest->processPass($password['pass']); // Required
    $data['fullName']  = htmlspecialchars($_POST['fullName']);
    $data['address']   = htmlspecialchars($_POST['address']);
    $data['city']      = htmlspecialchars($_POST['city']);
    $data['state']     = htmlspecialchars($_POST['state']);
    $data['zipCode']   = htmlspecialchars($_POST['zipCode']);
    
    // Validate length of password:
    if ($guest->isPassLongEnough($password['pass'])) {
      $errorMsg .= '<li class="stop-bullet">Password is too short, please re-enter</li>';   
    }
   
    // Unset the user's unecrpyted password:   
    unset($password['pass']);
   
    // Set the attributes (Member Class):   
    foreach($data as $property => $value) {
      $guest->$property = $value;   
    }
       
    // Validate username, email and pass attriutes:
    if ($guest->isUsernameValid()) {
       $errorMsg .= '<li class="stop-bullet">Username is empty, please enter.</li>';   
    }
   
    if ($guest->isUsernameAvailable()) {
       $errorMsg .= '<li class="stop-bullet">Username: ' . $guest->username . ' is already taken</li>';
    }

    if ($guest->isPassBlank()) {
      $errorMsg .= '<li class="stop-bullet">Password is empty, please enter.</li>';   
    }
       
    if ($guest->hasValidEmail()) {
       $errorMsg .= '<li class="stop-bullet">' .$guest->email . ' is an invalid email address.</li>';
    }   
   
    if ($guest->isEmailUsed()) {
       $errorMsg .= '<li class="stop-bullet">' .$guest->email . ' is already registered.</li>';   
    }
   
    // Store user's credentials if form data is validated:
    if(!$errorMsg) {      
      $query = 'INSERT INTO users (userType, username, email, pass, fullName, address, city, state, zipCode, dateAdded) VALUES (:userType, :username, :email, :pass, :fullName, :address, :city, :state, :zipCode, NOW())';
      $stmt = $pdo->prepare($query);
      $result = $stmt->execute(array(':userType' => $guest->userType, ':username' => $guest->username, ':pass' => $guest->pass, ':email' => $guest->email, ':fullName' => $guest->fullName, ':address' => $guest->address, ':city' => $guest->city, ':state' => $guest->state, ':zipCode' => $guest->zipCode));         
    }
}
?>


This is just a basic registration class, I plan to enhance by tighten the password security code, but seeing this I think one can see the benefits of Object-Oriented Programming.
User avatar
Strider64
New php-forum User
New php-forum User
 
Posts: 68
Joined: Sat Mar 23, 2013 8:24 am

Re: Two neat member classes

Postby Strider64 » Sat May 25, 2013 8:48 pm

I revised my classes and made for better validation:
This class is strictly for Registering a user, I figured it would be better and safer to contain it to just this one class, plus I have added better validation:
Code: Select all
<?php
class Registration extends DBConnect {
   
     // The member attributes containing required and optional information.
    // The attributes must correspond to the database table columns:
   
    private $id = NULL;
    private $userType=NULL; // Required (assigned)
    private $username=NULL; // Required
    private $email=NULL; // Required   
    private $pass=NULL; // Required
    private $fullName=NULL;
    private $address=NULL;
    private $city=NULL;
    private $state=NULL;
    private $zipCode=NULL;
   
    // Get the private attributes:
    public function __get($property) {
    if (property_exists($this, $property)) {      
      return $this->$property;
    }
    }
   
    // Set the private attributes:
    public function __set($property, $value) {
    if (property_exists($this, $property)) {
 
      $this->$property = $value;
    }
    return $this;
    }
     
   
   // Method checks to see if username isn't already taken and returns true if it is already taken:
   public function isUsernameAvailable() {
      // Connect to PDO database:
      $pdo = parent::connect();
      
        $query = "
            SELECT
                1
            FROM users
            WHERE
                username = :username1
        ";
      
        $query_params = array(
            ':username1' => $this->username
        );   

        // These two statements run the query against your database table.
        $stmt = $pdo->prepare($query);
        $result = $stmt->execute($query_params);

        // The fetch() method returns an array representing the "next" row from
        // the selected results, or false if there are no more rows to fetch.            
        return $row = $stmt->fetch();      
        // If a row was returned, then we know a matching username was found in
        // the database already and we should return a boolean value back.      
                     
   }
         
   // Method returns a Boolean if the user's email is valid:
   public function hasValidEmail() {
      return (!filter_var($this->email, FILTER_VALIDATE_EMAIL));        
   }
   
   // Method returns to check if password is strong enough:
   public function isPassWordStrong($pass=Null) {
      return (preg_match("/^.*(?=.{8,})(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).*$/", $pass) === 0);
   }
   
   // Check for valid user name:
   public function isUsername() {
      if (preg_match("/^[0-9a-zA-Z_]{5,}$/", $this->username) === 0) {
         return true;
      }
   }
   
     
   public function isEmailUsed() {
      
      $pdo = parent::connect();
      
        $query = "
            SELECT
                1
            FROM users
            WHERE
                email = :email1
        ";
      
        $query_params = array(
            ':email1' => $this->email
        );   
      
        // These two statements run the query against your database table.
        $stmt = $pdo->prepare($query);
        $result = $stmt->execute($query_params);

        // The fetch() method returns an array representing the "next" row from
        // the selected results, or false if there are no more rows to fetch.            
        return $row = $stmt->fetch();      
        // If a row was returned, then we know a matching email was found in
        // the database already and we should return a boolean value back.                   
   }
      
}


This is my limited MVC file:
Code: Select all
<?php #register.php
// Need the utilities file:
require('includes/utilities.inc.php');
require('includes/password.inc.php');

if ($user) {
   header('Location:index.php');
   exit;   
}

// Process form once user clicks on Register:
if (isset($_POST['action']) && $_POST['action'] == 'register') {
   
    $guest = new Registration();   // Registration Class extends DBConnect Class.          
      $errorMsg = NULL;
   
    $data['userType']  = 'public'; // User has no rights to add or edit pages.
    $data['username']  = trim($_POST['username']); // Required
    $data['email']     = trim($_POST['email']); // Required
    $password          = trim($_POST['pass']);
    $passOK            = $guest->isPassWordStrong($password);
    if ($passOK) {
       $errorMsg     = '<li class="stop-bullet">Password must be at least 8 characters, </li><li class="stop-bullet">and must contain at least one lower case letter, </li><li class="stop-bullet">one upper case letter and one digit</li>';
    }
    $data['pass']      = password_hash($password, PASSWORD_BCRYPT, array("cost" => 15));
    $password          = NULL;
    $data['fullName']  = trim($_POST['fullName']);
    $data['address']   = trim($_POST['address']);
    $data['city']      = trim($_POST['city']);
    $data['state']     = trim($_POST['state']);
    $data['zipCode']   = trim($_POST['zipCode']);    
   
    // Set the attributes (Member Class):   
    foreach($data as $property => $value) {
      $guest->$property = $value;   
    }
       
    // Validate username, email and pass attriutes:   
    if ($guest->isUsername()) {
           $errorMsg .= '<li class="stop-bullet">Username must be bigger that 5 chars and contain only digits, letters and underscore</li>';
    }
      
    if ($guest->isUsernameAvailable()) {
       $errorMsg .= '<li class="stop-bullet">Username: ' . $guest->username . ' is already taken</li>';
    }
       
    if ($guest->hasValidEmail()) {
       $errorMsg .= '<li class="stop-bullet">Email must is invalid, Re-Enter</li>';
    }   
   
    if ($guest->isEmailUsed()) {
       $errorMsg .= '<li class="stop-bullet">' .$guest->email . ' is already registered.</li>';   
    }
   
    // Store user's credentials if form data is validated:
    if(!$errorMsg) {      
      $query = 'INSERT INTO users (userType, username, email, pass, fullName, address, city, state, zipCode, dateAdded) VALUES (:userType, :username, :email, :pass, :fullName, :address, :city, :state, :zipCode, NOW())';
      $stmt = $pdo->prepare($query);
      $result = $stmt->execute(array(':userType' => $guest->userType, ':username' => $guest->username, ':pass' => $guest->pass, ':email' => $guest->email, ':fullName' => $guest->fullName, ':address' => $guest->address, ':city' => $guest->city, ':state' => $guest->state, ':zipCode' => $guest->zipCode));         
      header('Location: index.php');
      exit;      
    }
}
require('includes/header.inc.php');
?>
<section>
  <article>
    <div class="error-styling">
        <ul>
           <?php echo (isset($errorMsg)) ? $errorMsg : '<li class="start-bullet">Registration Page</li>'; ?>
        </ul>
    </div>
    <div id="format-form">
        <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
        <input type="hidden" name="action" value="register" />   
       
        <label class="label-styling" for="style-name" >Username:*</label>
        <input type="text" maxlength="40" id="style-name" name="username" value="">   
        <br>
        <label class="label-styling" for="style-pass">Password:*</label>
        <input type="password" name="pass" id="style-pass" value="">
        <br>     
        <label class="label-styling" for="style-email">Email:*</label>
        <input type="text" name="email" id="style-email" value="">
        <br>
        <label class="label-styling" for="style-fname">Full Name:</label>       
        <input type="text" name="fullName" id="style-fname" value="">
        <br>
        <label class="label-styling" for="style-address">Address:&nbsp;</label>       
        <input type="text" name="address" id="style-address" value="">
        <br>
        <label class="label-styling" for="style-city">City:&nbsp;</label>
        <input type="text" name="city" id="style-city" value="">
        <br>
        <label class="label-styling" for="style-state">State:&nbsp;</label>
        <input type="text" name="state" id="style-state" value="">
        <br>
        <label class="label-styling" for="style-zipCode">Zip Code:&nbsp;</label>     
        <input type="text" name="zipCode" id="style-zipCode" value="">
        <br>
        <br>
        <input type="submit" value="Register" />
        <br>
        <p> * - Required </p>
    </form>
    </div><!--/#format-form-->
   
  </article>   
</section>
</body>
</html>


I'm still working on security issues, but from the reading and testing code I have done so far using prepared PDO statements seems to be the way to go:

I revised my connection string to improve the security:
Code: Select all
<?php
abstract class DBConnect {
    protected static function connect() {
      $db_options = array(
         PDO::ATTR_EMULATE_PREPARES => false                     // important! use actual prepared statements (default: emulate prepared statements)
         , PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION           // throw exceptions on errors (default: stay silent)
         , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC      // fetch associative arrays (default: mixed arrays)
      );       
      $pdo = new PDO('mysql:host=localhost;dbname=cms;charset=utf8', 'root', '******', $db_options);
      return $pdo;
    }   
}


I will be definitely be updating this once I figure out the best security and if anyone can suggest a way to improve it just let me know. Note: Just saying that you should be doing it this way isn't going to cut it, back it up with something other than I read it somewhere on the internet.
User avatar
Strider64
New php-forum User
New php-forum User
 
Posts: 68
Joined: Sat Mar 23, 2013 8:24 am

Re: Two neat member classes

Postby mmogoingjian » Thu Jun 13, 2013 11:05 pm

I want to say press release is the best medium for promoting a new business or any news or products launched by a company or firm.It is a great medium of getting the traffic on a website.If i forget some points about press release please share your views.





_____________________________________________________
Rs Gold
d3 items
mmogoingjian
New php-forum User
New php-forum User
 
Posts: 1
Joined: Thu Jun 13, 2013 11:03 pm

Re: Two neat member classes

Postby Strider64 » Sat Jun 15, 2013 12:49 pm

Code: Select all
echo 'mmogoingjian + galloway8 = jackasses";
User avatar
Strider64
New php-forum User
New php-forum User
 
Posts: 68
Joined: Sat Mar 23, 2013 8:24 am


Return to Your Scripts

Who is online

Users browsing this forum: No registered users and 0 guests

Sponsored by Sitebuilder Web hosting and Traduzioni Italiano Rumeno and antispam for cPanel.