tags:

views:

121

answers:

3

Hey all.

I've been working in PHP5 for a couple of years now and have developed a lightweight MVC framework that I use to speed up site development. Works great, automated formbuilder, autoSQL module, etc.

One bad habit that I have developed, however, is relying on $this as an easy object param. I have yet to figure out how to truly encapsulate data without having to extend from a base class (where all site variables are defined) and using a setter method to populate each object instance with the passed $this object. Everything works, but it's ridiculous that each object has to know about the entire application state. I would like each object to perform it's designated task only requiring a minimum knowledge of the "outside" context.

For example, let's say I have a class that generates a customer's account details:

// pseudo account

Class account extends siteBase {

protected $formObj;
public $custID = 1;
public $name;
public $email;
// etc...

 function __construct() {

  $this->formObj = new FormBuild($this); // easy $this passing

  $this->formObj->getFormData();

  $this->formObj->build();

}
}

// pseudo form builder class

Class FormBuild extends siteBase {

 protected $data;

 function __construct($caller) {

  $this->set($caller); 

 }

 function set($arr) { 

  foreach($arr as $key => $val) {

   $this->$key = $val;

  }

 }

 function getFormData() {

  $this->data = new FormQuery($this); // more easy $this passing

 }

 function build() {
  foreach($this->data as $key => $val) {
   echo $key . " " . $val . "<br>";
  }
 }
}

Class FormQuery extends siteBase {

function __construct($caller) {

  $this->set($caller); 

 }

 function query() { 

  $sql = "SELECT email, phone FROM account WHERE custID = '$this->custID'";

  // query & return return result, etc.

 }

}

What do the "pros" do this in situation? I'd love to clean up the interface a bit... thanks!!

+2  A: 

There are many approaches to this problem. Here are a few

  1. Global or class constants
  2. External config/static data (INI style, xml, yaml, database, etc) read by a config class of some sort
  3. The registry pattern
  4. The depdency injection/inversion-of-control pattern

They all have their ups and downs - there is no "one true solution."

Peter Bailey
Registry could work, good idea. The example I gave doesn't really address what I'm dealing with:Controller calls target class (the lookup in URI), which processes the request, as needed calling a formBuilder object (which itself calls a formQuery object to get DB stored formfield data). Controller then takes compiled content and sends to view object for display.I need to restructure formBuild object so it only needs a minimum of calling object properties -- with that I could pass a registry array param for formBuilder and formQuery objects, and get away from $this passing habit ;--)
MVC You Know Me
A: 

Try to take the perspective of the client code: a derived class should have the same interface as the parent class but a different implementation.

A messy interface such as methods in parent classes that aren't used in derived classes should never exist and would be a good hint to start refactor. Another strong hint that you most probably noticed is that the methods don't take the same arguments (comparing account::__construct() to FormBuild::__construct($caller), both deriving from siteBase::__construct()).

I would refactor with configuration in mind, what if siteBase includes a database but a deriving class needs a different/a set of different databases? Try to draw out your common classes and see which ones that really share signature, pair together a few at a time.

chelmertz
I gave a poor example of what I'm doing, see above. With formBuilder restructured, I'll be able to avoid relying on $this as an object param. The answer to my question is as you are saying, essentially, design classes to do their job without having extraneous methods hanging around pointlessly.Thanks for the feedback! Definitely scratching the surface of object programming, but am loving the diving in ;--)
MVC You Know Me
the registry pattern actually solves $this as method param entirely, via singleton.e.g. when I want access registry params in current object instance, do$this->set(reg::getAll());and then $this->regkey1, $this->regkey2, etc. are availablestill wind up consuming memory with the setter approach, but I'd prefer not to do reg::get('regkeyname');
MVC You Know Me
A: 

Both responses above are correct.

I have built-in a registry object/properties container that I pass to appropriate objects that no longer need to inherit from an application base class. Bit of a hassle compared to passing $this around, but makes for better planning and forces me to define what my objects need to know vs. knowing everything.

The refactoring advice also got me stripping down a few frequently used objects to only doing their job vs. several jobs at once.

Still a ways to go though, I've gotten used to knowing everything about the application from almost anywhere in the app...

MVC You Know Me