17

I'm a little bit confused as I don't have much experience in OOP in PHP. I always hear that using instance methods is a better practice than using static methods, why is that?

I need a deep answer with an explanation, please.

For example why this below should be done with the instance method?

Controller:

public function getProperty($id){
        $property = Property::getProperty($id);
        return $property;
}

Model:

public static function getProperty($id){
        //$query = DB::table('properties')...
        //Some Code;
        return $query;         
}

I'm reading about setter/getter, instance vs static and etc. But I need a complete answer to understand the how and why of things.

3
  • 1
    For static methods you have to pass all the information that it needs to operate on. This includes an 'instance' of the class if it has to manipulate it. This is just a normal 'procedure call passing everything'. i.e A 'standard' procedure call. But all the procedures are collected together inside the 'class' name so are 'self documenting' as to where they 'live' when you use them in the code. Remember: they are just normal function calls. Commented May 22, 2015 at 18:33
  • 2
    For instance method calls then is it quite different... The instance is a separate entity that has it's own data and access to the 'static' methods of the 'class'. When an instance method is called - it passes the instance as the first parameter of the non-static 'class' methods. It really is that easy. Commented May 22, 2015 at 18:37
  • @RyanVincent In fact, using instance you have to pass all object needed for operation. Using static method you can easily access to the main object by singleton
    – TomSawyer
    Commented Dec 4, 2016 at 5:05

4 Answers 4

24

In general, as you've already stated, instance methods are the better practice. That isn't to say that static methods are downright evil, they simply have a different and unique purpose.

It is important to note that when dealing with instance methods you are working with an object whereas with static methods you are working with a class. When using static methods you will not have access to any of your non-static properties that would normally be available with an instance.

Take the following code as an example:

class Foo
{
    private $bar;
    private static $tavern;

    public function changeBar($value)
    {
        $this->bar = $value;
    }

    public function getBar()
    {
        return $this->bar;
    }

    public static function changeTavern($value)
    {
        self::$tavern = $value;
    }

    public static function getTavern()
    {
        return self::$tavern;
    }
}

Class Foo has a static property $tavern and a non-static property $bar.

If an instance of Foo is created then all properties and methods are available to that object.

If Foo is referenced statically then only the $tavern property, changeTavern() method and getTavern() method are available to the class.

Let's look at the following code:

$foo = new Foo();
$foo->changeBar('Tipsy Turvy');
echo $foo->getBar(); // prints Tipsy Turvy

Since $foo is an instance of Foo, it has access to the entire class. Calling changeBar() will modify the $bar property. To change the $bar property directly from a static method will trigger an error since $bar is available to the object and not the class.

// Calling this method would trigger an error
public static function changeBar($value)
{
    $this->bar = $value; // PHP will crash and burn if you try this.
}

If you want to access class properties from static methods those properties must also be declared static. This will work in the context of the class above. You'll also note that an instance of Foo has no problem reading static properties.

Foo::changeTavern('Stumble Inn');
echo Foo::getTavern(); // prints Stumble Inn
echo $foo->getTavern(); // also prints Stumble Inn

Another thing to remember about static code is that it doesn't behave like an instance. When the first instance of Foo was built both properties $bar and $tavern had no value. If you were to create another instance of Foo you would find that only one of those properties no longer contains a value. (I'm sure by now you can guess which one.)

$anotherFoo = new Foo();
echo $anotherFoo->getBar(); // prints nothing
echo $anotherFoo->getTavern(); // prints Stumble Inn
echo Foo::getTavern(); // prints Stumble Inn

So again, static code means you are working directly with a class - instances mean you are working with an object. It is important to note that any type of class you write that intends to have some kind of state to it should be used as an instance.

Static classes can be a little difficult to debug and test. Testing can be problematic because static properties don't change when you create a new instance. Debugging can also be difficult since the value of a static property is the same across all instances of an class. Make a change in one and you will make that change in all of them. Tracking down which instance made the change is a pain.

Speaking metaphorically, use static classes like sugar - sparingly and only when necessary.

Hope that helps shed some light on the topic.

1
  • In addition to that, PHPUnit cannot mock / stub static methods: (phpunit.de/manual/6.5/en/test-doubles.html), so the best practice is to avoid static methods as much as you can unless you mean it. If you take a look at PHP projects on GitHub (e.g., Symfony/Yaml), you can see that the static method is used to instantiate another object conveniently and there's no complex logic inside it (github.com/symfony/yaml/blob/master/Yaml.php#L53)
    – Ahmad
    Commented Jun 7, 2018 at 14:13
4

Instance method is not better then static, they are simply meant to be used differently. For example it would be insane to make factory method non-static.

Generally make instance method when method has something to do with current instance of the class (uses some state of this object, configuration parameters maybe) and static if it just belongs to the class as a whole like creating a new object, processing primitives...

E.g. ActiveRecords pattern often uses instance as mapping of record, so instance methods read/operate on the record, and static methods like searching, mass updating/deleting etc.

3
  • 2
    Can you please provide me an example of a static and a non static and their difference?
    – Makis
    Commented May 22, 2015 at 18:46
  • @Makis last paragraph of my answer makes attempt at that.
    – Cthulhu
    Commented May 22, 2015 at 18:55
  • Ooh, i'm sorry. Misunderstood!
    – Makis
    Commented May 22, 2015 at 18:57
3

I would agree with Cthulhu. Making a static method means you should not need to create an instance of the class to initiate the function.

I would love to explain using a small example based on his ActiveRecord pattern.

Let's sat we are writing our own AR pattern using a class that represents the Table "orders", which contain (like you could imagine) multiple order records.

If you use PDO as an connection class, you need to initiate this somewhere. In this example the initialization is initiated in the static method of the "order" class. Since you need to be able to "run this" before being able to query the database to get an order.

class order {
   public $data;

   public static $connection;

   public static function dbConnect($host, $database, $username, $password)   
   {
       try {
           self::$connection = new PDO(
               'mysql:host='.host.';dbname='.database, 
               $username,
               $password
           );
       } catch (PDOException $e) {
           print "Error!: " . $e->getMessage() . "<br/>";
           die();
       }
   }

    public function getOrderById($id)
    {
        $stmt = self::$connection->prepare('SELECT * FROM orders WHERE id = :id LIMIT 1');
        $stmt->execute(
            array('id', $id)
        );

        $this->data = $stmt->fetch();
    }
}

$order::dbConnect('localhost', 'myDb', 'user', '123test');
$order1 = new Order();
$order1->getOrderById(1);

$order2 = new order();
$order2->getOrderById(2);

print_r($order1->data);

print_r($order2->data);

Please ignore the fact that there are a lot of optimizations you could do to the actual result set or save it to the actual object. The main purpose of this code is to explain the fact when I would use static versus instance.

1

First of all it's not always better but in most cases it is. There are several reasons behind not using static methods:

  1. It's harder to put class on tests if it has static methods
  2. It's harder to extend this class if you want a little different behavior for same method
  3. Very often your static methods in class are just a way of making it global variable which almost always is a bad idea
  4. Refactoring this class will become hell if suddenly you decide that you need some class variable inside static method (change all Class::Method() calls to $c = new Class(); $c->Method())

I strongly invite you to read a little bit more about unit tests. When some other class is using yours with static method, then putting it to tests may be a challenge.

1
  • Can you please provide me an example of a static and a non static and their difference?
    – Makis
    Commented May 22, 2015 at 18:46

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