Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use class getters or class properties? (PHP)

What's considered best practice writing OOP classes when it comes to using a property internally.

Consider the following class;

<?php
Class Foo
{
    /**
     * @var null|string
     */
    protected $_foo;

    /**
     * @return null|string
     */
    public function getFoo()
    {
        return $this->_foo;
    }

    protected function _doSomething()
    {
        $foo    = $this->_foo;
        $result = null;
        // ...
        return $result;
    }
}

As you see im using the property _foo in _doSomething() although a sub-class could override getFoo() returning a computed value not stored back into _foo; that's a flaw.

What should i do?

  1. mark getter as final, use property internally (no extra function calls, enforce end-developer to use _foo as a property since it's protected)
  2. use getFoo() internally, mark _foo as private (extra function calls)

Both options are waterproof however im seriously concerned about all the extra function calls so i tend to use option 1 however option 2 would be more "true OOP" imho.

Also read http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private which also suggests option 2 :/

Another related question; If a property has a setter should that property be private, enforcing end-developers to use it in sub-classes or should it be an unwritten rule the programmer is responsible to set a valid property value?

like image 416
Roland Franssen Avatar asked Dec 31 '11 15:12

Roland Franssen


People also ask

Should you use getters and setters in PHP?

In this article, we learn the best way to create getter and setter strategies in PHP. Getter and setter strategies are utilized when we need to restrict the direct access to the variables by end-users. Getters and setters are methods used to define or retrieve the values of variables, normally private ones.

What is a class property PHP?

Data members declared inside class are called properties. Property is sometimes referred to as attribute or field. In PHP, a property is qualified by one of the access specifier keywords, public, private or protected.

What are getters and setters and why are they important?

Getters and setters are used to protect your data, particularly when creating classes. For each instance variable, a getter method returns its value while a setter method sets or updates its value. Given this, getters and setters are also known as accessors and mutators, respectively.

How do I access properties in PHP?

Within class methods non-static properties may be accessed by using -> (Object Operator): $this->property (where property is the name of the property). Static properties are accessed by using the :: (Double Colon): self::$property .


1 Answers

The second approach is, as you say, the more correct way according to OOP. You're also right that there is more cost in terms of CPU cycles in calling a method than in accessing a property as a variable. However, this will in most cases fall into the category of a micro-optimization. It won't have a noticeable effect on performance except if the value in question is being used heavily (such as in the innermost part of a loop). Best practice tends to favour the correct over the most performant unless the performance is genuinely suffering as a result of it.

For simple variables the use of a getter internally is not immediately obvious, but the technique comes into its own if you're dealing with a property that gets populated from an external data source such as a database. Using the getter allows you to fetch the data from the DB in a lazy way, ie on demand and not before it's needed. For example:

class Foo
{
    // All non-relevent code omitted
    protected $data = NULL;

    public class getData ()
    {
        // Initialize the data property
        $this -> data = array ();
        // Populate the data property with a DB query
        $query = $this -> db -> prepare ('SELECT * FROM footable;');
        if ($query -> execute ())
        {
            $this -> data = $query -> fetchAll ();
        }
        return ($this -> data);
    }

    public function doSomethingWithData ()
    {
        $this -> getData ()
        foreach ($this -> data as $row)
        {
            // Do processing here
        }
    }
}

Now with this approach, every time you call doSomethingWithData the result is a call to getData, which in turn does a database query. This is wasteful. Now consider the following similar class:

class Bar
{
    // All non-relevent code omitted
    protected $data = NULL;

    public class getData ()
    {
        // Only run the enclosed if the data property isn't initialized
        if (is_null ($this -> data))
        {
            // Initialize the data property
            $this -> data = array ();
            // Populate the data property with a DB query
            $query = $this -> db -> prepare ('SELECT * FROM footable;');
            if ($query -> execute ())
            {
                $this -> data = $query -> fetchAll ();
            }
        }
        return ($this -> data);
    }

    public function doSomethingWithData ()
    {
        foreach ($this -> getData () as $row)
        {
            // Do processing
        }
    }
}

In this version, you can call doSomethingWithData (and indeed getData) as often as you like, you will never trigger more than one database lookup. Furthermore, if getData and doSomethingWithData are never called, no database lookup is ever done. This will result in a big performance win, as database lookups are expensive and should be avoided where possible.

It does lead to some problems if you're working in a class that can update the database, but it's not hard to work around. If a class makes updates to its state, then your setters can simply be coded so that they null their associated state on success. That way, the data will be refreshed from the database the next time a getter is called.

like image 67
GordonM Avatar answered Sep 27 '22 18:09

GordonM