Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: PHP Tricks and Best Practices?
28 points by jmtame on Oct 29, 2008 | hide | past | favorite | 37 comments
Hi everyone,

I have scoured the YC forum for a post on great PHP tricks and best practices, but found nothing. Maybe I'm not looking hard enough, but I would appreciate it if anyone knows of great sites or tutorials. I use CodeIgniter (excellent classes, typical MVC setup) and jQuery (uses a lot of method chaining, huge fan of this). But I still find myself writing a lot of native PHP for my app.

For example, I wasn't aware of the list() function until someone was helping me write a method to convert times. I've noticed when working with another programmer on a project that he's using sprintf() instead, and it surprisingly makes the code a lot cleaner. I'm finding myself doing more algorithm-style methods, dealing a lot with arrays and a bunch of if's/conditionals (tertiary if's are great!).

Just using these as examples, I feel like there should be a cheatsheet of best practices and ways to minimize the amount of native code written somewhere but I'm not seeing it =]

*Edit: I'm going to open up CI's class files and look at how they wrote everything. Perhaps a good way of doing this is to look at other frameworks? Any suggestions there?




You should learn how SPL (standard PHP library) works. Most PHP developers don't even know it exists! In my opinion its one of the most powerful parts of PHP if you can learn to use it correctly.

http://us.php.net/spl

http://www.php.net/~helly/php/ext/spl/

The documentation on php.net is pretty lacking. Heres are some tutorials and examples:

http://www.phpro.org/tutorials/Introduction-to-SPL.html

http://devzone.zend.com/article/2565-The-Standard-PHP-Librar...


For some more SPL examples, read through the source of the KohanaPHP framework (http://www.kohanaphp.com). The framework was originally a fork of CodeIgniter, but has evolved into a completely new and powerful framework -- completely written in PHP5. The framework source is very well written and has some excellent examples of using SPL and OOP along with some nice helpers and libraries.


Whoa thank you! this PHP developer included.


Holy crap, these are AWESOME.


Something that took me a number of projects and maintenance type work to realize is to use "helper" functions wherever possible.

For example, a profile link:

    <a href="/user/profile/<?=$user->id?>"><?=$user->name?></a>
Write a simple function:

    function user_profile_link ($user) {
        return '<a href="/user/profile/$user->profile">$user->name</a>';
    }
And use it:

    <?=user_profile_link($user)?>
I used to think the extra code upfront wasn't worth it, but after dealing with a bunch of 300+ line templates for a while, I can tell you that it definitely is.

Also, you can see a use of string interpolation (a common use case for sprintf), ie "count is: $count"


At the risk of running afoul of Muphry's Law, your example needs double-quoted strings and curly braces (or your identifiers need to be moved outside the quotes and concatenated in).

At any rate, a downside to this approach is that you can't easily add a class or target (or any other attribute) to the A tag (at least in your simplified example).

Of course you could have an optional named parameter that would allow you to pass them in, e.g.:

    function user_profile_link ($user, $attrs) {
        return build_tag('a', array_merge(array('href' => "/user/profile/{$user->profile}"), $attrs), $user->name);
    }

    function build_tag ($tag, $attrs, $content) {
        array_walk($attrs, create_function('$value, $name, $list', '{$list[] = htmlentities($name, UTF-8) . "=\"" . htmlentities($value, UTF-8) . "\"";}'), &$list);
        
        return "<$tag " . join(' ',  $list) . '>' . (($content !== '') ? htmlentities($content, UTF-8) . "</$tag>" : '/>');
    }
But trying to do method-chainey sorts of things in PHP quickly runs into the language's clunky syntax, not to mention keeping track of exactly what level of quotation you're at, and so on. This is one of the reasons I like Ruby, as this kind of stuff is much more natural. Something like this:

    def build_tag(tag, attrs, content)
        attr_string = attrs.collect { |name, value| h(name) + '="' + h(value) + '"' }.join(' ')
        "<#{tag} #{attr_string}>" + ((content != '') ? h(content) + "</#{tag}>" : '/>')
    end
Both of these are probably a little denser than a sane person would put into production code, but the Ruby example is much more human-parseable to my eyes. (I'm using rails helper 'h', which could easily be defined in PHP as well).


I definitely prefer the ruby build_tag too, php's fine.. until you try to do something even remotely interesting.

And yeah, in real code the helpers sometimes need to get a bit more advanced. Something I like to do is add a class name corresponding to the function name (which I usually grab from __FUNCTION__) -- it helps keep a nice consistency between server-side/html/js/css


So is anyone using Smarty anymore? Or is this short form php now all the rage? Just curious because I'd update if it was.


I could never understand the advantage of using a templating system inside another templating system. Smarty has loops. PHP has loops. Did I miss the train?


Smarty produces slightly cleaner code but is worthless otherwise IMHO.


It's adding an extra layer of work which is unnessacary unless you're handing templates to people who really can't do PHP. If your designers are working on the HTML use Smarty tbh.


I use smarty mainly for it's templating benefits. Also you can write your own custom functions to call from the template files if needed, I found this to be very handy.


I've used smarty extensively at work, but I've always felt like I was fighting with the iteration constructs and odd choice of syntax.

I've always hated that in smarty, associative arrays are accessed with a dot. Associative array indices don't have to be valid php variable names, so what happens when you want to access $user['home-address'] in smarty?


With Smarty 2.x you're left needing to do something like: {assign var=foo value="some string"} {$user[$foo]}

Smarty 3.x has a legitimate lexer/parser so the templates will be much more flexible. I think they finally realized that since they are compiling the templates anyway the parsing can be slow.


Smarty is awesome, but a little dated. They are finally working on 3.0 alpha which will have much better php5 support.

http://smarty.net

Even as is though, it is worth using.


Funny, I do the exact same thing, I do it for everything. I thought that this was standard procedure - it gets you much cleaner code and it's easy to reuse all your little functions in other projects.

Maybe a simple website with little boilerplate functions would be something to do as a weekend project?


that's exactly what I'm talking about. I've been struggling with an easy way to link like this, as I use profiles. After you see it, you wonder why you never thought of it in the first place.


This is a bit of a specific one, but the array_shift function is really slow on large arrays. The workaround I found is to use array_slice and unset the array index afterward.

Overall though, I find out about a lot of cool things just from the comments on the php.net site. For example, I learned how to use pcntl_fork from the socket_accept page, and then I found out about socket_create_listen from one of the process control pages.

My approach is basically just to figure out what I want to do on a higher level, and look for sample code on all the individual parts. Then who knows, I might discover something amazing.


If you want to review very clean code you should better look at the Zend Framework. It's very good object orientated PHP 5 Code.


Have you looked through this: http://codeigniter.com/user_guide/ ?

It has a lot of a lot, so you don't have to write so much native PHP. Even Rasmus recommends it as his "framework" of choice (although he does not "like" frameworks).


Some of the stuff you've mentioned is really good old-school stuff, like list and sprintf, that's fallen out of vogue.

With regard to suggestions to check out Zend Framework, my advice is: Don't.


I'd say check it out - to read - but don't use it. They've got some interesting things in there, like OpenID implementation that's worth a read.


fluent expressions (when uses appropriately) can be great for constructing DSLs. Also any time you see boiler plate code take the time to refactor to eliminate it - often times figuring out how to do that will make new abstractions apparent. As a matter of practice search for the coolest things you can do in python (list comprehensions etc.), lisp and ruby and figure out how to do things in a similar way (if possible) in php.

Such as:

  //python version:
  noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
  primes = [x for x in range(2, 50) if x not in noprimes]

  //phparrayplus version:
  $noprimes = xR(2,8)->for_each('xR($x*2,50,$x)->out()')->flatten();
  $primes = xR(2,50)->diff($noprimes);

  //common lisp:
  (loop for x from 0 to 100 if (> (* x x) 3) collect (* 2 x))

  //phparrayplus version:
  $C = xR(100)->if_only('($x*$x) > 3')->for_each('2*$x');

  //factorial in phparrayplus, nothing else to compare this too  - just cool:
  function fac($n){
    return xR(1,$n)->reduce('$x*$y'); 
  }


Wow that shit is hot! Let us know when you have released the library.


Is "phparrayplus" a library you wrote. If so, where can it be had?


yes, it should be available next week on http://code.google.com/p/phparrayplus


I've had trouble for a while now with chained ifs, as in:

  [CHUNK A]
  if (chunk a succeeds) {
      [CHUNK B]
      if (chunk b succeeds) {
          [CHUNK C]
          if (chunk c succeeds) {
              echo 'yay!'
          }
          else {
              echo 'boo!';
          }
      }
      else {
          echo 'boo!';
      }
  }
  else {
      echo 'boo!';
  }
This gets messy if there's anything interesting in those chunks. Instead, take advantage of short-circuiting and put those chunks in functions. Then you can rewrite the above as:

  $success = do_chunk_a();
  
  $success = $success && do_chunk_b();
  
  $success = $success && do_chunk_c();
  
  echo $success ? 'yay!' : 'boo!';
Also, use the ternary operator EVERYWHERE YOU CAN - you'll clean up so much code with it.


even better is:

    $success =
        do_chunk_a() &&
        do_chunk_b() &&
        do_chunk_c();
    ...


Don't look at other frameworks. I did that and found it a complete waste of time. The best I found was to loosely follow the Ideals of a framework you like. I say loosely because frameworks always have the best intentions but they can't be built for everyone. So sometime I've had to cheat. I've seen code where somebody has made a work around instead of cheating and it's a mess.

Other than that my personal preference is to use jquery for form submits and manipulation, smarty for templating and everything is tied together following MVC ideals. Class inheritance is where it's at too. Simple one is that your Page class inherits the functions in your DB access class which inherits your config class. Silly I know but it works great for me. Which in the end is the point.


Oh and also sometime I stop writing features and review the code base thus far. This allows me to bring everything up to snuff with the the latest Ideas I may have had. I've rewritten my own code about 20 times and it's now the way I like it.


If PHP is your choice and not the result of prior mismanagement, then I would immediately schedule a two-week vacation. Rent a suite at a hotel with no internet service. Bring your laptop. Pick a language: Scheme, Groovy, Python, Ruby, Clojure, scala, Haskell... and implement something fun for twelve days. Do nothing but immerse yourself in the language. Take a couple days of rest. Then return to work freed of the huge mistake that is PHP.


More a trick than a best practice, heredoc

http://us.php.net/manual/en/language.types.string.php#langua...

You should recognize this immediately if you have done any unix shell scripting.

I use it to spit out large pieces of HTML.


Write your own collection of object oriented php classes or use someone else's. This will speed up your projects a ton. I tend to stay away from frameworks unless it is commissioned work that involves a lot of boiler plate code (forum, blog, etc.).


I think it would be a better idea to look at an application than a framework. It will likely match your future work better.

MediaWiki has in my experience a very well-written codebase, so I would designate it a good candidate for code-reading.


if speed of execution is relevant, just use echo (which takes any number of arguments), and single quoted strings (concatenating, or parsing double quoted strings is slower):

function user_profile_link ($user) { echo '<a href="/user/', $user->profile, '">', $user->name, '</a>'; }


list() isn't a function, it just looks like one, just like array() looks like a function but isn't. There apparently wasn't enough syntax to spend on making things like this less ambiguous, but now we do have \ as a namespace separator.


Cool PHP trick: write a compiler from a better language to PHP and write your code in that ;)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: