PHP

Useful PHP coding tips

I hope the following tips help some of the newer php coders and prevent errors I either had to face or did myself.

Don’t use private attributes/methods without a good reason

There are some libs or classes that use private attributes or methods for no good reason.
It makes it impossible to extend and modify this class.

Example:

class Doc {
    private $title = "";
    
    private function foo() {
    }
    ...
}

Now what if we want to add another method by using "extends"?

class MyDoc extends Doc {
    ...
}

We cannot access any of the attributes and have to redeclare them and stuff.
So: protected is more than enough.

Additionally, many still add the _ prefix for easier identification (although I am not sure what is the better practice here^^):

class Doc {
    protected $_title = "";

    protected function _foo() {
    }
    ...
}

Using prefixing is still the Cake way and makes it a little bit better to spot the different types. I prefer it. It also prevents naming collisions between the main public methods and its protected helper methods in some cases.

Now everything’s nice and extendable (even if there is absolutely no need right now)!

Same goes for 99% of all class functions.
The only case where private attributes make sense is when a private (for whatever reason) method is the only method accessing an attribute. Then we can make this one private, as well. And even then its debatable.

Using too much private attributes and methods even is kind of arrogant, if you think of it. You are making assumptions of what parts are so perfect that they will never have to be overridden. Impossible for all possible scenarios. At least for any class that is even remotely likely to be extended (which usually all are).

I would even say: Never use "private" anywhere. Especially since – in an extendable class environment (framework or not) – "protected" gives you everything you will ever need (You cannot use this item from outside – who cares what an the extended class does? Not your responsibility).

PS: I just recently stumpled upon a good article that not only states the very same, but also elaborates, why "private is evil".

Don’t count on arrays to start with int 0

Well, at least in some places it can easily be avoided to expect the array to have integer array keys starting with 0 (zero) or a specific key name for that matter.
One good example (it even shortens the code) is the custom model validation rules:

/**
 * usage: rule => array('validateIcq')
 * @return boolean $success
 * note: $data is in format: array('fieldname'=>'value')
 */
public function validateIcq($data) {
    $value = array_shift($data);
    //validate
}

It doesn’t matter if the array key is 0, 1, 2 or "whatever". We are only interested in the array value. So why bother using $value = $data[0] or $value = $data['fieldname']?
In most cases where the array is pre-processed and could have some array values removed this can end in unexpected behavior if we want to get the first record.
In my example from above the keyword would be the current validation field name. but it still could change – with this approach it is always working without error.

Note: array_shift() removes the current value. There are other methods which won’t do that. In any case, don’t simply put this $data[0] stuff in if there might be the slightest change it could also be 1 or 2 already.
Of course there are some appropriate cases for key access – but in most cases there are not, causing unnecessary errors.

Using current() and reset() you can easily go through any array that might have some "gaps".
Also note that foreach() works perfectly here, too.
Hard-coded keys only if the content of the array is reliably structured in all cases. Same with for($i = 0; $i < $x; $++) loops.

Remember to call parent methods

class MyFoo extends Foo {
    ...
    public function __construct($paramX, $paramY = null) {
        parent::__construct($paramY, $paramY); # with all contructor params!
        //your overriding content
    }
}

This is especially important for overriding model constructors in CakePHP!

Another example are callbacks like beforeFilter(), beforeRender() etc:

public function beforeRender() {
    parent::beforeRender();
    //your overriding content
}

I usually call the parent ones first, then move on to the overriding part. This can depend on the current case sometimes, though.

Note: For E_STRICT you also need to assert that the method declaration of your overriding class is the same then the parent one.
This would be WRONG:

    public function beforeRedirect(Controller $controller, $url, $status = null) {
        return parent::beforeRedirect($controller, $url, status); // $exit is missing
    }

This is correct (the declaration for this component is now exactly the one of the extended method):

    public function beforeRedirect(Controller $controller, $url, $status = null, $exit = true) {
        return parent::beforeRedirect($controller, $url, status, $exit);
    }

Respect coding standards

If you are developing for a framework together with others, for example, it is wise to find out what the coding standards are and try to adjust to them.
The sooner the better. Not only for framework related submissions, but also for your own extending code. It makes it easier to migrate pieces from your code into the framework or vice versa. It also helps to keep things in order. Imagine everybody would use different indentation, bracket positions, whitespace rules and so on.
Pretty soon the code is a mess no one can really work with.

More

// to be continued – maybe
// you got sth i missed? drop my a line

3 Comments

  1. Sounds reasonable!
    In this case we shouldn’t prefix the protected ones, either.
    Just to be on the same side. Would look odd to have the underscore there but for private ones not.

  2. To clarify (and rectify my previous comment) after working with Cake for a while now:
    If you do not use private methods (which you shouldnt^^), you can stick to the underscore prefixing (which is also Cake standard, by the way), since single ones are just fine.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.