4 Replies - 613 Views - Last Post: 04 November 2012 - 09:26 AM Rate Topic: -----

#1 kiasta  Icon User is offline

  • D.I.C Regular

Reputation: 23
  • View blog
  • Posts: 263
  • Joined: 18-November 07

Error caused by foreach?

Posted 02 November 2012 - 03:11 PM

I am close to finishing my login system but I have come accross a snag and I don't understand what the problem is. I get this error after successfully registering:

Warning: Invalid argument supplied for foreach() in /xxx/xxxx/xxx/xxxxx/user.class.php on line 127


The bit of code in question is this:

user.class.php

public function display_notice($action)
    {
        echo "<h3>";
        foreach ($this -> noticeCode as $element => $value)
        {
            if (!empty ($value))
            {
                switch($action)
                {
                    case 'login': echo "<br>Login: ";new Message($value); break;
                    case 'register': echo "<br>Register: ";new Message($value); break;
                }
            }
        }
        echo '</h3>';
    }


Is there something wrong with that foreach? Here is the entire user_cp.php file where the function is called:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
        <title>xxx</title>
        <!-- Stylesheet -->
        <link rel="stylesheet" type="text/css" href="xxx" />
        <!-- Javascript codes -->
        <script src="xxx" type="text/javascript"></script>
        <script src="xxx" type="text/javascript"></script>
        <script type="text/javascript">
            var FullscreenrOptions = {  width: 1920, height: 1080, bgID: '#bgimg' };
            jQuery.fn.fullscreenr(FullscreenrOptions);
            //Delayed redirect
            function delayer(){
                window.location = "../user_cp.php?action=login";
            }
        </script>
    </head>
<?php
require 'user.inc.php';
global $user;
if(empty($_SESSION['user']))
{
    if (isset ($_GET['action']))
    {
        $action = $_GET['action'];
        switch ($action)
        {
            case 'login':
            {
                echo '<img id="bgimg" src="xxx"></img>';
                echo '<div id="realBody">';
                echo '<div id="login-container">';
                if (isset ($_POST['submit']))
                {
                    $canLogin = $user -> login ($_POST);
                    if (!$canLogin)
                    {
                        $user->form($action);
                        $user->display_notice($action);
                    }
                    else if ($canLogin)
                    {
                        $user->redirect();
                        $user->display_notice($action);
                    }
                }
                else
                {
                    $user->form($action);
                }
                break;
            }
            case 'register':
            {
                echo '<img id="bgimg" src="xxx"></img>';
                echo '<div id="realBody">';
                echo '<div id="register-container">';
                if (isset ($_POST['submit']))
                {
                    $canRegister = $user -> register ($_POST);
                    if (!$canRegister)
                    {
                        $user->form($action);
                        $user->display_notice($action);
                    }
                    else if ($canRegister)
                    {
                        //$user->redirect();
                        $user->display_notice($action);
                    }
                }
                else
                {
                    $user->form($action);
                }
                break;
            }
        }
    }
    else
    {
        echo "<br> User not logged in";
        //$user->redirect();
    }
    echo "</form></div>";
}
else //For testing purposes this check has been removed
{
    $user->display_private();
}
?>
</body>
</html>


I'm able to register, the data is created in the database and everything works like it should, I just get that error when registerign a new user... and do not know why that foreach is causing the issues. If you need more code, let me know because I'm all out of solutions. Thanks in advance for your help.

In case you have questions abotu the Message class here is the code:

message.class.php

<?php

require 'message.inc.php';

class Message
{

    private $message;

    public function __set ($name, $value)
    {
        switch ($name)
        {
            case 'message':
                {
                    if (property_exists ($this, 'message'))
                    {
                        $this -> message = $value;
                    }
                    else
                    {
                        echo "<br> Member does not exist";
                    }
                }
        }
    }

    public function __get ($name)
    {
        switch ($name)
        {
            case 'message':
                {
                    if (isset ($this -> message))
                    {
                        return $this -> message;
                    }
                    else
                    {
                        return NULL;
                    }
                }
        }
    }

    public function __construct ($message)
    {
        /*
         * Error Codes
         * 1 = Can only use Alphanumeric characters in Username
         * 10 = Username too short
         * 11 = Username too long
         * 13 = Username Exists
         * 14 = Username verified
         * 20 = Password too short
         * 21 = Password too long
         * 22 = Passwords do not match
         * 24 = Password Verified
         * 30 = Email is too short
         * 32 = E-mails do not match
         * 33 = E-mail Exists
         * 34 = E-mail Verified
         * 45 = Registration Successful
         * 46 = Registration Failed
         * 55 = Login Successful
         * 56 = Login Failed
         * 67 = Empty Fields
         * 9005 = Unidentified Error
         * ?? = Unknown Error
         */

        switch ($message)
        {
            case INV_USER: $this -> message = "You can only use alphanumeric characters in your username (a-z, 0-9).";
                break;
            case SHORT_USER: $this -> message = "Username needs to be 4 characters or longer.";
                break;
            case LONG_USER: $this -> message = "Username can not exceed 15 characters.";
                break;
            case EXISTS_USER: $this -> message = "Username already exists.";
                break;
            case VER_USER: $this -> message = "Username has been verified.";
                break;
            case SHORT_PASS: $this -> message = "Password needs to be 6 characters or longer.";
                break;
            case LONG_PASS: $this -> message = "Password can not exceed 30 characters.";
                break;
            case MATCH_PASS: $this -> message = "Passwords do not match.";
                break;
            case VER_PASS: $this -> message = "Password has been verified.";
                break;
            case SHORT_EMAIL: $this -> message = "E-mail is too short.";
                break;
            case MATCH_EMAIL: $this -> message = "E-mails do not match.";
                break;
            case EXISTS_EMAIL: $this -> message = "E-mail already exists.";
                break;
            case VER_EMAIL: $this -> message = "E-mail has been verified.";
                break;
            case LOGIN_SUCCESS: $this -> message = "Login was successful";
                break;
            case LOGIN_FAILED: $this -> message = "Login was unsuccessful, please check your credentials and try again.";
                break;
            case REG_SUCCESS: $this -> message = "Registration was successful";
                break;
            case REG_FAILED: $this -> message = "Registration was unseccessful, please check your credentials and try again.";
                break;
            case EMPTY_FIELD: $this -> message = "There are one or more empty fields, please check your credentials and try again.";
                break;
            case UNI_ERROR: $this -> message = "Unidentified Error";
                break;
            default: $this -> message = "Unknown Error";
                break;
        }
    }

    public function __destruct ()
    {
        echo $this -> get_message ();
    }

    public function get_message ()
    {
        return "<br> " . $this -> message;
    }

}

?>



message.inc.php

<?php

//define message() constants
define (INV_USER, 1);
define (SHORT_USER, 10);
define (LONG_USER, 11);
define (EXISTS_USER, 13);
define (VER_USER, 14);
define (SHORT_PASS, 20);
define (LONG_PASS, 21);
define (MATCH_PASS, 22);
define (VER_PASS, 24);
define (SHORT_EMAIL, 30);
define (MATCH_EMAIL, 32);
define (EXISTS_EMAIL, 33);
define (VER_EMAIL, 34);
define (REG_SUCCESS, 45);
define (REG_FAILED, 46);
define (LOGIN_SUCCESS, 55);
define (LOGIN_FAILED, 56);
define (EMPTY_FIELD, 67);
define (UNI_ERROR, 9005);
//define DEBUG mode
define (DEBUG, true);

?>



Is This A Good Question/Topic? 0
  • +

Replies To: Error caused by foreach?

#2 Martyr2  Icon User is offline

  • Programming Theoretician
  • member icon

Reputation: 4405
  • View blog
  • Posts: 12,262
  • Joined: 18-April 07

Re: Error caused by foreach?

Posted 02 November 2012 - 04:25 PM

Figures you would show everything but the actual relevant code. We need to see your "User" class where I believe you have defined your display_notice() function. I believe your $this->noticeCode is not actually an array. Foreach requires the format foreach(array as key => value) If noticeCode is not an array, that would be your issue right there.

:)
Was This Post Helpful? 2
  • +
  • -

#3 kiasta  Icon User is offline

  • D.I.C Regular

Reputation: 23
  • View blog
  • Posts: 263
  • Joined: 18-November 07

Re: Error caused by foreach?

Posted 02 November 2012 - 05:47 PM

View PostMartyr2, on 02 November 2012 - 07:25 PM, said:

Figures you would show everything but the actual relevant code. We need to see your "User" class where I believe you have defined your display_notice() function. I believe your $this->noticeCode is not actually an array. Foreach requires the format foreach(array as key => value) If noticeCode is not an array, that would be your issue right there.

:)


Sorry about that, here is the full user.class.php file:

<?php

class User
{
    public $noticeCode;
    private $loginData;
    private $registerData;
    private $statement;

    public function set_array ($member, $element, $value)
    {
        switch ($member)
        {
            case 'loginData':
                {
                    if (property_exists ($this, 'loginData'))
                    {
                        $this -> loginData[$element] = $value;
                    }
                    else
                    {
                        echo "<br> Member does not exist";
                    }
                    break;
                }
            case 'registerData':
                {
                    if (property_exists ($this, 'registerData'))
                    {
                        $this -> registerData[$element] = $value;
                    }
                    else
                    {
                        echo "<br> Member does not exist";
                    }
                    break;
                }
        }
    }

    public function get_array ($member, $element)
    {
        switch ($member)
        {
            case 'loginData':
                {
                    if (isset ($this -> loginData[$element]))
                    {
                        return $this -> loginData[$element];
                    }
                    else
                    {
                        return NULL;
                    }
                    break;
                }
            case 'registerData':
                {
                    if (isset ($this -> registerData[$element]))
                    {
                        return $this -> registerData[$element];
                    }
                    else
                    {
                        return NULL;
                    }
                    break;
                }
        }
    }

    public function __construct ()
    {
        /* Prevents Javascript from reading SESSION cookies */
        ini_set ('session.cookie_httponly', true);
        /* Check if last session is from the same pc */
        if (!isset ($_SESSION['last_ip']))
        {
            $_SESSION['last_ip'] = $_SERVER['REMOTE_ADDR'];
        }
        if ($_SESSION['last_ip'] !== $_SERVER['REMOTE_ADDR'])
        {
            /* Clear the SESSION */
            $_SESSION = array ();
            /* Destroy the SESSION */
            session_unset ();
            session_destroy ();
        }
        require_once("user.inc.php");
    }

    public function redirect()
    {
        echo '<body onload="setTimeout(\'delayer()\', 2500)">';
    }

    public function form($action)
    {
        switch($action)
        {
            case 'login':
            {
                echo '<h1>LOGIN</h1><br>';
                echo '<form name="login" action="user_cp.php?action=login" method="post">';
                echo 'Username: <input type="text" name="username" /><br>';
                echo 'Password: <input type="password" name="password" /><br>';
                echo '<input type="submit" name = "submit" value="Login" />';
                break;
            }
            case 'register':
            {
                echo '<h1>REGISTER</h1><br>';
                echo '<form name="register" action="user_cp.php?action=register" method="post">';
                echo 'Username: <input type="text" name="username" value="xxx" /><br>';
                echo 'Password: <input type="password" name="password" value="xxx" /><br>';
                echo 'Verify Password: <input type="password" name="password2" value="xxx" /><br>';
                echo 'E-mail: <input type="text" name="email" value="xxx" /><br>';
                echo 'Verify E-mail: <input type="text" name="email2" value="xxx" /><br>';
                echo '<input type="submit" name = "submit" value="Register" />';
            }
        }
    }

    public function display_notice($action)
    {
        echo "<h3>";
        foreach ($this -> noticeCode as $element => $value)
        {
            if (!empty ($value))
            {
                switch($action)
                {
                    case 'login': echo "<br>Login: ";new Message($value); break;
                    case 'register': echo "<br>Register: ";new Message($value); break;
                }
            }
        }
        echo '</h3>';
    }

    public function display_private()
    {
        echo '<body>';
        echo '<img id="bgimg" src="xxx"></img>';
        echo '<div id="realBody">';
        echo '<div id="user_cp-container">';
        echo '<h3> You are logged in!</h3>';
        echo "</form></div>";
    }

    private function salt($action)
    {
        switch($action)
        {
            case 'login': $this->loginData['salt'] = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647)); break;
            case 'register': $this->registerData['salt'] = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647)); break;
        }
    }

    private function hash($action)
    {
        switch($action)
        {
            case 'login':
            {
                $this->salt('login');
                for ($round = 0; $round < 65536; $round++)
                {
                    $this->loginData['hash'] = hash('sha512', $this->loginData['password'] . $this->loginData['salt']);
                }
                break;
            }
            case 'register':
            {
                $this->salt('register');
                for ($round = 0; $round < 65536; $round++)
                {
                    $this->registerData['hash'] = hash('sha512', $this->registerData['password'] . $this->registerData['salt']);
                }
                break;
            }
        }
    }

    private function validate($action)
    {
        global $database;
        switch($action)
        {
            case 'login':
            {
                $query = "
                        SELECT
                            id,
                            username,
                            password,
                            salt,
                            email
                        FROM users
                        WHERE
                            username = :username
                ";
                $queryParams = array (
                    ':username' => $this->loginData['username']
                );
                try
                {
                    $this -> statement = $database -> prepare ($query);
                    $this -> statement -> execute ($queryParams);
                }
                catch (PDOException $ex)
                {
                    echo $ex -> getMessage ();
                    $this -> noticeCode['login'] = LOGIN_FAILED;
                    return false;
                }
                $row = $this->statement->fetch();
                if ($row)
                {
                    return $row;
                }
                else
                {
                    return false;
                }
                break;
            }
            case 'register':
            {
               /******************************************
                * CHECK IF CREDENTIALS FOLLOW GUIDELINES *
                ******************************************/

                //CHECK EMAIL
                if(!filter_var($this->registerData['email'], FILTER_VALIDATE_EMAIL))
                {
                    $this -> noticeCode['email'] = INV_EMAIL;
                }
                //CHECK USERNAME
                $count = mb_strlen ($this->registerData['username'], 'UTF-8');
                if (!ctype_alnum ($this->registerData['username']))
                {
                    $this -> noticeCode['username'] = INV_USER;
                }
                else if ($count < 4)
                {
                    //echo "<br>validate_registration: registerData['username']=".$this->registerData['username'];
                    $this -> noticeCode['username'] = SHORT_USER;
                }
                else if ($count > 15)
                {
                    $this -> noticeCode['username'] = LONG_USER;
                }
                //CHECK PASSWORD
                $count = mb_strlen ($this->registerData['password'], 'UTF-8');
                if ($count < 6)
                {
                    $this -> noticeCode['password'] = SHORT_PASS;
                }
                else if ($count > 30)
                {
                    $this -> noticeCode['password'] = LONG_PASS;
                }
                if (!empty ($this -> noticeCode))
                {
                    return false;
                }

               /****************************************************
                * VERIFY USERNAME WITH DATABASE, UNIQUE USERS ONLY *
                ****************************************************/

                $query = "
                    SELECT
                        1
                    FROM users
                    WHERE
                        username = :username
                ";

                $query_params = array(
                    ':username' => $this->registerData['username']
                );

                try
                {
                    $this -> statement = $database->prepare($query);
                    $this -> statement->execute($query_params);
                }
                catch(PDOException $ex)
                {
                    echo $ex -> getMessage ();
                    $this -> noticeCode['register'] = REG_FAILED;
                    return false;
                }

                $row = $this->statement->fetch();

                if($row)
                {
                    $this -> noticeCode['username'] = EXISTS_USER;
                    return false;
                }

               /**************************************************
                * VERIFY EMAIL WITH DATABASE, UNIQUE EMAILS ONLY *
                **************************************************/

                $query = "
                    SELECT
                        1
                    FROM users
                    WHERE
                        email = :email
                ";

                $query_params = array(
                    ':email' => $this->registerData['email']
                );

                try
                {
                    $this -> statement = $database->prepare($query);
                    $this -> statement->execute($query_params);
                }
                catch(PDOException $ex)
                {
                    echo $ex -> getMessage ();
                    $this -> noticeCode['register'] = REG_FAILED;
                    return $regSuccess;
                }
                $row = $this->statement->fetch();

                if($row)
                {
                    $this -> noticeCode['email'] = EXIST_EMAIL;
                    return false;
                }
                if (empty ($this->noticeCode))
                {
                    return true;
                }
                else
                {
                    return false;
                }
                break;
            }
        }
    }

    public function login ($post)
    {
        global $database;
        if (!empty ($post))
        {
            foreach ($post as $element => $value)
            {
                if ($element != 'submit')
                {
                    echo "<br>loginData['$element'] = '$value'";
                    $this -> loginData[$element] = $value;
                }
            }
            if (!empty ($this -> loginData['username']) && !empty ($this -> loginData['password']))
            {
                $loginOK                     = false;
                $row                         = $this -> validate('login');
                if ($row)
                {
                    $this->hash('login');

                    if ($this->loginData['hash'] === $row['password'])
                    {
                        $loginOK = true;
                    }
                }
                if ($loginOK)
                {
                    unset ($row['salt']);
                    unset ($row['password']);
                    $_SESSION['user'] = $row;
                    return true;
                }
            }
            else
            {
                $this -> noticeCode['login'] = EMPTY_FIELD;
                return false;
            }
        }
    }

    public function register ($post)
    {
        global $database;
        $regSuccess = false;
        if (!empty ($post))
        {
            foreach ($post as $element => $value)
            {
                if ($element != 'submit')
                {
                    echo "<br>registerData['$element'] = '$value'";
                    $this -> registerData[$element] = $value;
                }
            }

           /**************************************
            * CHECK IF PASSWORD AND EMAILS MATCH *
            **************************************/

            if ($this -> registerData['password'] == $this -> registerData['password2'] && $this -> registerData['email'] ==
                    $this -> registerData['email2'])
            {
                /*DETERMINES IF USER CAN REGISTER DATA ENTERED*/
                $canRegister = $this->  validate('register');

               /************************************************************
                * INSERT DATA TO DATABASE, USING PDO STRUCTURED STATEMENTS *
                ************************************************************/
                if ($canRegister)
                {
                    $query = "
                        INSERT INTO users (
                            username,
                            password,
                            salt,
                            email
                        ) VALUES (
                            :username,
                            :password,
                            :salt,
                            :email
                        )
                    ";
                    /*GENERATE PASSWORD HASH AND ASSIGN VALUE TO "registerData" ARRAY*/
                    $this->hash('register');
                    $query_params = array(
                            ':username' => $this->registerData['username'],
                            ':password' => $this->registerData['hash'],
                            ':salt' => $this->registerData['salt'],
                            ':email' => $this->registerData['email']
                    );
                    try
                    {
                        $this->statement = $database->prepare($query);
                        $this->statement->execute($query_params);
                    }
                    catch(PDOException $ex)
                    {
                        echo $ex -> getMessage ();
                        $this -> noticeCode['register'] = REG_FAILED;
                        return $regSuccess;
                    }
                    $regSuccess = true;
                    return $regSuccess;
                }
                else
                {
                    return $regSuccess;
                }
            }
            else
            {
                if ($this -> registerData['password'] != $this -> registerData['password2'])
                {
                    $this -> noticeCode['password'] = MATCH_PASS;
                }
                if ($this -> registerData['email'] != $this -> registerData['email2'])
                {
                    $this -> noticeCode['email'] = MATCH_EMAIL;
                }
                return $regSuccess;
            }
        }
        else
        {
            $this -> noticeCode['register'] = EMPTY_FIELD;
            return $regSuccess;
        }
    }
}

?>



I will add an
=array()
to see if that helps. Thanks Martyr.

*edit* I didn't realize I needed to explicitely initialize the variable as array. I'll know that for next time. That did the trick though, thanks.

This post has been edited by kiasta: 02 November 2012 - 05:52 PM

Was This Post Helpful? 0
  • +
  • -

#4 Jstall  Icon User is offline

  • Lurker
  • member icon

Reputation: 434
  • View blog
  • Posts: 1,042
  • Joined: 08-March 09

Re: Error caused by foreach?

Posted 03 November 2012 - 07:46 AM

View PostMartyr2, on 02 November 2012 - 10:25 PM, said:

I believe your $this->noticeCode is not actually an array. Foreach requires the format foreach(array as key => value) If noticeCode is not an array, that would be your issue right there.

:)


Actually foreach just requires an object that implements the traversable interface :) , although of course it most commonly used with arrays.



@op
It looks like you use $noticeCode as an array in your validate() method but you don't set it as an array any time before that. So, you should either make sure validate is called before and/or instantiate $noticeCode as an array in your constructor:
$this->noticeCode = array();



I would do the latter at the very least, the constructor is, in part, meant to be used for assigning property values and , in my opinion, it helps make the code more readable thus more maintainable.

Hope this helps :)
Was This Post Helpful? 1
  • +
  • -

#5 kiasta  Icon User is offline

  • D.I.C Regular

Reputation: 23
  • View blog
  • Posts: 263
  • Joined: 18-November 07

Re: Error caused by foreach?

Posted 04 November 2012 - 09:26 AM

View PostJstall, on 03 November 2012 - 10:46 AM, said:

View PostMartyr2, on 02 November 2012 - 10:25 PM, said:

I believe your $this->noticeCode is not actually an array. Foreach requires the format foreach(array as key => value) If noticeCode is not an array, that would be your issue right there.

:)


Actually foreach just requires an object that implements the traversable interface :) , although of course it most commonly used with arrays.



@op
It looks like you use $noticeCode as an array in your validate() method but you don't set it as an array any time before that. So, you should either make sure validate is called before and/or instantiate $noticeCode as an array in your constructor:
$this->noticeCode = array();



I would do the latter at the very least, the constructor is, in part, meant to be used for assigning property values and , in my opinion, it helps make the code more readable thus more maintainable.

Hope this helps :)


That helped, i initialized it in the constructor, and everything works fine. Thanks.

I'm using my mobile and it doesnt show who's quoting who but thanks to you both :)

This post has been edited by kiasta: 04 November 2012 - 09:27 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1