SEO guidelines

  1. Submit your site to the major search engines for indexing:
    1. http://www.google.com/addurl/
    2. http://search.yahoo.com/info/submit.html
    3. http://www.bing.com/docs/submit.aspx
  2. Check that your robots.txt file is correct and not preventing crawlers from getting into your site: http://www.robotstxt.org/
  3. Use Video and Flash sparingly, and knowing it doesn’t get indexed by crawlers
  4. Promote important content to home page, and make sure there are clean links from the home page to your site’s key content.
  5. Avoid duplicated content.
    1. If two or more urls on your site are pointing to the same content, use Canonical Urls as follows (to indicate the page to be indexed):  <link rel=”canonical” href=”http://example.com/original_content_here”>
    2. Use plugings for CMS packages to avoid this problem: http://yoast.com/wordpress/canonical/, http://yoast.com/tools/magento/canonical/
  6. Use friendly URLs with keywords about your content on it. It is ok to use the “-” sign to separate words.
  7. Use Meta tags to describe your page content.
  8. The page title is really important, make sure you choose one with keywords about your content as well.
  9. H1 headings: as important as page title, h2-h6 not as important but also take them into account.
  10. The first 100 words of your content carry more weight than the rest, use them wisely.
  11. For images, use descriptive image names, as well as good alt tags for them.
  12. The following online tools could help:
    1. http://www.google.com/insights/search/#
    2. http://www.seomoz.org/term-extractor

Design patterns: singletons

Singleton classes basically mean there is only one object class of a certain type running at all times. That could be used to store Global variables, for example.

The way to implement it on PHP:

class Preferences {
    private $props = array();
    private static $instance;

    private function __construct() { }  // By setting the class constructor to private, it can’t be instantiated from outside

    public static function getInstance() { // This static method will serve as instantiation, or to serve the only instance available
         if ( empty( self::$instance ) ) {
              self::$instance = new Preferences();
         }
         return self::$instance;
      }

      public function setProperty( $key, $val ) {
          $this->props[$key] = $val;
      }

      public function getProperty( $key ) {
          return $this->props[$key];
      }
}

Example of the driver class that is calling this:

$pref = Preferences::getInstance();
$pref->setProperty( “name”, “matt” );

unset( $pref ); // remove the reference

$pref2 = Preferences::getInstance();
print $pref2->getProperty( “name” ) .”n”; // demonstrate value is not lost

Design patterns: Composition and Inheritance (Strategy pattern)

Instead of creating child classes, you create a new tree of classes and move some of the functionality away from the main tree.

You connect the trees via object creation, meaning some of the classes in one tree contrain objects with the other classes type.

The advantage is that the trees are more specialized in what they do, so functionality in one tree is independent from the other tree, and it just complement it.

The disadvantages is that now you are creating more classes, so it may be difficult to maintain and keep track of it.

PHP __toString() method

Useful to convert objects that, when printed (say in debugging), will give you output like “Resource ID blah blah”, or error messages telling you you can’t print the object.

Example:

class Person {
    function getName()  { return "Bob"; }
    function getAge() { return 44; }
    function __toString() { // Controls how this object will represent itself when printed
        $desc  = $this->getName();
        $desc .= " (age ".$this->getAge().")";
        return $desc;
    }
}
$person = new Person();
print $person; // We get the printout defined in __toString() here...

PHP __clone() method

In PHP5, objects are passed by reference, and when we do assignments with the equal sign in objects, we are in fact using the same object for both variables, all pointing to the same reference:

$a = new TestObject();

$b = $a; // We end up with one object, two variables pointing to it.

In order to create two different objects, we can use the clone keyword instead:

$b = clone $a;

We can also clone parts of the object at the method or variable level, for instance, if we put the following method inside the class TestObject used above, everytime we clone it, we end up with two objects with some differences regarding the variables or property objects that compose them:

function __clone() {
    $this->id  = 0; // No matter what the value of id is on the original object, we will set it to 0 on the clone
    $this->account = clone $this->account; // If we have an “account” property object in the original class, we

                                                                                        // ensure its “uniqueness” this way in the clone object, making it a different

                                                                                        // object as well
}

PHP Error handling

When there are problems, always return an Exception object to the client.

Exception constructor accepts two optional arguments: an error string (error description in “plain english”) and an error code.

These are the Exception object’s public methods available:

  • getMessage() – Get the message string that was passed to the constructor.
  • getCode() – Get the code integer that was passed to the constructor.
  • getFile() – Get the file in which the exception was generated.
  • getLine() – Get the line number at which the exception was generated.
  • getTrace() – Get a multidimensional array tracing the method calls that led to the exception, including method, class, file, and argument data.
  • getTraceAsString() – Get a string version of the data returned by getTrace().
  • __toString() – Called automatically when the Exception object is used in string context. Returns a string describing the exception details.

The “throw” keyword basically stops the current method’s execution, passing an Exception object back to the calling client, and expecting it to handle the exception problem raised.

Error handling best practices call for subclassing Exceptions, so you have an exception per type of error, and handle the problem according to the exception type:

class XmlException extends Exception {
    private $error;

    function __construct( LibXmlError $error ) { // In this case we are expecting a LibXmlError already, but not
           // neecesary to have Type Hinting here
        $shortfile = basename( $error->file );
        $msg = “[{$shortfile}, line {$error->line}, col {$error->col}] {$error->message}”;
 $this->error = $error;
      parent::__construct( $msg, $error->code ); // Exception parent class is still called
    }

  function getLibXmlError() {
      return $this->error;
  }
}

class FileException extends Exception { } // Classes not “filled out yet”, but they will handle
class ConfException extends Exception { } // other kind of exceptions simmilar to XmlException

A typical client code that takes care of multiple exception types will look like this:

class Runner {
     static function init() {
        try {
            $conf = new Conf( dirname(__FILE__).”/conf01.xml” );
            print “user: “.$conf->get(‘user’).”n”;
            print “host: “.$conf->get(‘host’).”n”;
            $conf->set(“pass”, “newpass”);
            $conf->write();
        } catch ( FileException $e ) {
           // permissions issue or non-existent file
        } catch ( XmlException $e ) {
           // broken xml
        } catch ( ConfException $e ) {
           // wrong kind of XML file
        } catch ( Exception $e ) {
           // backstop: should not be called
        }
    }
}

When you have multiple catches this way, the first catch that matches the Exception type will be executed, so always try to put the more generic errors at the end. At this point, when an exception is catched, you can throw it again for further handling in subsequent catches.

PHP interfaces

Interfaces are pure class templates that define functionality. It can contain properties and methods, but no method implementation. See the example below:

interface Chargeable {
    public function getPrice();
}

So any class that implements this interface, will look something like this:

class ShopProduct implements Chargeable {
    // …
    public function getPrice() {
    return ( $this->price – $this->discount );
    }
    // …

When a class implements an interface, it takes on the Type of the interface as well, effectively having more than two types if that same class is also extending other classes, or implementing other interfaces. This way you can join types that are otherwise unrelated when creating a new class.

In PHP you can only inherit from one parent, but you can have multiple interfaces:

class Consultancy extends TimedService implements Bookable, Chargeable {

    // ...
}

OOP Best Practices and architecture

  1. When creating classes, make a really general abstaction of the object you have in mind (usually an abstact class or interface), and then start working your way down to the specifics using inheritance, encapsulation and polymorphism. For example: to create a book object for an ecommerce site, create something like Product / Item / Books / Book.
    • Advantages: This way your architecture can accomodate other objects later (cars / clothes / other categories)
    • Inside your classes, you avoid using hard to maintain “If” flags and clauses to perform different tasks per type of class
    • At the same time, you maintain a hierarquical structure of your objects that help you control variables and methods per level.
    • Make sure your classes are not overloaded with responsibilities. Spread responsibilities around the hierarquical structure of classes, if you can’t define a class responsibility with 25 words, and without using “and” and “or” words, you may be overloading your class with tasks. This will be hard to maintain.
    • But always remember: OOP best practices are not set on stone. If you have a good reason to bend the rules (performance, etc), do it, but think hard before you go ahead.
  2. As a general safety rule, you can set all methods and variables to private, and start resetting them to protected or public as you go along.
  3. Add error handling to all places things can go wrong (unexpected input / output usually). See PHP Error Handling section for more details, but basically extend the provided Exception class with a new class for each kind of error, and at the catch part of your try catch statement, have several catches that will deal with the particular error the proper way based on Exception type detection.
  4. Here are four possible indications of design problems:
    1. Code duplication: if you get a deja vu feeling at code writing a class, think: if I change something fundamental in this routine, will the other simmilar routine need ammendments? If so, then you may have a dup class you can compress in one.
    2. If a class depends too much on Globals variables and its context, this class will be hard to maintain. Try to make each class its own environment.
    3. If a class is doing too much, think of ways to reduce responsibility and extend down to other classes.
    4. Testing for the same condition with “if” statements throughout diffent classes may call to review your polymorphism. Where you can do the “if” test once, and spawn different objects with no “if” conditions down that fork
  5. Inside your classes, seek for those lines of code that express variation and fork the behavior of the current class given different values or conditions, and try to encapsulate them in their own type class.
  6. The golden rules: “Do the simplest thing that work”, and “are you sure you are going to need this extra complexity?”
  7. Avoid global variables like the plague, they make your classes highly coupled with the system, can’t be reused easily, and it’s hard to encapsulate stuff when using those. If you are to use Globals (say, to avoid passing too many variables or objects around) use singletons instead.
  8. Use phpDocumentor to add documentation to your code, even the default, do nothing and just run it option is better than nothing: http://www.phpdoc.org/
  9. Make sure you include Unit testing with PHPUnit