Jump to content

Passing variable to function from form.


tomce

Recommended Posts

Hi Guys,

 

I am struggling to pass form input data to function (store to blob).

 

FORM:

    <form action="admin.php?action=<?php echo $results['formAction']?>" method="post" enctype="multipart/form-data">

   <input type="file" name="file" size="40" id="file" required autofocus maxlength="255" />
        <input type="hidden" name="MAX_FILE_SIZE" value="50000000">

FUNCTION:

 public function uploadImage() {
  if ( !is_null( $this->img_id ) ) trigger_error ( "cmsImagesClass::uploadImage(): Attempt to insert an object that already has its ID property set (to $this->img_id).", E_USER_ERROR );
  // Prepare image
  $imageFile = file_get_contents($_FILES['file']['tmp_name']);
  // Insert link
  $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
  $sql = "INSERT INTO images ( img_name, img_blob) VALUES ( :img_name, :imageFile)";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":img_name", $this->img_name, PDO::PARAM_STR );
    $st->bindValue( ":imageFile", $this->img_blob, PDO::PARAM_LOB);

What I am doing wrong? As image not being stored. If I am commenting out imageFile and storing img_name - when is fine, I can see that record was added, but storing file - not giving any errors

Link to comment
Share on other sites

A couple things I notice:

 

1. As mentioned, it's generally a bad practice to store blob images inside of a database. Instead, store the images on the server and the image paths in a database.

 

2. the uploadImage() method should only be concerned with, you guessed it, uploading an image, not establishing a connection to the database and querying data. You should look into the idea of using utility classes to help abstract these tasks.

Link to comment
Share on other sites

I don't care about performance guys, can somebody answer my question - how to pass "blob" variable to "uploadImage()" function. This is only what I am asking.

 

Why "file" cannot be viewed/stored and "img_name" can be stored without any issues?

 

I am not asking about performance.

Edited by tomce
Link to comment
Share on other sites

I'm not entirely agree about performance which was mentioned above. It really depends!

 

@tomce, did you execute() the sql statement at the end?

 

Well this is what is strange, if I am commenting out : 

$st->bindValue( ":imageFile", $this->img_blob, PDO::PARAM_LOB);

I mean storing only img_name - yes, it executes sql statment. However if I am adding line with blob - it doesn't stores..

Link to comment
Share on other sites

 


 However if I am adding line with blob - it doesn't stores..

 

Then surely it must give an error, which is why I wanted to know how tou check the query for errors.

 

Is it even possible to load binary data into the database like that? Shouldn't it be encoded i some way? Most databaes have separate functions for storing blobs (because they can give performance problems).

Link to comment
Share on other sites

Then surely it must give an error, which is why I wanted to know how tou check the query for errors.

 

Is it even possible to load binary data into the database like that? Shouldn't it be encoded i some way? Most databaes have separate functions for storing blobs (because they can give performance problems).

Agree with you, but it doesn't shows any errors to be honest. It looks like it even doesn't call PDO statment if blob is enabled. This is very strange and hard to debug.

Link to comment
Share on other sites

Then surely it must give an error, which is why I wanted to know how tou check the query for errors.

 

Is it even possible to load binary data into the database like that? Shouldn't it be encoded i some way? Most databaes have separate functions for storing blobs (because they can give performance problems).

 

For example, if I commenting out blob:

 $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
  $sql = "INSERT INTO images ( img_name) VALUES ( :img_name)";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":img_name", $this->img_name, PDO::PARAM_STR );
    //$st->bindValue( ":imageFile", $this->img_blob, PDO::PARAM_LOB);

SQL log shows:

 

          299 Connect    root@localhost on cms

          299 Query    INSERT INTO images ( img_name) VALUES ( 'asass')

 

But if I am Leaving it as it is:

$sql = "INSERT INTO images ( img_name, img_blob) VALUES ( :img_name, :imageFile)";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":img_name", $this->img_name, PDO::PARAM_STR );
    $st->bindValue( ":imageFile", $this->img_blob, PDO::PARAM_LOB);

SQL log shows nothing:

 

 313 Query    INSERT INTO images ( img_name, img_blob) VALUES ( 'asas', NULL)

          313 Quit  

Edited by tomce
Link to comment
Share on other sites

Ok, so what does PHP say? Does the execute command return an error, or does the bind statement return false? What kind of error checking are you ding there?

Thanks for help Vinny42, well I am using xdebug, but perhaps I am not using it properly as for this case it doesn't return any errors.

 

I have enabled loggin in my config so it shows all syntax, variables issues in the output.

 

// Display errors

ini_set( "display_errors", true );

 

But for this specific case - I cannot find out why uploadImage thinks thta "file" is "NULL".

 

For more details:

 

My Form:

     <form action="admin.php?action=<?php echo $results['formAction']?>" method="post" enctype="multipart/form-data">
        <input type="file" name="file" size="40" id="file" required autofocus maxlength="255" />
        <input type="hidden" name="MAX_FILE_SIZE" value="50000000">

My Class/Function:

class cmsImages
{

  // defining variables for web_files table
 
  public $img_id = null;                // img_id [image unique id]
  public $img_name = null;              // img_name [like filename.jpg]
  public $img_blob = null;              // img_blob [a file stored into blob]
 public function __construct( $data=array() ) {
    if ( isset( $data['img_id'] ) ) $this->img_id = (int) $data['img_id'];    
    if ( isset( $data['img_name'] ) ) $this->img_name = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['img_name'] );    
    if ( isset( $data['img_blob'] ) ) $this->img_blob = $data['img_blob'];   
// Function to store form values [sets the object's properties using the edit form post values in the supplied array]
  public function storeFormValues ( $params ) {

    // Store all the parameters
    $this->__construct( $params );
  }

And function:

 // Function uploadImage [function to add image]
  public function uploadImage() {
  // Does object already have an ID?
  if ( !is_null( $this->img_id ) ) trigger_error ( "cmsImages::uploadImage(): Attempt to insert an object that already has its ID property set (to $this->img_id).", E_USER_ERROR );
  // Prepare image
  //$imgfp = fopen($_FILES['userfile']['tmp_name'], 'rb');
  $imageFile = file_get_contents($_FILES['file']['tmp_name']);
  // Insert image
  $conn = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
  $sql = "INSERT INTO images ( img_name, img_blob) VALUES ( :img_name, :imageFile)";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":img_name", $this->img_name, PDO::PARAM_STR );
    $st->bindValue( ":imageFile", $this->img_blob, PDO::PARAM_LOB);

What I am doing wrong here ?

Link to comment
Share on other sites

Your script works fine, I tested.

<?php

// Prepare image
  $imageFile = file_get_contents($_FILES['file']['tmp_name']);

  // Insert link
  $conn = new PDO( 'mysql:host=localhost;dbname=DUMB_DB', 'jazzman', 'password' );
  $sql = "INSERT INTO images (img_blob) VALUES (:imageFile)";
    $st = $conn->prepare ( $sql );
    $st->bindValue( ":imageFile", $imageFile, PDO::PARAM_LOB);
    $st->execute();

Result:

SELECT LENGTH( img_blob) FROM DUMB_DB.images WHERE id=1; // 770042 bits

So, I would suggest to change the type from BLOB to LongBlob.

Link to comment
Share on other sites

Dunno, you are still not posting the only bit of code that I want to see :-)

 

 

You are using $data['img_blob'], but how to you fill $data? Where does the content of img_blob come from?

 

You prepare the $st variable but you don't show that you execute the statement and how you catch the errors it might return.

Link to comment
Share on other sites

Change this line: 

$st->bindValue( ":imageFile", $this->img_blob, PDO::PARAM_LOB);

To this: 

$st->bindValue( ":imageFile", $imageFile, PDO::PARAM_LOB);

and it should work fine, although you shouldn't be doing this in the first place.

We see your class structure but not the call to the class, show that as well, the problem appears to be the data that you are sending to the class.

Link to comment
Share on other sites

Change this line: 

$st->bindValue( ":imageFile", $this->img_blob, PDO::PARAM_LOB);

To this: 

$st->bindValue( ":imageFile", $imageFile, PDO::PARAM_LOB);

and it should work fine, although you shouldn't be doing this in the first place.

We see your class structure but not the call to the class, show that as well, the problem appears to be the data that you are sending to the class.

 

Yes, it works now. Thank you so much for this. "although you shouldn't be doing this in the first place." --> what I am doing wrong here?

 

Call to class:

function newImage() {

  $results = array();

$results['formAction'] = "newImage";

 if ( isset( $_POST['saveChanges'] ) ) {

    // User has posted image - edit form: save the new image
    $image = new cmsImages;
    $image->storeFormValues( $_POST );
    $image->uploadImage();
    header( "Location: admin.php?status=changesSaved" );

  } elseif ( isset( $_POST['cancel'] ) ) {

    // User has cancelled their edits: return to image list
    header( "Location: admin.php" );
  } else {

    // User has not posted the image edit form yet: display the form
    $results['image'] = new cmsImages;
    require( TEMPLATE_PATH . "/admin/webImages/editImage.php" );

I hope this will be more clear

Edited by tomce
Link to comment
Share on other sites

 

Where $this->img_name comes from?

$st->bindValue( ":img_name", $this->img_name, PDO::PARAM_STR );
$st->bindValue( ":imageFile", $this->img_blob, PDO::PARAM_LOB);

Ohh I see, well I am using single php file - for editing and inserting new record. So my edit file appears with empty form fields if I am trying to insert new record + parameters and file appears with content if specific row needs to be updated only. I know it sounds confusing - but it works.

Link to comment
Share on other sites

 

So my edit file appears with empty form fields if I am trying to insert new record + parameters and file appears with content if specific row needs to be updated only. I know it sounds confusing - but it works.

Why? This is very good practice. If you want to upload some data no needs to use a hidden field inside the form, but when you try to update the same data, it's always good to have a hidden filed with this id. 

 

EDIT: The part that I don't understand is how (where) you instantiated these objects?

Edited by jazzman1
Link to comment
Share on other sites

Okay, let's take a step back here.

As much as I love spaghetti, I don't enjoy trying to read spaghetti code.

 1. These two lines 

$image = new cmsImages;
$image->storeFormValues( $_POST );

call the class construct twice. storeFormValues() is not needed, instead it should read.

$image = new cmsImages( $_POST );

2. The image information is stored in $_FILES not $_POST, which is why file_get_contents($_FILES['file']['tmp_name']) holds the correct data.

 

3. Read my first post in this thread because I state the reasons why your logic is flawed.

 

4. But since it seems like you don't want to listen to reason and just want an answer, your construct should read something like this:

public function __construct( $post_data = array(), $file_data = array() ) {
    if ( isset( $post_data['img_id'] ) ) $this->img_id = (int) $data['img_id'];    
    if ( isset( $post_data['img_name'] ) ) $this->img_name = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['img_name'] );    
    if ( isset( $file_data['file'] ) ) $this->img_blob = file_get_contents($file_data['file']['tmp_name']);   

then you would pass the construct its arguments like so:

$image = new cmsImage( $_POST, $_FILES );

I feel so dirty writing this.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.