1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Need help on this code

Discussion in 'PHP' started by Jesse27, Jul 3, 2013.

  1. #1
    Hi, I'm trying to create a php GPA Calculator.
    I can't seem to get this code to work :/
    SEMrush
    <?php
     
    $multGradeAndUnit = 0;
    $totalUnits = 0;
    $fGPA;
     
     
    $units = 0;
    for($i=0; $i<7; $i++) {
     
        //these are just the names in input name = "", can rename yo anything you want
        $courseName = 'course'.$i;
        $courseUnits = 'units'.$i;
        $courseGrade = 'coursegrade'.$i;
     
        //we are using post to retrieve these form input variables
        $courseGrade = $POST[$coursegrade];
        $units = $POST[$courseUnits];
        $course = $POST[$courseName];
     
        if ($courseUnits == "" && $courseGrade == "")
        {
            $multGradeAndUnit = $courseUnits * $courseGrade;
            $totalUnits = $courseUnits + $totalUnits;
        }
            }
           
        $fGPA = $multGradeAndUnit / $totalUnits;
        echo "Your GPA is: ". $fGPA
     
    ?>
    PHP:
     
    Solved! View solution.
    Jesse27, Jul 3, 2013 IP
    SEMrush
  2. EricBruggema

    EricBruggema Well-Known Member

    Messages:
    1,731
    Likes Received:
    26
    Best Answers:
    13
    Trophy Points:
    175
    #2
    $_POST? instead of $POST?

    And please next time provide more information about what's not working, and if possible give more code (like the HTML part)
     
    EricBruggema, Jul 3, 2013 IP
  3. ekim941

    ekim941 Member

    Messages:
    74
    Likes Received:
    7
    Best Answers:
    7
    Trophy Points:
    33
    #3
    Eric is mostly right. You need an underscore before your POST variable but the parameters need to be in single quotes, not a variable name.
    $courseGrade = $_POST['coursegrade'];
    $units = $_POST['courseUnits'];
    $course = $_POST['courseName'];
    PHP:
     
    ekim941, Jul 3, 2013 IP
  4. sarahk

    sarahk iTamer Staff

    Messages:
    27,266
    Likes Received:
    4,185
    Best Answers:
    118
    Trophy Points:
    665
    #4
    Not necessarily but they do need to match up with the form.
     
    sarahk, Jul 3, 2013 IP
  5. GORF

    GORF Well-Known Member

    Messages:
    216
    Likes Received:
    21
    Best Answers:
    3
    Trophy Points:
    115
    #5
    Would you agree it is better practice to save the double quotes for echo'ed HTML to avoid escaping characters?
     
    GORF, Jul 3, 2013 IP
  6. sarahk

    sarahk iTamer Staff

    Messages:
    27,266
    Likes Received:
    4,185
    Best Answers:
    118
    Trophy Points:
    665
    #6
    absolutely, but your comment was related to variables versus a name.

    In this case the OP has 7 sets of questions. Rather than repeat the names of the variables 7 times s/he has a loop going. Looks like good practice to me.
     
    sarahk, Jul 3, 2013 IP
    ryan_uk likes this.
  7. Jesse27

    Jesse27 Well-Known Member

    Messages:
    145
    Likes Received:
    8
    Best Answers:
    1
    Trophy Points:
    165
    #7
    Hi guys, sorry :/ Here is the index.html file,​
    I was advised to use php arrays in getting the inputs from the form, i just don't know how will i do it :S​
      <form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>" target="_self">
      <div class="row">
          <div class="large-4 columns">
            <label>Course Name</label>
            <input type="text" placeholder="Course Code" name="course$i" id="course1">
          </div>
          <div class="large-4 columns">
            <label>Units</label>
            <input type="text" placeholder="No. of Units" name="units$i" id="units1">
          </div>
          <div class="large-4 columns">
            <div class="row collapse">
              <label>Grade</label>
              <div class="small-9 columns">
                <input type="text" placeholder="Grade" name="coursegrade$i" id="coursegrade1">
              </div>
              <div class="small-3 columns">
              </div>
            </div>
          </div>
        </div>
     
          <div class="row">
          <div class="large-4 columns">
            <input type="text" placeholder="Course Code" id="course2">
          </div>
          <div class="large-4 columns">
            <input type="text" placeholder="No. of Units" id="units2">
          </div>
          <div class="large-4 columns">
            <div class="row collapse">
              <div class="small-9 columns">
                <input type="text" placeholder="Grade" id="coursegrade2">
              </div>
              <div class="small-3 columns">
              </div>
            </div>
          </div>
        </div>
    HTML:
     

    Attached Files:

    Jesse27, Jul 6, 2013 IP
  8. #8
    There's a LOT in this code that raises warning flags of broken or just sloppy methodologies. Extra variables for nothing, vague/meaningless presentational use of classes with pointless DIV for nothing, incomplete form, attributes like TARGET that have no business on any website written after 1997, false simplicity with that stupid malfing HTML 5 placeholder garbage (that are redundant to your LABELs), etc, etc, etc...

    Even the logic disconnect on this:

    if ($courseUnits == "" && $courseGrade == "")
    
        {
    
            $multGradeAndUnit = $courseUnits * $courseGrade;
    
            $totalUnits = $courseUnits + $totalUnits;
    
        }
    Code (markup):
    You're only calculating values when they are EMPTY?!? That doesn't make any sense...

    First order of business is to clean up the markup. The big trick is to, as you said someone else suggested, is using arrays. To do that, you just put brackets in your markup names. I would index them off a single parent to make it easier to work with.

    So for your three fields, they'd go something like this:

    name="course[1][name]"
    name="course[1][units]"
    name="course[1][grade]"

    Updating that number for each fieldset (and I'd be grouping each 'course' info by fieldset, NOT DIV!)

    On the PHP side, that will give you an array like this to work with:

    $_POST['course'] 
    [
    
    	[1] => [
    		[name] => 
    		[units] => 
    		[grade] => 
    	],
    	
    	[2] => [
    		[name] => 
    		[units] => 
    		[grade] => 
    	]
    	
    ];
    Code (markup):
    Which you can then simply foreach to add together.

    To generate that I'd make a function to use as a template so you can pass it an action and how many 'courses' to show. I'd put it in it's own file so you can call it separately from the actual form handler -- since it appears you want to make this self calling doing so lets us avoid loading code you might not actually be running.

    gradeForm.php
    <?php
    
    function gradeForm($action,$courseCount) {
    
    	echo '
    		<form action="',$action,'" method="post" id="gradeForm">';
    	
    	for ($t = 1; $t < $courseCount; $t++) {
    		$idBase = 'course_'.$t.'_';
    		$cBase = 'course['.$t.']';
    		echo '
    			<fieldset>
    				<label for="',($id = $idBase.'Name'),'">Course Name</label>
    				<input type="text" name="',$cBase,'[name]" id="',$id,'" />
    				<br />
    				<label for="',($id = $idBase.'Units'),'"># of Units</label>
    				<input type="text" name="',$cBase,'[units]" id="',$id,'" />
    				<br />
    				<label for="',($id = $idBase.'Grade'),'">Grade</label>
    				<input type="text" name="',$cBase,'[grade]" id="',$id,'" />
    			</fieldset>';
    	}
    
    	echo '
    			<div class="submitsAndHiddens">
    				<input type="submit" value="Calculate GPA" />
    				<input type="hidden" name="fromForm" value="gradeForm" />
    			<!-- .submitsAndHiddens --></div>
    			
    		</form>';
    		
    }
    
    ?>
    Code (markup):
    Pre-building values used repeatedly and saving string additions that are used more than once inline in the output reduces the code and speeds things up a wee bit.

    I really don't think your math/logic for adding them up makes any sense, shouldn't multGradeAndUnit be adding together the multiplier, since you want the value at the end, not for each and every course?

    I'd also put this into it's own function in it's own file:

    gradeCalc.php
    
    <?php
    
    functon gradeCalc() {
    
    	// technically there is no A+, treat as A should some dipshit type it in.
    	$gpLookup = [
    		'A+' => 4.0,  'A'  => 4.0,  'A-' => 3.7,
    		'B+' => 3.33, 'B'  => 3.0,  'B-' => 2.7,
    		'C+' => 2.3,  'C'  => 2.0,  'C-' => 1.7,
    		'D+' => 1.3,  'D'  => 1.0,  'D-' => 0.7
    	];
    
    	$sumGradeTimesUnits = 0;
    	$totalUnits = 0;
    	foreach ($_POST['course'] as $course) {
    		if (
    			!empty($course['units']) &&
    			!empty($course['grade'])
    		) {
    			if (is_numeric($course['grade'])) {
    				$grade = ($course['grade'] <= 4) ? $course['grade'] : 0;
    			} else {
    				$grade = (
    					isset($gpLookup[$index = strtoupper($course['grade'])]) ?
    					$gpLookup[$index] :
    					0
    				);
    			}
    			$totalUnits += $course['units'];
    			$sumGradeTimesUnits += $course['units'] * $grade;
    		}
    	}
    	if ($totalUnits > 0) {
    		echo '
    			<p>
    				Your GPA is: ',number_format($sumGradeTimesUnits / $totalUnits, 2),'
    			</p>';
    	} else {
    		echo '
    			<p>
    				<strong>You failed to enter any courses!</strong>
    			</p>';
    	}
    	echo '
    			<a href="test.php">Click here to enter another set of courses</a>';
    			
    }
    
    ?>
    Code (markup):
    You might be wondering why I wrap these in functions -- it helps keep their vars out of the global namespace, and means if you call their files directly they don't output anything. Security 101 in scripting languages, any file the user shouldn't call directly shouldn't blindly start outputting values or running code. Functions and classes help prevent that.

    A demo test.php would go something like this:

    <?php
    
    require_once('template.php');
    
    template_header('GPA Calculator');
    
    if (
    	isset($_POST['fromForm']) &&
    	($_POST['fromForm'] == 'gradeForm') &&
    	isset($_POST['course'])
    ) {
    	require_once('gradeCalc.php');
    	gradeCalc();
    } else {
    	require_once('gradeForm.php');
    	gradeForm('test.php',7);
    }
    	
    template_footer();	
    
    ?>
    Code (markup):
    I tossed a live copy up on my server here:
    http://www.cutcodedown.com/for_others/jesse27/test.php

    As with all my examples the directory:
    http://www.cutcodedown.com/for_others/jesse27/

    ... is wide open for easy access to the gooey bits and pieces. I've added .phps files for direct viewing of the source, and a .rar of the entire working code.

    Hope this helps.
     
    deathshadow, Jul 7, 2013 IP
    Jesse27 and ryan_uk like this.
  9. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,530
    Likes Received:
    1,934
    Best Answers:
    247
    Trophy Points:
    515
    #9
    Oh, forgot to mention, I added the ability to enter either the grade points for the class, or a letter grade. A better version would have form validation too.

    Also, I use php 5.4 style arrays, so the above won't run on php 5.3/lower. I'm dropping support for 5.3- as there's just too much nice stuff in 5.4 for me to continue to bend over backwards supporting versions of PHP that hosts shouldn't even have installed. [] arrays, ?:, and a host of other things are just too cool not to use.

    ... and I'm REALLY close to going 5.5 only. array_column much?
     
    Last edited: Jul 7, 2013
    deathshadow, Jul 7, 2013 IP