This is mostly a design question. I am creating a Laravel app and cannot figure out the design to use to provide what I want. My Laravel application is completely modular, with every module having their own routes, config, Models, Controllers and everything, and them loading in using a ServiceProvider.
My problem is as follows:
I have a Pages module, which consists of a Page model (Eloquent\Model). This module is used by other models to generate out pages.
I want other modules to extend that model. So for example, if I have PagesFiles module, then the Page module should have a way to access its files, like Page->files, which I could easily do within the actual Pages module with a simple relationship. But I need that method to be available without actually coding anything into the Page class, but from within other classes.
I also cannot just do PageWithFiles extends Page, because there will be multiple Modules extending same Page module providing it with additional functionality.
Please do let me know, if I can provide more information to help me solve this design problem.
Related
As far as I know, currently Yii 2 doesn't have an out of the box method to resolve ambiguity of controller and module names. An example of module hierarchy to describe what exactly I mean:
app\modules\v1\controllers\UserController // resolves the /v1/users and /v1/users/{id} actions
app\modules\v1\modules\user\Module.php // nested module, resolves the /v1/user/... controllers and their actions, e.g. /v1/user/something/{id}
In this case, the UserController conflicts with the user Module. The main reason of the ambiguity is the singular-plural magic of Yii 2 framework. I didn't find an appropriate solution to resolve this ambiguity. Further my ideas how to resolve it.
Rename the module.
Rename the UserController to the UsersController.
Create an additional submodule, and place there the UserController. E.g. app\modules\v1\modules\root\controllers\UserController
I'm not sure that at least one of these options is a quite elegant one and a proper solution in view of the Yii 2 philosophy.
Coming back to the main question, what is a more appropriate approach to resolve this issue by the Yii 2 philosophy? Controller and Module is two different types of objects, which is differently pluralized or not, thus should be right way to separate them in the routing for the described case.
How I usually deal with this depends a bit on how I'm structuring things.
Let's say I have users, departments, orders and maybe some other stuff. All these concepts have their own module in which all interactions take place. If I want to create REST controllers for all these concepts I can choose to add a controller to every module or I can create a dedicated API module for the controllers.
When creating a dedicated module for this purpose I usually name it api, maybe with some nested versioning module(s) inside. So in this situation I would get the following structure app\modules\api\controllers\UserController which would result in the URL /api/user. No ambiguity there and pretty clear what this is meant for.
When adding such a controller to the module itself I choose a better name than just 'UserController'. When asking myself the question 'What does this controller accomplish?/What does it do?' I find that just UserController doesn't cut it; Especially when inside a User module, resulting in /user/user. This controller is probably going to exist alongside one or more different controllers in the User module, all meant for something different. So, usually, I end up naming it just ApiController, resulting in /user/api. Another controller could be the ProfileController. So when looking at the URLs it's pretty clear what /user/api and /user/profile do. Without the ambiguity.
I am not sure I can fully understand the question, but probably you're asking about classname aliases?
use My\Full\Classname as Another;
I searched HMVC and know what it is and its advantages.
Modularization: Reduction of dependencies between the disparate parts of the application.
Organization: Having a folder for each of the relevant triads makes for a lighter work load.
Reusability: By nature of the design it is easy to reuse nearly every piece of code.
Extendibility: Makes the application more extensible without sacrificing ease of maintenance.
But just in Codeigniter without HMVC, different sub-folders for controller and multiple model folders and multiple view folders can be created. I do not comprehend the exact reasons for using HMVC.
I found in https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc.
This is most useful when you need to load a view and its data within a view. Think about adding a shopping cart to a page. The shopping cart needs its own controller which may call a model to get cart data. Then the controller needs to load the data into a view. So instead of the main controller handling the page and the shopping cart, the shopping cart MVC can be loaded directly in the page.
The main controller doesn’t need to know about it, and is totally isolated from it.
In CI we can’t call more than 1 controller per request. Therefore, to achieve HMVC, we have to simulate controllers. It can be done with libraries, or with this “Modular Extensions HMVC” contribution.
The differences between using a library and a “Modular HMVC” HMVC class is:
No need to get and use the CI instance within an HMVC class
HMVC classes are stored in a modules directory as opposed to the libraries directory.
I think native CI is not HMVC, it's just MVC. There's only 'controller', 'model', and 'view' inside of it, no 'module'.
So don't worry about why CI is HMVC if you don't need the benefit from HMVC.
By the way, if you really need HMVC pattern and the benefit from modularization, you can use the extentions:
https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc
https://github.com/jenssegers/codeigniter-hmvc-modules
Let us say I have a controller that takes care of login/registration/password recovery and such in my app. I want to share this across different modules and controllers. What's the best way?
Should I make an action helper, Or use inheritance? Of course I don't mean logic of those action, those are implemented by models (different for every module), I just want to share common parameters, interpretation and passing results to views.
I'm targeting to do some kind of a generic library for those things in my project. So I would have some abstract user model from which all other models that want to use login/registration function will inherit, but I'm wondering what about the controller stuff.
Any idea?
Basically I think what you are trying to create are widgets . Here is an great article how to create them using action helper by ZF team lead http://weierophinney.net/matthew/archives/246-Using-Action-Helpers-To-Implement-Re-Usable-Widgets.html .
Creating a re-usable authentication service is what you want to do. Creating it as a service allows you to test it in isolation. Inject the service into a front-controller plug-in so it is run during each request. The actual checking can be encapsulated into a custom validator so you can simply call ->isValid(). If not valid, re-route to the login page.
I have a pretty good handle on using models to make database calls and handing the data off to...
I understand views and ideal usage. My general thoughts are to create the following for each section (for the most part):
PEOPLE
- controller
- model
- view(s) // add, edit, profile, etc
- library // specific logic and output
then when I want to access people related data; Say from my BORROWER controller I’ll call the people library function and load the appropriate people view into the BORROWER controller and into its view. AND, same naturally for PEOPLE logic. DRY.
Is this ideal?
You can try using HMVC extension for CI where you can develop on modular approach for MVC. This will allow you to load application modules with its own controllers, models and views. The modules can call any other module and can load models of other modules. Have a look in here
I'm thinking of re-working my MVC before I get to far along with it. At the moment it uses a sinle controller which takes the user input and determines the model. The model has maby differ methods which I call actions, because one is called automatically. The model loads its view file, which again holds many different methods. The model can set properties which can be used in the view. Then the controller calls th template classwhich parses the output for display.
Is this the bst way to do it?
Or should each different part (news, contact, about) have its own controller, which loads a specific model and view. Essentially, instead of grouping methods into a single file, it uses multipe files.
I'm kind of lost as to how I should do it.
Cheers
Start using a MVC that works and is well-known like in Symfony or Cake. From that you will decide:
what do to in your own, knowing the best practices;
to drop your own if you feel like you can save time by using theses.
If you are thinking of advancing your own MVC model, like #e-satis have said, you will need to experience what is happening in already developed systems. However, as based on my experience in designing MVC model and determining what is there in opensource community, I stick back to my own MVC for two good reasons. One reason is the flexibility of customization and the other is own MVC privacy.
I used the following approach for MVC design pattern.
A Router.php file identifying user-request urls. This router will be able to fetch controllers and include the file and call the controller default method.
The loaded controller is also able to load other controllers if required to function. This is done using a global method, where all controller Class will extend to a MainController Class which is able to call to other controllers.
I do use a global registry to set and get variables from one controller to the other.
The Models are used to get the Data from Table, and most of my Models will represent Database functions which includes CRUD (Create Read Update Delete). So that a controller can easily manipulate database table data using a model.
Naming conventions in all controller, models, and views is also important, if you want to system to be more intelligent to identify the required action knowing the file name.
I use the Views separately for each type of controller. And these views will be sent to a Master Template View file.
Same as models, the controller will be able to set Views to Master View.
There are other customizations which you can do, like applying security methods before calling a class, or after calling a class/controller/model/view etc.
This is done by the MainController, which it will always look into a folder with autoload class which states what files should be loaded before and after of different actions during the process of building the content and delivering the output.
MVC is not a small scale idea, but it is a design idea which can always be developed. There are so many PHP MVC open source frameworks to be found if you know how to search the major search engines like google.com
But I do advice you that, MVC is not a good solution if you are simply developing a small dynamic website, as it will consume more time in developing compared to developing small websites. MVC is ideal, if you have business logic and needs system automation in order to avoid most routine tasks of developing, and like that I would say MVC is most ideal for larger applications.
The model loads its view file
The Controller should act as a Mediator between the Model and the View.
The Model shouldn't be aware of the way the view renders it, and also the View shouldn't be aware of any kind of logic of the Model.
In theory, if your MVC is well structured, you should be able to represent the same Model with different types of Views (HTML, XML, JSON for example).
Build FrontController which parses request uri and decides which controller to load and which method to run. With .htaccess rewrite all request to index.php
//index.php
class FrontController{
function run(){
//parse request uri here /comment/new
//load controller comment
//run controllers method new and pass some request attributes
}
}
// ../controllers/comment.php
class Controller_Comment extends Controller{
function new($request){
//do stuff here
}
}