• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Best Practices HMVC?

#1
Hello,

Is it considered a good practice to call a controller using modules::run from a view?
Suppose I have a price field that is calculated based on user.
In my view I could issue modules::run('product/getPrice');

or I can construct a query in the controller that says fldA as price.
Because the user is stored in session, either method is dependent on session.

I am trying to make sure my code does not end up sloppy and hard to maintain down the road.

Thanks
Reply

#2
I'm not a big fan of calling controllers like that, personally. In CodeIgniter the solutions that I've seen will confuse the framework a bit, as it's not intended to be used that way.

From all of my reading about HMVC over the years, there are two "valid" reasons to use that type of a system:

The first is for scaling purposes, allowing you to convert an internal request to an external request (on a different server) very easily, as referenced in this article. That's a perfectly valid use case, though one that neither of the CI-based solutions that I'm aware of will handle.

The second, and the main reason that I see people asking about this, is for a form of "widgetization" of content, to keep content clean and organized. A noble idea. I just don't believe that controllers are the place for that.

Part of that is purely from an architectural stand-point: controllers have one very real purpose: control the flow of information between the model and view layers. That's basically it. I'm aware it could be argued that it's still solving that issue. The other, larger, part is the very real danger of confusing your code between the separate "requests". When you load up that controller again, all of your constructor items will happen again. So, if you're using different base controllers, which I very much advocate for, then all of their process will fire again, even though they already fired. First, that's unneeded overhead. Second, the CI instance is a singleton and any processes in your controller constructor process would have to be extremely careful not to change anything that could mess with the primary request object, since they're the same thing. While it's doable, it can make debugging some things much more challenging then they need to be.

So, what's the solution? Use a library or other namespaced class to handle it. Calling a single class' method is no different that use Modules::run(). If you use a namespaced class instead of a CI library, it's even cleaner. To clean things up even more, create a single Widget class that is called that can then find the correct class/library. I do something similar in my template layer for Sprint, using "view callbacks".
Support Development  • Practical CodeIgniter 3  •
Myth:AuthVulcan - CLI Tools for CI4
Reply

#3
Thanks for responding.
So if I understand you correctly.
Instead of do modules::run in my view that calls another controller to paint a add to cart box.

I should create a library that returns a partial view and call that in my main view?

The problem is that add_to_cart_box has a dropdown that contains a number of 1 to how many items are available for the current product being listed. Without using HMVC, I am not sure how to code this correctly.
Reply

#4
Without seeing the code it's a little bit difficult to say for sure, but I would simply make sure that your library method can accept whatever parameters you need it to know. From your library, you can always call a model, or the cart class or the session or whatever you need to call, in order to get the total number of items and pass that into the view.
Support Development  • Practical CodeIgniter 3  •
Myth:AuthVulcan - CLI Tools for CI4
Reply

#5
ok, but you are saying it is ok to replace modules::run with call a library from my product list view?
Sorry I am being thick, still stuck in HMVC mode. Smile

Here is my code. in view.
loop through product results
show sku
show price
show qty in stock
...
modules::run('cart/show_add_to_cart_box', qty in stock)
Reply

#6
No worries. Smile

The ideal solution IMHO is to create a new class that is just responsible for loading the library for you and passing the parameters to it. Would probably be best as a static method so you could call something like: Widgets::display('cart:add_to_cart_box', ['qty' => $in_stock]) It would simply be a replacement for the modules::run() method that wouldn't route things through the controller.

As a slightly hackier version, you could call the library directly. Something like get_instance()->{library}->{method}($qty). You would have to make sure the library was already loaded.

(Again - I prefer the dedicated library solution, personally.)
Support Development  • Practical CodeIgniter 3  •
Myth:AuthVulcan - CLI Tools for CI4
Reply

#7
Thanks again,
I just created a library that loads a view and I can call it using Widgets::display_cart(2)
so I would just use Widgets::display_cart($Qty) in my products list.
Reply

#8
That sounds like that would work.
Support Development  • Practical CodeIgniter 3  •
Myth:AuthVulcan - CLI Tools for CI4
Reply

#9
Thanks, I guess I may have to buy your book. Smile
Reply

#10
Ha! Thanks. Smile

But glad I could help.
Support Development  • Practical CodeIgniter 3  •
Myth:AuthVulcan - CLI Tools for CI4
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.