One of the major issues I keep seeing in many threads is that rarely is anyone filtering their request/input variables.
What does this mean? In short, it means you are trying to validate any information submitted to the form before using it. If you use a variable from the $_GET superglobal in an SQL query, you open yourself up to SQL Injection. If you use one to determine which files to include, you open yourself up to a complete site takeover.
If a script is available on the internet, then it can be called by anyone and can be passed any variables that person decides to use. Just because you have a nice system setup where only a couple variables are used, hackers will try submitting many common variable names (via GET and POST) to see if they can crack in.
In short, ANYTIME you need to get the value of a GET or POST variable, you need to filter and/or sanitize it. Lucky for you, PHP has a library for this (PHP5+, but PHP4 support stopped in 2007, so its not good to use). There are other libraries out there in various frameworks, if you need more advanced functionality, such as Zend Framework Zend_Filter.
Here are some ways you can use it. The list above will show all of the flags to use.
Getting a POST variable, validating it
Getting a POST variable, sanitizing it
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
You can create your own filtering function if you really need to. You can also use this class just to validate any variable, by using filter_var() instead.
$url = filter_input(INPUT_POST, 'url', FILTER_SANITIZE_URL);
So to recap, the majority of security problems with PHP programs are due to the program trusting the input data. I think that most training materials do not cover this topic, or do not cover it early enough in the training. Filtering doesn't make it 100% certain you cannot be hacked, but it is certainly the best way to start thinking about security in your programs.