PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!
I'm currently reading the book "PHP in Action". I'm a newbie in OOP, and I'm reading the first part of the book which talks about Object-oriented design and programming.
I have a question which arose after I read the following paragraph from section 3.2:
For example, the data needed to create an instance might need to be read from a database. This behavior, reading from the database, is related to the class but cannot be done by an instance of the class. One possible home for this behavior is in a class method (static method): one that be called using just the class name rather than a variable representing an instance:
What's wrong with $product = new Product($productCode) ?
The constructor will find the requested product based on $productCode and a new instance will be created. If the product does not exist in DB, an exception will thrown.
Let's say we have a class to represent Users in phpBB. In the profile page, we have the User's ID passed to the script. Now what is the best way to create an instance for the requested User and fill in the member-variables by information read from DB?
if you want a complete object you have to initialize it and then you have access to object properties and methods.
But sometimes you may want a method that you can access directly without creating an object (which may involve several sql queries etc)
then you use static methods
I already know the difference between static and non-static methods. My question is: Which one should be used in the situation which I described above?
Suppose you have inserted FirstName, LastName, Phone, Address, etc. of a user into the database and you have a page which displays these details (profile.php). Each user has a unique ID which you pass to profile.php in order to see her details. We're now going to visit profile.php?id=10. What will happen in this page?
In OOP you're exposed to plenty of design patterns. Static methods provide a great opportunity to use the factory design pattern (creating new objects) as a means of convenience.
Take a class which represents a row of data from a table in the database:
if ($user = User::retrieveByUsername("foo"))
{
echo "User group is ". $user->getUserGroup();
}
The static method is a factory which looks in the DB for the correct user, creates a new object from the class "User" itself, put the correct values in it and then returns it for use. Contextually this just feels right and it's one of the places where static methods come in useful. Static methods do just come in handy generally as convenience methods though
public static function retrieveByUsername($username) {
// first check if user exists
$db_result = mysql_query("blah blah blah");
if (db_num_rows($db_result)) {
// then create a new class instance
$user_info = mysql_fetch_assoc($db_resullt);
$myObj = new User();
foreach ($user_info as $key => $value) {
$myObj->$key = $value;
}
return $myObj;
} else {
return false;
}
}
Behzad wrote:Thanks a ton for your example! I understand the concept now, but for the implementation, how a static method can return an instance of the same class?
That is exactly the problem. Consider the following:
class User extends ActiveRecord {
// User-specific stuff
}
$user = User::find(10);
var_dump($user);
Surprise! The variable $user has the type 'ActiveRecord' and not 'User' as we could expect. The reason is that static methods are not virtual in php and there's no way around that (virtual static methods are proposed for php6).
I'm afraid I don't know the meaning of "virtual static methods", since I'm a newbie in OOP. Man, you really know this language from depth! I'm impressed.
I tested your code and I surprised as you expected; It seems that a static method always holds the type of the class where it is defined; it does not move down in the inheritance hierarchy and we need to override the method in order to fix the type problem or make the class final.
By the way, Is there a specific name for this problem?
Behzad wrote:I'm afraid I don't know the meaning of "virtual static methods", since I'm a newbie in OOP.
You described it pretty well in your own reply.
"Normal" methods in php are bound dynamically, depending on the runtime value of "$this". This is also known as "late binding" or "virtual methods" (as in C++) . Static methods are bound lexically, at compile time, depending on the declaration point, this is called "early binding".
Is it possible to have "soon/early binding" for a language like PHP?
Because of interpretation nature of PHP, I guess it should use "late biding" at Language Execution Time (L.E.T.).
I guess: Everything in PHP should be bounded dynamically.