Skip to main content

Create image upload field using Drupal Form API

Product Form with Image Field

Product Form with Image Field


We can create a image/file upload field using Drupal Form API. Here I am considering an example of product form so we can easily understand its use and its implementation. Our product form have two fields product name and product image. I am considering only three fields productid, product name and product image in our product table. The productid is primary key and set to auto increment. Our module name is ‘product.module’.

STEP 1.

function new_product_form() {
	$form['product_name'] = array(
	'#title' => t('Product Name'),
	'#type' => 'textfield',
	'#required' => TRUE,
	'#description' => t('Please enter product name.'),
	);
 
	// Product picture
	$form['picture'] = array('#type' => 'fieldset', '#title' => t('Product image'));
    	$form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload product image'), '#size' => 48, 
		'#description' => t('Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => 	'250x250', '%size' => '30')));
 
    	$form['#validate'][] = 'product_validate_picture';
 
	$form['submit'] = array(
	'#type' => 'submit',
	'#value' => t('Submit'),
	);
 
	$form['#redirect'] = 'product_list';	
	$form['#attributes']['enctype'] = 'multipart/form-data';
 
	return $form;
}

We have set the enctype of form as multipart/form-data because we are uploading the file. We also set a validation function product_validate_picture() for validating our uploaded image.


STEP 2.
Now we are creating product_validate_picture() function.

function product_validate_picture(&$form, &$form_state) {
	$validators = array(
    		'file_validate_is_image' => array(),
	    	'file_validate_image_resolution' => array('250x250')),
    		'file_validate_size' => array(30 * 1024),
  	);
  	if ($file = file_save_upload('picture_upload', $validators)) {
    		// Remove the old picture.
    		if (isset($form_state['values']['_product']->image_path) && file_exists($form_state['values']['_product']->image_path)){
      			file_delete($form_state['values']['_product']->image_path);
    		}
 
		$productid = 0;
		if (!isset($form_state['values']['productid'])) { // Execute in case of new product
			$query = "SHOW TABLE STATUS LIKE 'product'";
			$rs = db_query($query);
			$row = db_fetch_object($rs);
 
			$productid = isset($row->Auto_increment) ? $row->Auto_increment : 0;
		}
		else {
			$productid = $form_state['values']['productid'];
		}
 
		$info = image_get_info($file->filepath);
    		$destination = variable_get('product_picture_path', 'product_pictures') .'/picture-'. $productid .'.'. $info['extension'];
    		if (file_copy($file, $destination, FILE_EXISTS_REPLACE)) {
      			$form_state['values']['picture'] = $file->filepath;
    		}
    		else {
      			form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", 
                        array('%directory' => variable_get('product_picture_path', 'product_pictures'))));
    		}
  	}
}

Drupal provide a function file_save_upload() for saving the uploaded file to a new location. Its also take associative array of callback functions used to validate the file as optional argument. Here we passing three callback functions file_validate_is_image, file_validate_image_resolution, and file_validate_size for validating file type as image, image resolution and file size respectively. This function return an object containing the file information or 0 in case of error.

We are using this product_validate_picture() function in both new product and edit product form. So, if ‘_product’ is not set in form values then its fetch the id of next auto_increment value set in product table. In case of edit product form it replace the old product image with new image if user uploaded a new image.

We assign the uploaded image path in our form values so we can store that path in out product table.

$form_state['values']['picture'] = $file->filepath;

STEP 3.

function new_product_form_submit($form_id, $form) {
	$form_values = $form['values'];
 
	$product_name = trim($form_values['product_name']);
	$image_path = $form_values['picture'];
 
	$query = "INSERT INTO product(product_name, image_path) VALUES('%s', '%s')";
	db_query($query, $product_name, $image_path);
 
	drupal_set_message(t('Product has been added successfully.'));
}

Then we will save the product imformation in out product table.

STEP 4.
In case of edit product form we are passing productid as arg(2). We fetch the product imformation using this productid and set the default values in form. We also save the product information and productid in form values.

function edit_product_form() {
	$productid = arg(2);
 
	$query = "SELECT * FROM {product} WHERE productid = '%d'";
	$rs = db_query($query, $productid);
	$product_data = db_fetch_object($rs);
 
	$form['_product'] = array('#type' => 'value', '#value' => $product_data);
	$form['productid'] = array('#type' => 'value', '#value' => $product_data->productid);
 
	$form['product_name'] = array(
	'#title' => t('Product Name'),
	'#type' => 'textfield',
	'#default_value' => stripslashes($product_data->product_name),
	'#required' => TRUE,
	'#description' => t('Please enter product name.'),
	);
 
	// Product picture
	$form['picture'] = array('#type' => 'fieldset', '#title' => t('Product image'));
    	$picture = theme('product_picture', (object)$product_data);
    	if ($product_data->image_path) {
      		$form['picture']['current_picture'] = array('#value' => $picture);
      		$form['picture']['picture_delete'] = array('#type' => 'checkbox', '#title' => t('Delete picture'), 
	  		'#description' => t('Check this box to delete your current picture.'));
    	}
    	else {
     		$form['picture']['picture_delete'] = array('#type' => 'hidden');
    	}
    	$form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload product image'), '#size' => 48, 
		'#description' => t('Maximum dimensions are %dimensions and the maximum size is %size kB.', 
		array('%dimensions' => '250x250', '%size' => '30')));
 
    	$form['#validate'][] = 'product_validate_picture';
 
	$form['#redirect'] = 'product_list';
 
	$form['#attributes']['enctype'] = 'multipart/form-data';
 
	return $form;
}

STEP 5.
Then we will update the product detail. If user want to delete product image then we will delete the current image of product.

function edit_product_form_submit($form_id, $form) {
	$form_values = $form['values'];
 
	$product_name = trim($form_values['product_name']);
	$image_path = $form_values['_product']->image_path;
 
	 // Delete picture if requested, and if no replacement picture was given.
  	if (!empty($form_values['picture_delete']) && $form_values['picture'] == '') {
    	if ($form_values['_product']->image_path && file_exists($form_values['_product']->image_path)) {
	      	file_delete($form_values['_product']->image_path);
    	}
    	$image_path = '';
  	}
 
	if (isset($form_values['picture']) && $form_values['picture'] != '') {
		$image_path = $form_values['picture'];
	}
 
	$query = "UPDATE {product} SET product_name = '%s', image_path = '%s' WHERE productid = '%d'";
	db_query($query, $product_name, $image_path, $productid);
 
	drupal_set_message(t('Product has been updated successfully.'));
}

STEP 6.
We are also theming our product image. For this, we are using a product-picture.tpl.php file. First we register our theme in theme registry using hook_theme() callback function.

function product_theme() {
  	return array(
    	'product_picture' => array(
      	'arguments' => array('product' => NULL),
      	'template' => 'product-picture',
    	),
  	);
}
 
function template_preprocess_product_picture(&$variables) {
    $variables['picture'] = '';
 
    $product = $variables['product'];
    if (!empty($product->image_path) && file_exists($product->image_path)) {
      $picture = file_create_url($product->image_path);
    }
    else if (variable_get('product_picture_default', '')) {
      $picture = variable_get('product_picture_default', '');
    }
 
    if (isset($picture)) {
      $alt = t("@product's picture", array('@product' => $product->product_name ));
      $variables['picture'] = theme('image', $picture, $alt, $alt, '', FALSE);
    }
}
<?php 
//product-picture.tpl.php file 
?>
<div class="picture">
  <?php print $picture; ?>
</div>

, ,