HMVC and dynamic widgets

2020-06-20 05:28发布

问题:

Background

I use the word widget as a partial view that have its own controller (so its own actions) and it is placed in almost all pages. I implement the rendering of this via HMVC, that is just great.

Problem

Now, the problem is that the widget itself execute actions. Think about a shopping cart widget. That widget is placed in all pages so the user can see his/her stuff all along. And the widget have actions that are related to it, for instance: RemoveItem, RefreshCart, ApplyDiscountCoupon, etc. Such actions should trigger by a button or link and the link should be something like (in HMVC):

<a href='<?site_url()?>/cart/cart/removeitem/the_item_id'>Remove this item</a>

Ok. Now the user clicks that link, the cart module and cart controller are loaded and the action is executed, the action should look something like:

function removeitem($itemid)
{
     // remove the item from db
     ...

     // "load the view"  ???
}

As you can see, my question is how to load the view in a HMVC module. The thing is that if I only load the cart view, it will only show my cart, and I can’t just redirect or load the main page because it can be any main page, that is: the cart could be in any main page (select product, keep buying, see product details, billing info, checkout, etc). :/

Another thing: a requirement is that I can’t use AJAX in this project.

Do you know how HMVC handle this?

Thanks in advance.

回答1:

Ok. No luck with the community. Nevertheless I found a workaround. Hope would be helpful to someone.

HMVC doesn't have a natural solution to this. So I decided to use this workaround:

  1. Into each main controller (that is, no widget, no partial view) I grab the current url in session this way (/controllers/keep_buying.php):

    class Keep_buying extends Controller
    {
        function Keep_buying()
        {
            parent::Controller();
            $this->session->set_userdata('main_uri', uri_string()); 
        }
        ...
    }
    
  2. Then in my partial view widget (HMVC module view) I have a normal link to my widget controller (/modules/cart/views/cart_show.php):

    <a class="button" href="cart/cart/additem">Add Item</a>  
    
  3. At the controller action (HMVC module controller action) I retrieve the current main page, do stuff and then redirect to that page, that implicitly will get into my widget flow (due to HMVC).

    class Cart extends Controller
    {
        ...
        function additem()
        {
            $to_redirect = $this->session->userdata('main_uri');
            // add-item work stuff...
            redirect($to_redirect);
        }
    }
    

That is. Is not the ideal approach IMHO, but works.



回答2:

I know that this topic is over a year old, however I have been Googling to gain some more insight into the structure an HMVC program should take, and how it can be implemented in CI, and have not found very many answers.

I'm pretty sure that for HMVC to work properly, with several widgets incorporated on all pages of a site, they need to be orchestrated by one main controller. This will be the top level of the heirarchy. Let me try to give an example:

You have a site with a shopping cart widget on every page. When you wish to use the cart functionality, you will need to link to methods in the cart module, e.g.:

<a href="cart/add/<?=$item?>">add</a>

The problem using this link is that you do not want to reload the rest of the site from that module. Instead, you can route the link through your main controller and have it reload the module, calling the desired method. e.g.

<a href="site_controller/cart_add/<?=$item?>">add</a>

Then in the site controller, it will simply pass the method call to the main view

<?php
function cart_add($item){
$data['cart'] = 'cart/add/'.$item;
$this->load->view('main', $data);
}
?>

The view will call the cart widget with the following:

<?php echo modules::run($cart); ?>

Obviously this is a simplified explanation, and the main site controller will be handling several widgets in one main view, so passing the correct data will need to be managed better than just calling the main view from within a method. But hopefully this gives an idea of the structure I am referring to.

If anyone reads this and thinks I'm wrong, I would love to hear other solutions people have found to this issue.