Document Your Code

When you started learning to program, documenting your code was the last thing on your mind. You’re were here to learn, and learn is what you did. As your programs started to grow in complexity, your college professors preached to you “You must document your code! What if you have to come back to it in 6 months? Will you remember how everything works?”. So, you dutifully documented your code. But then something strange happened: you got a job. In the real world there are deadlines, and that extra minute you should have taken to document the code is gone. But the thing is, you MUST document your code. If not for you, do it for me. Because guess what, I’m the one that has to go in and fix it, and knowing what’s going on would make my life a lot easier.

A Story

When I started my current job, one of the other programmers was assigned to get me up to speed with our CMS. My first question was “Is there any documentation I can go over?”, to which he responded “Nah, just dive in and you’ll be fine.”. So I dove in and it only got worse from there. As I looked through the code, nothing was documented. Nothing! I spent the next 3 months sifting through code trying to figure out how it all works. I eventually did figure it all out, but it was 3 months where I was working at maybe 50%-60% of my maximum efficiency. Having any sort of documentation would have made this process much easier. Not only that, but because of the lack of documentation we constantly create duplicate functionality. After all, how are you supposed to know what functionality exists if there no documentation on it?

Now that I’ve been at my current job awhile, I’ve decided to change things. I’ve started taking 15 to 30 minutes a day to document our CMS using the PHPDoc format. It may or may not catch on with the rest of the programmers, but I know that every function and class that I write has full documentation, and it feels good when the documentation gets generated with PHPDoc. I believe the quote is “You need to be the change you believe in”.

How to Document Your Code

It’s easy. Really easy actually.

/**
* Function short description
*
* This is a long description of the function.  Discuss what this function does in
* any detail that is necessary.
*
* @global void $globalVariable
* @param int $aParameter This is the description of the parameter.
* @param mixed $bParameter This is the description of another parameter.
* @return bool This is a description of the return variable.
* @todo Does something need to be done?  Put it here.
*/
function my_function($aParameter, $bParameter) {
     global $globalVariable;
 
     //If you are doing something extra complicated, make a comment inside the
     //function.  Otherwise, you code should speak for itself.
     for($i=0; $i < 20; $i++) {
          echo $i;
     }
 
     return true;
}

That’s it. That’s all you need to get started documenting PHP code. There’s a lot more you could be doing, but it’s not all that important. So long as you document the parameters, the return type, and write a description about what the function does, you have the important bits.

So next time you think to yourself “I’ll document it later.”, just take the time to do it now. Because guess what? You aren’t going to go back. Something else is going to come up, and then the rest of us will suffer.

PHP: Echo Versus Print(f)

One of the things I remember about when I started programming in PHP was the confusion I ran in to when deciding how to print text.  Should I use the print construct?  Or maybe I should use the echo construct?  Perhaps the C-style printf function instead?  Eventually most people just latch on to the echo construct because “That’s what everyone else is doing”.  Is that the fastest method to use though? Well, that’s what I’m going to find out.

The Test

The test I decided to use loops 1000 times, and inside the main loop, there is a sub-loop creating the output which runs from 0 to N (where N is the value of the outer-loop counter).

1
2
3
4
5
6
7
$start = microtime(true);
for($i = 0; $i < 1000; $i++) {
     for($x = 0; $x < $i; $x++) {
          //Output here.
     }
}
$end = microtime(true);

After the test has been completed, I just wrote the times to a text file for collection later.

The Results

  • echo – 16.470 seconds
  • print – 16.473 seconds
  • printf – 16.432 seconds

As I expected, the difference between print and echo were negligible.  I suspect that they use the same underlying code.  The real surprise was from printf(), which is a function and is supposed to have taken longer because of the overhead of calling it.  I’m at a loss as to why it’s faster than the other two, but the difference isn’t really significant enough to worry about.  If someone wanted to be a bit more scientific about this, this program should be run probably a couple thousand times so that we can get a good sample and see what happens then.

If you would like to run this code yourself and let me know your results, it’s available for download here.

PHP Dark Arts: Semaphores

Note:  The full example code can be downloaded here.

Dijkstra contributed many important things to computer science, and among them was the semaphore.  A semaphore is a protected variable or abstract data type that is used for controlling access to some resource.  Semaphores can be used to control access to almost anything.  For example, lets say that I have multiple instances of a program running and this program counts how many rows are in table ‘X’ every 15 seconds.  We don’t want the program instances clobbering the database all at once, so we use a semaphore to control the access (I realize this is a silly idea, but it’s to illustrate a point).  Before a program instance can access the database, it must first acquire the semaphore.  Once acquired, it may run it’s query, and then release the semaphore so another program instance can use it.  In this way, access to the database is strictly controlled.

Semaphores have drawbacks of course.  The most obvious is that it’s easy to enter a state of deadlock.  Let’s say in the previous example, one program instance never releases the semaphore.  What happens then?  Everything comes to a screeching halt.  That’s why it’s important to be extremely careful when using a semaphore.  If you acquire it, be sure to release it.

PHP’s Semaphore Implementation

Using semaphores in PHP is actually very straight forward.  There are only 4 semaphore functions:

  • sem_acquire() – Attempt to acquire control of a semaphore.
  • sem_get() – Creates (or gets if already present) a semaphore.
  • sem_release() – Releases the a semaphore if it is already acquired.
  • sem_remove() – Removes (deletes) a semaphore.

So how do they all work together?  First, you call sem_get() to fetch the identifier for the semaphore.  After that, one of your processes will call sem_acquire() to try and acquire the semaphore.  If it’s currently unavailable, sem_acquire() will block until the semaphore is released by another process.  Once the semaphore is acquired, you may access the resource that you are controlling with it.  After you are done with the resource, call sem_release() so that another process can acquire the semaphore.  When all is said and done, and you’ve made sure that none of your processes require the semaphore anymore, you can call sem_remove() to remove the semaphore completely.

Getting and Removing

The first step in using a semaphore is calling sem_get().

1
2
3
4
5
6
$key = 123321;
$maxAcquire = 1;
$permissions =0666;
$autoRelease = 1;
 
$semaphore = sem_get($key, $maxAcquire, $permissions, $autoRelease);

The parameters for this function are pretty straight forward, but here is a break down just in case.

  • $key – A unique integer so that the semaphore is easily identifiable.
  • $maxAcquire – How many process can acquire the semaphore at once?
  • $permissionsUnix style permissions on the semaphore.
  • $autoRelease – Do you want the semaphore to release automatically if the request shuts down?

Each process needs to call sem_get() using the same parameters, otherwise it will get a different semaphore.  And if you want to remove your semaphore?  Just make sure you have a valid semaphore resource and then call sem_remove().

1
2
3
4
5
if(sem_remove($semaphore)) {
     echo "Semaphore removed. \n";
} else {
     echo "Failed to remove semaphore. \n";
}

Acquiring and Releasing

Once you’ve created (or retrieved) a semaphore, you can then start using it by calling sem_acquire().  Both sem_acquire() and sem_release() only take one parameter: a semaphore resource.

1
2
3
4
$semaphore = sem_get($key, $maxAcquire, $permissions, $autoRelease);
sem_acquire($semaphore);  //blocking
echo "hello world!";
sem_release($semaphore);

Now that you understand how to use PHP’s implementation of semaphores, we should try them out fully.

Controlling Access to Standard Input (STDIN) Using Semaphores

When learning about semaphores, a classic example is to control access to standard input.  There honestly isn’t much to the example, so I’ll just give you a quick breakdown of what happens and then let the code do the talking.

  1. Set the semaphore properties.
  2. Get the semaphore.
  3. Start a loop, and try to acquire the semaphore.
  4. Once acquired, access standard input.
  5. Once input is received store it, then release the semaphore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//Semaphore properties
$key = 123456;
$max = 1;
$permissions = 0666;
$autoRelease = 1;
 
//Open a new or get an existing semaphore
$semaphore = sem_get($key, $max, $permissions, $autoRelease);
if(!$semaphore) {
     echo "Failed on sem_get().\n";
     exit;
}
 
//Try to aquire the semaphore.
for($i = 0; $i < 2; $i++) {
     echo "\nAttempting to acquire semaphore...\n";
     sem_acquire($semaphore);
 
     echo "Aquired.\n";
     echo "Enter some text: ";
     $handler = fopen("php://stdin", "r");
     $text = fgets($handler);
 
     fclose($handler);
     sem_release($semaphore);
 
     echo "Got: $text \n";
}

Running the Example


First, you should download the example here.  After that open up two terminal windows and run the following in each:

{code} php semaphore.php {/code}

Did you like this article?  You’ll probably like these other PHP Dark Arts articles too.

PHP Dark Arts: Shared Memory Segments (IPC)

Note: The full source code for the examples can be downloaded here.

In my previous articles on using PHP for multi-process programming, we kept it very simple.  By simple, I mean we didn’t have any inter-process communication (IPC).  IPC is a set of techniques for the exchange of data amongst separate processes and/or threads.  There are many different ways to set up IPC, such as files, signals, sockets, pipes, semaphores, shared memory, and message passing.  This time around, we’re going to cover PHP’s implementation of shared memory segments.

So what does it mean to share a memory segment?  It means that the program will create a section of memory that can be accessed by other processes on the system.  Normally this isn’t the case, since most processes have mutually exclusive address spaces.  The benefit of using a shared memory segment is that communication between processes is extremely fast.  The main downside is that processes must be running on the same machine (and same processor in some cases), where as other types of IPC can be used over a network.

Creating a Shared Memory Segment

In order to share memory between processes, you first need to create the shared memory segment.  This is accomplished with PHP’s shm_attach() function.  The shm_attach() function takes 3 parameters.

  • $key (int) – This is an integer value that identifies your shared memory segment.  If you used 123456 for this value in one process, you would need to use the same key in another process to access the shared memory segment.
  • $memsize (int) –  This is the amount of memory (in bytes) you would like to share.  Deciding how large this should be is sort of a pain.  The easiest way it to simply pick an arbitrary amount and make sure anything you try to share isn’t larger then that.  The best way would be to know the maximum size of data you will need to share and set it to that value.
  • $perm (int) – The permissions for the shared memory segment.  These permissions follow typical Unix style permissions.  The default is 0666 which means that everyone can read from and write to this memory segment.

On success, shm_attach() returns an identifier of the shared memory segment.

1
2
3
4
5
6
7
//Define shared memory segment properties.
$key = "987654";
$permissions = 0666;
$size = 1024;
 
//Create or open the shared memory segment.
$segment = shm_attach($key, $size, $permissions);

Using Your Shared Memory Segment

Now that you have created a shared memory segment, you’ll obviously want to try it out.  Using it is pretty straight forward with the shm_put_var() and shm_get_var() functions.  They work as you might expect them to.  shm_put_var() has 3 parameters:

  • The shared memory segment key.
  • An integer used basically as an index on the data (making it easier to retrieve).
  • Some variable.  This can be anything so long as it’s smaller than the size you’ve defined the memory segment to be.

The shm_get_var() function is very similar.  It only takes 2 parameters, one of which is the key for the shared memory segment, and the other is the integer value (index) associated with the stored data.  Now that you know what the functions do, let’s put it all together in a little program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
//Check the command line arguments
if(sizeof($argv) < 2) {
     echo  "Usage: php shared_memory.php <send|get|delete> <integer identifier> <value>\n";
     exit;
}
 
//Define shared memory segment properties.
$key = "987654";
$permissions = 0666;
$size = 1024;
 
//Create or open the shared memory segment.
$segment = shm_attach($key, $size, $permissions);
 
//Handle operations for the segment.
switch($argv[1]) {
     case "send":
          shm_put_var($segment, $argv[2], $argv[3]);
          echo "Message sent to shared memory segment.\n";
          break;
     case "get":
          $data = shm_get_var($segment, $argv[2]);
          echo "Received data: {$data}\n";
          break;
     case "delete":
          shm_remove($segment);
          echo "Shared memory segment released.\n";
          break;
}
?>

A quick glance at the code reveals that I’m making this program a little interactive for easier use.  All it does is check to make sure your command line arguments are correct, creates / opens the shared memory segment, and then performs the given operation on the segment.  An example:

<->php shared_memory.php
Usage: php shared_memory.php send|get|delete integer identifier value;
<->php shared_memory.php send 1 "Hello.  This is the shared memory segment."
Message sent to shared memory segment.
<->php shared_memory.php get 1
Received data: Hello.  This is the shared memory segment.
<->php shared_memory.php delete
Shared memory segment content deleted.

You’ll also notice that at the end I delete the contents of the shared memory segment.  It’s important to understand the difference between detaching and deleting(removing) here.  When you detach the shared memory segment, it’s possible for your data to still exist in memory until it’s overwritten by something else.  This poses a big security threat, so you should always delete(remove) the data first.  So how do we release the memory?  By using the shm_detach() function.

<->
//Define shared memory segment properties.
$key = “987654”;
$permissions = 0666;
$size = 1024;

//Create or open the shared memory segment.
$segment = shm_attach($key, $size, $permissions);

//Detach the memory segment.
shm_detach($segment);

Download

Now that your done, check out the full source code for the examples here.  In the near future I hope to have a virtual machine available for download, so users who don’t want to mess with configuration can just start it up and go.

PHP Dark Arts: Multi-Processing (Part 2)

Note: Part 1 of this series can be found here.  Also, after feedback from the development community, this series was renamed to “Multi-Processing” instead of “Multi-Threading”.   To most people the distinction probably doesn’t matter, but this title is more accurate.

Priority

The priority of a process is a ranking given to it. The higher priority the process is given, the more CPU time it will get.  How much time on the processor each process gets is determined by the scheduling algorithm that is used, but in general, higher priority processes will get more CPU time.  All this begs the question, what is process X’s priority and how can I set it?

When compiled with the –enable-pctl option, PHP gives you access to the pcntl_getpriority() function.  This function is, well, obvious.  It gets the priority of the current process, or if a PID (Process ID) is specified, that process instead.

1
2
3
4
5
$priority = pcntl_getpriority();
echo "This process priority is: {$priority}.";
 
$priority = pcntl_getpriority(1234);
echo "Process 1234's priority is: {$priority}.";

So that one’s pretty easy. Not much explaining to do there. But what about setting process priority? For that, we use pcntl_setpriority().

1
2
3
4
5
6
7
8
9
10
11
if(pcntl_setpriority(-15)) {
     echo "Priority set successfully.";
} else {
     echo "Failed to set priority.";
}
 
if(pcntl_setpriority(15, 1234)) {
     echo "Priority of process 1234 set successfully.";
} else {
     echo "Failed to set priority of process 1234.";
}

The first parameter of this function is the priority.  In most cases, this value can range between -20 and 20. The lower the number, the higher priority your process receives (counter-intuitive right?). These numbers can change though, so you may want to view the man page for your operating system’s setpriority(2) function.  The second parameter is the process id.  If left blank, it sets the current processes priority, otherwise it tries to set the priority of the PID that is given.

Signals

A signal is a limited form of inter-process communication used in Unix systems.  Believe it or not, you probably use signals often when you are using a Linux box (CTRL+C anyone?).  Signals can be a problem when you’re doing important work that you don’t want interrupted, so PHP allows us to install signal handlers so that we can handle these situations gracefully.  To install a custom signal handler, you use the pcntl_signal() function.  Calling this function isn’t as straight-forward as the others though.  The first parameter is the signal which you are intercepting, which is an integer.  Most of the signals are defined as constants(here), so that’s what we’ll be using.  The second parameter is a callback function to handle the signal processing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
declare(ticks = 1);
function signal_callback($signalNumber) {
     switch($signalNumber) {
          case SIGTERM:
               echo "Handling shutdown tasks.";
               exit;
               break;
          case SIGHUP:
               echo "Handling restart stuff.";
               break;
          default:
              echo "Handling all other signals.";
     }
}
pcntl_signal(SIGTERM, "signal_callback");
pcntl_signal(SIGHUP, "signal_callback");

The above code first declares our callback function, then has a simple switch statement to handle the different signals.  After the function is constructed, we just call pcntl_signal() to set up the handler.  But why would you want to handle signals in the first place?  There are many reasons, but a good example would be financial data.  Wouldn’t you want to make sure a transaction goes all the way through before the system dies?  Or perhaps you want to send a message to someone if all transactions couldn’t be completed?  It’s situations like these where handling signals makes sense.

Now that we know how to handle signals, there are all sorts of neat functions we can play with.  If you interested in learning more, I suggest you check out the PHP documentation on the subject.

PHP Dark Arts: Multi-Processing (Part 1)

Note:  Part 2 of this post can be found here.

Of all the glorious programming languages in existence, you’ve chosen to work with PHP.  Okay, maybe you were forced to, but that doesn’t mean you can’t have fun right?  Hmm, fun… What’s fun?  Threading, race conditions, and deadlocks.  Sounds like loads of fun!  But alas, PHP doesn’t have functionality to cover this.  True, but the host operating system does.  We can just fork processes manually like in the good ‘ole days and then ride off into the sunset.  But we shouldn’t do that, it’s wrong.  It’s taking advantage of PHP.  Bah! We’re going to do it anyways.  And FOR THE LOVE OF GOD, do not do this in production code.  If you need multi-threading, use a different language.

Process Control

One of those things that you are bound to learn about if you go through a computer science degree is process control.  Process control usually comes up slowly and then bites you in the ass REALLY hard during operating systems courses.  Thinking about race conditions, deadlocks, and collisions are all part of the game.  And guess what?  When you are writing multi-threaded programs this is exactly the type of thing you will encounter.

When thinking about process control, people often cite some form of a producer-consumer problem.  You have one process (thread) producing information, and another thread consuming it.  For instance, a producer may spit out a stream of integers, and the consumer will, well, consume them.  However, the consumer will terminate itself when it hits a non-integer character.  That’s called out exit condition, and it’s very important.  You have to always remember to have some sort of fool-proof exit condition, otherwise the process is going to hang and go zombie on your.  If your program get’s executed a few thousand times a day, you get a few thousand zombies (process zombie apocalypse!).  So, the import part here is to remember that you need to have exit condtions.

Getting Started

The first step into multi-threading in PHP is making sure your build is compiled with the –enable-pcntl flag set.  If that’s not set, you’re dead in the water.  Otherwise, we can take a look at a simple example.

1
2
3
4
5
6
$processID = pcntl_fork();
if($processID) {
     echo "I'm in the parent process!";
} else {
     echo "I'm in the child process!";
}

Now, a quick explanation.  The pcntl_fork() function takes the current running process and makes a copy of it.  Everything (for practical purposes) is copied into this new child process except the process id(pid) which is changed to something new.  This is where things get a bit weird.  When pcntl_fork() executes, the pid of the child process is returned to the parents thread of execution.  A value of 0(zero) is returned to the child process’ thread of execution.  Since you can differentiate between threads of execution, you can make them do different things with a simple if statement like above.  So what does this program print?

I'm in the parent process!
I'm in the child process!

or

I'm in the child process!
I'm in the parent process!

It can actually go either way here.  It depends entirely on how your operating system decided to schedule the processes.  But remember, the child process is an exact (not entirely true, but let’s go with it) copy of the parent process.  So what happens if we change the code a bit.

1
2
3
4
5
6
7
$processID = pcntl_fork();
if($processID) {
     echo "I'm in the parent process!";
} else {
     echo "I'm in the child process!";
}
echo "End of the line folks.";

Since the last echo statement exists in both parent and child processes, you’ll get:

I'm in the parent process!
End of the line folks.
I'm in the child process!
End of the line folks.

Waiting for the Child

One of the problems that you run in to with writing multi-threaded programs is that the child process can finish before the parent, or the parent can finish before the child.  You just never really know.  So you need a way to wait for processes to finish.  Lucky for us, PHP at least provides this functionality for us.

1
2
3
4
5
6
7
$pid=pcntl_fork();
if($pid) {
     pctnl_waitpid($pid,$status,WUNTRACED);
     echo "In parent process!";
} else {
     echo "In child process!";
}

By using the pcntl_waitpid() function, we can force the parent process to wait for the child process to finish executing.  This is handy for if you have a critical procedure that your child process must complete before the parent can continue.  In our case, the output will always be:

In child process!
In parent process!

Next Time…

That’s all for now, but soon I’ll have The 2nd (and last) part of this article up for your enjoyment.  In that part, we’ll cover some more advanced notions like getting/setting priority, setting alarms, and signal processing.   You should follow me on Twitter and/or become a fan on Facebook to find out when this exciting(?) article comes out.

WordPress Shortcode API Tutorial

One neat feature of WordPress plugins is shortcode.  Shortcode enables a user to put something like “[myplugin]” in their posts or pages and have it display content from their plugin.  Making WordPress shortcode work for you isn’t terribly difficult, but without some help it can be confusing.  In this tutorial, I’ll show you how to use shortcode in your plugins.

Wordpress Shortcode API Tutorial

Shortcode Example

Let’s say you want to print out the current time anywhere in your post where you put “[time]”.  Easy enough!  Open up your theme’s functions.php and enter the following.

function time_func($atts) {
     $thetime = time();
     return date("g:i A",$thetime);
}
add_shortcode('time', 'time_func');

So now, “[time]” will be replaced with the current server time formatted like hour:minute AM/PM.  But what if you aren’t sure what format you want the time to come out in?  Well, you just need to add an attribute.  I’m going to be using PHP’s date() function formatting in this example.

function time_func($atts) {
     extract(shortcode_atts(array(
          'timeFormat' =&gt; 'g:i A'
          ), $atts));
     $thetime = time();
     return date($timeFormat, $thetime);
}
add_shortcode('time', 'time_func');

What the above code does is add the possibility of an attribute to your shortcode.  So you could use it like “[time timeFormat=’d.m.Y’]”, which return today’s date.  In the extract function, you can specify the default value (which I set as hour:minute AM/PM).  You can add as many attributes as you need to your shortcode.

For more information, please see the WordPress Shortcode API.

Search PDFs With PHP, MySQL, and PdfToText

Being able to search a PDF is a very useful feature on any web site.  The problem is that there aren’t many languages that give you the tools to do so right out of the box.  PHP is no exception to this.  If you want to search PDF files you’ll need some third-party tools and a little bit of ingenuity.

Pre-requisites

You’ll server will need to have the following configuration.

  • PHP (>=4)
  • MySQL (>=4)
  • Linux (Distro of your choice)

Step 1:  Download PdfToText

PdfToText is a program written in C that will quickly convert the contents of a PDF to text.  We’re going to use it just for that purpose.  You download the file at http://www.foolabs.com/xpdf/download.html.  Once you have downloaded the file, go ahead and place it somewhere in your web site directory and extract it (on most linux systems “tar -xzf [file]” will do the trick).  Once it’s unzipped, you’ll see a program called “pdftotext”, which is what we’re after.

Step 2:  Convert the PDF to Text

As an astute reader, you’ve probably noticed by now that PdfToText is not a PHP file.  So how are we going to use it?  Well, we’re going to use the “backtick” (the ~ [tilda] key) operator.

function convert_to_text($pdf) {
     $output = `./pdftotext {$pdf} temp.txt`;
     return $output
}

The backtick operator will execute any command on the command line, trap it’s output, and return it to the caller.  It’s worth noting that the backtick operator will only return output from standard out.

This is probably the hardest part of this tutorial.  There may be problems with write permissions on the directory, or ownership problems, but if you can get it to work, you’re all set.

Step 3:  Read the Text

Now that the PDF has been converted to a text file, we need to get that information back in to PHP.  To do that, we use the file_get_contents functions.

function get_text() {
     $text = file_get_contents("temp.txt");
     return $text;
}

Step 4:  Store the Data

This part of the tutorial assumes 2 things.  1) That you have a table named pdf_data, and 2) That the table has a column called pdf_contents that is full-text searchable (If you need help setting this sort of thing up, leave a comment).

function store_data() {
     $text = mysql_real_escape_string(get_text());
     $query = "INSERT INTO pdf_data (pdf_contents) VALUES ('{$text}')";
     mysql_query($query);
}

Step 5:  Search the Data

The final step is actually searching the data.  To do that, we’ll use the full-text searching capability of MySQL.

function search_data($term) {
     $term = mysql_real_escape_string($term);
     $query = "SELECT * FROM pdf_data MATCH(pdf_contents) AGAINST ('$term')";
     $result = mysql_query($query);
     while($row = mysql_fetch_array($result)) {
          //Do stuff with returned data.
     }
}

Where “Do stuff with returned data” is, you can do whatever you want.  MySQL is going to return the rows to you in order of relevance (descending).  The most relevant result will be first, followed by the second most, and third most, and so on.

Other Notes

  • PdfToText may or may not be the best way to do this, but it is one of the simplest.  There are a handful of libraries out there for creating PDFs in PHP, but surprisingly few for something as common as reading a PDF.
  • There are binaries and source files available for PdfToText on their web site(here).
  • This tutorial could be expanded a lot.  If you have questions or requests, please ask!