To maintain loose coupling between the components of your application, you should not call the model directly, but call an "API" controller method in the users module using an HMVC request, have that run the query, and return the results.
If your application needs to be scalable, you should use the same technique for all I/O, splitting the application's modules into a frontend layer (html generation, user input, data caching if needed) and a service layer (backend I/O, business rule processing, etc).
Encapsulate your HMVC call in a generic method, so you can switch from a local HMVC request (everything runs on a single webserver) to cURL requests (frontend and service layer are separate webservers) without impact to your code.
class Controller_Parent { public function action_index() { try { $result = Request::forge('child/index')->execute()->response()->body(); var_dump($result); // should be an array of Model_Child's... } catch (\HttpNotFoundException $e) { // controller could not be found/loaded } } }
and
class Controller_Child { public function action_index() { // run whatever query you want here, and return the result return Model_Child::find('all'); } }
If you want to pass parameters, you can do that either throw the URI (like you would do in the browser) or pass then via an array in the execute() method of the request. In both cases, you can fetch them like you would in any action, via the method parameters.
As to access control, I would have separate HMVC controllers, and do an is_hmvc() check in the before() method of that controller. Or alternatively make sure your HMVC isn't routable (so it isn't accessable from the browser) and use Request::forge($uri, false) to bypass the routing engine.
If you have a separate controller for your "service layer", you don't have to check for HMVC requests, as that is all it's receiving. It will keep your code clean as well.
If the controller is accessable via the browser too, you can prevent browser access by using:
public function before() { if ( ! \Request::is_hmvc()) { // fake a 404 so the controller appears not-found throw new \HttpNotFoundException(); }