tags:

views:

85

answers:

4

Hi.

I think I get the OOP paradigm at its basic level but I'm having a hard time conceptualizing the proper way to lookup records in a database. I suspect this is because I don't really get OOP as much as I think I do...

The application I'm trying to write is a shopping cart because it has a lot of good candidates for objects. The object I'll be working with is a product (yes, this is very primitive).

<?php
 class Product
 {
  public $id = 0;
  public $name = '';
  public $price = 0;

  function __construct($id)
  {
   // if $id exists try to retrieve
   // a product with $id
   // else create a new product
   // and set $this->id
  }
 }

 $product = new Product();
 echo $product->name;
?>

Easy enough. But now I want to look up multiple products (for a search results page) and I'm not sure how to handle it.

My inclination is to write another class that takes some input and performs a SQL query that just returns a list of product ids. I would then loop through those results and create a product object for each one. I could then loop through the array of objects and build my search results page.

I'm not sure why but this just doesn't feel like the right way. Seems like too much work because first I'm doing a query to just get a list of product ids and then I do more queries to get each product's data. It'd be a lot faster if just did one query that returned all the data I need.

What's the right thing to do? Something else perhaps?

+2  A: 

Write a product class that isn't aware of the database (hard to believe but products can exist without a database ;)) and a class that can create product objects from a database result.

VolkerK
By "isn't aware of the database" do you mean that the object should not populate itself with data?
barophobia
At least not by querying the database itself in the constructor. Maybe there is a static method that creates an array (or another collection) of object from a data source of "records" e.g. an iterator. pdo results can be used as iterator; the method doesn't even have to know that it's the result of a database query.
VolkerK
A: 

I think you're thinking on the right lines - one thing though, why return only ids, return the array (or list) of matching products.

How about a ProductFinder which has query methods, parameters being definitions of products the return type being a collection of Products.

You then may see that the ProductFinder could also take responsibility for creating products (inserting to the DB), deleting products etc. Hence the Product itself knows little or nothing about the db. The ProductFinder might then get a slightly different name such as ProductKeeper or ProductHome.

If you have quite a few entities in addition to products you then may find that their "keepers" have an awful lot of code in common, before long you end up with a persistence framework. There seems to be at least one already for php, I suggest you have a look at it.

djna
Who would be responsible for editing the data of a product and making the necessary db calls? ProductKeeper or Product?
barophobia
ProductKeeper (or the persistence framework). Hence if you different databases, or indeed other persistence mechanisms, you can just have different Keepers.
djna
+2  A: 

Mapping from a database to an object oriented application isn't trivial. There are different ways to approach this, but a simple strategy is to have an entity class (Product) and a gateway class (could be called different things, but typically ProductGateway or ProductFinder). The gateway class has access to the database and it knows how to fetch and initialize entities. The same class would also know how to map the object back to the database.

For example:

class ProductGateway {
  function getProductById($id) {
    $result = $this->db->query("select * from products where id = ?", $id);
    return new Product($result->next());
  }
  function save($product) {
    if ($product->getId()) {
      return $this->update($product);
    } else {
      return $this->insert($product);
    }
  }
  ...
}

The point is that you application level code doesn't need to know if the product came from a database or not. It just changes the entity object and leaves it for the gateway to deal with persistence.

troelskn
A: 

Dont be averse to using already-existing frameworks for dealing with databases in OOP. Zend_Db has different usage methods, most notably the Table Gateway/Row Gateway method as is sort of described above. TableGateway is intended to do queries and return Rows. Rows represent a single row and can be manipulated independently.

If you're doing a query for many rows, a separate class that represents the table (or even 'virtual' table in the case of some complex join) is the cleanest way to keep the concerns of that table and the individual rows separate.

Justin