How can i do this? Login code

Hey,

I have successfully managed to get my login code working (Recently switched from php4 to php5, as my company wanted to move forward :))

Anyway, I have one final problem. I am enabling normal users to login which is fine, but i need to check for admin users. So the way i am doing this is, i have a members table and i will have a type column saying “admin” or “normal” depending on the user privilege.

Anyway in php4 i did this:

if($row['type'] == "admin")
{
$_SESSION['normalUser'] = $row['username'];
}else{
$_SESSION['adminUser'] = $row['username'];
}

Or something like that anyway…

Now i have this code, apologies in advance as there is write a bit of code :slight_smile:

Models/database.class.php



<?php
require_once('Person.class.php');

class Database {
    protected $mysqli;

    public function sanitise($data) { // Escapes parameters before sending SQL query
        foreach($data as $key => $value){
            $data[$key] = $this->mysqli->real_escape_string($value);
        }
        return $data;
    }

    public function __construct($host, $username, $password, $dbname) {
        $this->mysqli = new mysqli($host, $username, $password, $dbname);
        if ($this->mysqli->errno){
            echo 'Unable to connect'.$this->mysqli->error;
            exit();
        }
    }

    public function login($username, $password) { // Login
        $data = $this->sanitise(array('email'=>$username, 'password'=>$password));
        $sql = 'SELECT * FROM hussaini_members
            WHERE email = \\''.$data['email'].'\\' AND password = \\''.$data['password'].'\\'';
        $results = $this->mysqli->query($sql);
        $personArray = array();
        while($row = $results->fetch_array(MYSQLI_ASSOC)) {
            $personArray[] =  new Person($row);
        }
        return $personArray;
    }

    public function __destruct() {
        $this->mysqli->close();
    }
}

Person.class is just a class which uses getter’s to retrieve user details. Anyway in my login.php i have this code:


require_once('Models/Database.class.php');
$database = new Database('localhost', '****', '', '****');
session_start();

$message = "";

  if(isset($_POST['submit']))
  {
    $personArray = $database->login($_POST['email'], $_POST['password']);
    if(sizeof($personArray) == 1) {
      $_SESSION['normalUser'] = $personArray[0];
      $_SESSION['loggedin'] = true;
      $message = "";
      header ("Location: homepage");
    }
    else {
      $message = "<span style=\\"color:#00cc00\\">Invalid user credentials.</span>";
    }
  }

Now how can i check to see if the type row is “admin” or “normal” and THEN set the session to either “normalUser” OR “adminUser” ?

I would really appreciate if anyone can help me out with this…

Thanks

You seem to create a Person object which in the end gets put into the $_SESSION[normalUser] variable.

The Person object is created on the base of the fetched row info from the database. So your distinction should be done inside this person object.

One of the many ways:


if(isset($_POST['submit'])) {

    $personArray = $database->login($_POST['email'], $_POST['password']);
    if (sizeof($personArray) == 0) {
        $message = "<span style=\\"color:#00cc00\\">Invalid user credentials.</span>";

    } elseif (sizeof($personArray) == 1) {

          $person = $personArray[0];

          if ($person->has_admin_power()) {
              $_SESSION['adminUser']  = $person;
          } else {
              $_SESSION['normalUser'] = $person;
          }

          $_SESSION['loggedin'] = true;
          $message                    = "";

          header ("Location: homepage");

    } else {

          $message = "<span style=\\"color:#00cc00\\">Inpossible Error happend.  The end of the universe as you know it is near</span>";

    }
} 

Of you could just have a $_SESSION[‘user’] and don’t care about the priveliges on login but later on. by just checking if ($person->has_admin_power()) {}

after this line


    if(sizeof($personArray) == 1) {

temporarily dump the db result set and take a look at its’ content.


var_dump( $personArray[0]  );

and that should tell you what conditional code to put there, but I’d guess you need to do something similar to what you had previously.


if($personArray[0]['type'] == "admin") {
//do stuff
}

Edit:

Ah, beaten to it, yes I’d agree get your class to do a bit more work - even though it seems to know a bit too much for its own good to be honest. Im a bit bemused by the sanitize function, isnt mysqli like PDO in that it uses prepared statements?

Hey,

would i need to create the has_admin_power() function in my database.class?

Would this function be a simple select where type = “admin”?

P.S. I am only new to php5 and OOP so thanks for pointing that out about the sanitize function. I have actually been attending advanced php classes to enhance my current php skills, the developers there said it’s better to have the escape string in a function instead of using it again and again, if you know what i mean :slight_smile:

I’m trying to become familiar with MVC structure as most developers use this now?

Something like that should be done in the Person class.
In this line you are creating the object:


$personArray[] =  new Person($row);

So somewhere in your code you have a


class Person
{

     public function __construct($person_info)
    {
         /* code */
    }

   /* code */

}

The has_admin_power() function should go in this class.


class Person
{

     public function __construct($person_info)
    {

        /* code */
        $this->_type = $person_info['type'];

    }

    public function has_admin_power()
    {
        return ($this->_type  == 'admin') ? true : false;
    }

    /* code */
}

Wow, how did you know my class would be exactly like that? :eek:

I think i have it working, but i cant seem to test it, this is my person class:


<?php

class Person {
    public $id, $email, $password, $forename, $surname, $address, $postcode, $date_added, $type;

    public function __construct($dbrow) {
        $this->id = $dbrow['ID'];
        $this->email = $dbrow['email'];
        $this->password = $dbrow['password'];
        $this->forename = $dbrow['forename'];
        $this->surname = $dbrow['surname'];
        $this->address = $dbrow['address'];
        $this->postcode = $dbrow['postcode'];
        $this->date_added = $dbrow['date_added'];
        $this->type = $dbrow['type'];
    }

    public function getId(){
        return $this->id;
    }

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

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

    public function getForename(){
        return $this->forename;
    }

    public function getSurname(){
        return $this->surname;
    }

        public function getAddress(){
        return $this->address;
    }

    public function getPostcode(){
        return $this->postcode;
    }

    public function getDateAdded(){
        return $this->date_added;
    }

    public function has_admin_power()
    {
        return ($this->_type  == 'admin') ? true : false;
    }
}

This is the login.php code:


<?php
$view->pageTitle = 'Login';
require_once('Models/Authenticate.class.php');
$login = new Authenticate('localhost', '****', '', '****');
session_start();

$message = "";

if(isset($_POST['submit'])) {
    $personArray = $login->login($_POST['email'], $_POST['password']);
    if (sizeof($personArray) == 0) {
        $message = "<span style=\\"color:#00cc00\\">Invalid user credentials.</span>";
    } elseif (sizeof($personArray) == 1) {
          $person = $personArray[0];
          if ($person->has_admin_power()) {
              $_SESSION['adminUser']  = $person;
          } else {
              $_SESSION['normalUser'] = $person;
          }
          $_SESSION['loggedin'] = true;
          $message = "";
          header ("Location: homepage");
    } else {
          $message = "<span style=\\"color:#00cc00\\">Impossible Error happend.  The end of the universe as you know it is near</span>";
    }
}

And then when i try to test:


                    <?php if (isset($_SESSION['normalUser'])) { ?>
                    <p>You are logged in as <strong> <?php echo $_SESSION['normalUser']->getForename();?> </strong></p>
                    <p><a href="logout">Log Out</a> | <a href="">My Account</a> | <a href="">Shopping Cart</a> | <a href="">Checkout</a></p>
                    <?php } else if (isset($_SESSION['adminUser'])){ ?>
                    <p>You are logged in as <strong> administrator </strong></p>
                    <p><a href="logout">Log Out</a> | <a href="">Manage site</a></p>
                    <?php } else { ?>
                    <p>Welcome <strong>Guest</strong>, you are not logged in. <a href="login">Login</a> or <a href="register">Register</a> now.</p>
                    <?php } ?>

When i login as admin it still returns the name (getForename()) which it shouldn’t do. It should say :

You are logged in as <strong> administrator </strong>

Have i missed something out?

It’s just now recognising that an admin user is logged in, it always assumes it’s a normal user… so this means it does not check for type “admin”??

I have the habbit of starting my private variables in a class with an underscore.
You didn’t do that, so you are checking a variable that doesn’t exist in you has_admin_power method.


    public function has_admin_power()
    {
        return ($this->_type  == 'admin') ? true : false;
    }

should be:


    public function has_admin_power()
    {
        return ($this->type  == 'admin') ? true : false;
    }

Off Topic:

So I didn’t know exactly how your class looked like :wink:
I came close because it just was a logical step looking at th erest of your code :slight_smile:

Thanks, thats worked perfectly.

One final thing i wanted to ask, as i am new to this approach i don’t know what is the best way of building a big site, in terms of common practice.

Now as you may already have guessed i am building an e-commerce website, now when i do a SELECT i am always returning am array like so:


    public function selectCategory() {
        $sql = 'SELECT * FROM hussaini_categories';
        $results = $this->mysqli->query($sql);
        $categoryArray = array();
        while($row = $results->fetch_array(MYSQLI_ASSOC)) {
            $categoryArray[] =  new Category($row);
        }
        return $categoryArray;
    }

then i have a category class just the same as the person class which returns all the rows. So i can see now that for every table i have in my database i will have a separate class which gets all the rows? So far i have a Person, Category and Items class.

I know i will have more tables, so does this mean a separate class every time? Is this a good idea?

Or is there an alternative way to do this? Not having to make a class at all and do everything in the function?

Which way is best?

Let’s say i don’t want to do this:


 $categoryArray = array();
        while($row = $results->fetch_array(MYSQLI_ASSOC)) {
            $categoryArray[] =  new Category($row);
        }
        return $categoryArray;

Is there a simpler way? Please can you offer any advice?

Thanks

I don’t have enough experience in that last question of yours. Someone else will need to help you with that.

Looking at the idea behind OOp I would say that Everything that could be concidered an object in real life, should be an object/class in your code.
So looking that Person, Item, and Category are object in real life, they should be objects in your code…

But wait for some more experienced answer please, don’t want to put you in the wrong direction :wink:

No worries, i appreciate your honesty and help. Thats hy this forum is one of the best! :slight_smile:

So can anyone answer this question then? :slight_smile:

I would really appreciate it.

Thanks

I divide each domain level entity into separate data access objects. The primary advantages are well organized, flexible and reusable code to access information. The primary disadvantages is no-automation (you write the SQL pure simple) and SQL repetition of similar SQL operations that require a different domain interface. Even so this may be the case I’ve found in a production environment for this method to be most practical and extensible.


class DAOCategory {
	
	/*
	* Retrieve all categories
	*/
	public function fetchCategories() {
	
	}

}

class DAOUser {
	
	/*
	* Authenticate a user
	*/
	public function authenticate($username,$password) {
	}

}

class DAOProduct {
	
	/*
	* Get individual product information
	*/
	public function fetchProduct($id) {
	}

}

The only tricky part here is when your overlapping entities, such as all products with their categories. In that case the DAO which is responsible for retrieving such information is generally the one which makes most sense.

So determining whether a user should be logged in would now be as simple as the below code.


$objDAOUser = new DAOUser();

if($objDAOUser->authenticate('person','password') === true) {
	// do authenticated actions
} else {
	// do unauthenticated actions
}

OK, so would you suggest having one file let say classes.php, and within that having all the classes and functions i need?

So for example the code you have provided, will this all be within the one file? In my situation i currently Select Categories, Register users, and a Login…

Billy

Each data access layer would be placed in a separate file ideally all under the same directory such as; DAO. Others will do it differently but that is what I’m accustom to.