Forum Moderators: coopster
Separate the HTML from the PHP. Sounds simple, but I never really caught on until recently.
Let me give you an example:
I work with a lot of form data -- I check it for abnormalities, sanitize it, and then insert it into a database.
A lot of tutorials I've seen will show you a single file to handle these functions. They'll use a $_GET or $_POST to find out which part of the script to call. For instance, if you're previewing the post, they may have a variable?step=preview. This tells the script to bring up a preview of the post.
This single file will be loaded each time, with the form action set to itself, and the proper section will be ouput to the browser. These pages can easily come to be a hundred or two hundred lines in length.
Don't do that.
What I've begun to use most recently is a traffic cop like setup. Every page on my site gets routed through this traffic cop, and it determines where to send the user.
For instance, suppose a user wants to create a new post. They get sent to the traffic cop page. The traffic cop checks a $_POST variable, $_POST['page'] for instance, and if it is unset then it knows this is you first time at the page. It include()s the proper page --> a blank form to create your post. It also has a hidden input field named "page" which it will set to "1".
Then the form's action sends you back to the traffic cop.
The traffic cop checks and finds that $_POST['page'] is set to 1. So it now checks all the $_POST data to find out if you've left a field blank, or if your email address is gibberish, or any other thing. If there's a problem, the traffic cop includes the edit_bad_post.php page. This page will bring up the form populated with your bad data, and will again have a hidden input field named "page" with a value=1.
Once the user corrects their data, they're sent to the traffic cop. It checks their data, and if it's all good it includes preview.php. This page shows a preview of the post, and has a publish button. It also has a hidden field "page" that it sets=2.
When the user clicks the publish button they're sent back to the traffic cop. The traffic cop sees that this is ready to be published, so it again checks all the data to be sure it's still good -- if somebody is trying to throw a wrench in things they'll be stopped here -- and then prepares the data using mysql_real_escape_string() and htmlspecialchars() or any other thing you want to do to sanitize the data.
Finally, it inserts this into the database.
Then the traffic cop inclues the page post_successful.php which says "Thanks for posting!".
The user is always at a single URL, and has no idea that 3 or 4 pages are being called. The traffic cop makes sure no rowdy business goes on or any injection of harmful data, so you don't have to do this on all your individual pages.
This could probably be done with functions, but I find that it makes it much easier when you can break the parts of a site down into individual pages, and then have a traffic cop that makes sure everything is well.
I also like to set a $traffic_cop="yes"; variable on my traffic cop page, and then at the beginning of every other page check to be sure this variable is set to "yes". If it is not, then somebody is trying to access one of your pages directly -- which they never should -- and you can just throw up a 404.
Works real slick for me.
This why I have quite successfully run sites with millions of pages.
SN
Personally I set up all my sites this way. I usually use PATH_INFO to select pages and mod_rewrite to remove th escript url. the scrupt is usually index.php and creates teh whole site. Since much of my sites is DB driven, I don't have scripts for individual pages (that concept hardly exists on my sites) but for "classes" of pages.
That's an excellent idea. I've never taken it to that level, mainly because my sites tend to be small in page number but with many different functions/features. I just find it's a little easier for me to organize the comments into one area, the blog entries into another, the contact forms into another, etc.
When you say you don't have scripts for individual pages but for classes, what exactly do you mean? I'm always looking for ways to organize my structure more efficiently, and this sounds interesting.
Currently I have a folder set up for each different function of my site. Then I mod_rewrite all the search engine friendly urls to the index/traffic cop in each folder.
This way, if the process is successful you can redirect to a 'success' page and not have problems with people hitting reload etc. If the process fails you can use the $_POST data to re-display the form and point out errors.
Using this method the files that I use for a 'guestbook', 'photo gallery' or 'latest news' page can be directly copied from one site to another.
I guess if you were running a single site then some kind of 'fat controller' might be handy, but for anyone building a lot of sites, I'd advise staying 'lean and mean' ;)
I have few main php files (sth like districts). Each of them is protected by one inlude script (if user validation fails it redirects to login page), then the cop directs to whatever resource.
However I validate the input by javascript and functions that do sth.
Before I wrote one site with such a cop as you described, but after some time it's really hard to understand and extend the script.
Michal Cibor
A couple of notes.
If you set a variable $traffic_cop = 1, a potential problem is that if register_globals ever gets turned on, people can add this to the parameters in a url and still call your include files directly. It's preferable to define this as a constant, which can't be modified by simple script parameters:
define('TRAFFIC_COP', 1);
and then in your include files:
if(!defined('TRAFFIC_COP')){
header($your_404_header);
die($your_404_message);
}
Another note: a couple of hundred lines isn't generally a big deal in a php script. What you're describing generally falls under the category of making your scripts more 'modular.' This can indeed reduce your script's memory requirements and make your scripts more maintainable - everything in a nice, easy-to-find place. However, a couple of hundred lines isn't really such a big deal when it comes to PHP scripts - if your script files get this long, don't sweat by all means. If it's just code that gets jumped over by code branching (ifs and other control structures) it might not be as big deal as one might think. Most ready-to-use web scripts will have at least one file that approaches or exceeds a thousand lines. If you can save yourself time and confusion by just adding a few extra lines, e.g. your 'thanks' page or for a simple form, go for it. Modularizing, if it creates extra work, imho is only worth it for chunks of code more than a few hundred lines, unless you have an incredibly high-traffic site.
Rather than including another PHP script, you'd populate the variables you want to send to the template, select the template, and generate it.
The reason you moved to your cop model is to make the code shorter and simpler. Templates will separate the code from the display and make it even more clear.
Sean
SN
I'm not a traffic cop kind of guy. If I'm building a login page, that code goes on /login/index.php. A register page may be found at /register/index.php. A thank you page for registering may be /register/thank_you.php. Now I've built up quite a library of functions and classes that I use on most of my websites. I like to throw these in an _incs folder. I have a function that determines whether the page has any form data submitted to it, and whether that form data can be trusted. I have classes set up to create user login data. My big pride and joy which I've created recently is a class that creates forms, collects and validates the posted data, and submits it to a database. It saves me a ton of time.
So my individual pages are pretty lean. I like being able to go to separate pages like that and follow the same file structure that my website has. Of course the bulk of the webpages on my sites are dynamically created, but pages that have a general function, really do exist on my servers. It's just the way I like it. I wouldn't go as far as saying it's better than any other method of coding. It just makes sense to me, and it has never hindered me in any way. I've never experienced a con.
Now you've stated that this is a tip for new PHP users, but please share how you feel that this method is beneficial. You've just shared how you code, not why.
Now you've stated that this is a tip for new PHP users, but please share how you feel that this method is beneficial.
Over the past months I have created about a dozen sites, all very much different from each other. For whatever reason I always like to reinvent the wheel when I create a new site -- every one of them starts with a blank notepad. Although I recycle a few bits of code here and there, almost all the site functions are for the most part unique.
I've spent a lot of time working to deal with form-input user data. The three things that I've come up against most often are:
1) I hate quotes and apostrophes and slashes and happyquotes. Absolutely hate them. I wish there was some unambiguous symbol that couldn't be spoofed by users that meant BEGIN STRING ¦ END STRING and nothing else.
If you want to maintain the utmost security in your form/preview/insert site functions, you're going to have to a lot of checking and manipulation along the way. On one of my sites I run the data through many unique functions along the way, where the string is potentially altered in as many as 30 ways. Most of these are there with security in mind (e.x. after the page is previewed I still run checks on the data before I insert it into the database, even though it should never have changed since the last checks/sanitization).
2) When you realize you forgot to add a textarea or drop down box, or want to add one in the future, you will invariably have troubles getting right the first time when you insert it in on all the different preview and publish pages.
3) The longer your pages, the more difficult they become to manage. I still haven't found a way I'm comfortable with that allows me to completely separate the PHP from the HTML when I have to output data into a template. I use the traffic cop to minimize the number of pages that have PHP which is used for non-display purposes.
I'm not an expert by any means -- in fact, I really don't know all that much about PHP or programming in general. I've only learned how to do the things I needed to accomplish the task at hand. I'm sure there are some other much more simplified ways of doing some of these tasks, but as of yet this is the one I have found that I feel most comfortable with.
I know it probably doesn't make any sense, but I still feel uncomfortable trusting *everything* to a database. I like to have a skeleton site there, even if all the content is coming from a database. I also find that a skeleton site allows me to more easily customize headers and footers and columns when I want a sub-class or even a single page to have a different look than the rest of its siblings.
The benefits for me probably wouldn't be worth it for somebody who has a very finite number of template pages with few functional differences between those of the same class.
Even if my method is not right for somebody else, I think it is interesting to see the ways people organize their sites.
I've just started writing in php. In fact, the only thing I've written is a form handler for some gaming clan application.
I want badly to get into php, because I was a C/vb programmer a few years ago and felt the utter joy of creating my own programs that other people wanted.
PHP has the very similar feeling to it when I see something created run, as well as the aspect of it's all over the internet and anyone can now enjoy my creations.
My question is this: What is a good source to start learning php from basic commands to running a site? I know include and $_POST, and that's about it -- and I wont mention I'm having a difficult time getting include to work right...
I've read a few e-books and I read the documentation on php.net, but I need something that will teach me.. not only show me, without going into a classroom and spending big bucks.