Question

I have been designing a site locally in PHP 5, but have come across a few design issues I'd like advice now.

Currently there are three features of the site and each feature has a class . These features are as follows :

  • a blog
  • a friends list
  • a set of images

I have a class for each but in each class I basically define a similar method that gets all [blogs | Friends | images]. I was wondering if any of you know how I could reduce these classes to be much thinner and probably have one class that is generic between all three features for all methods that are the same for each feature. (i.e getAllById($feature, $id)).

An example function for my existing blog class is as follows:

function getBlogsByUserId($userId) {
    global $db;
    $blogs = array();
    $db->where(array("userId"=>$userId));
    $rows = $db->get("blog")->fetch(0);
    foreach($rows as $row) {
 $blog = new Blog();
 $blog->id = $row['id'];
 $blog->userId = $row['userId'];
 $blog->content = $row['content'];
 $blogs[] = $blog;
    }
return $blogs;
}

Note: I have defined my own class for the DB stuff so don't worry about that.

I've looked at the gateway design pattern but haven't yet found a solution. I also want this to be reusable so if I increase the features to seven or more then I won't have to change much of the class.

Thanks, Matt

Was it helpful?

Solution

You could create a parent class called, say, Model, like so:

abstract class Model {
  protected static $_featureTable;

  static public function getAllById($id) {
    global $db;
    $items = array();
    $db->where(array("userId"=>$userId));
    $rows = $db->get(self::$_featureTable)->fetch(0);
    foreach($rows as $row) {
      $item = self::getInstance();
      $item->setValues($row);
      $items[] = $item;
    }
    return $items;
  }

  abstract static protected function getInstance();
  abstract protected function setValues($row);
}

class Blog extends Model {
  protected static $_featureTable = 'blogs';

  protected static function getInstance() {
    $self = __CLASS__;
    return new $self();
  }

  protected function setValues($row) {
    $this->content = $row['content'];
    // etc.
  }
}

Then, to get a list of blogs:

$blogs = Blog::getAllById($id);

OTHER TIPS

Maybe you should have a look at some ORM systems like Doctrine or Propel. This will help you a lot with your database <-> object mapping.

And I know that at least Doctrine supports inheritances of tables and of course maps this structure also to a class hierarchy (which enables you to implement common methods in the parent class).

You could create a parameterizeable Factory object/function. It would aggregate a 'row_to_object' function and a 'query' object:

function row_to_blog( $row ) {
    return new Blog( $row["id"], $row["title"] );
}

function create_from_query( $query, $row_to_object ) {
    $objects=array();
    foreach( $row as $db->fetch( $query ) ) {
       $objects[]=$row_to_object( $row );
    }
    return $objects;
}

$query=new Query( "blogs", new Where("userid",$id) );
$blogs=create_from_query( $query, row_to_blog );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top