Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

If I had my products stored like this:

tbl_products
id, price, stock
1, 20, 5
2, 30, 5

And the texts are on another table:

tbl_texts
id, item_id, type, field, value
1, 1, 'product', 'name', 'Programming Book'
2, 1, 'product', 'description', 'A fine book'
3, 2, 'product', 'name', 'Bicycle'
4, 2, 'product', 'description', 'Goes very fast'

And the campaign prices are on another table too:

tbl_product_campaign_prices
id, item_id, price, valid_from, valid_to
1, 1, 5, null, null
2, 2, 10, null, 2014-10-10

Okay, there's my imaginary tables.

I'd like to handle the products as objects and since I don't always want to get all data related to the products because it's database heavy and I rarely need to access all of it.

For example, sometimes I only need the name or description of a product. Sometimes I need the campaign prices. The base info on the tbl_products would be fetched always.

The real question is; what are my options on the code. I came up with a few:

1.

$product_id = 1;
$fetch_name = 1;
$fetch_description = 0;
$fetch_campaign_prices = 0;
$product = ProductFactory::get($product_id, $fetch_name, $fetch_description,
           $fetch_campaign_prices);

// This takes a lot of space and is very impractical 
// when I have to add new data to be fetched.

// Worst case would be having to add a bunch 
// of null, null, null to get the last data.

2.

// Same as 1. but adding all the $fetch_ into an array and only use 2 parameters on the
// get() function.

$product = ProductFactory::get($product_id, $fetch_array);

// Still pretty ackward way to fetch data but much easier to add stuff 
// since I don't have to add any new parameters

3.

$data_to_fetch = array('name', 'description');
ProductFactory::Prepare($data_to_fetch);
$product = ProductFactory::get($product_id);

Is there a common way to do this? An efficient way to do this? I've never done anything like this and these are from the top of my head.

Thanks for your upcoming input!

share|improve this question
1  
Option #4 - passing a set of bitmapped flags in the way you do when setting error levels or sort flags: $product = ProductFactory::get($product_id, FETCH_NAME | FETCH_PRICES); –  Mark Baker Oct 1 '13 at 11:44
1  
Mark has the right vision. @MarkBaker, why did you post this as comment? The best way to solve problem is using bit masks. –  Michael Sivolobov Oct 1 '13 at 12:21
    
@Michael - mainly because I consider that if I can answer in fewer characters than a tweet, it only deserves to be a comment –  Mark Baker Oct 1 '13 at 12:44
    
Maybe you can start answering... someone will edit your answer (by adding more information)... someone else will edit again and it will be community answer with best practices of solving the problem. –  Michael Sivolobov Oct 1 '13 at 13:15

2 Answers 2

up vote 0 down vote accepted

Basically you are asking about ways to express subsets of a small set of configuration flags. This is pretty much unrelated to the database thingy you are using it for.

  1. Using separate parameters: ugly to maintain, changes in one place will require changes in all places. This might however make sense if there can be no reasonable default. In those cases it might be better to have the call fail than do the wrong thing.

  2. Using an ordered array of parameters: very ugly, since you have to remember the meaning of the order, and it is even harder to tell when a call is incorrect. Don't do that.

  3. List of names: very flexible and easy to read. This would probably be the python way to do things. But checking which values are included and which are not requires a number of string comparisons, so this might be a bit costly. Probably not more than a medium database query, though. One thing to consider is whether or not to check for names which the called function doesn't know about. You might report these as errors to avoid spellin mistakes, or you might choose to ignore them for e.g. forward compatibility.

  4. Bit masks: as Mark Baker pointed out, you can define a number of constants with readable names and values which are powers of two. You could or them together using | to form a single value. You could then use bitwise and to extract single bits from that combined value in your function. This is the C way to do things. It has high performance, and low danger of spelling mistakes. But it might clobber up your namespace with those symbolic constants.

  5. Configuration object: you could define a class for the parameter you pass to that function. You'd have setters to set the various flags. Most importantly, you'd have a constructor which can set defaults. So the key benefit here would be that you could establish sane defaults, even if some things should be fetched by default while others should not, and without calling constants names like FETCH_FOO and DONT_FETCH_BAR.

I'd go for 4.

share|improve this answer

Firstly, I assume this is a hypothetical example - but be careful about the trade-off you're making between performance and complexity - you may well find that the additional complexity within the PHP code becomes a maintenance issue. Perversely, you may also find that the additional PHP code outweighs the benefit of not loading the additional data.

Secondly, the way most Object-relational-mapping frameworks solve this problem is through "lazy loading". The ORM would only load data from your campaign-prices table when it needs to; this is mostly transparent to the developer.

Of course, that doesn't really work with your "texts" table, which is effectively an entity-attribute-value store. In this case, it depends on how fixed your texts schema is. If you know you always have "name" and "description", you could hardcode that into a bitmask. However, this kind of design tends to grow over time (otherwise, you'd be much better of having a "name" and "description" column on the products table). In that case, I'd stick with passing in the text type as a string parameter - "name", "description". This means that when you add a new text type - "shortDescription" - you don't have to revisit the productFactory code to make it aware of the new text type.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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