/dashboard/user goes directly to the module without being routed first to front/index route, thus dashboard is displayed alone without to be included in the general template.
I can't figure out where is the logic in that case.
Module routes can only be used for routes inside that module. In other words, the lefthand site must define a route that starts with the module name, so (:any) will not work in a module, you can to define that in the global (=app) routes.php.
In our webengine the front controller also handles the backend (your dashboard), for us that is just another uri within the application. So we only have a catch all route, no others needed.
If your design has a separate front and backend controller, you need two catch-alls:
/** * Global application routes. */ return array( '_root_' => 'webengine/loader', // The default route
'_403_' => 'webengine/loader/403', // The main 403 route '_404_' => 'webengine/loader/404', // The main 404 route '_500_' => 'webengine/loader/500', // The main 500 route
// download front controller 'download(:any)' => 'download$1',
// rest api front controller 'api(:any)' => 'api/index$1',
// all other requests to the web front controller ':any' => 'webengine/loader' );
It must be a route, otherwise your catch-all would have caught the request for your dashboard.
I can't judge your architecture, but either your controller has a route and can act autonomous (being called directly) or it doesn't, but you can't have both.
Module routes are autoloaded, and are only loaded when the router detects it's a potential request for a module, in other words, if the first segment in the request URI matches a module name.
And if you have a module route like "dashboard/(:any)", then all of a sudden none of your dashboard requests will go to your front controller anymore, as this route will match all URI's starting with "dashboard/".
then I invoke the module without anything except his name and i pass the rest as 'param' to the index method as I noticed that if no action were detected it fallback to 'index' method, so i have my catch all with no routes in the module.
some remarks about my little piece of code? no drawback?
Of course i have to make some checks about module exists and write some code for when no module were invoked..
If you have a mix between controller actions that can be called directly and actions that produce widgets and need to be called by your front controller, make sure your routes are as specific as possible.
You could also come up with an architecture that maps all these controller actions to a single entry point, like we do with the download or api routes.
Or do like we do in our webengine, record in config what type of data a defined endpoint returns (a full page, a widget, a menu structure, a json response, etc), and have your front controller deal with all requests.
Don't know, I'm not a native speaker either. ;-). We use the phase "a second pair of eyes".
I personally find it very important to provide as much support as you can, when you maintain an open source product other people rely on. Too many open source products die an early death because the developer(s) abandon it or can't be bothered to respond to questions or bug reports.
Hi Harro and sorry for the delay, i didn't receive the email notification of your answer, i have to check spam.
No, i can't as all calls are Hmvc, \Request::is_hmvc() checks this 'static::active() !== static::main()'
But in that kind of structure, it's always true since all requests come from the front loader...
The only hack i've found is to add this function to module's controllers :
public function is_hmvc() { return \Request::active()->uri->get() !== \Request::main()->uri->get(); }
At the end I'm a bit confused about this kind of architecture as it breaks some of the framework build-in functions. I don't know...
What caused me wanting to setup this kind of things is what you wrote in the thread i mentioned at beginning of this talk :
"What doesn't work is:
- call cross-module (or app to module) the PHP way, like $result = \Module\Some_Controller::some_action(); - do an HMVC call using Request but don't use the called action in isolation, but attempt to do Theme stuff in there"
The 2nd point was what i was doing. Then i tried to start the right way. But it cause me more drawbacks than i thought, maybe I'm wrong and my old way was worst.
Requests from the frontloader aren't HMVC calls, HMVC is a controller requesting a secondairy controller. So maybe you are talking about something else?
Perhaps you should do one step back, and first explain what you want to do at the functional level, so I can explain how you would go about that?
In MVC terms, the index.php is referred to as the front controller, so that is what confused me.
That is what we use in our app framework, yes, and that is a regular controller. And that calls other controller actions via a secondary request, so yes, those are HMVC calls.
And in all cases, Request::is_hmvc() returns true in those controllers, so what is your problem?
The problem is that some methods of module's controllers don't have to be accessed by browser, or even a whole module. but no way to prevent that except my small hack.
Read again my first post of today please.
When you have autonomous modules you know which one can ( and have to ) be called directly, and which have to be called by other module. But then your autonomous module do themes things, and you said this is not a good thing to do...
to say short, I'm trying to figure out what is the best way to use Fuelphp, to figure out which architecture it is meant to work best with.
In the basics, every controller action is callable either by the browser or by an HMVC call. The only way to prevent a direct call is via routing (i.e. do not allow any routing to the method).
Ideally, this is the path you should take, if you have an application architecture that uses a widget engine, no controllers should be called directly, possibly with the exception of api controllers out output controllers (for downloads, pdf or image generation, etc). Ideally, these will have a frontcontroller too, but you could use routes to limit access, for example by using /api/module/controller/method, and route these to /module/api/controller/method (and group all your api controllers).
When an action is called, you can always use Request::is_hmvc(). It will return false when called by a client, and true when called by a Fuel request.
If you want to mix hmvc and non-hmvc usage in a single controller (which I think from a design and architecture perspective is a bad idea), you can always use
// only allow HMVC calls if ( ! \Request::is_hmvc()) { throw new \HttpNotFoundException(); }
which would return a 404 if a client would request it.
"if you have an application architecture that uses a widget engine, no controllers should be called directly"
Of course because they are all called from the front loader controller.
but you might want to have controllers you don't want to be called from front loader but from another module controller only, because they build only a part of a page, a component, like a form that can be used in multiple places. Unfortunately if you try to type the route for them in the browser, it works, the front loader will call them.
And \Request::is_hmvc() will NOT help you in that case, it will return true.
If you have an application architecture that uses a frontcontroller to assemble the page, it should receive ALL requests (except for non-HTML reponses like API or downloads), there are no controllers that can be called directly?
And if you have this, your frontcontroller knows exactly what to call, it should not need or use a route.
Your front controller captures all browser requests, so how a user could type in something that would route to and load one of these component controllers is beyond me...
it will call: $document = \Request::forge('blog')->execute()->response->body(); right?
which will render the blog index content
This content will probably have a 'sidebar' part, which will be loaded by the blog module by a call to a 'sidebar' module, lets say the route to the sidebar for the blog is 'sidebar/blog'.
your blog module will call: $sidebar = \Request::forge('sidebar/blog')->execute()->response->body();
to fill in the sidebar part of the blog index.
and return it to the front loader as the main document part, am I still right?
The sidebar part should never been returned to the front loader as a document for the main template, isn't it?
But what if i call this uri : http://example.com/sidebar/blog ?
the front loader will call: $document = \Request::forge('sidebar/blog')->execute()->response->body(); right?
The sidebar module is not aware of which purpose it is called for, then it will return its content to the front loader as document part of the main template : fail!
Indeed, the front loader cannot have the responsibility to know what a module return is good or not.
Then it's the sidebar module business to "know" if it can be called that way or not.
That was the purpose of \Request::is_hmvc() isn't it? but in that case it will return 'true' and the poor sidebar module will do its job and return a content instead of a beautiful 404 error.
Is that more clear for you? I know it's not easy sometimes to be understood on a forum ;)
I repeat, I'm trying to figure out what is the best way to use Fuelphp, to figure out which architecture it is meant to work best with.
How would the frontloader know what a valid page is and what not? The frontloader is in charge of creating your output, it should know!
How would you deal with additional information on a page? Some could have a different menu (for example logged-in or not), some could have multiple widgets in the page body or the sidebar, etc.
So you need an internal mapping, which defines the components that should be fetched for each of your page sections when a user requests /blog. And if you don't have such a mapping, have the frontloader throw a 404. A user should never be able to request any controller directly.
Our frontloader goes much further than this, as we also store theme information (so you can have different themes for frontend and backend pages, or custom user themes), page templates (so you can define repeating items like headers and footers in a template,. and don't have to define them all for very page), symlinks to other pages or other site trees (our engine has multi-site support) so you an have a different url for frontend and backend, but still expose a single backend page on the frontend site, etc.
You said "That is poor design. " I agree, I didn't feel good with that design, that's why i posted here ;)
At first i was in the way of autonomous modules like 'blog', 'dashboard', 'products' etc...
All modules inherited from a front controller class that populate the main template except the document part, then each module was intended to populate this document part, eventually calling small modules like sidebar or what ever.
But I've read your post saying that doing theme stuff in a module isn't a good idea:
"What doesn't work is:
- call cross-module (or app to module) the PHP way, like $result = \Module\Some_Controller::some_action(); - do an HMVC call using Request but don't use the called action in isolation, but attempt to do Theme stuff in there"