Scripts from the Command-Line and Using Cron [top]
Running PHP scripts over the web via a browser is just one way of using PHP. You can also run it from the command line if end-user output is not the goal. You might have a script that creates thumbnails of images, or checks for image attachments in emails, or makes changes to your database. In this case, you'd want to execute this script from the command-line on the web server and at regular intervals (every day, every 10 min, etc).
Scripts from the Command-Line
Any script that you can run from the web can also be run from the command line. Simply SSH into your Stage account, change directory to your dwd directory and issue the following command:
php [name of any PHP script]such as:
php hello.phpYou should see the contents of the web page that normally would have been sent to the browser. This is the script executing but sending its output to the shell window and not to the browser. Using this concept, we can create scripts that don't actually interact with the browser. They can insert into or modify data in your database without printing anything to the user.
Scheduling Script Execution Using Cron
Cron is the built-in task scheduler inherent to UNIX-based systems. Using this functionality, any user with an account can schedule a certain process or job to start at a single or repeating intervals up to one minute apart. One easy way to schedule jobs to run using cron is to create a text file (let's call it cron.txt) that has entries like the following:
1 * * * * php /home/[netId]/public_html/dwd/hourly.php >/dev/null 45 4 1 * * php /home/[netId]/public_html/dwd/monthly.php >/dev/nullYou may have noticed that besides the numbers and asterisks to the left, we've added " >/dev/null" to the end of our cmd. What is this and why?
In UNIX, if your cron job generates any output text, this text is automatically saved as mail for you on the system and if the scripts executes often and the text is lengthy, can clog up the system. To suppress these messages, we send it to the directory /dev/null which exists specifically for this purpose. The ">" character means pipe or send. Our PHP scripts always generate "Context-type: text/html\n\n", so this needs to be suppressed.
OK, so the six fields for the above format are:
So for the two example above, the hourly script will run at 1 minute past every hour, while the monthly script corresponding to the second entry will run at 4:45am on the 1st day of every month.
Within these fields, there's some other ways to change the range:
Single number: shown above, it denotes a single instance
Sequential range: use the dash delimiter (1-5) and no spaces
0-3 6 * * * php /home/[netId]/public_html/dwd/hourly.php >/dev/nullThe above runs the hourly.php script at 6:00am, 6:01am, 6:02am, and 6:03am every morning.
Random range: use the comma delimiter (1,3,5) and no spaces
1,3,5 9 * * * php /home/[netId]/public_html/dwd/hourly.php >/dev/nullThe above runs the hourly.php script at 9:01am, 9:03am, and 9:05am every morning.
Repeating: use the slash delimiter (*/2) and no spaces
*/2 * * * * php /home/[netId]/public_html/dwd/hourly.php >/dev/nullThe above runs the hourly.php script every 2 minutes.
Before we install the task file, let's make sure of several things in our cron text file:
crontab cron.txt
To see your current listing of jobs, simply issue the command:
crontab -l
In general, the commands are:
crontab filename
Install filename as your crontab file.
crontab -l
Display your crontab file.
crontab -r
Remove your crontab file.
crontab -e
Edit your crontab file, or create one if it doesn't already exist. Note that this will invoke whatever default editor is defined for you on Stage, most likely "vi". If this sounds unfamiliar, simply edit your cron.txt job file locally, re-upload, and re-install.
Nancy has been kind enough to set up a help page about using cron jobs on Stage:
GD and Image Processing [top]
GD is an open source code library for the dynamic creation of images by programmers. GD is written in C, and "wrappers" are available for Perl, PHP and other languages. GD creates PNG, JPEG and GIF images, among other formats. Most stock installations of PHP come with GD library support enabled.
Let's consider the following two examples. In both of them, we will use the GD library to create an image with a random text string (think "captcha" security codes for site login) using the following code:
# Create a random six letter alpha-numeric string
$string_a = array("A","B","C","D","E","F","G","H","J","K",
"L","M","N","P","R","S","T","U","V","W","X","Y","Z",
"2","3","4","5","6","7","8","9");
$keys = array_rand($string_a, 6);
foreach ($keys as $name=>$value)
{ $string .= $string_a[$value];
}
# Define background image URL
$bgimage = "images/background.gif";
$image = imagecreatefromgif($bgimage);
$color = imagecolorallocate($image, 0, 0, 0); # Create the color black
# Add the text
imagestring($image, 4, 15, 15, $string, $color);
In our first example, we'll actually write the file to the server, and then embed it in an <img> tag in order to show it:
$outfile = "images/random.gif"; imagegif($image,$outfile); echo <<<END Here is a PHP-generated image with random text: <p> <IMG SRC="$outfile" border="1"> END;
In our second example, the image data is actually sent straight to the browser
# Output the image
header("Content-type: image/gif");
imagegif($image);
and this script, which we'll call "gd-image.php", can be used as the source in the image tag in another script:
Here is a PHP-generated image with random text: <p> <IMG SRC="gd-image.php" border="1">
For resizing, you first choose the method of how you want to resize - either to a set width and height, or to a percentage. You then call imagecopyresized() and output the data to a file. Because of security, newly created image files will have permissions set to 600, which means they can't be seen in a webpage. Invoking chmod() to change this to permissions 644 will fix this:
# Image names
$filename = "images/original.jpg";
$outfilegif = "images/thumb.gif";
$outfilejpg = "images/thumb.jpg";
$filetype = "";
if (preg_match("/\.(jpeg|jpg)$/i", $filename)) $filetype = "jpg";
if (preg_match("/\.(gif)$/i", $filename)) $filetype = "gif";
# Get new sizes
list($width, $height) = getimagesize($filename);
# set as a percentage
$percent = 0.5;
$newwidth = $width * $percent;
$newheight = $height * $percent;
# or set explicitly
$newwidth = 80;
$newheight = 80;
# create the thumb image
$thumb = imagecreatetruecolor($newwidth, $newheight);
# get the source data
if ($filetype=="gif")
{
$source = imagecreatefromgif($filename);
$outfile = $outfilegif;
}
elseif ($filetype=="jpg")
{
$source = imagecreatefromjpeg($filename);
$outfile = $outfilejpg;
}
# resize
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
# create the thumb
if ($filetype=="gif")
imagegif($thumb,$outfile);
elseif ($filetype=="jpg")
imagejpeg($thumb,$outfile);
# Change permissions on the new file - needed for proper web display
# default of newly created file is 600 - need it to be 644
chmod($outfile, 0644);
All of these examples are served over the web, but they just as easily could have been created via the command-line interface and scheduled via cron. If users are uploading lots of images, and you wish to have thumbnails of these assets, you could scehdule a script to run every 5 minutes that resizes any newly uploaded images and deposits the output in a thumbnail directory.
Intro to Regular Expressions [top]
One of the most powerful tools for matching and manipulating text is the regular expression (regex). In short, it's the ability to match specific patterns in text, and then perform tasks based upon how these patterns match strings of interest. For example, if we look at a US phone number:
212-555-1212we inherently know that we should see 3 digits for the area code, 3 digits for the exchange, and 4 for the rest. But what if, in an HTML form that we were going to parse and put into our DB, someone typed:
212-5551-212A typo for sure, but the meaning is clear. In the end, as humans, we look for 10 digits in a US phone number. If we see 11 digits, and the first digit is a "1", we know we don't need the leading "1":
1-212-555-1212Using a regular expression, we could strip out all non-digit chars and then check the length to see if it's legit.
Regular expressions come in a few different flavors, with the most popular based upon the syntax of Perl:
For reference, the atoms of pattern matching in Perl are:
Metacharacters
^ Match the beginning of the line
. Match any character (except newline)
$ Match the end of the line (or before newline at the end)
| Alternation
() Grouping
[] Character class
Useful Patterns
\w Match a "word" character (alphanumeric plus "_")
\W Match a non-word character
\s Match a whitespace character
\S Match a non-whitespace character
\d Match a digit character
\D Match a non-digit character
Quantifiers
* Match 0 or more times
+ Match 1 or more times
? Match 1 or 0 times
{n } Match exactly n times
{n,} Match at least n times
{n,m} Match at least n but not more than m times
You can test these out using these interactive regular expression tools for PHP below. Note that they are password-protected. Please use your regular Stage login to access:
For some more background on regular expressions, here's what the WikiPedia has to say, along with a set of bookmarks for further study:
Using HTTP in PHP [top]
In the same way you used the mail() function to interface to SMTP to send e-mail, you can use HTTP to get the contents of a web page into a string in PHP. The Client URL (Curl) library excels at this:
$urlToGet = 'http://www.yahoo.com'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $urlToGet); # This option causes the curl_exec function to return response as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); # Use the following if you need to submit a FORM # curl_setopt ($ch, CURLOPT_POST, 1); # curl_setopt ($ch, CURLOPT_POSTFIELDS, "zip=10003"); $rawText = curl_exec($ch); curl_close($ch); $statusMsg = "Successfully obtained: $urlToGet";The real trick with getting web pages is parsing them. Fortunately, PHP has lots of methods for manipulating text. One method is to use unique tokens to define where the text of interest starts and where it ends. For example, if we're trying to find all the links in a page, we know:
<a : indicates that a link is present href=" : indicates start of a link "> : indicates end of a link and start of the linked text </a> : indicates end of the linked textSo we can use a regular expression to find out where these things occur. Then with the preg_match_all() function, these values will be populated into an array, which we can then traverse to find all the URLs and link titles:
$parts = array();
$pattern = '/<a .*?href="(.*?)".*?>(.*?)<\/a>/s';
preg_match_all($pattern,$rawText,$parts);
# $parts[0] now contains the entire part of the text that matched the expression
# $parts[1] now contains the URLs that matched between href="(.*?)"
# $parts[2] now contains the linked text that matched between >(.*?)<\/a>
# Uncomment this is you want to view the entire result array
# print_r($parts);
# htmlspecialchars() subs the HTML equiv for certain chars, i.e. & for &
for($i=0; $i<count($parts[1]); $i++)
{ $parts[1][$i] = trim($parts[1][$i]);
$parts[2][$i] = trim($parts[2][$i]);
print "<li>".htmlspecialchars($parts[1][$i])." - ".htmlspecialchars($parts[2][$i])."\n";
}
Object Oriented Design [top]
When talking about object oriented design in the context of software, one is usually referring to a class-based system of grouping functionality to achieve a simplicity in the organization and maintenance of your code. As we've seen from some of the previous procedural examples, things can become a bit unruly very quickly.
In the PHP realm, classes essentially consist of properties and methods:
class Pizza
{
# in seconds
private $bake_times = array(
'cheese' => 480,
'sicilian' => 720,
'veggie' => 600,
);
public function getBakeTime($type)
{
$time = $this->bake_times[$type];
return $time;
}
}
$my_pizza = new Pizza;
$time_to_cook = $my_pizza->getBakeTime('veggie');
The above example is a tremendous oversimplification of how object-oriented PHP is put to good use, but it's presented to give you an idea of its syntax and conventions.
Web Application Frameworks and the MVC Model [top]
In the real world, a lot of the heavy lifting in serving a larger website is done for you by web frameworks, which are object-oriented in nature. Usually, a web framework is an integrated library of code that provides methods and resources for common tasks used in creating and serving a web application such as:
The Favorite Sites Demo as faux MVC Model [top]
To illustrate this concept, we can recast our favorite sites demo using the MVC metaphor.
Favorite Sites Demo using faux MVC Model
In order to restrucure this, we'll use a few different files:
$site_defs = array(
'db' => array(
'host'=>'localhost',
'database'=>'net_id',
'un'=>'net_id',
'pw'=>'mysql_pw',
),
);
In our PHP class in model.php that handles database interaction, we can then refer to it as needed:
public function getConnection()
{
require "info.php";
$connection = mysql_connect($site_defs['db']['host'], $site_defs['db']['un'], $site_defs['db']['pw']);
if (!$connection) return;
$db_selected = mysql_select_db($site_defs['db']['database'], $connection);
if (!$db_selected) return;
return $connection;
}
public function closeConnection($connection)
{
mysql_close($connection);
}
public function getSites()
{
$conn = $this->getConnection();
if (!$conn) return;
$sql = "SELECT s.id as site_id, s.title, s.url, s.description,
s.votes, c.id as cat_id, c.name as cat_name
FROM class05_table2 s, class05_category c
WHERE s.category_id=c.id
ORDER BY s.votes desc, s.title";
$result = mysql_query($sql,$conn);
if (!$result) return;
while(($rows[] = mysql_fetch_assoc($result)) || array_pop($rows));
# Augment the data with the category name
$data = array();
foreach($rows as $row):
if ($row['cat_id']<=1) unset($row['cat_name']);
$data[] = $row;
endforeach;
return $data;
}
Introduction to Codeigniter [top]
CodeIgniter is a powerful PHP framework with a very small footprint, built for PHP coders who need a simple and elegant toolkit to create full-featured web applications. CodeIgniter is an Application Development Framework - a toolkit - for people who build web sites using PHP. Its goal is to enable you to develop projects much faster than you could if you were writing code from scratch, by providing a rich set of libraries for commonly needed tasks, as well as a simple interface and logical structure to access these libraries. CodeIgniter lets you creatively focus on your project by minimizing the amount of code needed for a given task.
Related Resources [top]