Matt's PHP Notes
THIS PAGE IS A WORK IN PROGRRESS. SOME OF THE CONTENT HERE HAS NOT BEEN EDITED OR VERIFIED YET
Below is a fairly disorganized, growing list of notes on PHP – useful links, cheatsheets, and other things I find helpful. Some are trivial; some are not – they're just little things I keep coming back to, and some things I've noticed are helpful to other programmers from helping people out on Experts Exchange. Feel free to borrow anything you want from this page, with two restrictions: (1) If you copy and paste this code without understanding what it does and something goes wrong, the responsibility is entirely yours. I've tested some of this code carefully; some of it might not be tested at all, so it's up to you if you want to use it. (2) Don't steal my code. This means that you should put comments next to any code I've written, with a URL for this page, so that anyone looking at your source knows where it came from originally. Also, don't put this code up as content on another site (e.g. as a tutorial, on Experts-Exchange, or any other forum) and call it your own. If you modify my code, but have based your work on what I've done here, again, please reference this page.
If you have comments or questions, you can email me at info [at] nicholassolutions [dot] com
If you're my age or a little older, and you were a fan of Guns N' Roses before Axl completely lost his mind, you might remember that song. So what's your point, Walter? The point is, there's no need to re-invent the wheel. PHP has been around for a while now, and there are some great scripts around. A lot of the time, someone else has already gone to the trouble of writing code to perform the task you are interested in, and it's just a matter of downloading their free, open-source script. Most of the time you can just Google what you're looking for, and it will become clear in a minute or two if it's available (or if there's something close enough that you can modify to suit your needs). The links below are scripts that I either use/suggest frequently, or that I find otherwise interesting and/or unique. Oh, and they're all free/open-source :-)
| PHPMailer | Try this script out, and you will never use PHP's mail() function again. I won't bore you with the details, since the docs and tutorial are so good. |
| PEAR Mail_Mime | This class is another favorite of mine, and personally I'd say it's a toss-up whether PHPMailer or Mail_Mime is better at sending mail for you. One thing that I love about this class is the Mail_mimeDecode::decode() method, which allows you to decode multipart MIME email. If you've ever tried to do this yourself, you'll know it can be a severe pain in the rear, and you'll really appreciate that someone has done this for you. Have a look at my example below if you're interested. |
| PHPflow | A neat class for dynamically generating flowcharts using PHP's GD library. It's still in it's early stages, but it's really pretty cool, and as far as I know, it's the only free script out there that does this. |
| File Thingie | Don't let the name fool you -- this is actually pretty cool. This is a file managing script with a quite a few features, and it allows you to give users file management abilities without granting them full FTP access and passwords. |
| ezPDF | Dynamic generation of PDF documents, without installing (or paying for) any extra modules or extensions like pdflib. 'Nuff said. |
| FPDF | Another free class for generating PDFs, without installing anything else. This is actually my favorite, but I've heard some people say ezPDF is easier to use, so check out both and take your pick. |
| Snoopy | I can't say enough good things about this one. Snoopy imitates a web browser, so your PHP scripts can surf the net, submit data to forms, etc. And all of this through a very intuitive set of object methods which require no outside modules. Snoopy even supports frames, and SSL (if you have the cURL extension). This really allows you to start thinking somewhat differently about PHP as more than just a serverside language, since you can effectively control a browser on the server side in response to user input. And of course, it's also great for prorgamming repetitive tasks like filling out forms at set intervals |
| phpBB | A full-blown bulletin board/forum system, with pretty much all the features you could ask for. Check it out. |
| MediaWiki | This is the software that runs Wikipedia, and it is a great tool for content and workflow management. In fact, their homepage runs the software itself. Here's a quick link to a list of features. |
| Levelten Formmail | A nice formmail script, much like popular Matt's Formmail for Perl. |
| WordPress | A very nice blog script with many features and plugins. It's actually much more than a blog. In fact, you can run a whole site using WordPress. |
| Priado Blender | Well this isn't actually a script -- it's a program that allows you to 'compile' your scripts as standalone Windows executables. By executable, I mean that you don't have to have PHP installed to run the 'compiled' file — not that there is only one file to distribute — you have to include some DLLs that will interpret the 'compiled' script. Still, the addition files are actually fairly small, and it's a handy way to write and distribute applications very quickly. In fact, if you know GTK, you can even make windowed applications. |
| WinBinder | This one is very much like Priado Blender, except that it allows you to program windowed applications directly through the Windows API. This has a lot of cool features, and it's especially nice because windowed apps have a look and feel that is just like any other application written using the Windows API (GTK does quite 'look' like Windows most of the time. Whether that's a bad thing is just a matter of opinion). |
There are several ways that a PHP script may receive data from the outside world. By far the most common way is through data passed by web forms using either the GET or POST methods (the GET method can also be used by simply adding a query string onto the end of the scripts URL), but there are other ways too, including retrieving session and cookie data, and reading input from command line parameters and standard input streams. You can see just about every way to retrieve input in a PHP script from the examples below.
<?php
// POST data (e.g. from a form)
// <input type="text" name="MyVariableName" value="foobar">
echo $_POST['MyVariableName'];
// GET data (e.g. from a form or directly entered in a URL);
// http://www.mysite.com/myscript.php?MyVariableName=foobar
echo $_GET['MyVariableName'];
// Cookie data (e.g. set with setcookie('MyVariableName', 'foobar'); )
echo $_COOKIE['MyVariableName'];
// POST, GET, or cookie data
echo $_REQUEST['MyVariableName'];
// NOTE: To determine how the page was called look in $_SERVER['REQUEST_METHOD']
// If it is important where the variable came from, individually check
// $_POST, $_GET, and $_COOKIE
//session data, possibly passed from variables set in another referring script
session_start();
echo $_SESSION['MyVariableName'];
// Command line parameters, e.g. at an SSH prompt
// %prompt> php myscript.php InputParam1 InputParam2 InputParam3
// or from a script: exec('php myscript.php InputParam1 InputParam2 InputParam3');
$num_args = $_SERVER['argc']; //in this case, equal to 3
for ($kk=0; $kk<$num_args; $kk++){
echo $_SERVER['argv'][$kk];
}
//or with a foreach()
foreach ($_SERVER['argv'] as $var) echo $var;
// Standard input, e.g. pipes at the command line
// %prompt> echo "foobar" | myscript.php
// or called from another application like procmail
$stdin = fopen('php://stdin', 'r');
$input = '';
while (false !== ($line = fgets($stdin))) $input .= $line;
echo $input;
?>
Sometimes it's useful to be able to chop up a file into chunks of a certain size. For example, maybe you need to put a very large file in a MySQL database, and the file size exceeds the maximum MySQL packet size allowed by your hosting company. FileChop() will chop the file up for you and return an array with the pieces.
<?php
function FileChop($file_path, $chunk_size){
$handle = fopen($file_path, 'rb'); //read the file in binary mode
$size = filesize($file_path);
$contents = fread($handle, $size);
fclose($handle);
//find number of full $chunk_size byte portions
$num_chunks = floor($size/$chunk_size);
$start = 0;
for ($kk=0; $kk < $num_chunks; $kk++){
$chunks[] = substr($contents, $start, $chunk_size); //get $chunk_size bytes at a time
$start += $chunk_size;
}
if ($start < $size) $chunks[] = substr($contents, $start); //get any leftover
return $chunks;
}
/*------------------- Example usage -----------------------------------*/
$path = 'file.mp3'; //the file to chop up
$bytes = 512000; //size of the chunks in bytes (500k in this case)
$pieces = FileChop($path, $bytes);
echo "$path was chopped into " . count($pieces) . " $bytes-byte chunks stored in \$pieces";
//the last piece may be smaller than $bytes bytes
foreach ($pieces as $bit){
//insert $bit into your database
}
/*----------------------------------------------------------------------*/
?>
PHP's mkdir() will only make a new directory if its parent directories exist. So, if /home/user/dir1 doesn't exist, you can't make /home/user/dir1/dir2/dir3 without first creating /home/user/dir1 and /home/user/dir1/dir2. The function my_mkdir can be used to do just that.
<?php
function my_mkdir($new_path, $base_dir='', $sep='', &$error=''){
if(empty($sep)) $sep = '/';
if (empty($base_dir)) $base_dir = '.';
$dir_array = explode($sep, $new_path);
$lastdir = '';
foreach($dir_array as $thisdir){
if(!file_exists($base_dir.$lastdir.$sep.$thisdir)){
if (mkdir($base_dir.$lastdir.$sep.$thisdir)){
$lastdir .= $sep.$thisdir;
}
else{
$error = "Unable to create $thisdir";
return FALSE;
}
}
}
return TRUE;
}
/*----------------- Exmample Usage -------------------------*/
$home = '/home/user'; //part of the path that already exists
$new = 'dir1/dir2/dir3'; //new directories to create
//make a new path in current folder
if (my_mkdir($new)) echo "success";
else echo "failure";
//make a new path starting in another foler
if (my_mkdir($new, $home)) echo "success";
else echo "failure";
//for windows, the separator is \ rather than /
//the my_mkdir() calls in the two examples above would then be:
$homeW = 'C:\\';
$newW = 'dir1\dir2\dir3';
my_mkdir($newW, '', '\\'); //first example, pass $base_dir an empty string
my_mkdir($newW, '.', '\\'); //the would work for the first example too
my_mkdir($newW, $homeW, '\\'); //second example
//to get detailed error reporting, you can pass in a string for $error
//something like the first example would be:
if(my_mkdir($new, '', '', $err_str)) echo "success";
else echo "failure: $err_str";
//my_mkdir() will create structure as far as it can. The error message
//will contain the name of the first directory it was unable to create
/*-----------------------------------------------------------*/
?>
Note that you could also use the mkdir command on your system to do this
<?php
//*nix
$response = shell_exec('mkdir -p' . escapeshellarg($wholepath));
//Windows
$response = shell_exec('mkdir ' . escapeshellarg($wholepath));
?>
If you need to decode MIME email that your website receives, the PEAR Mail_Mime package has everything you need in the Mail_mimeDecode object. This example goes through all the messages in a POP3 mailbox, and extracts the subject and main message content, and also gets any jpeg or gif attachments so you can either save them to files or database fields. You might use this script to allow people to upload files via email. It would be wise to do some further verification of the file type, and to restrict the email you process based upon the sender. You might also consider parsing the body or subject fields for passwords
<?php
//email account info
$host = 'localhost';
$username='user';
$password='pass';
require_once '/Mail/mimeDecode.php'; //include the pear package
$mbox = imap_open ("{$host:110/pop3}", "$username", "$password");
$num_messages = imap_num_msg($mbox);
if ($num_messages == 0) exit ("No messages: exiting");
$messages = array();
for ($msg_num = 1; $msg_num <= $num_messages; $msg_num++){
$raw_body = imap_body($mbox, $msg_num);
$raw_header = imap_fetchheader ($mbox, $msg_num);
$raw_mail = $raw_header.$raw_body; //this is the full, unparsed email
$images = array();
$body = '___EMPTY___';
$subject = '___EMPTY____';
$num_images =0;
$image_name ='';
$params['include_bodies'] = TRUE;
$params['decode_bodies'] = TRUE;
$params['decode_headers'] = FALSE;
$decoder = new Mail_mimeDecode($raw_mail); //create a new object from the raw email
$structure = $decoder->decode($params); //decode it
$subject = $structure->headers['subject']; //get the subject line
foreach ($structure->parts as $part) {
if ($part->ctype_primary=='image' //is an image attached?
and $part->disposition=='attachment') {
if (isset($part->ctype_parameters['filename'])) //get the file name
$image_name =$part->ctype_parameters['filename'];
else
$image_name =$part->ctype_parameters['name'];
$ext = strtolower(substr($image_name, -3));
if($ext == 'jpg' or $ext == 'gif'){ //check extensions
$images[$num_images]['name'] = $image_name;
$images[$num_images]['data'] = $part->body;
$num_images++;
}
}
elseif($part->ctype_primary == 'text'){
if ($part->ctype_secondary == 'html') $body = trim(strip_tags($part->body));
else $body = trim($part->body);
}
}//end of foreach part loop
//save the information we've gathered in $messages
$messages[($msg_num-1)]['subject'] = $subject;
$messages[($msg_num-1)]['body'] = $body;
$messages[($msg_num-1)]['num_images'] = $num_images;
$messages[($msg_num-1)]['images'] = $images;
imap_delete ($mbox, $msg_num); //mark message for deletion
}//end of for loop over all messages
imap_close($mbox, CL_EXPUNGE); //remove the messages marked for deletion and close the imap stream
/*---------------------- Example Usage -----------------------------------------*/
//Now we have a multi-dimensional array $messages that contains all the info we want
//Each element $i of $messages is comprised as follows:
echo $messages[$i]['subject']; //subject of message $i, or '___EMPTY___' if there was none
echo $messages[$i]['body']; //body of message $i in plain text, or '___EMPTY___' if there was none
echo $messages[$i]['num_images']; //number of images attached to message $i
echo $messages[$i]['images'][$k]['name']; //the name of the $k-th image attached to message $i
//write the data of the $k-th image attached to messsage $i to file handle $fh
$fh = fopen($messages[$i]['images'][$k]['name'], 'wb');
fwrite($fh, $messages[$i]['images'][$k]['data']);
fclose($fh);
//or maybe you want to store everything in a database:
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
mysql_select_db('dtabase_name', $link);
foreach ($messages as $message){
$subject = mysql_real_escape_string($message['subject']);
$body = mysql_real_escape_string($message['body']);
$num = $message['num_images'];
for($jj=0; $jj<$num; $jj++){
$name = mysql_real_escape_string($message['images'][$jj]['name']);
$data = mysql_real_escape_string($mensaje['images'][$jj]['data']);
$query = "INSERT INTO table_name (id, subject, body, image_name, data) VALUES";
$query .= "('', '$subject', '$body', '$name', '$data')";
mysql_query($query);
}
}
/*----------------------------------------------------------------------------------------*/
?>
Many people run into the problem of needing to write files on their server with PHP, but get permission denied errors when they try (for example when trying to move uploaded files from the /tmp directory. This is because PHP typically runs as the user 'nobody' in shared hosting environments. 'nobody' doesn't have permission to write files in your folders, which is generally a good thing. One option is to chmod 777 your folder, but this presents security risks, since it allows anyone on your server to write to your folder. A workaround is to write your files to the /tmp folder (where everyone has write access), and then FTP them from there to yourself, as the fwriteFTP() function given below does. WARNING! This requires that you put your FTP password in a PHP script. Before doing this, you should verify that others on your server cannot browse through your files, using either shell (SHH/Telnet) or using scripts (e.g. by writing PHP or Perl scripts that navigate the file system, open files, and print the contents). If they can, this is far worse than changing the permissions on your directory, because it effectively makes your password available to anyone who cares to look. Even if other users do not have malicious intent, their scripts may have security holes that allow other individuals to browse the server's file system. One way to check is obviously to simply try looking at other people's files (if you can see theirs, they can see yours), but this may be considered hacking, so it is best to consult your system admin or hosting company and ask them.
This can also be a nice function if you just need to write files to a remote server (see the second-to-last example below).
<?php
function fwriteFTP($filename, $str, $user, $pass, $dir, $mode, $server='localhost'){
$fh = @fopen('/tmp/'.$filename, 'w');
if (!$fh) return FALSE;
else{
fwrite($fh, $str);
fclose($fh);
}
$ftp_conn = @ftp_connect($server);
$ftp_log = @ftp_login($ftp_conn, $user, $pass);
$ftp_cd = @ftp_chdir($ftp_conn, $dir);
if (is_resource($ftp_conn) and $ftp_log and $ftp_cd){
$ftp_put = @ftp_put($ftp_conn, $filename, '/tmp/'.$filename, $mode);
}
else{
unlink('/tmp/'.$filename);
return FALSE;
}
if ($ftp_put){
unlink('/tmp/'.$filename);
ftp_close($ftp_conn);
return TRUE;
}
}
/*--------------------- Example Usage ----------------------------*/
//---simple text file
$content = 'This is a test text file';
//write to base ftp directory
fwriteFTP('testfile.txt', $content, 'username', 'password', '', FTP_ASCII);
//write to www/mydir
fwriteFTP('testfile.txt', $content, 'username', 'password', 'www/mydir', FTP_ASCII);
//---binary file
fwriteFTP('testfile.jpg', $jpeg_data, 'username', 'password', 'www/mydir', FTP_BINARY);
//---to another server
fwriteFTP('testfile.ext', $data, 'username', 'password',
'www/mydir', FTP_BINARY, 'ftp.myserver.com');
//--checking success
$f = fwriteFTP('testfile.txt', $content, 'username', 'password', '', FTP_ASCII);
if ($f) echo "File Created!";
else echo "Error creating file";
?>
Here's a useful one if you are accepting user input as text and want to display it as HTML. The Linkify() function will take a string, find URLs, web addresses, and email addresses, and hyperlink them intelligently, preserving the original text. In fact, it will even accept HTML that already contains hyperlinks. It recognizes web addresses and URLs containing all (I think) currently acceptable top-level domains. If you want to add more, it is straightforward to do so by modifying the $tld variable. The recognized protocols are also easy to add to, by modifying the $proto variable. Web addresses containing no protocol are assumed to be http:// unless they begin with ftp (e.g. ftp.myserver.net).
<?php
function Linkify($string){
//private helper function, used below
function writeproto($var1, $var2){
if (empty($var1)){
if (substr($var2, 0, 4) == 'ftp.') return 'ftp://';
else return 'http://';
}
else return $var1;
}
//valid top level domains
$tld = 'com|net|org|info|biz|aero|coop|museum|name|pro|gov|edu|mil|int|';
$tld .= 'ac|ad[a-z]|ae|ag|am|as|au|bb|be|bg|bi|bm[a-z]|.\br|bt|bv|ca|cc|cd|ch|';
$tld .= 'ck|cl|cm|cn|cr|cu|cx|cz|de|dk|do|ec|ee|es|fj|fm|fo|fr|gb[a-z]|ge[a-z]|';
$tld .= 'gi|gl|gm|gr|gs|gt|gu|hk|hm|hr|hu|id|ir[a-z]|ie|il|in|io|is|it|jo|jp|';
$tld .= 'kr|ky|kz|lb|li|lk[a-z]|lt|lu|ly|mc|mn[a-z]|ms|mw|mx|na|nc[a-z]|nl|no|nu|';
$tld .= 'nz|pe|ph|pk|pl|pm[a-z]|py|re|ro|ru|sa|se|sg|sh|si|sk|sm|su[a-z]|tc|tf|';
$tld .= 'th|tj|to|tr|tv|tw|ua|ug|uk|us|uy|uz|va[a-z]|vc[a-z]|vg|vi|vn[a-z]|';
$tld .= 'vu|wf[a-z]|ws|za[a-z]';
//protocols
$proto = 'http://|https://|ftp://|ftps://|rtsp://|mms://';
//convert html hyperlinks to text, with link text surrounded by -~~----## as a delimiter (used below)
$ret = preg_replace('#<a.*?href="([^"]+)".*?>([^<]+?)</a>#i', "$1 -~~----##$2##----~~-", $string);
//convert urls and web addresses to hyperlinks. If no protocol is given, and address
//does not begin with "ftp.", use http://
$ret = preg_replace('#('.$proto.')?([\w.\-@]+\.)('.$tld.')(?![a-z])([\w/\#~:.?+=&%@!\-]+)?#ie',
"'<a href=\"'.writeproto('\\1', '\\2').'\\2\\3\\4\\5\">\\1\\2\\3\\4\\5</a>'", $ret);
//move ending punctuation outside link
$ret = preg_replace('#<a href="([\w/\#~:.?+=&%@!\-]+?)([^\w])">([\w/\#~:.?+=&%@!\-]+?)([^\w])</a>#i',
"<a href=\"$1\">$3</a>$4", $ret);
//fix any original hyperlinks
$ret = preg_replace('@(<a href="[^"]+">)[^<]+?</a> -~~----##(.*?)##----~~-@', "$1$2</a>", $ret);
//change protocol on email addresses from http:// to mailto:
$ret = preg_replace('#<a href="http://([^\s@]+@[^w.]+?\.)('.$tld.')">#i', "<a href=\"mailto:$1$2\">", $ret);
return $ret;
}
*---------------------- Example Usage -----------------------------------------*/
$text = "You can visit my website at www.mysite.com! My FTP server is ftp.server1.mysite.com!";
echo Linkify($text);
/*output:
You can visit my website at <a href="http://www.mysite.com">www.mysite.com</a>! My FTP server is
<a href="ftp://ftp.server1.mysite.com">ftp.server1.mysite.com</a>!
*/
$text = "visit mms://mymovies.com/mymovie.wmv at mymovies.com!";
echo Linkify($text);
/*output:
visit <a href="mms://mymovies.com/mymovie.wmv">mms://mymovies.com/mymovie.wmv</a> at
<a href="http://mymovies.com">mymovies.com</a>!
*/
/*----------------------------------------------------------------------------------------*/
?>
Here's a fun piece of code. Suppose you want to 'pseudo-encrypt' a string; that is, obscure it through some kind of encoding, but still be able to decode it back into the original string (PHP's crypt() function provides rock-solid one-way encryption, but you cannot get your original string back). One easy method is by one-to-one character substitution, which is a method of cryptography that's been around almost from the beginning of civilization (read here), and is essentially the same as the 'decoder rings' you might have played with as a child.
Consider a method where you encode a string by shifting every letter 5 characters ahead in the alphabet. The asciicrypt() function below does essentially that, except it uses the ASCII character set rather than the alphabet. This means that it can encode any ASCII string (not just A-Z), and more importantly, that there are more characters (256) to choose from, which makes cracking it by brute force (a little) harder. The function accepts a string, and an integer offset by which it should 'shift' the characters. Decryption is done with the same function, simply passing it the encoded string, and the negative of the offset used during encryption.
So, this function is fun, but is it the encryption hard to crack? Absolutely not; don't use this to hide creditcard numbers or passwords in a database. However, it may be pretty handy if you want to obscure data that may have to pass through insecure pathways (like email, or GET query strings in URLs) so that it is not easily human readable by anyone who happens to stumble across it.
<?php
function pcrypt($string, $offset){
$len = strlen($string);
$ret = '';
for ($kk=0; $kk<$len; $kk++){
$num_1 = ord($string[$kk]);
if ($num_1 + $offset <= 255) $num_2 = $num_1 + $offset;
else $num_2 = $num_1 + $offset - 255;
$ret .= chr($num_2);
}
return $ret;
}
/*---------------------Example Usage---------------------------------------------------*/
$secret = "I could tell you, but then I'd have to kill you";
$secret_enc = pcrypt($secret, 132);
$secret_enc_url = urlencode($secret_enc);
echo "$secret_enc \n"; // -ñt=·=Fñ°T==ñ²=·¦ñµ·°ñ°8T=ñ-½Fñ8s·Tñ°=ñnf==ñ²=·
echo "$secret_enc_url \n";
//%CD%A4%E7%F3%F9%F0%E8%A4%F8%E9%F0%F0%A4%FD%F3%F9%B0%A4%E6%F9%F8%A4%F8%EC%E9%F2%A4%CD
//%AB%E8%A4%EC%E5%FA%E9%A4%F8%F3%A4%EF%ED%F0%F0%A4%FD%F3%F9
echo pcrypt($secret_enc, -133) . "\n"; // H?bntkc?sdkk?xnt+?ats?sgdm?H&c?g`ud?sn?jhkk?xnt
echo pcrypt($secret_enc, -132) . "\n"; // I could tell you, but then I'd have to kill you
echo pcrypt(urldecode($secret_enc_url), -100) . "\n"; //i@âÅòîä@öàîî@ÖÅòL@éòö@öêàÄ@iGä@êüûà@öÅ@ïëîî@ÖÅò
echo pcrypt(urldecode($secret_enc_url), -132) . "\n"; //I could tell you, but then I'd have to kill you
/*-------------------------------------------------------------------------------------------------------*/
?>
You may notice that in the examples below, code gets re-used a little. I may eventually bottle a few image functions up in a class to reduce the repetition and make things easier to use.
<?php
function cropresize($INfile, $OUTfile, $x, $y, $boxW, $boxH, $destW, $destH, $quality=75, $format=''){
$ext = strtolower(substr($INfile, -3));
if (empty($format)) $format = $ext;
$format = strtolower($format);
//get a source image resource
if ($ext == 'jpg' ) $im_src = @imagecreatefromjpeg($INfile);
elseif ($ext == 'gif') $im_src = @imagecreatefromgif($INfile);
elseif ($ext == 'png') $im_src = @imagecreatefrompng($INfile);
elseif ($ext == 'bmp') $im_src = @imagecreatefrombmp($INfile);
else return false; //not a supported file type
if(!is_resource($im_src)){
@imagedestroy($im_src);
return false;
}
//create a destination resource
$im_dest = @imagecreatetruecolor($destW, $destH);
if(!is_resource($im_dest)){
@imagedestroy($im_src); @imagedestroy($im_dest);
return false;
}
//copy the specified portion of the source to the destination.
$suc = @imagecopyresampled($im_dest, $im_src, 0, 0, $x, $y, $destW, $destH, $boxW, $boxH);
@imagedestroy($im_src); //free source resource memory
if(!$suc){
@imagedestroy($im_dest);
return false;
}
//output a header if the image is not going to a file (if $OUTfile is empty)
if (empty($OUTfile) && $ext == 'jpg') header("Content-type: image/jpeg");
elseif(empty($OUTfile)) header("Content-type: image/$format");
if ($format == 'jpg') $suc = @imagejpeg($im_dest, $OUTfile, $quality);
elseif ($format == 'gif') $suc = @imagegif($im_dest, $OUTfile, $quality);
elseif ($format == 'png') $suc = @imagepng($im_dest, $OUTfile, $quality);
elseif ($format == 'bmp') $suc = @imagebmp($im_dest, $OUTfile, $quality);
imagedestroy($im_dest); //free destination resource memory
if ($suc) return true;
else return false;
}
/*---------------------------------------------------------------------------------
ARGUMENT DESCRIPTIONS:
$INfile The path to the source file to work on
$OUTfile The path to the output file. This can be the same file as $INfile. To output
to the screen instead of a file, supply an empty argument ""
$x Distance in pixels from the left image edge to the left side of the cropping box
$y Distance in pixels from the top image edge to the top side of the cropping box
NOTE: The coordinates (x,y) give the location of the top left corner of the cropping box
$boxW Width of the cropping box in pixels
$boxH Height of the cropping box in pixels
$destW Width of the output image in pixels
$destH Height of the output image in pixels
$quality Quality of the output image (0-100). Optional, but MUST be supplied if using $format
$format Format of the output image: 'jpg', 'gif', 'png', or 'bmp'. Optional
HINTS
1) If you don't want to crop the image, use $x=0, $y=0, $boxW = width of source image,
$boxH = height of source image. If you don't know the dimensions, use getimsize() (see below)
2) If you don't want to resize the image, set $boxW = $destW and $boxH = $destH
----------------------------------------------------------------------------------*/
?>
If you do not know the image size to start with, you can use the getimsize() function below:
<?php
function getimsize($file){
$ext = strtolower(substr($file, -3));
//get a source image resource
if ($ext == 'jpg' ) $im = @imagecreatefromjpeg($file);
elseif ($ext == 'gif') $im = @imagecreatefromgif($file);
elseif ($ext == 'png') $im = @imagecreatefrompng($file);
elseif ($ext == 'bmp') $im = @imagecreatefrombmp($file);
else return false; //not a supported file type
if(!is_resource($im)) return false;
if(!is_resource($im)){
@imagedestroy($im);
return false;
}
$ret = array('width' => imagesx($im), 'height' => imagesy($im));
imagedestroy($im);
return $ret;
}
//$file is the path to the image file
//function returns false on failure, and an array with the dimensions on success.
?>
Here's a quick illustrative example: Consider this photo from Public Domain Photo
:
Let's keep just the part with the ladybug, and shrink it down a little. The top left corner of the lady bug is around 30 px from the left edge and 20 px below the top. A nice looking box to cut out the lady bug is about 260 x 180 px. Let's reduce the size to 50% of the original, i.e. make the output 130 x 90 px. It's as simple as:
<?php
cropresize('ladybug.jpg', 'ladybug_rs.jpg', 30, 20, 260, 180, 130, 90);
?>
And the output looks like:
