Welcome Guest, Not a member yet? Register   Sign In
Large-scale application using HMVC
#1

[eluser]inc[/eluser]
hello everyone,

i am using codeigniter for more than five years now and i really love it! this is my first post here, but i am reading you a lot and i have found many useful informations so far. now i am somewhat stuck in the middle of thinking about the new project and i really need your ideas and help.

so, the application i need to make will be very large and it will be used by many clients. i can only have one installation which will be a central point for all of them. clients will be using default functionality but many of them will require some modifications that will differ from defaults (some of them will have slightly different forms, field names, business logic etc.)

i thought about using hmvc and modular approach but i am stuck. first of all, every module (triad) must work on its own without the need of calling some others module methods right? but what if i have some situations where i need to mix their functionalities? i don't want to call module b from module a, and module c from module b. in that way i will achieve nothing by modular approach, only dependencies, and in the end everything will depend on everything.

should i create some kind of layer on top of them which will be responsible to control modules and mix their data? something like:

Code:
controllers
    dashboard.php
models
    dashboard_model.php
views
modules
    module_a
        controllers
            module_a.php
        models
            ...
        views
    module_b
        controllers
            module_b.php
        models
            ...
        views

how to structure slight changes in modules from defaults (each client can have some modifications on some module)?

should i generate view from modules or from main controller (in this case dashboard) which calls them? why i am asking this is because sometimes it will work to call a table (grid view presentation) generation from module_a, but what if i have a complex form which is mixture of data that belongs to module_a and module_b? i cannot make a view in module_a which will be using some of the fields from module_b.

i hope you understand me Smile i appreciate any help you can give me! i know i have complicated a lot and i really want to keep it simple as much as i can, but this time i want to code clean without module dependencies between them because in that way i don't really need modules.

thanks in advance!
#2

[eluser]PhilTem[/eluser]
Which HMVC library do you use? If you use @wiredesignz' HMVC library (can be found on bitbucket) then you can easily call any modules logic defined in a controller with

Code:
echo Modules::run('module/controller/method', $variable, $list, $of, $arguments);

which will either echo the code generated by the given controller or simple return nothing (not even an error if I'm right, it'll only log that it cannot find the file).

On the topic of triads working on their own: You're almost right. Not all triads can work on their own, but - and that's the way I see it - once you have set up your basic modules (like auth, acl, staticpage display) all other modules should be independent of each other but of course dependent on the auth or acl or staticpage module.
But of course you could put auth, acl,... not into a separate module but include it within the root-folders (controllers, libraries, models, views) but then you won't have modular separation.

Regarding how to structure slight changes in modules from defaults: Got no idea. Maybe store these changes in a database? And once there are changes found let the module handle these otherwise display it's default functionality.
What exactly can these changes be like? Maybe you can provide a little more information so I/we can drop off some help Wink
#3

[eluser]inc[/eluser]
thanks for your fast response! i already made a fresh new copy of codeigniter with hmvc library (by wiredesignz) installed. it is the library that is the most talked about and i see many of people are using it. i played with it a year or two ago but not enough.

isn't it a little bit nasty to echo some segment from module_a into module_b? it is a similar problem i came across using models and in the end, you came up with a problem that everything depends of everything. i would love to create a module (a real nice self depended mvc triad) which i could use in some other projects. but to make that happen, i need to create every module independent of other module. so if i echo some snippet from other module, the module i'm coding starts to lose its functionality. so you can either separate these modules like module_a or module_b, or in a first place, you can plan to work only on one module with this whole functionalities. but sooner or later this way you will end up with tiny application which is coded like module and it is not a part of small logic parts any more.

so i end up thinking about creating an above layer of modules. something like the controling unit which will combine different module outputs and create a group view of them - something like dashboard i've mentioned before. but then i fell in a trap of thinking about presentation, because module_a is separated from the module_b and sometime in the future you will need both of functionalities in the same user interface form, what will you do?

in this simple example everything works as expected: you have a dashboard that is displaying a some grid panel from module_a and some grid panel from module_b. so lets say that module_a is cars, and module_b is people. cars can have parts, engines etc but not people. so we need to create another module people. but people can drive cars! but what car? so in the dashboard you click on add() link or something like that... and a client wants me to do a complex form where he would like to enter car details, but also a person and its information who's driving that car. how to deal with that kind of complexity but not to ruin the pattern?

i cannot make an add_edit view in the module cars which will show some fields from module people and i cannot do that otherwise also because that two modules will start to depend on each other. what i can do is to make some top layer which will control them right? but then, this top layer (add edit on dashboard for example) needs to have its own add edit view which is merged between module cars and module people. and this is where i start to argue with myself Smile

because i will end up with views in modules, with views in top layer (main application/controllers, model, view) and in the end i am afraid it will be a real mess to support or update.

this will also affect this client changes i mentioned. the main problem with that is that we don't know yet what their requirements will be! it can be a small one like some field cannot be named as organization but company, but it can be that you will need to hide some view segments to them, or it could be a large enough to think about whole new module creation only for them.

i hope i explained it a little bit more... it is a really complex thing to plan especially when you don't have clean paths - but that is not my fault and i cannot have a big influence on that.

i have also saw a post mikertjones and i think he is in similar position like i am but i am not sure. hope i will find some good thoughts beacuse i would really like to start as clean as possible this time and simple. very very simple because i am enough of complex 'systems' that became impossible to maintain years later. i made a couple of them and later i regretted it.
#4

[eluser]PhilTem[/eluser]
Alright, I see your troubles. But unfortunately I'm not sure whether I can give you full advice like do this and then this and then that. But maybe I can help with my point of view Wink

Last year I finished a project to manage staff for a party. It was my first real project with CI and HMVC so I thought the same way as you did: I wanna make things right and have real HMVC right from the beginning. But how do I separate my modules? Where will the business logic go? And, oh, there is one module dependent to another.
I'll shortly explain what the app was intended to do:
Some friends of mine organized a big party (over 2k guests) and wanted to have an easy way to let people register as staff members within different areas (like a beer-bar, cocktail bar, long drinks, cashier, wardrobe, and stuff like that). Of course they also wanted to have shifts (like 3 for the time from 8pm to 5am but maybe 4 for the wardrobe section and only 2 for the cashiers). Another part was user registration, authentication and authorization. Then they came up with a static pages management. And the staff should get t-shirts for free to recognize them.

By the end of getting the requirements I had thought of these modules
acl - for access control management)
users - for registration and authentication
zones - for managing the zones e.g. cashier, wardrobe
shifts - for managing the shifts per zones
shirts - for managing the shirts (global and per user)
pages - for managing static pages
preferences - for system preferences
logging - for action-logging
export - for exporting lists

But these modules weren't totally independent. Every actions depends on the users and acl module - is the user logged in and does he have the required rights to access a resource?
The registration form had to display - besides user credentials input fields - fields for the shift and shirt to choose. Since the shifts were assigned to a zone the registration was also dependent on the zones module.

Methods from the preferences and logging modules were called from other modules, too. If I removed any of these modules the page wasn't accessible anymore.

For add/edit-links I choose the approach to make multiple forms on the same page. The first one for the direct action (e.g. for the users/edit-page you'd have inputs for the user's credentials). All other forms were for dependent information e.g. a form to update the shirt's size - I echo'd the content with Modules::run() which would return an empty string if the module doesn't exist. And the update logic was chosen by a hidden input field which got evaluated after the user hit submit. That way I was able to ensure to update as less information as need (only user creds OR the shirt size) and I was able to allow e.g. the shirt-module to break.

But I'm not sure if this is a real HMVC approach - but for my understanding it looks pretty good actually Big Grin

Global actions like auth and acl were handled by a parent-controller

Code:
class MY_Controller extends MX_Controller {};
class Public_Controller extends MY_Controller {}
class Registered_Controller extends Public_Controller {};
class Admin_Controller extends Registered_Controller {};
so any action required for e.g. all admin-controllers was implemented within class Admin_Controller - like acl-check.

For your use case - to pick up the example with cars and people - I'd probably create three modules:
cars - to manage the cars and just the cars
people - to mange people and only people
drivers - to manage the relation between people and cars

Don't know if this sounds suitable or not but it'd be my first sketch of modular separation. I always think of modules to take care of one specific part. As soon as I got two modules which are dependent on each other I tend to creating a third module which handles these dependencies.

Hope I was able to help you a little more with my first time experience with HMVC even though I don't know how much help there was for your special case. But I think it's better to separate the modules by their core-target and the dependencies get on top.

If you wanna have another point of view on your project, you can hit me up with an email so we won't spam the forum with too long posts.
#5

[eluser]inc[/eluser]
nice post, thank you for sharing your experiences and it is always nice to hear real situations and workarounds. i did not quite understand what you meant with global actions that were handled by a parent-controller. did you created my_controller that extends mx_controller because it is auto loaded by hmvc library, then extended it with public controller which is later extended by other stuff? i don't understand my_controller which i didn't find in hmvc library. can you please tell me more about this? everything is auto loaded or you need to require controller classes before your controller class?

i see what you're trying to tell me about deciding of base modules and making a new module if it must be a mixture of two existing modules. it is a nice idea and i will definitely go into that direction! but instead of making a 'base modules' from which other modules will depend, what do you think about creating a 'base mvc' (which will be called from the default CI dir structure app/controllers, models, views) that will act like a responsible group unit for calling modules, generate their output data, checking if user has some rights to access to some kind of module etc. by combining functionalities of 'installed' modules?

so lets say we have modules like you said: acl, users, zones, shifts, shirts, pages, preferences, logging, export. all of these modules are depended only on themselves and they will work standalone if you call them. many of them if not all (tell me is that a good idea? Smile) can be accessed through a restful service (using phil sturgeon restful library). that way i will extend possibility to make every module reachable from the outside (which i will need also because this application will need to share and receive data from other applications created by me and by others). and, i need a base controller/model unit which will act like a top layer above all of these modules and which will be the responsible user interface unit that handles, combine and generate module's outputs.

so lets say we have a structure like this:

application
controllers
dashboard.php
models
views
modules
users, zones, shifts, shirts...
controllers
models
views

and you call dashboard/view, dashboard will ask auth/acl module is user logged in? if it is, then will ask acl module does user have rights to access dashboard/view, and if it does, dashboard will create all his main user interface template which will be combined with several templates from modules like users and zones for example. what do you think about this approach? if you call for an example add or edit method which will be a mixture of two modules we can do a quick entry from dashboard model and name it like a mixture of something that will require both modules installed.

yes, you helped me a lot with thinking and i enjoy sharing experiences. i don't know how other's will react with long posts, but i find this discussion very helpful and i can see it like an interesting read to a wider audience. it would be nice to see different approaches and experiences from others on this subject also.
#6

[eluser]North2Alaska[/eluser]
I'm at the beginnings of a complex project and this discussion sounds right inline with my own struggles. Can you share what your final design? It may be too early as it has only been a month or so, but I would be very interested in your process.
#7

[eluser]PhilTem[/eluser]
Since my project is finished by almost 90% (at least the most important things are done) you can have a look at my code via
https://svn.ignitedco.de/helferportal/trunk/ (as a remark: the source code is no longer updated/maintained, since the project is only important each November and I'm porting my code to GitHub/BitBucket, too).

To give a brief info about the code:
It's the project mentioned in my second post in this thread and you may use any part you want but please provide proper attribution (it's licensed under CC-BY-SA 3.0).
If you need further help either with the code or maintaining a large project, you can also contact me via email (via the forums).
#8

[eluser]inc[/eluser]
[quote author="North2Alaska" date="1334534800"]I'm at the beginnings of a complex project and this discussion sounds right inline with my own struggles. Can you share what your final design? It may be too early as it has only been a month or so, but I would be very interested in your process.[/quote]

hello! sorry about delay i have been quite busy these days. it isn't too early to ask because i have made important decisions and i am deeply into developing process right now. i had to restructure it several times before i came to a solution that fits my needs. i cannot tell you if it's a right direction or not and i think i got it a little bit too complicated but i really think that this will show its advantages when the project will become bigger and bigger any time soon.

controller extends:

Code:
my_controller extends mx_controller {}
logged_in extends my_controller {/*checks if user is logged in, if it's not - redirect*/}
admin extends logged_in {/*checks if user has admin rights*/}
member extends logged_in {/*checks if user has member rights*/}

modules structure (writting from memory hope i will not make mistakes):

Code:
modules
  core
    config
      _
      admin
      ext
      member
    controllers
      _
        auth.php
      admin
        users.php
        menus.php
      ext
        ext_auth.php
        ext_users.php
      member
        users.php
        menus.php
    language
        croatian
          _
            auth_lang.php
          admin
            users_lang.php
            menus_lang.php
          ext
            users_lang.php
          member
            users_lang.php
            menus_lang.php
        english
          _
            auth_lang.php
          admin
            users_lang.php
            menus_lang.php
          ext
            users_lang.php
          member
            users_lang.php
            menus_lang.php
    libraries
      _
    models
      _
        auth_model.php
        users_model.php
        menus_model.php
      ext
        ext_auth_model.php
        ext_users_model.php
    views
      _
        auth
          index.php
      admin
        users
          index.php
          add_edit.php
      ext
        module_name
          controller_name
            method_name.php
      member
          index.php
          edit.php

i call admin and member as sections and '_' something that not strictly apply to any section rules.

ext serves as a 'component' which will recognize a call from some other module and it will serve the data made only for that module. methods convention in ext 'components' are like this: module_controller_method()

you have to follow some rules:

Code:
1. each module must work independently from other modules
2. modules share their informations (data, views) through and only through ext components
3. admin and memeber sections are two different worlds and they will never share any info between themselves
4. each section loads everything from its section subdir (or from '_' which is not strictly defined for any section)

some examples:

Code:
class Users extends Admin
{
  $autoload = array(
    'language' => array('users/admin/users'),
    '' => array(),
    '' => array(),
    ...
  );

  public function __construct()
  {
    parent::__construct();
    $this->load->model('users/_/users_model', cu_model);
  }

  public function index()
  {
    ...
  }

}

---

class Users extends Member
{
  $autoload = array(
    'language' => array('users/member/users'),
    '' => array(),
    '' => array(),
    ...
  );

  public function __construct()
  {
    parent::__construct();
    $this->load->model('users/_/users_model', cu_model);
  }

  public function index()
  {
    ...
  }

}

---

class EXT_Users extends Logged_in
{
  $autoload = array(
    'language' => array('users/ext/users'),
    '' => array(),
    '' => array(),
    ...
  );

  public function __construct()
  {
    parent::__construct();
    $this->load->model('users/ext/ext_users_model', cu_model);
  }

  // method for module institutions/applications/index
  public function institutions_applications_index()
  {
    ...
  }

}

i really don't have time to recheck everything, but if i made some mistakes i will correct them through edit. i hope i helped a little bit.
#9

[eluser]ns8814[/eluser]
[quote author="inc" date="1330693631"]

in this simple example everything works as expected: you have a dashboard that is displaying a some grid panel from module_a and some grid panel from module_b. so lets say that module_a is cars, and module_b is people. cars can have parts, engines etc but not people. so we need to create another module people. but people can drive cars! but what car? so in the dashboard you click on add() link or something like that... and a client wants me to do a complex form where he would like to enter car details, but also a person and its information who's driving that car. how to deal with that kind of complexity but not to ruin the pattern?

i cannot make an add_edit view in the module cars which will show some fields from module people and i cannot do that otherwise also because that two modules will start to depend on each other. what i can do is to make some top layer which will control them right? but then, this top layer (add edit on dashboard for example) needs to have its own add edit view which is merged between module cars and module people. and this is where i start to argue with myself Smile

[/quote]
Hey I realize this thread is a few months old. I am not the best at php or codeigniter completely new. I had a similar problem on my first project which I am still working on. For me I wanted to be able to create an estimate which used model->estimate_model but when it came time to add the customer to the estimate I wanted to be able to add or edit the customer which has a separate table and model from my current page. I turned to J query JavaScript. Using the Jquery ajax request you can ultimately access as many different controllers and models as you want. Not sure if your able to use the javascript or not but it adds great functionality and useability to the pages.




Theme © iAndrew 2016 - Forum software by © MyBB