Hey guys..

I will try this again later but yesterday i was delighted to get my implode to work for my second table named memberships but only temporary. For some reason, it has stopped inserting my information into this table but does only insert into my users table. I will post the code later because i am not on my pc but just thought that you might have some ideas? I have checked my sql query and i have got the correct number of values... this is pulling my head..

    but for some reason, I didn't get any error messages... Here is my code...

    <?php


    if (!isset($_POST['submit'])) {
    header("Location: ../signup.php");
    exit();
    } else {


       include_once 'dbh.php';
    
       // information from users table
    
       $first = $_POST['first'];
       $last = $_POST['last'];
       $email = $_POST['email'] ;
       $uid = $_POST['uid'];
       $password = $_POST['pwd'];
       $user_permission = 'Standard User';
       $freelesson = $_POST['freelesson'];
       $datejoined = date('Y-m-d H:i:s', strtotime('+1 day'));
       $user_activate = 0;
       $premium = 0;
    
    
    
      // information from memberships table
    
        
       $subscriptionplan = $_POST['subscriptionplan'];
       
      
       $subscriptionplandate = date('Y-m-d H:i:s', strtotime('+1 day'));
       $subscriptionplandate2 = date('Y-m-d H:i:s', strtotime('+1 day'));
       $subscriptionplandate3 = date('Y-m-d H:i:s', strtotime('+1 day'));
       $fees =  0;
       $fees2 = 0;
       $fees3 = 0;
       $totalfees = 0;
       $paid = 0;
       $paid2 = 0;
       $paid3 = 0;
       $expirydate = date('Y-m-d H:i:s', strtotime('+1 day'));
       $expirydate2 = date('Y-m-d H:i:s', strtotime('+1 day'));
       $expirydate3 = date('Y-m-d H:i:s', strtotime('+1 day'));
       $paidbydate = date('Y-m-d H:i:s', strtotime('+1 day'));
       $paidbydate2 = date('Y-m-d H:i:s', strtotime('+1 day'));
       $paidbydate3 =  date('Y-m-d H:i:s', strtotime('+1 day'));
       $overdue = 0;
       $overdue2 = 0;
       $overdue3 = 0;
       
      // $fees = mysqli_real_escape_string($conn, $_POST['fees']);
      // $totalfees = mysqli_real_escape_string($conn, $_POST['totalfees']);
       
      
       
       $activate =  0;
       
      
       //Error handlers...
    
       if (empty($first) || empty($last) || empty($email) || empty($uid)|| empty($password)) {
       	   header("Location: ../signup.php?signup=empty");
       	   exit();
       } else {
          //Check if input characters are valid
       	    if (!preg_match("/^[a-zA-Z]*$/", $first) || !preg_match("/^[a-zA-Z]*$/", $last)) {
                header("Location: ../signup.php?signup=invalid");
                exit();
       	    } else {
       	    	
       	    	//Checking for valid emails
                 if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
                     header("Location: ../signup.php?signup=email");
                     exit();
                 } else {
                   if (Strlen($password) < 5) {
                   header("Location: ../signup.php?signup=invalidlength");
                   exit();
                   } else {
                      if (!preg_match('/^(?=.*\d)(?=.*[A-Za-z])[0-9A-Za-z!@#$%]{8,20}$/', $password)) {
                       header ("Location: ../signup.php?signup=notalphanumeric");
                       exit();
                      } else {
                      	
                      		
    
                      		
    
                           
                      $sql = "SELECT * FROM users WHERE user_uid = ?;";
                      // Create a prepared statement
                      $stmt = mysqli_stmt_init($conn);
                      //Prepare the prepared stement
    
                      if (!mysqli_stmt_prepare($stmt, $sql)) {
                         echo "SQL statement failed";
    
                      } else {
                      	   //Bind parameters to the placeholder
                      	mysqli_stmt_bind_param($stmt, "s", $uid);
                      }
    
                      
                      if($resultCheck > 0) {
                         header("Location: ../signup.php?signup=usertaken");
                         exit();
                      } else {
    
                    
    							
                                           
    									
    						            
                            
    
    
    
           // Select subscription 
    
          
    
    
                                     
       
    
                         // Supply a random generated token for email activation
                        
    
                      	$token = 'qqewreqreqwsdfdfdafcbvcQERFGHFGHGFHRETERTDF!@#$%^^()';
                      	$token = str_shuffle($token);
                      	$token = substr($token, 0, 10);
    
                      	$token2 = 'qqewreqreqwsdfdfdafcbvcQERFGHFGHGFHRETERTDF!@#$%^^()';
                        $token2 = str_shuffle($token2);
                      	$token2 = substr($token2, 0, 10);
                        $paid = 0;
                      	
                      	$activate = 0;
    
                      	//Hashing the password
                      	$hashedPwd = password_hash($password, PASSWORD_DEFAULT);
                      	//Insert the user into the database
                      	$sql ="INSERT INTO users (user_first, user_last, user_email, user_uid, user_password, user_permission, freelesson, datejoined, user_token, user_activate, premium) VALUES (?,?,?,?,?,?,?,?,?,?,?);";
    
                      	$stmt = mysqli_stmt_init($conn);
                      	if(!mysqli_stmt_prepare($stmt, $sql)) {
                      		 echo "SQL error";
                      	} else {
                      		mysqli_stmt_bind_param($stmt, "sssssssssss", $first, $last, $email, $uid, $hashedPwd, $user_permission, $freelesson,$datejoined, $token, $user_activate, $premium);
                      	  mysqli_stmt_execute($stmt);
                      	}
    
                       // insert into user_lessonsubscription table
    
                       
                       
                         
                       
    
                          
                     
    
                   // $subscriptionplan  = implode(',',$subscriptionplan);
    
                        
                        
                       
                  
    
                      $sql ="INSERT INTO memberships (user_uid, subscriptionplandate, subscriptionplandate2, subscriptionplandate3, fees, fees2, fees3, totalfees, paid, paid2, paid3, expirydate, expirydate2, expirydate3, paidbydate, paidbydate2, paidbydate3, overdue, overdue2, overdue3, token, activate) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
    
                      $stmt = mysqli_stmt_init($conn);
                      	if(!mysqli_stmt_prepare($stmt, $sql)) {
                      		 echo "SQL error";
                      	} else {
                      		mysqli_stmt_bind_param($stmt, "sssssssssssssssssssssss", $uid, $subscriptionplandate, $subscriptionplandate2, $subscriptionplandate3, $fees, $fees2, $fees3, $totalfees, $paid, $paid2, $paid3, $expirydate, $expirydate2, $expirydate3, $paidbydate, $paidbydate2, $paidbydate3, $overdue, $overdue2, $overdue3, $token2, $activate);
                      	  mysqli_stmt_execute($stmt);
                      	}
    
                      
    
    
                        // Send an email to the user:
                        $company = "pianocourse101@hotmail.com";
                        $subject = "Activate your email account";
                        $mailTo = "piano0011@hotmail.com";
                        $headers = "From: ".$company;
                       $txt = "Thank you for registering with pianocourse101! At pianocourse101, your child can now learn how to play the piano right from the comfort of your own home! \n\nOur lessons are based from the Bastien Piano Basics series because it is both fun and educational for your child. \n\nHowever, you must activate your FREE membership account by clicking on the link below: \n\n http://localhost/loginsystem/includes/activate.php?email=".$mailTo."&activatetoken=".$token."" ;
    
                        mail($mailTo, $subject, $txt, $headers);
                        
    
    
    
    
    
                      	header("Location: ../signup.php?signup=success");
                      	exit();
                        }
                 }
             }
         }
     
       }
      }
    }



      Hmm... I think you need to work on these areas first:

      Break up your code into functions that do one thing and do it well
      Presently, your code is in one long stanza, but in fact it is comprised of quite a few different parts, some of which have been described by comments (e.g., "Error handlers", "Select subscription", "Send an email to the user"). Instead of just commenting, move the relevant code into a well named function of its own. This way, you reduce the context for that part, making it easier to analyse the correct for correctness since for the most part you only need to think about the variables local to the scope of the function. Furthermore, if the same/similiar piece of code is used multiple times in ways that cannot be replaced by moving it into a loop, you could move it into a function and hence call the function multiple times instead of repeating the piece of code. This is the DRY principle: Don't Repeat Yourself.

      Normalise your database
      This is a big topic on its own, but one obvious thing is that generally, database tables shouldn't have numbered fields. So, instead of having "subscriptionplandate, subscriptionplandate2, subscriptionplandate3", perhaps you should have a subscriptions table, then link that to the memberships table through the use of a foreign key. It looks like quite a few other numbered fields should also be moved to this subscriptions table.

      Check the return value of functions that are called, unless they are designed to returning nothing but instead throw an exception on failure
      You did that sometimes, but you missed out mysqli_stmt_execute and mail.

        You need to greatly simplify the logic. You have far too much implementation logic, so its hard to see what the code is trying to accomplish (cannot see the forest for the trees problem.)

        See the following -

        1) You need to put the form and the form processing code on the same page (the processing code would be above the form.) This will simplify a lot of the logic and you can then re-populate the form fields when there is a validation error so that user doesn't need to keep reentering the same data, which will increase the chance of a typo. This will also eliminate the redirects back to the signup page and let you validate all the inputs at once.

        2) Don't create variables without a good reason and don't copy variables to other variables without a good reason. Programming shouldn't give you carpal tunnel syndrome, typing out line after line of code that's not needed. The literal (default) values that will be used in a query, should either be set up as defaults in the database table definition or the literal values should be put directly into the sql query statement. Things that are configuration values, such as some of the mail values, that could change if the code is re-used, should be variables or defined constants. The only time you should copy variables to other variables is if you make a change to the value (meaning) of the data in the variable. For processing user data, it is a good idea to trim all the data so that you can detect if all white-space characters were entered. You can do this with a single statement that operates on the data as a set, not by writing a line of code for each possible variable.

        3) You need to validate all the input data at once, storing individual, helpful, validation errors in an array. The current code stops at the first validation error, so it can take multiple form submissions to find all the errors. At the end of the validation logic, if the array holding the errors is empty, you can use the submitted data. When you (re)display the form, you can display all the validation errors by looping over the array holding the validation error messages.

        4) Don't use mysqli_stmt_init(). There's no need as mysqli_stmt_prepare() does the same thing. In fact, you need to switch to use the php PDO extension. The PDO extension is simpler and more consistent then the mysqli extension. This will simplify all the database code.

        5) Use exceptions to handle database statement errors and in most cases let php catch any exception where it will use its error_reporting, display_errors, and log_errors settings to control what happens with the actual error information. This will eliminate the error handling logic you have now and give you error handling for the statements that don't have any now.

        6) The current code is receiving a uid value from the form submission and is trying to test if the uid value is already in use (this part of the code is incomplete), and is also using this value to relate data in the second db table back to the user. If this value is a user entered username, you should call it that in the code. However, to relate data stored in additional db tables back to the user, you should insert the user data into the user table, then get the last insert id from that query, to use when storing related data in other table(s).

        7) To enforce uniqueness in data (email and uid/username), you need to define those columns in the db table as unique indexes. To detect if the values already exist, simply try to insert the data and detect if there was a duplicate key error from the query. When there is more than one possible column, you need to run a select query if there is a duplicate error to determine which column(s) caused the duplicate error. This actually simplifies the logic, because if you try to select the data first to find out if it already exists, you can still get a duplicate error if concurrent users (or your code requests the page multiple times) try to insert the same values, so, you might as well just try to insert the data and only run the select query logic if there is a duplicate.

          Write a Reply...