Posts Tagged ‘php’

Converting XML to Associative Array in PHP

// March 2nd, 2011 // No Comments » // Code Codex

Sometimes there are situations where I have had code that is expecting an Associate Array with its corresponding values to deal with. However, as can often stand the case when propagating over to XML, sometimes its not possible (or digitally healthy) to convert everything all at once and I end up in a situation where I have all my data in single layer XML objects but need to interact with it on an associate array level.

So, as a quick to fix I wrote this small function entitled xml2AssArray() to deal with the children of a single layer XML object and turn it into an array with the children’s names used as the key-names of the array.

function xml2AssArray($xmlobj)
{
    $assarray = array(); // Initialize the Array
    // Loop through the XML object's children
    foreach ($xmlobj->children() as $child)
    {
        // Assign the childs name as the key for the next entry while assigning the value itself as well
        $assarray[$child->getName()] = $child;
    }
    return $assarray; // Return the new Array
}

Let’s take this XML object (called $myxml which we create using SimpleXML) for example:

<?xml version="1.0"?>
<Lead>
    <ID>1213</ID>
    <SSN>123450000</SSN>
    <FullName>Israel Smith</FullName>
</Lead>

When we run it through our new function, the array that is returned, is now an associate array:

> $myarray = xml2AssArray($myxml);
> echo $myarray['FullName'];
Israel Smith
>

Huzzah!

PHP Simple Outbound Email API Library

// November 4th, 2010 // No Comments » // Code Codex

On occasion I find it necessary on a project to setup my mini library for outbound email. I may not need a full set of functionality like the super large libraries (nor do I want the bloat), however, I do have some basic (semi-advanced) features as a requirement.

1. Sending an E-mail should be as Simple as 1 function call
2. Normal Text Mail Support
3. HTML Mail Support
4. Attachment Support

My “email” function which I’ve aptly named “email” can be used like thus:

For a simple E-mail Message:
email($to, $subject, $text_message);

For an E-Mail with both Text and HTML:
email($to, $subject, $text_message, $html_message);

For an E-Mail with just text and an Attachment:
email($to, $subject, $text_message, NULL, $attachment);

Lets go over the lib_email.inc file in 3 separate parts, the global variables/definitions whatever you’d like to call them, support function, and the main function.

Global Variables:



//////////////////////////////////////
// Globals
$__FROM_NAME__ = "Company Name";
$__FROM_ADDR__ = "israel@company.com";

//////////////////////////////////////
// MIME Types
$MediaTypes = array();
// Application Types
$MediaTypes['js'] = 'application/javascript';
$MediaTypes['ogg'] = 'application/ogg';
$MediaTypes['pdf'] = 'application/pdf';
$MediaTypes['ps'] = 'application/postscript';
$MediaTypes['zip'] = 'application/zip';
// Audio
$MediaTypes['mp3'] = 'audio/mpeg';
$MediaTypes['wma'] = 'audio/x-ms-wma';
$MediaTypes['wax'] = 'audio/x-ms-wax';
$MediaTypes['wav'] = 'audio/vnd.wave';
// Image
$MediaTypes['gif'] = 'image/gif';
$MediaTypes['jpg'] = 'image/jpeg';
$MediaTypes['jpeg'] = 'image/jpeg';
$MediaTypes['png'] = 'image/png';
$MediaTypes['svg'] = 'image/svg+xml';
$MediaTypes['tiff'] = 'image/tiff';
$MediaTypes['ico'] = 'image/vnd.microsoft.icon';
// Text
$MediaTypes['css'] = 'text/css';
$MediaTypes['csv'] = 'text/javasccsvript';
$MediaTypes['html'] = 'text/html';
$MediaTypes['txt'] = 'text/plain';
$MediaTypes['xml'] = 'text/xml';
// Video
$MediaTypes['mpg'] = 'video/mpeg';
$MediaTypes['mp4'] = 'video/mp4';
$MediaTypes['qt'] = 'video/quicktime';
$MediaTypes['wmv'] = 'video/x-ms-wmv';
// Other
$MediaTypes['rar'] = 'application/x-rar-compressed';
$MediaTypes['gz'] = 'application/x-gzip-compressed';

You should change __FROM_ADDR__ and __FROM_NAME__ to whatever fits into your project. Also, feel free to add to the MediaTypes array with any and all mime types you think you’ll be using / running across on your project.

We’ll move onto the only support function which I’m calling “createAttachment”. It takes filepath (e.g. /www/whatever/file.exa or ./file.exa) and then determines the filename, filetype and after reading in the file, stores all three bits of information into an associate array that we can use when we call the email() function.

Support Function

//////////////////////////////////////////////////////////////////////////////
// Function: createAttachment()
//////////////////////////////////////////////////////////////////////////////
// Description:
//        Takes a string which points at the file location and creates an
// array to be used by the email() function's $attachment parameter.
//////////////////////////////////////////////////////////////////////////////
// Returns: Array (3 parts; name of the file, mime type, and file contents)
//////////////////////////////////////////////////////////////////////////////
function createAttachment($filename)
{
    global $MediaTypes;

    $attachment = array();
    $filelocation   = explode('/', $filename);
    $attachment['filename'] = $filelocation[sizeof($filelocation) - 1];
    $filenameparts  = explode('.', $filename);
    $extension      = $filenameparts[sizeof($filenameparts) - 1];
    if ($MediaTypes[$extension])
    {
        $attachment['filetype'] = $MediaTypes[$extension];
    }
    $attachment['file'] = file_get_contents($filename);

    return $attachment;
}

Simple enough for my purposes, haven’t run across any problems yet.

Now we move onto the main function: email(). it will automatically generate the boundary types and set all of the appropriate headers for an e-mail. I know there are other header(s), and types, however in all my project I’ve never come across the need to use anything other than what this function produces.

If a message (of any type) or an attachment has been passed along, it will appropriately use them respectively and send out the e-mail using your hosts default PHP associated sendmail program/server.

Main Function

//////////////////////////////////////////////////////////////////////////////
// Function: email()
//////////////////////////////////////////////////////////////////////////////
// Description:
//        Takes self-explanatory parameters in order to send an email.
//
//        $to           - String (An email address)
//        $subject      - String (The Subject line)
//        $text_message - String (The body of the E-Mail Message)
//        $html_message - String (The body of the HTML E-Mail Message)
//        $attachment   - Non-Alphanumeric String (File contents)
//////////////////////////////////////////////////////////////////////////////
// See also: createAttachment()
//////////////////////////////////////////////////////////////////////////////
// Returns: Boolean (Based on Success)
//////////////////////////////////////////////////////////////////////////////
function email($to, $subject, $text_message = NULL, $html_message = NULL, $attachment = NULL)
{
    //////////////////////////////////////////
    // Initialize Message String
    $message = '';

    //////////////////////////////////////////
    // Boundary Section
    //////////////////////////////////////////
    // So we know where to look for the start of the data
    //////////////////////////////////////////
    $boundary = uniqid("Part_");
    $boundary = '----=_'.$boundary;

    //////////////////////////////////////////
    // Headers Section
    //////////////////////////////////////////
    $headers  = 'To: ' . $to . "\r\n";
    $headers .= 'From: "'.$__FROM_NAME__.'" <'.$__FROM_ADDR__.'>' . "\r\n";
    $headers .= 'MIME-Version: 1.0' . "\r\n";
    $headers .= "Content-Type: multipart/alternative;\r\n".
            "        boundary=\"$boundary\"\r\n\r\n";

    //////////////////////////////////////////
    // Plain Text Message
    //////////////////////////////////////////
    if ($message)
    {
        $message .= "--$boundary\r\n".
                "Content-Type: text/plain; charset=UTF-8\r\n".
                "Content-Transfer-Encoding: 7bit\r\n\r\n";
        $message .= $text_message;
        $message .= "\r\n\r\n\r\n\r\n";
    }

    //////////////////////////////////////////
    // HTML Message
    //////////////////////////////////////////
    if ($html_message)
    {
        $message .= "--$boundary\r\n".
                    "Content-Type: text/html; charset=UTF-8\r\n".
                    "Content-Transfer-Encoding: 7bit\r\n\r\n";
        $message .= $html_message;
        $message .= "\r\n";
    }

    //////////////////////////////////////////
    // Attachment
    //////////////////////////////////////////
    // $attachment should be an array with the
    // filename, filetype, and file entries.
    //////////////////////////////////////////
    if ($attachment)
    {
         $message .= "--$boundary\r\n".
                     "Content-Type: ".$attachment['filetype']."; name=".$attachment['filename']."\r\n".
                     "Content-Disposition: attachment; filename=".$attachment['filename']."\r\n".
                     "Content-Transfer-Encoding: base64\r\n\r\n";
         $message .= chunk_split(base64_encode($attachment['file']));
         $message .= "\r\n\r\n\r\n\r\n";
    }

    if (@mail($to, $subject, $message, $headers))
    {
        return true;
    }
    else
    {
        return false;
    }
    return true;
}

In theory you should be able to plug this code in and use right away, although having a general understanding of email construction and also on subjects like the 5-point SPAM detection scale (usually dictated by advanced anti-spam products like spamassassin) would be good.

Likewise, you’ll notice there isn’t much in the way of error-catching, nor multiple attachments.. go ahead and add that in if you please. (If you do, please feel free to share them on here or with me!)

Code Snippets: PHP Function secs2human_time

// October 27th, 2010 // No Comments » // Code Codex

On one project I was working on, it was driving someone crazy that the amount of time that had passed since an action occurred was being displayed in seconds (which was fine if the event had occurred 15 seconds ago, but not so much when 16,540 had).

I couldn’t find a builtin function (no wonder) that would do what I needed, which was to basically take the seconds and display the time in a human readable format. I set out to do that and came up with what I think works fairly well.

Here’s the code:

//////////////////////////////////////////////////////////
// FUNCTION: secs2human_time
// ///////////////////////////////////////////////////////
// Description:
//
// This function takes seconds and converts them into a
// human readable format.
//
// If a string is passed it will be converted into an int
//
// ///////////////////////////////////////////////////////
// Parameters:
//     $total      - Amount of time in seconds
// ///////////////////////////////////////////////////////
// Example:
//     write_time_exact(604927);
//     returns: '1 week 2 minutes 7 seconds'
// ///////////////////////////////////////////////////////
// Returns: string - Human readable length of time from seconds
//////////////////////////////////////////////////////////
function secs2human_time($total)
{
    $secsMinute = 60;
    $secsHour   = 3600;
    $secsDay    = 86400;
    $secsWeek   = 604800;
    $secsMonth  = 2592000;
    $secsYear   = 31104000;

    $result = '';

    $seconds = 0;
    $minutes = 0;
    $hours   = 0;
    $days    = 0;
    $weeks   = 0;
    $months  = 0;
    $years   = 0;

    $total = intval($total);

    if (!$total || $total < 0)
        return FALSE;

    if ($total >= $secsYear)
    {
        $years = floor($total / $secsYear);
        $total -= $secsYear * $years;
    }
    if ($total >= $secsMonth)
    {
        $months = floor($total / $secsMonth);
        $total -= $secsMonth * $months;
    }
    if ($total >= $secsWeek)
    {
        $weeks = floor($total / $secsWeek);
        $total -= $secsWeek * $weeks;
    }
    if ($total >= $secsDay)
    {
        $days = floor($total / $secsDay);
        $total -= $secsDay * $days;
    }
    if ($total >= $secsHour)
    {
        $hours = floor($total / $secsHour);
        $total -= $secsHour * $hours;
    }
    if ($total >= $secsMinute)
    {
        $minutes = floor($total / $secsMinute);
        $total -= $secsMinute * $minutes;
    }
    $seconds = $total;

    if ($years)  { $result = $years.' years '; }
    if ($months) { $result = $result.$months.' months '; }
    if ($weeks) { $result = $result.$weeks.' weeks '; }
    if ($days) { $result = $result.$days.' days '; }
    if ($hours) { $result = $result.$hours.' hours '; }
    if ($minutes) { $result = $result.$minutes.' minutes '; }
    if ($seconds) { $result = $result.$seconds.' seconds '; }

    return $result;
}

Now I toyed with the idea of adding in decades, centuries, millenniums, ages, and eons… but I doubt my code will survive long enough to warrant that.