kfirba's avatar
Level 50

Gathering statistics on products and nested resourceful controllers

Hello!

I'm planning to build an eCommerce application. I was starting thinking about the required functionality and one of the functionality will be gathering statitics about products for the admins.

currently I'm facing few difficulties.

1. How do I correctly nest the categories controller with the products controller? (Should I even do that?)

What I mean is that I want the functionality to view the products in 2 ways: https://example.com/categoryIdORname/productId And: https://example.com/products/productId - correct me if I'm wrong but I want to view the product under its respective category and also view the product as a single global product. Or maybe when I want to view it as a single global project I still should involve it with its respective category or vice-versa?

If my URLs suggested are good, how do I make my controllers reflect that? One of the URL show nested controllers (products nested in categories) and the second one shows a standalone products controller. Does it mean I should have 3 controllers? So I will have somewhat similar 2 products controllers. (Not sure it's good, might lead to code duplicates, may be solved with traits?)

Maybe I just need a product controller and not nest the products in the categories?

2. How should I treat gathering statistics in the application?

After deciding on the right way to construct my controllers, I want to track statistics for the products. For this question, let's stick with just storing the amount of times a product was viewed. I want to use the command bus to drive my application's main actions. I will also raise events to let other components hook to some actions.

When someone is viewing the product, should I raise an event that a product was viewed and let another part of the application do what ever it needs to do for that particular event or just before returning the product's view inject some statistics object and call a method on that object? Since collecting statistics isn't that "main" purpose of the application, how should I treat it? Should I always hook it to events or?

Thanks for reading this post. I know it's a long one with lot of questions and I may have been unclear. Please let me know if something isn't understood and share your experience with me.

P.S. It would be great if you could also share what you think the ideal URLs for an eCommerce site should be (not only the one I asked about in this questions, also something like:

  1. shopping cart: https://example.com/cart
  2. member area: https://example.com/username
  3. etc.)
0 likes
5 replies
kfirba's avatar
Level 50

Bump? (No idea whether it works in Laracasts or not)

bigbite's avatar

For question one, you will logically have two controllers. ProductsController and CategoryProductsController[? name is odd here]. The ProductsController is self explanatory but the CategoryProductsController would have a method of getProduct($category, $product). You can either use Route Model Binding to achieve the object's retrieval or you can have the controller get the category based on something like:

$this->category->where('slug', $category)->orWhere('id', $category)->first();

For your second question, you could add a middleware on the routes pertaining to product viewing and make that middleware handle the statistics alterations.

kfirba's avatar
Level 50

@bigbite Thanks for the reply!

I've edit my post to make it more readable. While editing the post it just hit me, do I really need to do something like https://example.com/categoryIdORname/productID ? or anytime I view a product it should be under https://example.com/products/productIdOrProductName?

What do you think?

About your second answer, when you say that I should handle the statistics gathering from middleware, do you mean that I will add a middleware wherever appropriate and in the middleware raise an event or use some statistics class? (I don't think writing the statistics logic straight inside the middleware is a good idea)

bigbite's avatar

I say /products/{slug/id} is a good idea to keep standard.

With the second thing, the statistics logic should be in a service not in the middleware. The middleware will simply tell the statistics service to "track something". :-)

pmall's avatar

IMHO The best way is

  • categories/{cat_id|cat_slug|whatever} => points to a CategoriesController
  • categories/{cat_id|cat_slug|whatever}/products/{prod_id|prod_slug|whatever} => points to a ProductsController

Because this way you always have the related category identifier when dealing with a product. Super useful for create/store, edit/delete.

class ProductsController extends Controller{

  //...

  public function store($cat_id, $prod_id)
  {
    $category = Category::findOrFail($cat_id);

    $product = new Product($input);

    $category->products()->save($product);
  }

  // ...

}

And by the way do not use route - model binding it is just the ugliest thing in laravel right now.

1 like

Please or to participate in this conversation.