1

I have always kept the code to load an object within the object itself. That way no matter what method is creating the object, it always has access to the method to load the object. However this does mean that if I'm loading a lot of objects I have to create a blank copy of an object to retrieve an array of objects, and it doesn't seem to be the most logical way of loading an array of objects. Take this code as an example, a page is loading a bunch of products.

class Product() {

    // product variables...

    public function LoadProducts($dbConn, $where) {
        $products = array();
        $query = "SELECT * FROM products $where";
        $results = $dbConn->query($query);
        while($row = $results->fetch_assoc()) {
            $products[$row['pId']] = new Product();
            $products[$row['pId']]->StoreVars($row);
        }
        return $products;
    }

    public function StoreVars($row) {
        foreach($row as $key => $val) {
            $this->$key = $val;
        }
    }

}


class Page() {

    // page variables...

    public function DrawPage($dbConn) {
        $product = new Product();
        $where = "Some where clause";
        $products = $product->LoadProducts($dbConn, $where);
        // Do something with products to output HTML to the page...
    }

}

Most of my objects like product follow a similar pattern. Is this good practice? Is there different / a standard way of doing this? Am I doing this correctly? It just seems a bit pointless to me to have to call a blank instance of product to load all the products, but I don't know where else to put that function so I don't have to have many copies of the same query.

1
  • I don't know if I entirely understood your question but maybe you could look at 'design patterns'. Design patterns introduce a couple of ways to load objects.
    – Julian
    Jul 11, 2014 at 14:57

3 Answers 3

6

You might consider making LoadProducts() a static method, so that you don't have to instantiate a blank object to load a product list:

class Product {
   public static function LoadProducts(...)
   {
   }
}

and then its just

$products = Product::LoadProducts( ...)
0
2

An Object that loads itself is not possible.

You may say, that the Class of an Object is responsible to load its instances. But then you assign the responsibility "loading" to the responsibility "template for objects" to the Class-Object so you violate SRP (Single Responsibility Principle). Furthermore you will end up in static methods that have at least some effect on testability.

To follow the path of SRP the responsibility falls into a total different class of objects that meet some other very important requirements.

  1. Who knows best to load an object?
  2. Who knows best to update an object in a valid way?
  3. Who knows best to delete an object?

The answer to all three questions is: The one who created the object.

As you can recognize: The mentioned operations are the CRUD-Operations. So for symmetry purposes all existential CRUD-Operations for an object should be tied to one object that is responsible.

Finally you will end up with Repositories or DAOs.

But be carefull: Repositories and DAOs only abstract from the type access to a datalayer and are not responsible for consistency. Consistency should be handled in the business layer (Business-Objects, Domain-Objects).

0

Using a static method as GrandmasterB suggested is definitely a step in the right direction, but I think you shouldn't have code for loading in this class at all. You should try to follow the Single Responsibility Principle and make your classes as focused, independent and modular as possible, so you don't want to tie them to a certain implementation for loading them. Decoupling classes from their context makes them more robust, more flexible and easier to test.

2
  • So where would the loading go? I definitely get your point but I can't see any other logical place to put it. Would I have a class for just loading all my objects that contains the LoadProducts, LoadCategories, LoadOptions and all the other Load functions?
    – Styphon
    Jul 11, 2014 at 22:00
  • 2
    I think there is more than one logical place, but I think it helps to consider the future before answering. Here's one possible future. Today you're loading products from the database. Tomorrow, you might be loading some of those objects from a config file. The next day you might also be loading some of them from a CSV import from a legacy system. With this many sources, how would you choose to group functionality?
    – J Trana
    Jul 12, 2014 at 3:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.