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.