Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm new to PHP in a professional context. I want a few macro thumb rules to keep me on the enlightened path. Here are a few I'm proposing to myself:

  • no absolute paths in include|require(_once)? statements
  • no .. dirname(foo), or other means of walking up in include|require(_once)? statements
  • put libs on the include path, not in subdirectories

You can see that all of this is focusing on managing dependencies, because that is the problem I've encountered thus far.

What other thumb-rule solutions to macro level problems do you have?

share|improve this question
4  
PHP? Use fire. And lots of it! :P –  FrustratedWithFormsDesigner Oct 4 '12 at 18:42
add comment

3 Answers

up vote 7 down vote accepted

Without a little more context it's hard to suggest anything, but here are a few replies to your points you've made:

Dependencies - use Composer to manage your dependencies. It'll dump them into vendor (configurable) and you'll be able to easily upgrade them or add new ones. Don't use the include path unless its truly system wide stuff (such as phpunit). If you have multiple apps on the same server, they may require different versions of libraries.

Relative Paths - use them where they make sense. If your package is to be portable, it makes more sense to use relative paths. __DIR__.'/some_subdirectory' is quite common and typically recommended for portability. It really depends on what you are using it for though.

Loading Classes - the PHP community has widely adopted autoloading. Composer will do this for you, but typically you see classes mapped to the filesystem

Company/Package/ClassName is located in src/Company/Package/ClassName.php (or that same Company/... structure inside a vendor directory).

Check out a new set of tutorials / guides called PHP: The Right Way which is trying to organize all these things into a large reference. If you want the latest from the professional community, that's the place to check. The web is littered with bad advice, so tread carefully!

share|improve this answer
add comment

There are very common approaches which are true for every language. This set of principles may help to audit the code. I can think of a few coding practices that smell.

  1. Error Suppression — From php.net:

    PHP supports one error control operator: the at sign (@). When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.

    Do yourself a favor and perform a find->all in your IDE for the @ symbol and divide and conquer.

  2. Error Notices — Along the same vein as above, PHP allows you to set your error reporting level at runtime. Many developers suppress simple warnings and notices. You should use the error_reporting() function with a parameter of E_ALL or E_STRICT to display all PHP errors: error_reporting(E_STRICT);.

  3. The global keyword — PHP allows programmers to define global variables to break function scope. Scope is a little upside down in PHP... If you create a variable outside of a function, it can be modified inside the function if it has been declared inside the function as global. That smells.

  4. Deprecated Features — PHP is rife with functions and features, and many of them have been deprecated.

  5. Hard-coded database query fragments - mysql_query() — If the devs haven't used or developed some kind of database abstraction, you're going to see a bunch of hard-coded database queries littered all over the place. This should probably be moved to Code Smell #1.

  6. Lots of Static Methods — maybe a code smell in any language, a developer can effectively globalize everything by making all of his classes/methods static. Per Jeremy Walton's suggestion, search for the word static and the Paamayim Nekudotayim operator (::).

  7. Complex String Syntax and Variable Parsing — hard to explain on a dime, check out the reference here: http://php.net/manual/en/language.types.string.php Look for the section on Variable parsing a few screens down. If this is abused it can be a nightmare to debug and/or understand.

  8. Variable Variables — another whopper. This article explains the madness best. Just search for two dollar signs $$ to identify if they've succumbed to the Dark Lord.

  9. Tricky functions - include_once() and require_once() — These functions are fine, to be sure. They are very useful when templating and separating view logic. They ensure that a file is included only once when scripts are parsed. However, if you see them used liberally in the business logic portion of the application, this is a red flag that the developer has written nested/circular includes, and may not be aware what portions of code have already been included. This isn't so bad per se, but it's definitely a window into the competency-level of the developer(s). Finally, @Phil suggests the use of autoloaders instead of require_once(). This article explains autoloading in good detail.

  10. String and Redundant Booleans — a lot of bad PHP code looks like this if ($is_true == "true"). This is easy to search for, and harder to fix. Something else to look out for--though not a PHP specific issue--is Redundant booleans: return ($isBad) ? true : false;.

  11. Short Tags — Here's what PHP.net has to say about short tags:

    Using short tags should be avoided when developing applications or libraries that are meant for redistribution, or deployment on PHP servers which are not under your control, because short tags may not be supported on the target server. For portable, redistributable code, be sure not to use short tags.

    ASP style tags are even worse.

  12. Accidental Assignment — More often than not, you'll see this happen in some non-critical component of the code, where it can sleep and/or lurk until you get an unexpected result one day: if ($foo = "Some Value"). This always evaluates true, of course, and was most likely due to a typo. However, in rare circumstances you'll actually want to test for assignment. If that is the case you should use double parenthesis to indicate intent: if (($foo = $this->bar()))

Tools

Some tools you might look into:

There are more I think, but have no list. However it's all a bit involving (setup). So try one or two which sound most helpful for the start. After you've exhausted the visualization tools of your IDE.

References:

share|improve this answer
add comment

Macro rules of thumb? Besides cross-language stuff like source-control or consistent naming styles?

  1. Try to use a Front Controller model if you can. It makes things much much simpler in the long-run. It sidesteps a lot of grief when it comes to relative paths and environmental setup.
  2. Avoid defining top-level functions/variables/constants. They just don't scale. Strongly prefer using classes to "host" anything, even if it ends up being a static method or a class-constant.
  3. Design you classes to take advantage of class autoloading. This typically means that class Foo_Bar_Baz is defined in file Foo/Bar/Baz.php, taking advantage of direct text replacements. However, if you have a better method of taking a classname and determining what file to include, go ahead.
  4. Avoid creating files which contain both class/method/constant definitions and also top-level procedural code that executes when the file is included or required.
  5. Take advantage of IDEs which allow you to annotate your PHP code and provide autocompletion.
  6. When you're building a web-page, remember that sometimes code that comes near the end will want to change a header, or add a <script> tag. Architecturally, try to defer generating HTML for as long as possible. (Interpreter-level output buffering is a helpful half-measure.)
  7. Do everything in UTF-8 from the very beginning, or you're gonna have a bad time.

And dangerous stuff for use only when the tradeoff is worth it:

  1. Careful usage of &references will allow you to make in-place changes to an array, which can be enormously helpful when trying to modify huge nested arrays. (Always unset() them afterwards.) Of course, those same huge arrays are a code-smell, and you should consider replacing them with classes which self-document and enforce structure.
  2. Variable Variables can be useful in small, contained areas, but using them widely is an invitation to problems when refactoring later on.
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.