UPS-PHP Patch to Log Requests and Responses

UPS doesn’t seem to be too big of a fan of Perl or PHP. They provide some powerful functionality through their API’s and their documentation is sufficient, but doesn’t contain examples of anything except for Visual Basic or Java. Fortunately their is an open source project called UPS-PHP that aims to fill that gap by providing some classes for interacting with UPS’s APIs. The UPS-PHP project seems to have lost steam though as the latest updates were over a year ago.

The latest version of the UPS shipping API requires the user to go through a process of creating test transactions, then voiding some transactions in a sandbox environment prior to allowing you access to the production environment. You have to email them every request and response that you send and received for the test transactions as well as various images and HTML documents that were created from their responses.

I added some logging ability to the UPS-PHP class responsible for sending and receiving the responses. A patch is available here if anybody else wants to try it. You basically call the new methods setDebugDir() and setTransaction() on the ‘ups’ object. Those tell it which directory to log to, and which filename to use respectively.

Usage would look something like this:

    $debug_dir = "{$_SERVER['DOCUMENT_ROOT']}/upsdebug/".date('Y')."/".date('m');
    // make sure that $debugdir exists... Create it if necessary
    $upsConnect->setDebugDir($debug_dir);
    $upsConnect->setTransaction(time());
    $upsConnect->setTemplatePath('../../xml/');
    $upsConnect->setTestingMode(1); // Change this to 0 for production
    $upsVoid = new upsVoid($upsConnect);
    $upsVoid->buildRequestXML($ShipmentIdentificationNumber);

At this point your $debugdir would have two files in it. One with the XML request and the other with the XML response, suitable for zipping up and sending to UPS for approval.

PROCEDURE can’t return a result set in the given context

I ran into a problem today when dealing with a very simple SQL Query. The query simply calls a stored procedure on the MySQL server. This is a trivial app, so I was using the very basic mysql_connect(), mysql_query() functions. The result wasn’t being returned an mysql_error() was saying that the error was:

PROCEDURE db.procedure_name can't return a result set in the given context

Of course ‘db.procedure_name’ was the actual name of the procedure I was calling. Googling for the error seemed to indicate that the MySQL client library was old, but this is on a fairly modern CentOS 5.5 server with the php-mysql package at version 5.1.6.

After a bit of experimenting, I found that I was able to change to using the mysql improved versions of the PHP functions and that worked fine

     $dbconn = mysql_connect($dbhost, $dbuser, $dbpass);
     $result = mysql_query("CALL db.procedure_name('arg1', 'arg2', 'arg3')", $dbconn)
     $row    = mysql_fetch_assoc($result);

Becomes

    $dbconn = mysqli_connect($dbhost, $dbuser, $dbpass);
    $result = mysqli_query($dbconn, "CALLdb.procedure_name('arg1', 'arg2', 'arg3')");
    $row    = mysqli_fetch_assoc($result);

Note that changing from mysql_query to myqli_query needs the parameters reversed.

After making that change I’m able to run the stored procedure correctly.

Southeast Linux Fest Presentation on MySQL Replication

I was fortunate to be selected to give a presentation at the 2010 Southeast Linux Fest held this year in Greenville, SC. The topic was MySQL replication which I picked from a similar presentation I gave about about 1.5 years ago at my local LUG. I’ve configured plenty of replicated servers and I think that I understand it well enough to explain it to others.

The 2-hour presentation is about half slides and half demo. Throughout the course of the presentation I set up a simple master-slave. Then I add a second slave. Taking it a step farther I set up the three servers to replicate in a chain, and finally I configure them to replicate in a full circle so that changes made on one are propagated to all of the others. I intentionally do things that break replication at certain points to show some of the limitations and configurable features that can help it to work.

Slides for the presentation are available OpenOffice format.

The presentation was recorded, so hopefully the SELF team will have those videos available shortly.