Page 1 of 1

Object-oriented design advice with PHP

Posted: Mon Feb 15, 2010 5:13 pm
by JobHoppingOrg
I have several PHP Objects (Classes) that are closely tied to database records, such as Accounts, Profiles and the like. As a rule, I've been using methods in the classes, such as the constructor, to load and commit the data to the database.

So, for example:

$Account = new Account ( $databaseparms , $key );

This loads a new Account record using $databaseparms for mysqli and by searching for primary key $key.

I pass$databaseparms to the constructor, because they aren't saved with the Class definition. But maybe it would be better design to save them, or to have them inherited from a parent Class' static members, e.g. Account Extends DBObject? Not sure which is more elegant and simple design. Actually, I just thought of that second idea while writing this. :-)

What do you think?

Also, when I load a dependent class, such as the user's inbox, I might do one of:

$Inbox = new Inbox ( $databaseparms, $Account) // let the code find the key

OR

$Inbox = new Inbox ( $databaseparms, $Account->getKey() ) // call out the key explicity.

Again, it's a slightly different question of the same type. Should the Inbox class know how to access the Account key?

Should Inbox be a member of Account, and then it can be accessed as?:

$Account.Inbox.getMessages();

I hope those questions make sense. I am a bit new to OO programming,but it sure beats procedural from a design perspective! :-)

Thanks!

Re: Object-oriented design advice with PHP

Posted: Mon Feb 15, 2010 5:54 pm
by Darhazer
First, I would separate low-level database access (including the DB connection) from the data classes. So instead of passing database access to each class, each class uses the DB abstraction layer to query the database.

The

Code: Select all

$Inbox = new Inbox ( $databaseparms, $Account->getKey() ) // call out the key explicity.
is the better approach imho. Decouple classes as much as you can. This means that your class should now know anything about the other one, unless it's really necessary or decoupling is rather complicated and the value is small.

Should be inbox a member of account? Well, think of a situation where you can have inbox without account. If you can come up with one, definitely inbox should not be part of the account.

Still, the account object can return instance to it's inbox. The important thing is to keep away from back-references - if account can return it's inbox, the inbox should not know anything about the account it's belonging to. Neither that it belongs to an account object at all. It should be possible to have another object, let's say Company, which can also return an inbox. The company inbox, not the personal one of some employee. :)

Go read "Head first design patterns". They have easy to understand examples of what coupling is and why it's bad :)

Re: Object-oriented design advice with PHP

Posted: Tue Feb 16, 2010 5:16 am
by Jenk
I can't see the harm in possibly using:

Code: Select all

$Indox = Inbox::ForAccount($databaseparams, $Account);

Code: Select all

class Inbox
{
  public static function ForAccount($db, $Account)
  {
     return new Inbox($db, $Account->getKey());
  }
 
  // snip ...
}

Re: Object-oriented design advice with PHP

Posted: Tue Feb 16, 2010 7:46 am
by Darhazer
Jenk wrote:I can't see the harm in possibly using:

Code: Select all

$Indox = Inbox::ForAccount($databaseparams, $Account);

Code: Select all

class Inbox
{
  public static function ForAccount($db, $Account)
  {
     return new Inbox($db, $Account->getKey());
  }
 
  // snip ...
}
I would prefer to keep this in an InboxService. Reason - keeping the Inbox class small and independent from other classes. although there's no tight coupling here, the account object is a parameter to the function, adding such functions will increase the code base of the class.

Re: Object-oriented design advice with PHP

Posted: Tue Feb 16, 2010 7:50 am
by Jenk
Again I don't see the harm in that. So what if the code base increases? It's static after all. :)

Re: Object-oriented design advice with PHP

Posted: Tue Feb 16, 2010 9:57 am
by Darhazer
Jenk wrote:Again I don't see the harm in that. So what if the code base increases? It's static after all. :)
And what's good with the static? Before version 5.3 you can go into big troubles with static calls. If you ever decide to call another static with self::ForAccount() you will find that you can subclass and predefine the ForAccount method.

Keep your objects relatively small, your methods short, and your classes decoupled from the rest of the code.

Re: Object-oriented design advice with PHP

Posted: Tue Feb 16, 2010 11:08 am
by Jenk
Where have I used self:: ?!

Why create an entire class just for one method?!

Re: Object-oriented design advice with PHP

Posted: Tue Feb 16, 2010 12:35 pm
by josh
Personally I recommend separating out database code from business logic.

Code: Select all

 
// business logic
$account = new Account();
$account  = new Account( array( 'id' => 1 ) );
$account->setBalance( 100 );
$account->getBalance();
 
// persistence
$accountMapper = new AccountMapper;
$account = $accountMapper->load( 1 ); // persistence logic
$account->setBalance( 200 ); // business logic
$accountMapper->save( $account ); // business logic
 
Now you can be sure you have an application that works from say.... data coming in from a web service API, as well as the database. Differ "mappers" can be used for different persistence systems (Mysql, Postrelsql, flat file, xml, amazon SAN storage, object database, couch DB, whatever)

Most importantly though you can use your code with NO persistence framework present.