One step closer to world domination
Posts tagged PHP
Making database changes to Drupal multi-sites
Dec 21st
The company I work for hosts over 150 Drupal sites in a multi-site configuration and every so often I need to publish a change to the code that requires a database change. The large number of sites we host means that performing manual changes would require too much time and carries a chance of error. I’ve come up with a simple solution.
I first create a PHP script that bootstraps Drupal. Here is an example of a script that will rebuild the menu router tables.
// Bootstrap require_once('includes/bootstrap.inc'); require_once('includes/common.inc'); drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); // Rebuild menus menu_rebuild(); print 'Menu rebuild complete\n';
I name this script rebuild_menus.php and upload it to my Drupal directory. Then, I create a text file on my desktop that contains a list of all the Drupal websites. This is an abbreviated example:
http://example1.com http://example2.com http://example3.com http://example4.com
Finally, I execute the script on all the sites by running the following command:
for url in `cat list.txt`; do echo "Running script on $url"; curl $url/rebuild_menus.php; echo; done
Programmatically create users in Drupal 6.x
Dec 16th
You can create a Drupal user by sending user_save() a null parameter and an array of user information. You can also assign a role by setting an array that is keyed with the role ID (rid). This can be obtained by calling user_roles() as shown in the example below.
// Get an array of roles $roles = user_roles(); // Basic account information $user = array( 'name' => 'Some User', 'pass' => 'some_password', 'mail' => 'user@example.com', 'status' => 1, 'init' => 'user@example.com', 'roles' => array(array_search('some_role', $roles) => 1), ); // See if the user exists by calling Drupal's user_load() $existing_user = user_load(array('name' => $user['name'])); if (!$existing_user->uid) { // Save the user $user = user_save(NULL, $user); }
Simple Reg-Ex to Validate an Email Address
Nov 24th
Regular expressions can be a pain sometimes. Here’s a code snippet to make your life a little easier when validating email addresses:
$email = 'user@example.com'; if (!eregi("^[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3}$", $email)) { print_error("Your email address is invalid!"); }
PHP MySQL class example
Feb 27th
Here is an example of a PHP 4.2 MySQL connector class. It handles all basic database queries and input filtering and validation.
<?php /**************************************************** * * File: class.mysql.php * Author: Matt West, http://mattdanger.net * Date: February 22, 2007 * Purpose: MySQL Class * ****************************************************/ class MySQL_Connection { // Private variables var $handler; var $hostname; var $username; var $password; var $database; // Public variables var $result; var $num_rows; /** * Constructor: Construct the object. * @param string $hostname Hostname of MySQL server (Default: localhost) * @param string $username Your MySQL account username * @param string $password Your MySQL account password * @param string $database The MySQL database to connect to */ function MySQL_Connection($hostname, $username, $password, $database) { $this->hostname = $hostname; $this->username = $username; $this->password = $password; $this->database = $database; $this->connect(); $this->select_db(); } /** * Destructor: Clean up */ function __destruct() { $this->db_close(); } /** * throw_error(): Print an error message * @param string $message A descriptive error message that will print when invoked */ function throw_error($message, $line = 0){ $line = ( !empty($line) ) ? $line = ' on line ' . $line : '' ; die ('There was an error on line' . $line .' in class "' . __CLASS__ . '": ' . $message); } /** * connect(): Connect to MySQL */ function connect() { $this->handler = mysql_pconnect($this->hostname, $this->username, $this->password) or $this->throw_error(mysql_error(), __LINE__); } /** * select_db(): Select the MySQL database */ function select_db() { mysql_select_db($this->database, $this->handler) or $this->throw_error(mysql_error(), __LINE__); } /** * select(): Select a row or rows from the DB * @param string $table Table name * @param array $columns Either '*' or a list of columns to select * @param array $where column => value * @param array $order_by column1 => DESC, column2 => ASC * @param array $limit 1 or 30 or 0, 30 or 30, 60 (etc) * @param bool $debug Returns query string if true * @returns MySQL resource */ function select($table, $columns, $where = '', $order_by = '', $limit = '', $debug = 0) { if ( $table == '' || !sizeof($columns)) { return; } // Set up columns $tmp = ''; if ( $columns != '*' ) { if ( is_array($columns) ) { foreach($columns as $column) { $data .= '`' . $column . '`, '; } $columns = preg_replace( "/, $/" , "" , $data); } else { $columns = '`' . $columns . '`'; } } // Set up the WHERE if ( !empty($where) ) { $tmp = ''; foreach ($where as $key => $val) { $tmp .= '`' . $key . "` = '" . $this->escape_str($val) . "' AND "; } $where = ' WHERE ' . preg_replace( "/ AND $/" , "" , $tmp); } // Set up the ORDER BY $tmp = ''; if ( !empty($order_by) ) { if ( is_array($order_by) ) { foreach($order_by as $val => $order) { $tmp .= '`' . $val . '` ' . $order . ', '; } $order_by = ' ORDER BY ' . preg_replace( "/, $/" , "" , $tmp); } else { $order_by = ' ORDER BY ' . $order_by . ' DESC'; } } // Set up the LIMIT $tmp = ''; if ( !empty($limit) ) { if ( is_array($limit) ) { foreach ($limit as $num) { $tmp .= $num . ', '; } $limit = ' LIMIT ' . preg_replace( "/, $/" , "" , $tmp); } else { $limit = ' LIMIT ' . $limit; } } $query = 'SELECT ' . $columns . ' FROM `' . $table . '`' . $where . $order_by . $limit; // Return query string for debugging purposes or just do the query if ( $debug ) { return $query; } else { // Perform the query return $this->query($query); } } /** * insert(): Insert data into a table * @param string $table Table to insert into * @param array $data The column name & data * @param boolean $slashes True if you want to add 's to the string * @returns boolean True if successful, false if not. */ function insert($table, $data, $slashes = false) { if ( $table == '' || $data == '' ) { return; } $fields = ''; $values = ''; foreach($data as $key => $val) { $fields .= '`' . $key . '`, '; $val = ( $slashes == true ) ? addslashes($val) : $val; $values .= "'" . addslashes( stripslashes($val) ) . "'" . ', '; } $fields = preg_replace( "/, $/" , "" , $fields); $values = preg_replace( "/, $/" , "" , $values); mysql_query('INSERT INTO `' . $table . '` (' . $fields . ') VALUES (' . $values . ')', $this->handler) or $this->throw_error(mysql_error(), __LINE__); } /** * update(): Update data into a table * @param string $table Table to insert into * @param array $data The column name & data * @param boolean $slashes True if you want to add 's to the string * @returns boolean True if successful, false if not. */ function update($table, $data, $where, $slashes = false) { if ( $table == '' || $data == '' || $where == '') { return; } $string = ''; $tmp = ''; foreach($data as $key => $val) { $string .= '`' . $key . "` = '" . $this->escape_str($val) . "', "; } $string = preg_replace( "/, $/" , "" , $string); if ( is_array($where) ) { foreach ($where as $key => $val) { $tmp .= $key . " = '" . $this->escape_str($val) . "' AND "; } $where = preg_replace( "/AND $/" , "" , $tmp); } else { $where = $where; } mysql_query('UPDATE `' . $table . '` SET ' . $string . ' WHERE ' . $where, $this->handler) or $this->throw_error(mysql_error(), __LINE__); } /** * delete(): Delete a row from a table * @param string $table Table to insert into * @param array $data The column name & data */ function delete($table, $data) { if ( $table == '' || $data == '') { return; } mysql_query('DELETE FROM `' . $table . '` WHERE `' . key($data) . "` = '" . $data[key($data)] . "'", $this->handler) or $this->throw_error(mysql_error(), __LINE__); } /** * query(): Query from MySQL. * @param string $query The MySQL query * @returns MySQL resource * * Warning: This function is only ment to be called manually if being used in * a development environment because it does not do any input validation. */ function query($query) { if ( $query == '') { return; } $this->result = mysql_query($query, $this->handler) or $this->throw_error(mysql_error(), __LINE__); $this->num_rows = mysql_num_rows($this->result); if ($this->num_rows > 1) { $tmp_array = array(); while ($row = mysql_fetch_assoc($this->result)) { array_push($tmp_array, $row); } $this->result = $tmp_array; return $this->result; } else { $this->result = mysql_fetch_assoc($this->result); return $this->result; } } function escape_str($string) { if ( is_array($string) ) { foreach($string as $key => $val) { $str[$key] = $this->escape_str($val); } return $str; } if ( function_exists('mysql_escape_string') ) { return mysql_escape_string( stripslashes($string) ); } else { return addslashes( stripslashes($string) ); } } /** * close_connection(): Close connection to MySQL */ function db_close(){ mysql_close($this->handler); } } ?>
PHP 5 Email Class
Jan 25th
Here is an example class that you can use to send email to users. It includes a properly formatted email body meta information that should avoid most spam filters.
<?php /**************************************************** * * File: class.email.php * Purpose: Email Class * Author: Matt West, http://mattdanger.net * Date: January 25, 2007 * ****************************************************/ class Email { // Public variables public $recipient; public $sender; public $reply_to; public $subject; public $body; public $cc; public $bcc; public $headers; /** * Constructor: Read in $file. * @param string $to Recipient * @param array $from "Sender's Name" => "Sender's Email" * @param string $subject Email subject * @param string $body Email body */ public function __construct ($to, $from = array(), $subject, $body) { // Set receiver $this->receiver($to); // Set sender if ( !empty($from) ) { $this->sender = array( key($from) => $from[ key($from) ] ); } else { $this->sender = array( $_SERVER['SERVER_ADMIN'] => $_SERVER['SERVER_ADMIN'] . '@' . $_SERVER['SERVER_NAME'] ); } // Set subject $this->subject($subject); // Set body $this->body($body); } /** * receiver(): Set receiver of the email * @param array $send_to List of Names & Email addresses */ public function receiver ($send_to) { foreach ($send_to as $name => $email) { if ( $this->email_is_valid($email) ) { if ( !is_numeric($name) ) { $this->recipient = ucfirst($name) . ' <' . $email . '>'; } else { $this->recipient = $email; } $this->recipient .= ', '; } else { exit( $email . " is not a valid email address." ); } } $this->recipient = preg_replace('/, $/', '', $this->recipient); } /** * sender(): Set send of the email * @param array $sender Name & Email address */ public function sender ($sender) { if ( email_is_valid($sender[0]) ) { if ( !is_numeric( key($sender) ) ) { $this->sender = ucfirst( key($sender) ) . ' <' . $email . '>'; } else { $this->sender = $sender[0]; } } else { exit( $sender[0] . " is not a valid email address." ); } } /** * reply_to(): Set send of the email * @param array $reply_to Name & Email address */ public function reply_to ($reply_to) { if ( email_is_valid($reply_to[0]) ) { if ( !is_numeric( key($reply_to) ) ) { $this->reply_to = ucfirst( key($reply_to) ) . ' <' . $email . '>'; } else { $this->reply_to = $sender[ key($reply_to) ]; } } else { exit( $reply_to[0] . " is not a valid email address." ); } } /** * cc(): Set Cc of the email * @param array $cc List of Names & Email addresses */ public function cc ($cc) { foreach ($cc as $name => $email) { if ( email_is_valid($email) ) { if ( !is_numeric($name) ) { $this->cc = ucfirst($name) . ' <' . $email . '>'; } else { $this->cc = $email; } $this->cc .= ', '; } else { exit( $email . " is not a valid email address." ); } } $this->cc = preg_replace('/, $/', '', $this->to); } /** * bcc(): Set Bcc of the email * @param array $bcc List of Names & Email addresses */ public function bcc ($bcc) { foreach ($bcc as $name => $email) { if ( !is_numeric($name) ) { $this->bcc = ucfirst($name) . ' <' . $email . '>'; } else { $this->bcc = $email; } $this->bcc .= ', '; } $this->bcc = preg_replace('/, $/', '', $this->to); } /** * set_headers(): Set email headers */ public function set_headers () { $this->set_from(); $this->headers = "MIME-Version: 1.0rn" . "From: ". $this->sender . "rn" . "To: " . $this->recipient . "rn"; if ( !empty($this->reply_to) ) $this->headers .= "Reply-To: " . $this->reply_to . "rn"; if ( !empty($this->cc) ) $this->headers .= "Cc: " . $this->cc . "rn"; if ( !empty($this->bcc) ) $this->headers .= "Bcc: " . $this->bcc . "rn"; $this->headers .= "X-Priority: 1rn" . "X-Mailer: PHP/" . phpversion() . "rn" . "Content-type: text/html; charset=iso-8859-1rn"; } /** * subject(): Sets the subject of the email. * @param string $subject The subject message. */ public function subject ($subject) { // Strip any newlines $this->subject = str_replace('n', '', $subject); } /** * body(): Sets the body message of the email. * @param string $body The body message. */ public function body ($body) { $this->body = $body; } /** * send(): Send the email * @returns boolean True if successful, false if not. */ public function send () { if (mail ( $this->recipient, $this->subject, $this->body, $this->headers)) { return true; } else { return false; } } /** * email_is_valid(): Check whether email address is valid * @param string $email Email address to check * @returns boolean True if address is valid, false if not. */ private function email_is_valid ($email) { if (eregi("^[_.0-9a-z-]+@([0-9a-z][0-9a-z-]+.)+[a-z]{2,3}$", $email)) { return true; } else { return false; } } } ?>
PHP Login Class
Jan 15th
Here is an example of a PHP 4.2 Login class that you can use when writing your own CMS.
<?php /**************************************************** * * File: class.login.php * Author: Matt West, 2007 * Purpose: Login class * *****************************************************/ class Login { // Public variables var $username; var $cookie; function Login() { } /** * login(): Authenticate the user's username & password * @param string $username User's username in the DB * @param string $password User's password in the DB * @param object $DB MySQL database class object * @param string $table Table to query from * @returns bool True if login successful, false if not */ function login ($username, $password, $DB, $table = 'users') { $this->username = $username; $DB->query("SELECT `username`, `salt`, `password` FROM `$table` WHERE `username` = '$username' LIMIT 1"); return ( $DB->result['password'] == sha1($DB->result['salt'] . $password) ) ? true : false ; } /** * login_admin(): Authenticate the an admin's username & password * @param string $username User's username in the DB * @param string $password User's password in the DB * @param object $DB MySQL database class object * @param string $table Table to query from * @returns bool True if login successful, false if not */ function login_admin ($username, $password, $DB, $table = 'users') { $this->username = $username; $DB->query("SELECT `username`, `salt`, `password`, `user_level` FROM `$table` WHERE `username` = '$username' LIMIT 1"); if ( ( $DB->result['password'] == sha1($DB->result['salt'] . $password) ) && ( $DB->result['user_level'] ) == '3') { return true; } else { return false; } } /** * set_cookie(): Set the user's cookie * @param string $cookie_name Name of the cookie * @param object $DB MySQL database class object * @param bool $remember Whether to set for 30 days or just this session * @param string $table Table to query from * @returns bool True if cookie was sent, false if not */ function set_cookie ($cookie_name, $DB, $remember = true, $table = 'users') { $expiration = ( $remember ) ? ( time() + (60 * 60 * 24 * 30) ) : null ; $DB->query("SELECT * FROM `$table` WHERE `username` = '" . $this->username . "' LIMIT 1"); return ( setcookie($cookie_name, base64_encode( $DB->result['username'] . ":" . $DB->result['id'] . ":" . $DB->result['user_level'] . ":" . $DB->result['first_name'] . ":" . $DB->result['last_name'] ), $expiration) ) ? true : false ; } /** * is_logged_in(): Check if user is currently logged in * @param string $cookie_name Name of the cookie * @returns bool True if cookie was sent, false if not */ function is_logged_in ($cookie_name) { $this->cookie = explode(':', base64_decode($_COOKIE[$cookie_name]) ); } /** * is_admin_logged_in(): Check if user is currently logged in * @param string $cookie_name Name of the cookie * @returns bool True if cookie was sent, false if not */ function is_admin_logged_in ($cookie_name) { if ( isset($_COOKIE[$cookie_name]) ) { $this->cookie = explode(':', base64_decode($_COOKIE[$cookie_name]) ); if ( $this->cookie[2] == 3 ) { return true; } else { return false; } } else { return false; } } /** * logout(): Clear the user's cookie * @param string $cookie_name Name of the cookie */ function logout ($cookie_name) { setcookie($cookie_name, ''); } } ?>
PHP photo resizing class example
Jan 12th
Here is an example of a PHP class that manages simple photo resizing and saving using the GD library.
<?php /**************************************************** * * Purpose: Photo Resizing Class * Author: Matt West, http://mattdanger.net * Date: January 12th, 2007 * ****************************************************/ class Photo { // Private variables private $orig_image; private $portrait_frame; // 1 = Landscape, 2 = Portrait private $image_size; private $src_width; private $src_height; private $src_image; private $dest_height; private $dest_width; private $dest_image; private $ratio; private $scale; // Public variables public $allowed_types = array('jpeg', 'jpg', 'png', 'gif'); /** * Constructor: Contruct the photo object * @param array $photo Array of photo data, usually $_FILES['photo_name'] */ public function __construct($photo) { $this->photo($photo); } /** * photo(): Create new image resource * @param string $photo Array of photo data */ public function photo($photo) { $this->orig_image = $photo; // Confirm photo is an allowed type; if ( !in_array(ereg_replace('image/', '', $this->orig_image['type']), $this->allowed_types) ) { exit("Photo type is '" . $this->orig_image['type'] . "' which is not allowed"); } // Get image X and Y values in order to determine photo framing $this->image_size = getimagesize($this->orig_image['tmp_name']); $this->src_width = $this->image_size[0]; $this->src_height = $this->image_size[1]; $this->dest_height = 0; // 1 = Landscape, 2 = Portrait $this->photo_framing = ($this->src_width > $this->src_height) ? 1 : 2 ; // Calculate the ratio at which to resize based on the dimentions $this->ratio = $this->src_width / $this->src_height; } /** * scale_to_width(): Sets the width of the resize value * @param int $width Width in pixels * @returns boolean Returns true if successful, false if it was not. */ public function scale_to_width($width) { // Set the destination width value $this->dest_width = $width; // Calculate the value at which to scale the image $this->scale = ($this->ratio) ? $this->dest_width / $this->src_width : $this->dest_height / $this->src_height; if ($this->scale_image()) { return true; } else { return false; } } /** * scale_to_height(): Sets the height of the resize value * @param int $height Height in pixels * @returns boolean Returns true if successful, false if it was not. */ public function scale_to_height($height) { // Set the destination height value $this->dest_height = $height; // Calculate the ratio at which to resize based on the dimentions $this->ratio = $this->src_width / $this->src_height; // Calculate the value at which to scale the image $this->scale = ($this->ratio) ? $this->dest_height / $this->src_height : $this->dest_width / $this->src_width ; if ($this->scale_image()) { return true; } else { return false; } } /** * scale_image(): Resize image proportionally * @returns boolean Returns true if successful, false if it was not. */ private function scale_image () { if ($this->scale > 1) { exit ("The scale width supplied is larger than the original image. Please try a smaller number."); } $this->dest_width = $this->src_width * $this->scale; $this->dest_height = $this->src_height * $this->scale; if ( $this->dest_width >= $this->src_width && $this->dest_width >= $this->src_width ) $this->scale = 1; $this->src_image = imagecreatefromjpeg ($this->orig_image['tmp_name']); $this->dest_image = imagecreatetruecolor ($this->src_width * $this->scale, $this->src_height * $this->scale); if ( imagecopyresampled( $this->dest_image, $this->src_image, 0, 0, 0, 0, $this->dest_width, $this->dest_height, $this->src_width, $this->src_height) ) { return true; } else { return false; } } /** * save_photo(): Saves the resized photo * @param string $filename The path and filename to save the file (ex: "/path/to/image.jpg") * @param int $compression A number from 1-100 representing the level of compression. 100 is the least compression. * @returns boolean Returns true if save was successful, false if it was not. */ public function save_photo ($filename, $compression = 80) { if ( imagejpeg($this->dest_image, $filename, $compression) ) { $return_value = true; } else { $return_value = false; } imagedestroy($this->src_image); imagedestroy($this->dest_image); return $return_value; } } ?>
Newest LiveJournal Images
Nov 24th
This script displays the newest images posted by LiveJournal users. The script is pretty basic and simply parses a feed from LiveJournal.
You can view it in action here: http://mattdanger.net/lj/ (Warning: Some images may be NSFW!)
The code:
<?php $n = 5; // Maximum is 250 $referrer = 'http://example.com'; // Your site $email = 'user@example.com'; // Your email if ($fp = fsockopen('livejournal.com', 80)) { fputs($fp, "GET /stats/latest-img.bml HTTP/1.0rn" . "Host: www.livejournal.comrn" . "User-Agent: " . $referrer . "; " . $email . "rnrn"); $data = ''; while(!feof($fp)) { $data .= fgets($fp); } fclose($fp); preg_match_all("<recent-image img='([^']+)' url='([^']+)' />", $data, $out); for ($i = 0; $i < $n; $i++) { echo '<a href="' . $out[2][$i] . '"><img border="0" src="' . $out[1][$i] . '" /></a><br /><br />' . "n"; } } else { echo "Connecting to LiveJournal failed."; } ?>
As an aside, if you’re a LiveJournal user and don’t want your images posted to the public feed you can go to your command console and type “set latest_optout yes”.










