PHP Classes and Objects
Defining Static Properties and Methods
Problem
You want to define methods in an object, and be able to access them without instantiating a object.Solution
Declare the method as static:class Format {
public static function number($number, $decimals = 2,
$decimal = '.', $thousands = ',') {
return number_format($number, $decimals, $decimal, $thousands);
}
}
print Format::number(1234.567);
1,234.57
Discussion
Occasionally, you want to define a collection of methods in an object, but you want to be able to invoke those methods without instantiating a object. In PHP, declaring a method static lets you call it directly:class Format {
public static function number($number, $decimals = 2,
$decimal = '.', $thousands = ',') {
return number_format($number, $decimals, $decimal, $thousands);
}
}
print Format::number(1234.567);
1,234.57
Because static methods don’t require an object instance, use the class name instead of the object. Don’t place a dollar sign ($) before the class name.
Static methods aren’t referenced with an arrow (->), but with double colons (::)—this signals to PHP that the method is static. So in the example, the number() method of the Format class is accessed using Format::number().
Number formatting doesn’t depend on any other object properties or methods. Therefore, it makes sense to declare this method static. This way, for example, inside your shopping cart application, you can format the price of items in a pretty manner with just one line of code and still use an object instead of a global function.
Within the class where the static method is defined, refer to it using self:
class Format {
public static function number($number, $decimals = 2,
$decimal = '.', $thousands = ',') {
return number_format($number, $decimals, $decimal, $thousands);
}
public static function integer($number) {
return self::number($number, 0);
}
}
print Format::number(1234.567) . "\n";
print Format::integer(1234.567) . "\n";
1,234.57
1,235
Here the integer() method references another method defined in Format, number(). So, it uses self::number().
Static methods do not operate on a specific instance of the class where they’re defined. PHP does not “construct” a temporary object for you to use while you’re inside the method. Therefore, you cannot refer to $this inside a static method, because there’s no $this on which to operate. Calling a static method is just like calling a regular function.
There’s a potential complication from using self::. It doesn’t follow the same inheritance rules as nonstatic methods. In this case, self:: always attaches the reference to the class it’s defined in, regardless whether it’s invoked from that class or from a child.
Use static:: to change this behavior, such as in this ORM example:
class Model {
protected static function validateArgs($args) {
throw new Exception("You need to override this in a subclass!");
}
public static function find($args) {
static::validateArgs($args);
$class = get_called_class();
// now you can do a database query, such as:
// SELECT * FROM $class WHERE ...
}
}
class Bicycle extends Model {
protected static function validateArgs($args) {
return true;
}
}
Bicycle::find(['owner' => 'peewee']);
With self::, PHP binds to Model::validateArgs(), which doesn’t allow for model specific validation. However, with static::, PHP will defer until it knows which class the method is actually called from. This is known as late static binding.
Inside of find(), to generate your SQL, you need the name of the calling class. You cannot use the Reflection classes and the __CLASS__ constant because they return Model, so use get_called_class() to pull this at runtime.
PHP also has a feature known as static properties. Every instance of a class shares these properties in common. Thus, static properties act as class-namespaced global variables.
One reason for using a static property is to share a database connection among multiple Database objects. For efficiency, you shouldn’t create a new connection to your database every time you instantiate Database. Instead, negotiate a connection the first time and reuse that connection in each additional instance, as shown:
class Database {
private static $dbh = NULL;
public function __construct($server, $username, $password) {
if (self::$dbh == NULL) {
self::$dbh = db_connect($server, $username, $password);
} else {
// reuse existing connection
}
}
}
$db = new Database('db.example.com', 'web', 'jsd6w@2d');
// Do a bunch of queries
$db2 = new Database('db.example.com', 'web', 'jsd6w@2d');
// Do some additional queries
Static properties, like static methods, use the double colon notation. To refer to a static property inside of a class, use the special prefix of self. self is to static properties and methods as $this is to instantiated properties and methods.
The constructor uses self::$dbh to access the static connection property. When $db is instantiated, dbh is still set to NULL, so the constructor calls db_connect() to negotiate a new connection with the database.
This does not occur when you create $db2, because dbh has been set to the database handle.
No comments:
Post a Comment