This is a very common problem. There are many solutions. The one you gave is one of them , to query db for each category - subcategory , one other is the nested tree model and many more. I will talk you about the Indexed List Model.
Let's see the fundamentals of it. If your categories have id's and parent id's (whith 0 in parent id meaning that is a top category) there is no reason to query db for each category - subcategory. You could retrieve all active categories and have them in a multidimentional array where id's are the keys with a recursive function (for example let's say $cat = "shoes" and $cat = "casual" that means that shoes is a top category that has a subcategory casual ...
I am very happy to see that over the last year that solution gained ground. And of course that maybe I wrote it but is not mine , the first idea of a indexed list born working with Cobol temporary tables and the first implementation was in Java and not in PHP. What you would gained using an IndexedList is that you could get an object based on the value of its property, or (if you have defined it) a sublist of the original list of objects having the same value in a specific property. (Just to comment that this architecture could apply in any OOP framework)
In PHP there is a fundamental way of reflection (with the larger meaning of the word) , variable variables , and with that way you can have a more robust indexed list of objects. I hope you don't see that post as theoretical nonsense but give you the motive to try new solutions your self.