OOP | When to use Static Methods @ Book: PHP in Action

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!

Moderator: General Moderators

Behzad
Forum Commoner
Posts: 28
Joined: Mon Jul 09, 2007 3:24 pm
Location: Tehran, Iran
Contact:

OOP | When to use Static Methods @ Book: PHP in Action

Post by Behzad »

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:

Code: Select all

$product = Product::find($productCode);
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?

Thank you
User avatar
arturm
Forum Commoner
Posts: 86
Joined: Fri Apr 13, 2007 8:29 am
Location: NY
Contact:

Post by arturm »

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
Behzad
Forum Commoner
Posts: 28
Joined: Mon Jul 09, 2007 3:24 pm
Location: Tehran, Iran
Contact:

Post by Behzad »

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?
User avatar
arturm
Forum Commoner
Posts: 86
Joined: Fri Apr 13, 2007 8:29 am
Location: NY
Contact:

Post by arturm »

if you want to use the object afterwards it it better to create an instance

if it is only one time check (like check if user exist in the database) it is better to use static method
Behzad
Forum Commoner
Posts: 28
Joined: Mon Jul 09, 2007 3:24 pm
Location: Tehran, Iran
Contact:

Post by Behzad »

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?

$user = User::FindUser($_GET['id']);
$user->DisplayInfo();

OR

$user = new User($_GET['id']);
$user->DisplayInfo();

That's my question. Which one is better?
User avatar
arturm
Forum Commoner
Posts: 86
Joined: Fri Apr 13, 2007 8:29 am
Location: NY
Contact:

Post by arturm »

in this case first method is better because if user is not found it will not create a new instance of an object (less memory consuming)
User avatar
stereofrog
Forum Contributor
Posts: 386
Joined: Mon Dec 04, 2006 6:10 am

Post by stereofrog »

The problem is, what should "new User($id)" return when no such user exists?
Behzad
Forum Commoner
Posts: 28
Joined: Mon Jul 09, 2007 3:24 pm
Location: Tehran, Iran
Contact:

Post by Behzad »

So that's the reason. I got it. Thanks.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

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:

Code: Select all

$user = new User();
$user->setUsername("foo");
$user->setPassword(md5("xyz"));
$user->setUserGroup("admin");
$user->save(); //store to DB permanently
Great, we made a new user in the database.

Now where a static method can come in useful:

Code: Select all

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 :)
Behzad
Forum Commoner
Posts: 28
Joined: Mon Jul 09, 2007 3:24 pm
Location: Tehran, Iran
Contact:

Post by Behzad »

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?

Code: Select all

public static function retrieveByUsername($username) {

  if ($self::isUsernameValid($username)) {
    $myObj = new User();     // or   $self::__construct()?
    $db_result = mysql_query("blah blah blah");
    $user_info = mysql_fetch_assoc($db_resullt);
    foreach ($user_info as $key => $value) {
         $myObj->$key = $value;
    }
    return $myObj;
  }

}
User avatar
arturm
Forum Commoner
Posts: 86
Joined: Fri Apr 13, 2007 8:29 am
Location: NY
Contact:

Post by arturm »

Code: Select all

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;
    }

}
User avatar
stereofrog
Forum Contributor
Posts: 386
Joined: Mon Dec 04, 2006 6:10 am

Post by stereofrog »

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:

Code: Select all

class ActiveRecord {
	function find($id) {
		// do stuff
		return new self();
	}
}

$record = ActiveRecord::find(10);
var_dump($record);
Looks ok, right? The problem comes when you extend the ActiveRecord class, what you most probably want to do in most applications

Code: Select all

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).
Behzad
Forum Commoner
Posts: 28
Joined: Mon Jul 09, 2007 3:24 pm
Location: Tehran, Iran
Contact:

Post by Behzad »

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?
User avatar
stereofrog
Forum Contributor
Posts: 386
Joined: Mon Dec 04, 2006 6:10 am

Post by stereofrog »

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".

The php6 proposal is here

http://www.php.net/~derick/meeting-note ... erent-name

I'm not aware of the current state though.
Behzad
Forum Commoner
Posts: 28
Joined: Mon Jul 09, 2007 3:24 pm
Location: Tehran, Iran
Contact:

Post by Behzad »

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.
Post Reply