MacLochlainns Weblog

Michael McLaughlin's Technical Blog

Site Admin

Archive for the ‘PHP’ Category

MySQL Local Connect Only

with one comment

Somebody asked if you really have to run the MySQL Configuration Wizard when you want to shut out network connections. The answer is no.

If you want to secure the database server to perform maintenance, you can comment out the port assignment line in the [mysqld] section and add the following in the same section:

# The TCP/IP Port the MySQL Server will listen on
# port=3306

# Instruct it to skip networking and enable named pipes.
skip-networking
enable-named-pipe
 
# Define the Pipe the MySQL Server will use.
socket=mysql

This allows only users on the local system to connect to the database. You can test it by running the following PHP program as a command-line process form the server.

1
2
3
4
5
6
7
8
9
10
11
12
<?php
  // Attempt to connect to your database.
  $c = @mysqli_connect("localhost", "username", "password", "somedb");
  if (!$c) {
    print "Sorry! The connection to the database failed.";
    die();
  }
  else {
    // Initialize a statement in the scope of the connection.
    print "Congrats! You've connected to a MySQL database!";
  }
?>

You call a command-line PHP program like this:

php phpConnect.php

It would fail when you call it from the Apache web server’s htdocs folder because network communication across TCP/IP is closed. Only local sockets are available across the mysql pipe. There’s no magic to the pipe name of mysql but it’s the default pipe name convention.

Written by maclochlainn

December 14th, 2010 at 12:36 am

Posted in MySQL,PHP

Bioinformatics Conference

without comments

This week I attended the first ACM conference on Bioinformatics and Computational Biology in Niagara Falls, NY. The next conference is in Rome next January. It was interesting to note who’s using what technology in their research.

Here’s a breakdown:

  • Databases: MySQL is the de facto winner for research. Oracle for clinical systems, mostly Oracle 10g implementations. That means moving data between the two is a critical skill. Specifically, exporting data from Oracle and importing it into MySQL. Oracle was criticized for being a DBA-preserve and unfriendly to development. When I probed this trend, it seemed to point to DBAs over managing sandbox instances at companies with site licenses. Microsoft SQL Server didn’t find a lot of popularity in the research community.
  • Programming Skills: C#, C++, Objective-C and PHP were high on the list. C# to import data into Microsoft SharePoint and develop Windows SmartPhones. C++ to extend MySQL. Objective-C to develop iPhone and iPad applications. PHP to build applications to manage studies and facilitate input, but there were a couple using Perl (not many).
  • Collaboration Tools: Microsoft SharePoint won handily. It’s made a home in the clinical and research communities.

Overall, they want programmers who understand biology and chemistry. They’d like knowledge through Medical Microbiology and Introductory Biochemistry, and they want strong math and statistical knowledge in their programming staff. They like Scrum development frameworks. They seem to emphasize a chief engineering team, which means the developers get maximum face-time with the domain experts. The developers also have to speak and walk the talk of science to be very successful.

As to Niagara Falls, I’m glad that I took my passport. The Canadian side is where I spent most of my extra time and money. It has the best views of the falls, the best food, and ambiance. Goat Island and the Cave of the Winds are the only two features I really liked on the U.S. side of Niagara Falls. The U.S. side is dreary unless you like gambling in the Seneca Niagara Casino & Hotel. Since I’m originally from Nevada, I never entered it to check it out. Technically, when you step on the casino property you enter the Seneca Nation of New York. The New York state government in Albany really needs to address the imbalance or they’ll continue to see Canada score the preponderance of tourist dollars.

Written by maclochlainn

August 6th, 2010 at 11:31 pm

Posted in C,MySQL,Objective-C,Oracle,PHP

Tagged with ,

PHP Function Primer

without comments

Added a new PHP Function Primer for my students. This one’s not large but fits as a page better. If you’re interested it’s here.

It covers:

  • Function Definitions
  • Creating & Using Functions
  • Pass-by-value Functions
  • Pass-by-reference Functions
  • Dynamic Functions
  • Function Default Parameters
  • Variable-length Parameter Lists

Written by maclochlainn

April 2nd, 2010 at 10:17 pm

Posted in LAMP,MAMP,PHP

PHP Tutorial Available

with 5 comments

I finally got around to writing that PHP Tutorial. It’s a bit large and takes about 10 seconds to load or longer depending on your connection and machine. It covers the basics from writing your first page to loops. It was too large for a blog post, so it’s a blog page. Click on the link if you’d like to check it out.

I plan others on functions, objects, and files. Then, I’ll get to tutorials against databases.

Naturally, suggestions are always welcome.

Written by maclochlainn

March 29th, 2010 at 11:11 am

Posted in LAMP,MAMP,OPAL,PHP

PHP Binding a Wildcard

with 8 comments

Somebody asked me about how you bind a parameter in mysqli when a multiple character wildcard needs to be next to the variable value. They’d found that it worked when creating a SQL statement by concatenation (string gluing), like this:

$sql = "SELECT item_title FROM item WHERE item_title LIKE '%".$title."%'";

However, they tried to bind the variable following the same pattern, and found that it failed. They used the following type of syntax:

$sql = "SELECT item_title FROM item WHERE item_title LIKE '%?%'";

It raised the following error:

Warning: mysqli_stmt_bind_param() [function.mysqli-stmt-bind-param]: Number of variables doesn't match number of parameters in prepared statement in program_name on line #

The reason is the parser, it expects variables to be independent tokens in the SQL string. You can’t bind a string into the shell of an apostrophe delimited string. You could naturally, make an assignment to the local PHP variable before binding it to the variable, like this:

$title = '%'.$title.'%';

It’s actually a better idea to concatenate the multiple character wildcard operator inside the SQL statement. The correct syntax requires that you use the CONCAT() function. You could reset to use piped concatenation but generally you should avoid that on the MySQL platform (see this post for an explanation of SQL concatenation on Oracle, MySQL, and SQL Server).

This is the required statement when using a MySQL database:

$sql = "SELECT item_title FROM item WHERE item_title LIKE CONCAT('%',?,'%')";

Written by maclochlainn

February 21st, 2010 at 1:13 am

Posted in LAMP,MAMP,MySQL,PHP

The ereg() function is gone

with one comment

Alas, poor ereg() I abused you well. PHP 5.3 has deprecated ereg() and now we must move forward with preg_match(). Along with that change, somebody asked me to show how to upload images to the file system as opposed to the database. Personally, I think they should be stored in the database.

With my bias toward databases, I threw in a virtual directory mapping in a MySQL database because it doesn’t natively support an Oracle equivalent BFILE data type. You can see this older post how to use the DBA_DIRECTORIES view in Oracle to mimic this behavior.

Naturally, MySQL is the preferred database of the person asking the question. You could also implement this exactly the same in Oracle but you really don’t want to do so. Using Oracle’s virtual directories has it’s own pre-built set of security features. They provide a more robust solution.

The code is presented as follows (setup for MySQL instructions):

  1. Create and seed the DIRECTORY table in MySQL:
-- Create a directory table.
CREATE TABLE directory
( directory_id   INT PRIMARY KEY AUTO_INCREMENT
, virtual_name   VARCHAR(30)
, directory_name VARCHAR(60));
 
-- Seed the table with a virtual directory mapping.
INSERT INTO directory VALUES ( NULL,'CMS_IMAGES','C:\\Data' );
  1. Create a MySQLCredentials.inc credentails file for inclusion in the PHP program:
1
2
3
4
5
6
7
<?php
  // Connection variables.
  define('HOSTNAME',"localhost");
  define('USERNAME',"student");
  define('PASSWORD',"student");
  define('DATABASE',"sampledb");
?>
  1. Create the PHP uploading program, named MySQLFileUpload.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?php
  // Set database credentials.
  include_once("MySQLCredentials.inc");
 
  // Declare input variables.
  $id = (isset($_POST['id'])) ? $_POST['id'] : 1021;
 
  // Upload a file to server in a mapped physical drive location.
  if (process_uploaded_file(map_virtual_directory($id)))
    print "Successfully Uploaded the file.<br />";
 
  // Map a virtual directory to a physical directory.
  function map_virtual_directory($virtual) {
 
    // Return successful attempt to connect to the database.
    if (!$c = @mysqli_connect(HOSTNAME,USERNAME,PASSWORD,DATABASE)) {
 
      // Print user message.
      print "Sorry! The connection to the database failed. Please try again later.";
 
      // Return error message.
      print mysqli_error();
 
      // Kill the resource.
      die();
    }
    else {
 
      // Initialize a statement in the scope of the connection.
      $stmt = mysqli_stmt_init($c);
 
      // Declare a case insensitive dynamic SQL statement.
      $sql = "SELECT directory_name FROM directory WHERE virtual_name = UCASE(?)";
 
      // Prepare the statement.
      if (mysqli_stmt_prepare($stmt,$sql)) {
 
        // Bind the input parameter to the prepared statement.
        mysqli_stmt_bind_param($stmt,'s',$virtual);
 
        // Execute the prepared statement.
        if (mysqli_stmt_execute($stmt)) {
 
          // Bind the result to a local variable.
          mysqli_stmt_bind_result($stmt,$directory);
 
          // FetchPrepare statement and link it to a connection.
          while (mysqli_stmt_fetch($stmt))
            return $directory;
        }
        else
          // Return error message.
          print mysqli_error();
      }
      else
        // Return error message.
        print mysqli_error();
 
          // Disconnect from database.
      mysqli_close($c);
    }
  }
 
  // Manage file upload.
  function process_uploaded_file($directory) {
 
    /* Assume the application may allow a virtual directory with a trailing backslash or forward
       slash to be stored in the database, and manage both scenarios across Windows and Linux. */
    if (preg_match(".Win32.",$_SERVER["SERVER_SOFTWARE"]))
      if (preg_match("/\b\\\/",$directory));
      else if (preg_match("/\b\//",$directory)) {
        $directory = substr($directory,0,strlen($directory)-1);
        $directory = $directory."\\";
      }
      else $directory = $directory."\\";
    else
      if (preg_match("/\b\//",$directory))
        $directory = substr($directory,0,strlen($directory)-1);
      else
        $directory = $directory."/";  
 
    // Check for, move uploaded file, and confirm processing.
    if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
 
      // Move temporary cache into a file directory with the uploaded file name.
      move_uploaded_file($_FILES['userfile']['tmp_name'],$directory.$_FILES['userfile']['name']);
 
      // Remove this from real code, it's here for example only. ;-)
      print "Uploaded [".$_FILES['userfile']['name']."] to".$directory."<br />";
 
      // Return true to encapsulate the functional logic on success.
	    return true;
    }
    else
      // Return false to encapsulate the functional logic on failure.
	    return false;
  }
?>
  1. Create a web page to test it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<html>
<head>
<title>
  UploadFileFormMySQL.htm
</title>
</head>
<body>
<form id="uploadForm"
      action="MySQLFileUpload.php"
      enctype="multipart/form-data"
      method="post">
  <table border=0 cellpadding=0 cellspacing=0>
    <tr>
      <td width=125>Item Number</td>
      <td>
        <input id="id" name="id" type="text">
      </td>
    </tr>
    <tr>
      <td width=125>Select File</td>
      <td>
        <input id="uploadfilename" name="userfile" type="file">
      </td>
    </tr>
    <tr>
      <td width=125>Click Button to</td>
      <td><input type="submit" value="Upload File"></td>
    </tr>
  </table>
</form>
</body>
</html>

Hope this helps a few folks. I imagine that the prepared statement with bound variables may help a few folks because it’s not found (at writing) on the php.net web site.

Written by maclochlainn

December 29th, 2009 at 2:03 am

Posted in LAMP,Linux,MAMP,PHP,Zend

Lobs with mysqli in PHP 5.3

without comments

We got away with a bit of lazy PHP, at least through PHP 5.29. Especially when we worked with LOB columns. All that is at an end with PHP 5.3. You must now call the mysqli_stmt_store_results($stmt); function (line number 76 in the program snippet below from source) between the execute and bind result phrases.

The function transfers a result set from a prepared statement. You need to use it when performing a SELECT, SHOW, DESCRIBE, or EXPLAIN statement that you will call by the mysqli_stmt_fetch($stmt); function.

Without using it, you may only see part of a MEDIUMTEXT column displayed. Likewise, an image from a MEDIUMBLOB column won’t be displayed at all unless you store their results too, by using the same function call.

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Prepare statement.
if (mysqli_stmt_prepare($stmt,$sql)) {
  mysqli_stmt_bind_param($stmt,"i",$id);
 
  // Execute it and print success or failure message.
  if (mysqli_stmt_execute($stmt)) {
 
    // Store result, which eliminates memory cutting off lob streams.
    mysqli_stmt_store_result($stmt);
 
    // Bind result to local variable.
    mysqli_stmt_bind_result($stmt, $desc);
 
    // Read result.
    mysqli_stmt_fetch($stmt);
 
    // Print result.
    print $desc;
  }
}

Also, that oldie ereg() function is deprecated for preg_match() in PHP 5.3 and removed in PHP 6. Don’t forget to make those changes if you were lazy like me before updating to PHP 5.3.

Written by maclochlainn

December 4th, 2009 at 11:59 pm

Posted in MySQL,PHP

Windows 7 and Zend CE

with 5 comments

Installed Zend Community Edition on Windows 7 64-bit. It worked easily. You just need to remember to install the JSDK 32-bit version for the Java Bridge. Clear notation about phpMyAdmin and MySQL being separate downloads has been added to the new Zend Community Edition Server (4.0.6), and it clearly does support Windows 7.

If you plan on installing MySQL and Oracle, I would recommend you install MySQL after you install Oracle and the Zend Community Server. However, it doesn’t matter because both ways work.

That completes my WAMP (Windows, Apache, MySQL, Perl, PHP, or Python) and OPAW (Oracle, Perl, PHP, or Python, Apache, Windows) installations. Actually, I’m not sure there is an OPAW acronym for a LAMP stack running Oracle on a Windows platform. OPAL is the acronym for a LAMP stack running an Oracle database, but I’ve never seen one before for Windows. Therefore, I created one.

My two cents worth …

I’d vote for clearer guidance on these acronyms. After all, they’re only purpose appears to be how to market variants of LAMP. The variants that I’ve seen for LAMP (Linux) are: MAMP (Mac OS X), SCAMP (Santa Cruz Operation), SAMP (Solaris), OAMP (OpenBSD, and WAMP (Windows) for MySQL database versions. The key seems to be swapping the first letter. I’ve only seen OPAL (Linux) officially for a LAMP stack that uses an Oracle database on a Linux platform. While my OPAW leverages what I perceive as a possible pattern, it may be wrong. Does anybody know what the right way to label these is?

Written by maclochlainn

November 28th, 2009 at 10:56 pm

reCAPTCHA on WordPress

with 7 comments

I put up a contact page (@Contact Me) for two reasons. Too many folks wanted to ask something and could only do so through a comment. I would review the comment, email them, et cetera. Reason two is simpler, I should have done it from the outset.

There were a few gotchas beyond installing and securing your public and private keys. I figured that it might be helpful to note them here, especially if I have to troubleshoot it later. 😉

  1. You need create a template, like contact.php script, which should include your contact form. You’ll also embed some reCAPTCHA PHP inside this file.

Make sure that your action attribute points to the following location, which is discussed later in step 5.

<?php
<form action="/wp-content/themes/<theme name>/contact_code.php" class="contact" method="post">
?>

The reCAPTCHA PHP should be the last element in your form tag set.

<?php
  // Include the reCAPTCHA library, this assumes a relative directory.
  require_once('recaptchalib.php');
 
  // Get a key from http://recaptcha.net/api/getkey
  $publickey = "<your public key value goes here>";
 
  // The response from reCAPTCHA
  $resp = null;
  // The error code from reCAPTCHA, if any
  $error = null;
 
  echo recaptcha_get_html($publickey, $error);
?>
  1. You need to put the following WordPress template stub at the beginning of your contact.php page.
<?php
  /*
    Template Name: contact
  */
?>
  1. After you create and position the contact.php file in the /wp-content/themes/<theme_name>/ within the document root, you should create a new blog page. You don’t put any text in the page, rather you simply choose the contact.php from your list of templates. You also need a title for the page, I used @contact-me (the @ won’t be used in any reference in the URL), which is an alias to the page
  1. You need to put the balance of your PHP code in a separate file, like contact_code.php and put the URL re-write and reCAPTCHA calls here.
<?php
  // Include the library for reCAPTCHA at the theme level in the file hierarchy.
  require_once('recaptchalib.php');
 
  // Put any form PHP here.
 
  // Declare your private key.
  $privatekey = "<put your private key here>";
 
  // Check whether there a reCAPTCHA response?
  if ($_POST["recaptcha_response_field"]) {
    $resp = recaptcha_check_answer($privatekey
                                  ,$_SERVER["REMOTE_ADDR"]
                                  ,$_POST["recaptcha_challenge_field"]
                                  ,$_POST["recaptcha_response_field"]);
    // Check for valid response.
    if ($resp->is_valid) {
      if(!$errors) {
        $to = '<email here>@<domain here>';
        $subject = $subject;
        $message = "From: ".$name."\nMessage: ".$message;
        $from = 'From:'.$email;
        mail($to,$subject,$message,$from);
 
        // Set the header to the document root when successful.
        header("Location: /");
      }
    }
    else {
      // Set the header to the virtual path for the contact page.
      header("Location: /contact-me/");
      $error = $resp->error;
    }
  }
?>

That’s about it. If I forgot something, you’ll let me know.

Written by maclochlainn

July 18th, 2009 at 10:08 pm

Posted in PHP,WordPress

PHP for loading a BLOB

with 2 comments

Sometimes you chalk something up as straightforward because you’ve done it a while. I did that in a lab assignment recently. It asked my students to upload a large text file and image to the MySQL database, store them in a TEXT and MEDIUMBLOB column, and read them back out of the database, like this:

mysql_lob4

The trick was that I wanted them to read the file into a string and then load the string. There wasn’t a single code example to do this out there, except some that might exist behind an account and credit card payment. I put together a complete example like the Oracle LOB processing page. You can find it here in the MySQL LOB processing blog page. More or less, it shows you how to stream an image into a MySQL database in chunks (I chose 8 K chunks).

The general tricks to upload a string require you enclose to enclose them with the addslashes() function before assigning a binary stream to a variable, then stripslashes() function by segment before you load it to the database. You really don’t need to do that. It’s a myth. The binary stream doesn’t require that extra handling. In fact, you can corrupt certain images when you use the addslashes() and stripslashes() functions; they should be avoided in this context.

You should do it in streams (at least when they’re larger than 1 MB), I chose the procedural mysqli to demonstrate it because there wasn’t an example that I or my students could find on the web. Just for information, some laptops don’t have the resources to accommodate LARGEBLOB datatypes on the Windows OS. The BLOB or MEDIUMBLOB should work fine, especially for this little example.

46
47
48
49
50
51
52
53
54
55
56
57
58
    // Declare a PL/SQL execution command.
    $sql = "UPDATE item SET item_blob = ? WHERE item_id =  ?";
 
    // Prepare statement and link it to a connection.
    if (mysqli_stmt_prepare($stmt,$sql)) {
      mysqli_stmt_bind_param($stmt,"bi",$item_blob,$id);
 
      $start = 0;
      $chunk = 8192;
      while ($start < strlen($item_blob)) {
        mysqli_send_long_data($stmt,0,substr($item_blob,$start,$chunk));
        $start += $chunk;
      }

You can find the code in that blog page referenced. Hope it helps some folks.

Written by maclochlainn

July 9th, 2009 at 2:57 am

Posted in LAMP,MAMP,MySQL,PHP