Category: "PHP"

Log ALL Errors

Graceful error trapping and display is important, both during development and after deployment. It is also good to have debug control that is manageable through environment variables. One nice solution is to use SetEnv in .htaccess or a .conf file.

Regardless of the trap and display code, be sure to log all errors, so you can resolve them if they occur. Check the error log (usually /etc/httpd/logs/error_log) frequently.

Along those lines, although using isset in Smarty template will not cause an error, if the Smarty variable inside the call is not set, a PHP will be thrown (http://smarty.net/manual/en/language.modifier.default.php). Possible solutions:

  • Do nothing - disk space is cheap and the logs get rotated (this is the wrong answer)
  • Initialize all Smarty variables for the templates in the PHP (a good answer)
  • Use PHP to initialize the template variables within the template, using {php} tags (also a valid approach)
  • Use AJAX to populate forms (may be much more difficult and take longer)

The best approach depends on the application architecture, and may vary by template within the application.

It is good to look at the compiled templates to see how they are constructed.

Interpretive File Architectures - PHP & Perl

If you are developing code for interpretive languages such as PHP & Perl, consider the use of the scripts carefully.

As a rule, you should strive to write code which evaluates only the code required for execution. Files should be as small as possible. This is especially important for scripts that run frequently or must be fast.

Key areas to check:

  • Use of ‘library’ files - large files with a collection of unrelated functions that support several types of scripts. These almsot always require the including files to read code that won’t be executed. Better to break them up by related functionality.
  • Common functions should be placed in a single, small, common file. Good components include database connection functions, simple error reporting, and constants.
  • Logging levels should be managed through environment variables. This allows adjustments without modifying code.
  • OOP architectures should probably be avoided for files that require high speed performance.

info2spec.sh - Translator from Drupal .info to RPM .spec files

This is a very simple translation of a Drupal .info file into an RPM .spec file. It may be useful in identifying methods to assemble complex Drupal installations on dedicated servers or VPSs where the modules can be managed as RPMs. This would not be useful for casual users. It also assumes the modules will not be modified, and requires careful composition of the .info files by contributors.

I had difficulty posting the script in the blog, so the link provided must be used.

To run it, pass the URL of the module to download, for example: ./info2spec.sh http://ftp.drupal.org/files/projects/annotationfield-5.x-1.x-dev.tar.gz

It was tested with the annotationfield module.

Be sure to set up an .rpmmacro file at the account level.

* CAUTION *

  • Hasn’t been (and isn’t going to be) tested with an actual RPM build
  • Does not (and probably won’t) handle intermodule dependencies or conflicts

Drupal RPM spec file generator module

A Drupal RPM generator module could scan the modules installed and extract the following information:

  • Source file (full URL)
  • Requires - the modules required to support each module
  • Provides - the name of the service/capability/feature provided by each module
  • Conflicts with - modules which cannot be installed with each module

The standard BUILD, SPECS, SOURCE, RPM, SRPM directories can be used for the build process. The Drupal RPM generator would write .spec files to the SPECS directory for each module. .rpmmacros would indicate the target directory, and other common constants.

This allows a development environment to be quickly converted from a .tgz installation to an RPM managed production server.

Commandline PHP emailer

A nice commandline PHP emailer (can be adapted for sites), derived primarily from code at http://php.net.

Worthy of note:

  • Use of $HOSTNAME to get the name of the host. This is good for commandline when the $_SERVER variables aren’t available.
  • Separate text and HTML source files, normally, text would be derived from HTML with strip_tags.

<?php

if ($argc < 4)
die('Usage: <destination email address> <text file> <html file>'."\n");

$sHost=trim(shell_exec('echo $HOSTNAME'));
$fromname='no-reply';
$fromaddress='no-reply@'.$sHost;

$sTo=$argv[1];
$sTextFile=$argv[2];
$sHTMLFile=$argv[3];

$boundary='=_'.time();

$plain=file_get_contents($sTextFile);

$html=file_get_contents($sHTMLFile);

/* Courtesy of: http://www.php.net/manual/en/ref.mail.php#77405 - Modified slightly */

$eol="\r\n";
$mime_boundary=md5(time());

# Common Headers
$headers .= "From: ".$fromname."<".$fromaddress.">".$eol;
$headers .= "Reply-To: ".$fromname."<".$fromaddress.">".$eol;
$headers .= "Return-Path: ".$fromname."<".$fromaddress.">".$eol; // these two to set reply address
$headers .= "Message-ID: <".time()."-".$fromaddress.">".$eol;
$headers .= "X-Mailer: PHP v".phpversion().$eol; // These two to help avoid spam-filters

# Boundry for marking the split & Multitype Headers
$headers .= 'MIME-Version: 1.0'.$eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"".$mime_boundary."\"".$eol.$eol;

# Open the first part of the mail
$msg = "--".$mime_boundary.$eol;

$htmlalt_mime_boundary = $mime_boundary."_htmlalt"; //we must define a different MIME boundary for this section
# Setup for text OR html -
$msg .= "Content-Type: multipart/alternative; boundary=\"".$htmlalt_mime_boundary."\"".$eol.$eol;

# Text Version
$msg .= "--".$htmlalt_mime_boundary.$eol;
$msg .= "Content-Type: text/plain; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
# $msg .= strip_tags(str_replace("<br>", "\n", substr($body, (strpos($body, "<body>")+6)))).$eol.$eol;
$msg .=$plain.$eol.$eol;

# HTML Version
$msg .= "--".$htmlalt_mime_boundary.$eol;
$msg .= "Content-Type: text/html; charset=iso-8859-1".$eol;
$msg .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$msg .= $html.$eol.$eol;

//close the html/plain text alternate portion
$msg .= "--".$htmlalt_mime_boundary."--".$eol.$eol;
# Finished
$msg .= "--".$mime_boundary."--".$eol.$eol; // finish with two eol's for better security. see Injection.

# SEND THE EMAIL
$mail_sent = mail($sTo, "Test From $sHost", $msg, $headers);

?>

Risks of HTML emails: http://www.mailchimp.com/resources/top10_html_email_mistakes.phtml

Recommending testing prior to production release
Receipt of emails on all major email clients
http://fingerprintapp.com/email-client-stats