views:

549

answers:

4

I wrote a small PHP application that I'd like to distribute. I'm looking for best practices so that it can be installed on most webhosts with minimal hassle.

Briefly: It's simple tool that lets people download files once they login with a password.

So my questions are:

1) How should I handle configuration values? I'm not using a database, so a configuration file seems appropriate. I know that other php apps (e.g. Wordpress) use defines, but they are global and there is potential that the names will conflict. (Global variables also have the same problem, obviously.) I looked at the "ini" file mechanism built into PHP. It only allows comments at the top - so you can't annotate each setting easily - and you can't validate syntax with "php -f". Other options?

2) How to handle templating? The application needs to pump out a form. Possibly with an error message. (e.g. "Sorry, wrong password.") I've have a class variable with the HTML form, but also allow an external template file to be used instead (specified in the config). I do some trivial search and replace - e.g. %SCRIPT% to the name of the script, %STATUS% to hold the error message. This feels a bit like reinventing the wheel, but including a templating system like Smarty is overkill. (Plus they may already have a templating system.) Other options?

3) i18n - There are only 3 message strings, and gettext doesn't seem to be universally installed. Is it such a bad idea just to make these three strings parameters in the config file?

4) How to best integrate with other frameworks? My app is a single class. So, I thought I could just include a php script that showed how the class was called. It would be a starting point for people who had to integrate it into another framework, but also be fine as-is for those not interested in customizing. Reasonable?

5) GET/POST parameters - Is it bad form for a class to be looking at $_GET and $_POST? Should all values be passed into my class during construction?

Thanks.

+2  A: 
  1. Can config be local to class instances? Or could you create a little class that you could create an instance of to query for config values? Also prepending any global vars with you application's name should go some way to stop clashes.

  2. If your templating is really simple, just write a short templater. It'll be easier than trying to fend off problems people get with any 3rd party templater. It might also simplify licensing issues. If you start worrying about what they already have, you'll never release anything. There are too many combinations.

  3. For 3 strings? Yeah do those the same way you're handling config.

  4. Good comments throughout with an intro explaining how you use the class.

  5. I don't think so. If it bothers you, you could use default arguments to use given arguments first, then search for GET/POST values if none are provided (though that might be a security risk)

There are other things to take into consideration. Lots of people are on shared hosts and as a result, don't have control over their php.ini or their php version. You need to make sure you're only using features that are as commonplace as possible.

One example is that shorttags aren't enabled on some hosts (you have to use <?php ... ?> and <?php echo "..."?> instead of <? ... ?> or <?= "..." ?>) which can be a royal PITA.

Oli
+7  A: 

Configuration

You can use a php file like this:

<?php
return array(
  'option1' =&gt; 'foobar',
  'option2' =&gt; 123,
  //and so on...
  );
?>

And in the main class just use:

$config = (array) include 'path/to/config/file';

And if you plan to mostly distribute your class as a component in other applications, then simply put config array/object as a parameter in your class' constructor and leave the details to the user.

Templating

For such simple application the method your described should be enough. Remember that one can always extend your class and overload your outputting method with his own.

I10N

As mentioned before, for 3 variables anything more than storing them as config is just overkill.

Integration

Comment each public method (or even better also protected and private ones) with explanations what do they do and what parameters are needed. If you combine that with an example, it should be enough for most users.

GET vs POST

Your class uses passwords and you even think of sending them via GET? ;) Think of browser history, referer headers etc - your users' passwords would be visible there.

Krzysztof Sikorski
I love that config style! I'm going to try it out right now.
Jason Moore
+2  A: 

In addition to Krzysztof's good advice:

  • Use <?php only
  • If you use functions that can be disabled, use function_exists() to ensure they're available. @missing_function() makes PHP die silently without any error logged.
  • You can't rely on things that can be disabled/changed via php.ini. Use ini_get() to adapt to different settings.
  • If magic_quotes are enabled, strip slashes only on from your copy of input – don't modify global arrays! Security of some lame code may rely on these slashes being present.
  • Expect that users will mindlessly copy&paste code from your documentation/website.
porneL
"Use <?php only"In other words, omit the "?>" ending tag, it is not needed if it would be the last characters of a file.
Krzysztof Sikorski
I get that short tags might cause problems - my PHP files are all PHP, so this isn't a big deal. But what does omitting the '?>' buy me? (Less risk of adding unintentional extra spaces?)
Jason Moore
You don't risk outputting white space at the end of the file - which may be bad if you want to send http headers later in the applications, for example start session. Of course you can bypass this problem with output buffering.
Krzysztof Sikorski
A: 

Thanks for the responses. Lots of good tips to keep in mind. I marked the Krzysztof's answer as "accepted" since the technique of including a configuration file into an array was new to me, and it nicely avoids global variables and namespace conflicts.

Jason Moore
Not exactly, the code in included file is executed in the same scope as the include statement. On the other hand, the file sets no variables so there should be no problems. If you want to make sure, just wrap the include statement in a function call.
Krzysztof Sikorski