title: PHP CRUD edit model with image
body: <p>i am making a training project using php. The website is a beer shop where as an admin i would like to be able to make all CRUD operations on beers. I have implemented all of them except the edit operation, where i have encountered a problem. The beer model has name, description, price, quantity and image. In the edit file i would like to be able to edit any of these fields. I have managed to make it work for everything, except the image field. Here is my php code:</p>
  
  <pre><code>&lt;?php
  require_once 'connect.php';
  if (isset($_SESSION['user']) &amp;&amp; $_SESSION['user'] == 'admin') {
  
  }
  else{
      header('HTTP/1.0 401 Unauthorized');
      echo 'You are not authorized to be here!';
      exit;
  }
  ?&gt;
  &lt;!DOCTYPE HTML&gt;
  &lt;html&gt;
  &lt;head&gt;
      &lt;title&gt;Edit Beer&lt;/title&gt;
  
      &lt;link rel="shortcut icon" href="images/logoNew_bubbles.png"/&gt;
      &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" /&gt;
      &lt;link type="text/css" rel="stylesheet" media="screen" href="https://netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css"&gt;
      &lt;link href="css/styles.css" rel="stylesheet"&gt;
  
  &lt;/head&gt;
  &lt;body&gt;
  &lt;header&gt;
      &lt;?php include_once "php_includes/header.php"; ?&gt;
  &lt;/header&gt;
  &lt;div class="container" style="margin-top: 150px; margin-bottom: 50px;"&gt;
  
      &lt;div class="page-header"&gt;
          &lt;h1&gt;Edit Product&lt;/h1&gt;
      &lt;/div&gt;
  
      &lt;?php
      // get passed parameter value, in this case, the record ID
      // isset() is a PHP function used to verify if a value is there or not
      $id=isset($_GET['id']) ? $_GET['id'] : die('ERROR: Record ID not found.');
  
  
  
      // read current record's data
      try {
          // prepare select query
          $query = "SELECT id, name, description, price, quantity, picture FROM products WHERE id = ? LIMIT 0,1";
          $stmt = $pdo-&gt;prepare( $query );
  
          // this is the first question mark
          $stmt-&gt;bindParam(1, $id);
  
          // execute our query
          $stmt-&gt;execute();
  
          // store retrieved row to a variable
          $row = $stmt-&gt;fetch(PDO::FETCH_ASSOC);
  
          // values to fill up our form
          $name = $row['name'];
          $description = $row['description'];
          $price = $row['price'];
          $quantity = $row['quantity'];
          $picture = htmlspecialchars($row['picture'], ENT_QUOTES);
      }
  
  // show error
      catch(PDOException $exception){
          die('ERROR: ' . $exception-&gt;getMessage());
      }
      ?&gt;
  
      &lt;?php
  
      // check if form was submitted
      if($_POST){
  
          try{
              // default sql query
              $query = "UPDATE products 
                      SET name=:name, description=:description, price=:price, quantity=:quantity
                      WHERE id = :id";
  
              // prepare query for excecution
              $stmt = $pdo-&gt;prepare($query);
  
              // posted values
              $name=htmlspecialchars(strip_tags($_POST['name']));
              $description=htmlspecialchars(strip_tags($_POST['description']));
              $price=htmlspecialchars(strip_tags($_POST['price']));
              $quantity=htmlspecialchars(strip_tags($_POST['quantity']));
  
              // if admin has selected a picture
              if($_FILES['picture']['size'] &gt; 0){
              //new query
                  $query = "UPDATE products 
                      SET name=:name, description=:description, price=:price, quantity=:quantity, picture=:picture
                      WHERE id = :id";
  
                  $picture=!empty($_FILES["picture"]["name"])
                      ? sha1_file($_FILES["picture"]["tmp_name"]) . "-" . basename($_FILES["picture"]["name"])
                      : "";
                  $picture=htmlspecialchars(strip_tags($picture));
                  $stmt-&gt;bindParam(':picture', $picture);
  
                  $target_directory = "beers/";
                  $target_file = $target_directory . $picture;
                  $file_type = pathinfo($target_file, PATHINFO_EXTENSION);
                  $file_upload_error_messages = "";
  
                  $allowed_file_types = array("jpg", "jpeg", "png");
                  if (!in_array($file_type, $allowed_file_types)) {
                      $file_upload_error_messages .= "&lt;div&gt;Only JPG, JPEG, PNG files are allowed.&lt;/div&gt;";
                  }
  
                  if (file_exists($target_file)) {
                      $file_upload_error_messages .= "&lt;div&gt;Image already exists. Try to change file name.&lt;/div&gt;";
                  }
  
  
                  if (($_FILES['picture']['size'] &gt;= (5242880)) || ($_FILES["picture"]["size"] == 0)) {
                      $file_upload_error_messages .= "&lt;div&gt;Image must be less than 5 MB in size.&lt;/div&gt;";
                  }
  
  
                  if (!is_dir($target_directory)) {
                      mkdir($target_directory, 0777, true);
                  }
  
                  if (empty($file_upload_error_messages)) {
                      if(move_uploaded_file($_FILES["picture"]["tmp_name"], $target_file)){
                          return;
                      }
                      else {
                          echo "&lt;div class='alert alert-danger'&gt;";
                          echo "&lt;div&gt;Unable to upload photo.&lt;/div&gt;";
                          echo "&lt;div&gt;Update the record to upload photo.&lt;/div&gt;";
                          echo "&lt;/div&gt;";
                      }
                  }
                   else {
                      // it means there are some errors, so show them to user
                      echo "&lt;div class='alert alert-danger'&gt;";
                      echo "&lt;div&gt;{$file_upload_error_messages}&lt;/div&gt;";
                      echo "&lt;div&gt;Update the record to upload photo.&lt;/div&gt;";
                      echo "&lt;/div&gt;";
                  }
              }
  
              // bind the parameters
              $stmt-&gt;bindParam(':name', $name);
              $stmt-&gt;bindParam(':description', $description);
              $stmt-&gt;bindParam(':price', $price);
              $stmt-&gt;bindParam(':quantity', $quantity);
              $stmt-&gt;bindParam(':id', $id);
  
  
              // Execute the query
              if($stmt-&gt;execute()){
                  echo "&lt;div class='alert alert-success'&gt;Record was updated.&lt;/div&gt;";
  
              }else{
                  echo "&lt;div class='alert alert-danger'&gt;Unable to update record. Please try again.&lt;/div&gt;";
              }
  
          }
  
              // show errors
          catch(PDOException $exception){
              die('ERROR: ' . $exception-&gt;getMessage());
          }
      }
      ?&gt;
  
      &lt;div class="col-sm-12"&gt;
          &lt;div class="col-sm-2"&gt;&lt;/div&gt;
          &lt;div class="col-sm-8"&gt;
      &lt;form action="&lt;?php echo htmlspecialchars($_SERVER["PHP_SELF"] . "?id={$id}");?&gt;" method="post" enctype="multipart/form-data"&gt;
          &lt;table class='table table-hover table-responsive table-bordered'&gt;
              &lt;tr&gt;
                  &lt;td&gt;Name&lt;/td&gt;
                  &lt;td&gt;&lt;input type='text' name='name' value="&lt;?php echo htmlspecialchars($name, ENT_QUOTES);  ?&gt;" class='form-control' /&gt;&lt;/td&gt;
              &lt;/tr&gt;
              &lt;tr&gt;
                  &lt;td&gt;Description&lt;/td&gt;
                  &lt;td&gt;&lt;textarea name='description' class='form-control'&gt;&lt;?php echo htmlspecialchars($description, ENT_QUOTES);  ?&gt;&lt;/textarea&gt;&lt;/td&gt;
              &lt;/tr&gt;
              &lt;tr&gt;
                  &lt;td&gt;Price&lt;/td&gt;
                  &lt;td&gt;&lt;input type='text' name='price' value="&lt;?php echo htmlspecialchars($price, ENT_QUOTES);  ?&gt;" class='form-control' /&gt;&lt;/td&gt;
              &lt;/tr&gt;
              &lt;tr&gt;
                  &lt;td&gt;Quantity&lt;/td&gt;
                  &lt;td&gt;&lt;input type='text' min=0 name='quantity' value="&lt;?php echo htmlspecialchars($quantity, ENT_QUOTES); ?&gt;" class='form-control'  required/&gt;&lt;/td&gt;
              &lt;/tr&gt;
              &lt;tr&gt;
                  &lt;td&gt;Picture&lt;/td&gt;
                  &lt;td&gt;&lt;p&gt;&lt;?php echo $picture ? "&lt;img src='beers/{$picture}' style='width:150px; height:150px;' /&gt;" : "&lt;img src='images/birichka.jpg' style='width:150px;; height:150px;';&gt;" ?&gt;&lt;/p&gt;&lt;/td&gt;
              &lt;/tr&gt;
              &lt;tr&gt;
                  &lt;td&gt;Change Picture&lt;/td&gt;
                  &lt;td&gt;&lt;input class="btn btn-default" type="file" name="picture"/&gt;&lt;/td&gt;
              &lt;/tr&gt;
              &lt;tr&gt;
                  &lt;td&gt;&lt;/td&gt;
                  &lt;td&gt;
                      &lt;input type='submit' value='Save' class='btn btn-success' /&gt;
                      &lt;a href='listAllBeers.php' class='btn btn-danger'&gt;Back to read products&lt;/a&gt;
                  &lt;/td&gt;
              &lt;/tr&gt;
          &lt;/table&gt;
      &lt;/form&gt;
          &lt;/div&gt;
          &lt;div class="col-sm-2"&gt;&lt;/div&gt;
      &lt;/div&gt;
  
  &lt;/div&gt; &lt;!-- end .container --&gt;
  &lt;footer class="footer navbar-fixed-bottom"&gt;
      &lt;?php include_once "php_includes/footer.php"; ?&gt;
  &lt;/footer&gt;
  
  &lt;script src="https://code.jquery.com/jquery-3.2.1.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"&gt;&lt;/script&gt;
  
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>With that current code i am getting the following error: "ERROR: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined" , but only if the admin has selected a picture to upload. If he has changed any other field and left the image field, without uploading a new image, everything works.</p>