Editor on June 29, 2012

In this tutorial, I will provide code which will send files to an FTP Server with cURL using PHP.
cURL has many advantages of standard FTP, one of which is better control over error handling.

 

Below is complete code to send a single file to a remote FTP server.

The connection time-out has been set at 10 seconds, and the transfer time-out also set at 10 seconds. This is usually enough time to wait for a response. If a file transfer fails, the script will try to sent the file again a further two times. A log is written out with results of the transfer.

Please refer to the in-line comments for a description of what each part does.

 

<?php
// create constants
define('FTP_SERVER', 'ftp.somedomain.com');
define('FTP_USER', 'ftpusername');
define('FTP_PASS', 'ftppassword');

// create curl handler
$ch = curl_init();
// set connection timeout to 10 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
// set transfer timeout to 10 seconds
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

function sendFile($filepath,$filename,$mode,$retry=0) {
  // enable function access to curl handler
  global $ch;
  // build the connection string
  $remoteurl = 'ftp://'.FTP_USER.':'.FTP_PASS.'@'.FTP_SERVER.'/'.$filename; 
  // open the file
  $fp = fopen($filepath.$filename, "r$mode");
  // set connection
  curl_setopt($ch, CURLOPT_URL, $remoteurl);
  // enable upload
  curl_setopt($ch, CURLOPT_UPLOAD, 1);
  // set file contents
  curl_setopt($ch, CURLOPT_INFILE, $fp);
  // set file size
  curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filepath.$filename));
  // execute the command
  $exec = curl_exec($ch);

  // check for errors
  if(curl_getinfo($ch) <> 226 && $retry < 3) {
    // filed, try again upto 3 times
    sendFile($filepath,$filename,$mode,$retry++);
  } elseif(curl_getinfo($ch) <> 226 && $retry == 3) {
    // all tries have failed
    return false;
  } else {
    // success
    return true;
  }

}

// set file path
$filepath = "/path/to/file/";
$filename = "somefile.jpg";
$mode = "b"; //"b" for binary or "t" for text

if(!sendFile($filepath,$filename,$mode)) {
  echo "failed to transfer $filepath $filename \n";  
}

?>

As mentioned, the above will send a single file. Now here is the same code again, but this time it will read a local directory sending each file.

 

<?php 

// create constants
define('FTP_SERVER', 'ftp.somedomain.com');
define('FTP_USER', 'ftpusername');
define('FTP_PASS', 'ftppassword');

// create curl handler
$ch = curl_init();
// set connection timeout to 10 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
// set transfer timeout to 10 seconds
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

function sendFile($filepath,$filename,$mode,$retry=0) {
  // enable function access to curl handler
  global $ch;
  // build the connection string
  $remoteurl = 'ftp://'.FTP_USER.':'.FTP_PASS.'@'.FTP_SERVER.'/'.$filename; 
  // open the file
  $fp = fopen($filepath.$filename, "r$mode");
  // set connection
  curl_setopt($ch, CURLOPT_URL, $remoteurl);
  // enable upload
  curl_setopt($ch, CURLOPT_UPLOAD, 1);
  // set file contents
  curl_setopt($ch, CURLOPT_INFILE, $fp);
  // set file size
  curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filepath.$filename));
  // execute the command
  $exec = curl_exec($ch);

  // check for errors
  if(curl_getinfo($ch) <> 226 && $retry < 3) {
    // filed, try again upto 3 times
    sendFile($filepath,$filename,$mode,$retry++);
  } elseif(curl_getinfo($ch) <> 226 && $retry == 3) {
    // all tries have failed
    return false;
  } else {
    // success
    return true;
  }

}

// set file path
$filepath = "/path/to/file/";
$mode = "b"; //"b" for binary or "t" for text

$dir = @opendir($filepath);
while ($file = @readdir($dir)) {
  if($file == "." || $file == "..") {
    // not files, ignore
  } else {

    if(!sendFile($filepath,$file,$mode)) {
      echo "failed to transfer $filepath $filename \n";  
    }

  }
}
?>

Tags: , , ,

Editor on June 27, 2012

In this quick example, I will provide code which will do the following:

 

  • Define database connection CONSTANTS
  • Connection to Oracle with a permanent connection
  • Create an INSERT statement with bind variables and empty blobs
  • Create new blob descriptor pointers
  • Bind the INSERT statement (non-blob) variables to PHP variables
  • Bind the INSERT statement blob variables to PHP
  • Execute the Oracle statement checking for any Oracle errors
  • Echo out any Oracle errors found during the execution
  • If no errors were detected, save the blob data
  • Commit the query
  • Free up the blob descriptors

 

Note: Using bind variables provides much better performance from Oracle as it can reuse an execution path.

Note: When inserting blobs, there are several additional steps required (in comparison to non-blob data). These include using descriptors, creating empty blobs in the SQL statement, mapping the blob field names to the descriptors, binding the SQL references to the descriptors using OCI_B_BLOB, and calling the ->save method before committing the query.

 

 

<?

// define some constants
define("DB_USER", "username");
define("DB_PASS", "password");
define("DB", "//host:1523/sid");

// connect to oracle
if(!$con = oci_pconnect(DB_USER, DB_PASS, DB)) {
  echo "Cannot connect to database.";
  exit(9);
}

// sql with variables
$sql = "INSERT INTO table_a 
        VALUES(:somevalue_a,:somevalue_c,EMPTY_BLOB(),EMPTY_BLOB()) 
        returning field_lob_a,field_lob_b into :LOB_A,:LOBA";
$parse_sql = oci_parse($con, $sql);

// create empty lob descriptor
// can use: OCI_D_FILE, OCI_D_LOB or OCI_D_ROWID
$lob_a = oci_new_descriptor($con, OCI_D_LOB);
$lob_b = oci_new_descriptor($con, OCI_D_LOB);

// bind the sql variable to php variable
oci_bind_by_name($parse_sql, ":somevalue_a", $somevariable_a);
oci_bind_by_name($parse_sql, ":somevalue_c", $somevariable_c);
// bind the LOB fields
oci_bind_by_name($parsed_sql, ':LOB_A', $lob_a, -1, OCI_B_BLOB);
oci_bind_by_name($parsed_sql, ':LOB_B', $lob_b, -1, OCI_B_BLOB);

if(!oci_execute($parse_sql, OCI_DEFAULT)) {
  $e = error_get_last();
  $f = oci_error();
  echo "Message: ".$e['message']."\n";
  echo "File: ".$e['file']."\n";
  echo "Line: ".$e['line']."\n";
  echo "Oracle Message: ".$f['message'];
  // exit if you consider this fatal
  exit(9);
} else {

  // save the blob data
  $lob_a->save($lob_date_a);
  $lob_b->save($lob_data_b);
  // commit the query
  oci_commit($con);
  // free up the blob descriptors
  $lob_a->free();
  $lob_b->free();

}
?>

 

 

In another post, I provide code for an Oracle SELECT statement using bind variables, and Oracle INSERT statement (no blobs) using bind variables..

 

 

 

Tags: , , , , ,

Editor on June 27, 2012

In this quick example, I will provide code which will do the following:

 

  • Define database connection CONSTANTS
  • Connection to Oracle with a permanent connection
  • Create an INSERT statement with bind variables
  • Bind the INSERT statement variables to PHP variables
  • Execute the Oracle statement checking for any Oracle errors
  • Echo out any Oracle errors found during the execution
  • Commit the query if the execution ran successfully

 

Note: Using bind variables provides much better performance from Oracle as it can reuse an execution path.

 

<?

// define some constants
define("DB_USER", "username");
define("DB_PASS", "password");
define("DB", "//host:1523/sid");

// connect to oracle
if(!$con = oci_pconnect(DB_USER, DB_PASS, DB)) {
  echo "Cannot connect to database.";
  exit(9);
}

// sql with variables
$sql = "INSERT INTO table_a VALUES(:somevalue_a,:somevalue_c)";
$parse_sql = oci_parse($con, $sql);

// bind the sql variable to php variable
oci_bind_by_name($parse_sql, ":somevalue_a", $somevariable_a);
oci_bind_by_name($parse_sql, ":somevalue_c", $somevariable_c);

if(!oci_execute($parse_sql, OCI_DEFAULT)) {
  $e = error_get_last();
  $f = oci_error();
  echo "Message: ".$e['message']."\n";
  echo "File: ".$e['file']."\n";
  echo "Line: ".$e['line']."\n";
  echo "Oracle Message: ".$f['message'];
  // exit if you consider this fatal
  exit(9);
} else {
  // commit the query
  oci_commit($con);
}

?>

 
 

In another posts, I provide code for an Oracle SELECT statement using bind variables, and Oracle INSERT statement with BLOB data using bind variables..

 

 

 

Tags: , , ,

Editor on June 27, 2012

In this quick code example, I will provide code which will do the following:

 

  • Define database connection CONSTANTS
  • Connection to Oracle with a permanent connection
  • Create a SELECT statement with bind variables
  • Bind the SELECT statement variables to PHP variables
  • Execute the Oracle statement
  • Loop through the returned record set using an associated array

 

Using bind variables provides much better performance from Oracle as it can reuse an execution path.

 

<?php

// define some constants
define("DB_USER", "username");
define("DB_PASS", "password");
define("DB", "//host:1523/sid");

// connect to oracle
if(!$con = oci_pconnect(DB_USER, DB_PASS, DB)) {
  echo "Cannot connect to database.";
  exit(9);
}

// sql with bind variable
$sql = "select field_a from table_a where field_c = :somevalue_a";
$parse_sql = oci_parse($con, $sql);

$somevariable_a = "some value";

// bind the sql variable to php variable
oci_bind_by_name($parse_sql, ":somevalue_a", $somevariable_a);
oci_execute($parse_sql);

// fetch the results and loop through
while ($row = oci_fetch_assoc($parse_sql)) {
  // grab the contents of the field
  $field_a = $row['FIELD_A'];
}

?>

 

 

In another post, I provide code for an Oracle INSERT statement using bind variables.

 

 

 

Tags: , , ,

Editor on June 26, 2012

On this quick lesson, I’m going to provide a way for you to capture PHP errors and write custom logs.

 

PHP can already create error logs for you, but you cannot control the details of them. It may be handy to capture some additional details.

 

When a PHP script ends, you can run some checks to see if any errors have happened, then log it to file.

 

First, we need to tell PHP to call a function whenever a script execution has ended, this is done using “register_shutdown_function”.

 

<?php

register_shutdown_function('catchErrors');

// rest of your code

?>

 

This has told PHP to call a function named “catchErrors” at the end of the script run.

In order to add some custom information to the log, we will use a variable $custom_error_string to hold this. Because this variable is created and set outside of our error function, it needs to be declared as global inside the function (this will allows the function to have access to it).

<?php

register_shutdown_function('catchErrors');

$custom_error_string = "";

function catchErrors() {
 global $custom_error_string;

}

?>

 

We only want the function “catchErrors()” to do anything if an error has occurred, so we need to check using the built-in function “error_get_last()”.

If any errors are found, write the log out to a file.

 

 

<?php

register_shutdown_function('catchErrors');

$custom_error_string = "";

function catchErrors() {
 global $custom_error_string;
 // location of the log file
 $error_log = "myerrors.log";
 // temp string to hold the error log
 $error_buffer = "";

 $e = error_get_last();
 if(isset($e['type']) {
  // an error has been found
  $error_buffer .= "Error recorded at: ".date("Y-m-d H:i:s")."\n";
  $error_buffer .= "Error type: {$e['type']}, ";
  $error_buffer .= "On Line: {$e['line']}, ";
  $error_buffer .= "Of File: $e['file'], ";
  $error_buffer .= "With message: $e['message']\n";

  // look for a custom error string to append to the log
  if($custom_error_string <> "") {
    $error_buffer .= "Custom error: $custom_error_string\n";
  }

  // write out to the log file
  $fp = fopen($error_log, 'w');
  fwrite($fp, $error_buffer);
  fclose($fp);
  // exist with non-zero exit code
  exit(9);
 }
 // clean exit
 exit(0); 

}

// you may want to create some custom message
$custom_error_string = "SQL Error 55 with $mysql_command\n";

?>

You may want to play around with what types of errors to handle – for example you may not be interested in E_WARNING (2) or E_NOTICE (8), but very interested in E_ERROR (1). Changing the IF statement to something like this may work for your needs:

 

// make sure error type is 1 (E_ERROR)
if(isset($e['type'] && $e['type'] == 1) {
 // rest of code in here
}

Tags: , ,