PHP PDO "Column cannot be null"

I have an attendance program written for conventions and part of my code doesn’t seem to work.

After the attendance form is submitted, the code first checks to see if an absence record already exists. If it does, then the program will ask if the user recording attendance wants to convert the absence record to an attendance record. If the user says yes, then the absence record is deleted and the attendance record is added.

But for some reason, I am getting this error:

Fatal error : Uncaught PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column ‘present’ cannot be null in /var/www/cabgop/record_attn.php:58 Stack trace: #0 /var/www/cabgop/record_attn.php(58): PDOStatement->execute() #1 {main} thrown in /var/www/cabgop/record_attn.php on line 58

This shouldn’t be happening because in the database, the present column is marked as NOT NULL and I’m not sure why it is happening. Here is what the code looks like:

<?php

include('nav/head.php');

$msg = "";

// Prepare SQL Statement
$stmt = $pdo->prepare("INSERT INTO attendance (member_id, member_email, member_phone, present, attend_state) VALUES (:member_id, :member_email, :member_phone, :present, :attend_state)");
$stmt->bindParam(':member_id', $member_id);
$stmt->bindParam(':member_email', $member_email);
$stmt->bindParam(':member_phone', $member_phone);
$stmt->bindParam(':present', $present);
$stmt->bindParam(':attend_state', $attend_state);

// insert a row and add new record
if(isset($_POST['btn_save'])) {
  // Check to see if delegate exists in the Absence table
  $fsQuery = $pdo->prepare("SELECT COUNT(*) AS num FROM absence WHERE member_id = :member_id");
  $fsQuery->bindParam(':member_id', $member_id);
  $id = $_POST["member_id"];
  $ary = explode("-", $id);
  $member_id = $ary[0];
  $fsQuery->execute();
  $check = $fsQuery->fetch(PDO::FETCH_ASSOC);

  if($check['num'] > 0) {
    $showModal = "true";
  } else {
    try {
      $id = $_POST["member_id"];
      $ary = explode("-", $id);
      $member_id = $ary[0];
      $member_email = $_POST["member_email"];
      $member_phone = $_POST["member_phone"];
      $present = $_POST["present"];
      $attend_state = $_POST["attend_state"];
      $stmt->execute();
      header('Location: record_attn.php');
      exit();
    } catch(PDOException $e) {
        $msg = "This delegate has already been marked present";
      }
    }
  }

// return to home screen
if(isset($_POST['btn_cancel'])) {
  header('Location: index.php');
}

if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['btn_convert'])):
  $delQuery = $pdo->prepare("DELETE FROM absence WHERE member_id = :member_id");
  $delQuery->bindParam(':member_id', $member_id);
  $id = $_POST["member_id"];
  $ary = explode("-", $id);
  $member_id = $ary[0];
  $delQuery->execute();
  $stmt->execute(); // This is line 58
  $msg = 'Delegate status converted.';
endif;
if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['btn_stop'])):
  $msg = "This delegate could not be marked present. Please try again.";
endif;

?>

<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="js/member_search.js"></script>
<script src="js/phonenumber.js"></script>

  <title>CABGOP | Mark Attendance</title>

  <?php include('nav/header.php'); ?>

	<h1 class="h3 mb-2 text-gray-800">Mark Attendance</h1>
	<br>
  <div class="small">
       <p style="text-align: left; font-size: 14px;"><b class="text-danger"><?php echo $msg; ?></b></p>
    </div>
	<form action="record_attn.php" method="post" id="record">
		<div class="form-group search-box">
			<label for="member_id">Member Search</label>
			<input type="text" class="form-control" id="member_id" name="member_id" placeholder="Enter Member's Last Name" maxlength="" autocomplete="off" autofocus="autofocus" required />
			<div class="result"></div>
		</div>
		<!--<div class="form-group">
			<label for="member_id">Member ID</label>
			<input type="text" class="form-control" id="member_id" name="member_id" placeholder="" maxlength="255" autocomplete="off" readonly/>
		</div>-->
    <div class="form-group">
			<label for="member_email">Member's Email Address</label>
			<input type="email" class="form-control" id="member_email" name="member_email" placeholder="" maxlength="255" autocomplete="off" />
		</div>
		<div class="form-group">
			<label for="member_phone">Member's Phone Number</label>
			<input type="tel" class="form-control" id="member_phone" name="member_phone" placeholder="(123) 456-7890" maxlength="14" autocomplete="off" onkeyup="maskPhoneNo();" />
		</div>
		<div class="form-group">
			<label for="present">Attended &nbsp</label>
			<input type="checkbox" id="present" name="present" placeholder="" value="1" autocomplete="off" required />
		</div>
		<div class="form-group">
			<label for="attend_state">Plan to Attend State Convention? &nbsp</label>
      <input type="hidden" id="attend_state" name="attend_state" placeholder="" value="0" autocomplete="off" checked/>
      <input type="checkbox" id="attend_state" name="attend_state" placeholder="" value="1" autocomplete="off" checked/>
		</div>
			<input type="submit" name="btn_save" class="btn btn-success" value="Save and Add New">
			<!--<input type="submit" name="btn_close" class="btn btn-danger" value="Save and Close">-->
      <a class="btn btn-danger" href="index.php">Return Home</a>
      <br>
      <br>
	</form>

<!-- checkModal -->
  <div class="modal fade" id="checkModal" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" data-backdrop="static">
				<div class="modal-dialog modal-lg modal-dialog-scrollable" role="document">
					<div class="modal-content">
						<div class="modal-header">
							<h5 class="modal-title" id="exampleModalLabel">Record Exists</h5>
							<!--<button class="close" type="button" data-dismiss="modal" aria-label="Close">
								<span aria-hidden="true">×</span>
							</button>-->
						</div>
						<div class="modal-body">
							<p>An absence record already exists for this delegate. Do you want to convert this record?</p>
						</div>
						<div class="modal-footer">
              <?php
              $member_id = (!empty($_POST['member_id']) ? explode("-", $_POST['member_id']) : '');
              $member_id = (!empty($member_id) ? trim(reset($member_id)) : '');
              $member_email = (!empty($_POST['member_email']) ? $_POST['member_email'] : '');
              $member_phone = (!empty($_POST['member_phone']) ? $_POST['member_phone'] : '');
              $present = (!empty($_POST['present']) ? $_POST['present'] : '');
              if (!empty($_POST['attend_state'])) {
                $attend_state = $_POST['attend_state'];
              } else {
                $attend_state = "0";
              }
              ?>
              <form action="" method="post">
              	<input type="hidden" name="member_id" value="<?php echo $member_id; ?>" />
                <input type="hidden" name="member_email" value="<?php echo $member_email; ?>" />
              	<input type="hidden" name="member_phone" value="<?php echo $member_phone; ?>" />
              	<input type="hidden" name="present" value="<?php echo $present; ?>" />
                <input type="hidden" name="attend_state" value="<?php echo $attend_state; ?>" />
              	<input type="submit" name="btn_stop" class="btn btn-secondary" value="No">
              	<input type="submit" name="btn_convert" class="btn btn-success" value="Yes">
              </form>
              <!--<button class="btn btn-secondary" type="button" data-dismiss="modal">No</button>
              <a class="btn btn-danger" href="convert.php">Yes</a>-->
						</div>
					</div>
				</div>
			</div>

      <?php
      if(!empty($showModal)) {
        echo '<script type="text/javascript">
        $(document).ready(function(){
          $("#checkModal").modal("show");
        });
        </script>';
      }

      ?>

        </div>
        <!-- /.container-fluid -->

      </div>
      <!-- End of Main Content -->

	<?php include('nav/footer.php'); ?>

</html>

Is this fixable?

That is why it is happening. If the column is NOT NULL then it can’t be null, you can’t give it a null value. So somehow $present is getting a null value. What values should it accept?

1 Like

$present comes from the HTML form shown below:

<div class="form-group">
			<label for="present">Attended &nbsp</label>
			<input type="checkbox" id="present" name="present" placeholder="" value="1" autocomplete="off" required />
		</div>
		<div class="form-group">
			<label for="attend_state">Plan to Attend State Convention? &nbsp</label>
      <input type="hidden" id="attend_state" name="attend_state" placeholder="" value="0" autocomplete="off" checked/>
      <input type="checkbox" id="attend_state" name="attend_state" placeholder="" value="1" autocomplete="off" checked/>
		</div>

The present alias is a checkbox. It would show a 1 if it was checked or a 0 if it wasn’t.

The attend_state alias is the same way.

The thing with checkboxes is, when unchecked, they give you nothing.
You will have to use an isset($_POST['present']) condition to make it a 0 value on false.
Or change the column to accept null and use 1 or null to indicate presence or not.
That’s what I generally do for boolean columns.

1 Like

Right, but the box is checked before “Yes” is clicked… so it should be going through as 1, not NULL… right?

Try before params binding…

$member_id = $member_email = $member_phone = $present = $attend_state = '';

Doesn’t this define those variables?

$stmt = $pdo->prepare("INSERT INTO attendance (member_id, member_email,
member_phone, present, attend_state) VALUES (:member_id, :member_email, 
:member_phone, :present, :attend_state)");
$stmt->bindParam(':member_id', $member_id);
$stmt->bindParam(':member_email', $member_email);
$stmt->bindParam(':member_phone', $member_phone);
$stmt->bindParam(':present', $present);
$stmt->bindParam(':attend_state', $attend_state);
$id = $_POST["member_id"];
      $ary = explode("-", $id);
      $member_id = $ary[0];
      $member_email = $_POST["member_email"];
      $member_phone = $_POST["member_phone"];
      $present = $_POST["present"];
      $attend_state = $_POST["attend_state"];
      $stmt->execute();

I’m not sure. That could be a reason of your problem.

This is where the problem is happening:

if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['btn_convert'])):
  $delQuery = $pdo->prepare("DELETE FROM absence WHERE member_id = :member_id");
  $delQuery->bindParam(':member_id', $member_id);
  $id = $_POST["member_id"];
  $ary = explode("-", $id);
  $member_id = $ary[0];
  $delQuery->execute();
  $stmt->execute(); <<-- (right here)
  $msg = 'Delegate status converted.';
endif;
$stmt = $pdo->prepare("INSERT INTO attendance (member_id, member_email, member_phone, present, attend_state) VALUES (:member_id, :member_email, :member_phone, :present, :attend_state)");
$stmt->bindParam(':member_id', $member_id);
$stmt->bindParam(':member_email', $member_email);
$stmt->bindParam(':member_phone', $member_phone);
$stmt->bindParam(':present', $present);
$stmt->bindParam(':attend_state', $attend_state);
if($check['num'] > 0) {
    $showModal = "true";
  } else {
    try {
      $id = $_POST["member_id"];
      $ary = explode("-", $id);
      $member_id = $ary[0];
      $member_email = $_POST["member_email"];
      $member_phone = $_POST["member_phone"];
      $present = $_POST["present"];
      $attend_state = $_POST["attend_state"];
      $stmt->execute();
      header('Location: record_attn.php');
      exit();
    } catch(PDOException $e) {
        $msg = "This delegate has already been marked present";
      }
    }
  }

I assume, you should declare the variable before to bind it.

$member_id = 0;
$delQuery->bindParam(':member_id', $member_id);

I try that, and I get this:

Fatal error : Uncaught PDOException: SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect integer value: ‘’ for column cabgop_db.attendance.present at row 1 in /var/www/cabgop/record_attn.php:63 Stack trace: #0 /var/www/cabgop/record_attn.php(63): PDOStatement->execute() #1 {main} thrown in /var/www/cabgop/record_attn.php on line 63

// Prepare SQL Statement
$stmt = $pdo->prepare("INSERT INTO attendance (member_id, member_email, 
member_phone, present, attend_state) VALUES (:member_id, :member_email, 
:member_phone, :present, :attend_state)");
$member_id = '';
$member_email = '';
$member_phone = '';
$present = '';
$attend_state = '';
$stmt->bindParam(':member_id', $member_id);
$stmt->bindParam(':member_email', $member_email);
$stmt->bindParam(':member_phone', $member_phone);
$stmt->bindParam(':present', $present);
$stmt->bindParam(':attend_state', $attend_state);

Looks like $present refreshes itself not. Is $_POST["present"] realy 1?

If I do var_dump($_POST) with checkboxes checked, I get a string 'on'
Unchecked, the input does not exist in $_POST

If the box is checked, yes.

Correction
That is the default, setting the value="1" (as the OP has) does give '1' if checked.

Try please…

var_dump($present);
$stmt->execute();

If I put a var_dump here:

if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['btn_convert'])):
  $delQuery = $pdo->prepare("DELETE FROM absence WHERE member_id = :member_id");
  $delQuery->bindParam(':member_id', $member_id);
  $id = $_POST["member_id"];
  $ary = explode("-", $id);
  $member_id = $ary[0];
  $delQuery->execute();
  var_dump($present);
  //$stmt->execute();
  $msg = 'Delegate status converted.';
endif;

I get this:

string(0) ""

I mean by second execution, for inserting.

This is what appears:

string(1) "1"
// Prepare SQL Statement
$stmt = $pdo->prepare("INSERT INTO attendance (member_id, member_email, member_phone, present, attend_state) VALUES (:member_id, :member_email, :member_phone, :present, :attend_state)");
$member_id = '';
$member_email = '';
$member_phone = '';
$present = '';
$attend_state = '';
$stmt->bindParam(':member_id', $member_id);
$stmt->bindParam(':member_email', $member_email);
$stmt->bindParam(':member_phone', $member_phone);
$stmt->bindParam(':present', $present);
$stmt->bindParam(':attend_state', $attend_state);

// insert a row and add new record
if(isset($_POST['btn_save'])) {
  // Check to see if delegate exists in the Absence table
  $fsQuery = $pdo->prepare("SELECT COUNT(*) AS num FROM absence WHERE member_id = :member_id");
  $fsQuery->bindParam(':member_id', $member_id);
  $id = $_POST["member_id"];
  $ary = explode("-", $id);
  $member_id = $ary[0];
  $fsQuery->execute();
  $check = $fsQuery->fetch(PDO::FETCH_ASSOC);

  if($check['num'] > 0) {
    $showModal = "true";
  } else {
    try {
      $id = $_POST["member_id"];
      $ary = explode("-", $id);
      $member_id = $ary[0];
      $member_email = $_POST["member_email"];
      $member_phone = $_POST["member_phone"];
      $present = $_POST["present"];
      $attend_state = $_POST["attend_state"];
      var_dump($present);
      //$stmt->execute();
      //header('Location: record_attn.php');
      exit();
    } catch(PDOException $e) {
        $msg = "This delegate has already been marked present";
      }
    }
  }

New Discovery:

I found out that if I go back and refresh the page, the code runs as it should. But why am I getting an error if it works properly?

image

if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['btn_convert'])):
  $delQuery = $pdo->prepare("DELETE FROM absence WHERE member_id = :member_id");
  $delQuery->bindParam(':member_id', $member_id);
  $id = $_POST["member_id"];
  $ary = explode("-", $id);
  $member_id = $ary[0];
  $delQuery->execute();
  $stmt->execute();
  $msg = 'Delegate status converted.';
endif;
if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['btn_stop'])):
  $msg = "This delegate could not be marked present. Please try again.";
endif;

UPDATE

Figured it out. The values weren’t being passed through the statement.