What is the best practices in Magento model rewrite? - magento

My company is making a module for Magento to fit the needs of Brazilian business rules.
Sometimes we need to override core models to add funcionality, sometimes need to rewrite core models to change some functionality. We are in doubt wich is the best practices to do this changes. For example, when a module needs to modify some behavior that is owned by other model.
We know that the modified files need to be created under "local/mycompany/modules..." but we're running into a problem that I will describe below.
A simple example is: Our Customer model needs to add the postcode with the '99999-999' mask, with the '-' before the last three chars. That is ok, its done and working. But when we need to use this postcode to make calculations, wee need to remove the '-' char. That was made in our rewrited "Shipping/Rate/Request.php" model.
That is the point of our doubt. Which is best?
Do this rewrite inside new "Shipping" module in "local/mycompany/Shipping/Model/Rate/Request.php" or do this rewrite inside the "Customer" module directory structure?
We are confusing about the structure we need to decide.
Something important is that we won't distribute or sell the modules rewrited as separated modules.
I'll put some code here:
The postcode is received by our "Customer" module, with masks in input, done by Javascript.
This "Customer" module add more fields to customer database.
Here, I rewrite "Shipping/Rate/Request.php", inside the "Customer" module:
in config.xml of "Customers" module:
<shipping>
<rewrite>
<rate_request>Mycompany_Customer_Model_Shipping_Rate_Request</rate_request>
</rewrite>
</shipping>
Then the file "Mycompany/Customer/Model/Shipping/Rate/Request.php" contains the code to remove '-' char from postcode.
Our doubt is: In some cases, we need to rewrite the "Shipping/Rate/Request.php" again to modify other methods. Which is best?
Every rewrite is done inside the module that came from? Creating repeated files of the same class.
Use the same directory structure of Magento's core inside the "Mycompany" namespace and modify all that we need inside one file of each class? Like Magento's core?
I don't know if I could explain what I need.
Thanks!

It's best to keep the contents of a module within it's module folder.
If the extends you are talking about are part of a module's functionality than you should place them inside that module's folder. The path would then be local/mycompany/Mymodule/Model/Shipping/Rate/Request.php.
I would create this extra level in the dir structure to make it clearer that the rewritten Request.php comes form the Shipping module, but this is absolutely not a necessity.
The reason why this is a good practice is of course modularity. You will be much more able to add, remove and version modules that are contained within one folder. Think about the module's xml file in app/etc/modules and the config files in your module's directory. They describe what is in your module's directory and not all the rewrites that belong to it but are in different module folders.
Besides, if you have extended or rewritten the same model from multiple modules and you decide to remove or totally rewrite a module of your own, how will you know which files or parts of files will belong to it if they are scattered around the app dir.
For a more detailed view on how to create Magento modules please also have a look at http://www.magentocommerce.com/magento-connect/create_your_extension/

Related

What is the naming convention of view folder for CamelCase type controller

I have a controller named: CustomAuthController. Now I want to create a folder for this controller. What should I choose for this folder name. I mean what name is the best practice for laravel. is custom_auth is best pick. Is there any rule?
View folders in Laravel are made to help the structure of the front end of the app. It has nothing to do with what Controller you use to provide functionality for it.
For instance, you can have the layouts folder where you put all your blades which can be used into another blade as a reusable section. The views under layouts folder might also use your CustomAuthController controller. Does that make sense?
Name your view folders in a way which helps you understand the front end structure of your website.
As for the naming convention, always try to keep it one word, all small case and usually a plural word as it holds a group of blade views.
If you need to make it as two words, mostly snake_case is used but there is no written rule about it.

Changing template inheritance order in Silverstripe

As per the documentation of Silverstripe, template inheritance is defined as follows:
mysite (or other name given to site folder)
module-specific themes (e.g. themes/simple_blog)
themes (e.g. themes/simple)
modules (e.g. blog)
framework
Now I've got a site that has quite a few different themes. Well, "different" in that they have different names, but they still got an awful lot in common. Now I am putting all the common files in the /mysite/templates folder, but that means that if one of my themes needs a change in one of the templates, I need to remove that file from the common folder, and move it to ALL the different theme folders. In this way I end up with a lot of duplicate templates.
In my case it would be beneficial to change the inheritance order, causing the specific theme folder to take precedence over the /mysite folder. In such a way I could just copy the template that has to be changed to the theme folder and that theme one will use the changed one, while the rest keeps using the generic one in the /mysite folder:
themes (e.g. themes/simple)
module-specific themes (e.g. themes/simple_blog)
mysite (or other name given to site folder)
modules (e.g. blog)
framework
It also seems to me to be the more obviuous way to do it, but I probably am missing some important point here. Nonetheless, would doing this be possible without hacking the core?
Template inheritance rendering seems to be managed by two classes predominantly, SSViewer (a core class for handling view rendering) and Controller (which all other controllers inherit from).
For view rendering, a SSViewer object can take an array in its constructor for template inheritance. This is important because the Controller class actually instantiates the SSViewer in a function called getViewer.
It is important to mention at this stage, a normal SilverStripe site you are normally inheriting from ContentController instead which overrides the getViewer of Controller. It won't really change too much of what you need to write but it is important depending how low-level you want this to apply.
For what you want to apply to pages in general, you would be looking at overriding getViewer in your Page_Controller. As for what specifically you would need to write, that is somewhat dependent on your entire site structure. I would imagine it would need to start off a little like this though:
public function getViewer($action) {
$viewer = Parent::getViewer($action);
$templates = $viewer->templates();
//Do your processing that you need to here
//Set it back via:
//$viewer->setTemplateFile($type, $file);
//Alternatively, you can create a new SSViewer object
return $viewer;
}
It will be a bit of experimentation to work out what exactly you need to do for shuffling around the data though this was never going to be easy. Once you start heading down this path, you likely will find a number of edge cases where this may not work properly (eg. template includes).
The question and the accepted answer are for SilverStripe 3, and should be referred to for queries relating to SilverStripe 3.x. The following refers to SilverStripe 4.
As SilverStripe 4 is currently the latest stable version and now sets theme inheritance instead of template inheritance, the question and answer may not be suitable for newer installations or up to date installations.
The best way to control inheritance in SilverStripe 4 is to ensure that the themes are configured in the correct order, and that the module inheritance is configured appropriately.
Your mysite/_config/theme.yml file typically declares the theme inheritance, and you should adjust this file to control theme inheritance appropriately. For modules, you need to specify the appropriate Before and After in your mycustommodule/_config/modules.yml file.
The following example is for a sile with both the mytheme and simple themes, a custom module without an _config/modules.yml file, and a vendor module without an _config/modules.yml file.
SilverStripe\View\SSViewer:
themes:
- 'mytheme'
- 'simple'
- '$default'
In this example, SSViewer::get_themes() will return those three items as an array in the same order: ['mytheme', 'simple', '$default]. When checking to see if a template exists, $default will then be replaced by the paths of all modules which define templates, in the same order as they appear in the manifest.
<?php
use SilverStripe\View\ThemeResourceLoader;
$templatePaths = ThemeResourceLoader::inst()->getThemePaths(SSViewer::get_themes());
$templatePaths === [
'themes/mytheme',
'themes/simple',
'mycustommodule',
'vendor/silverstripe/asset-admin',
'vendor/silverstripe/campaign-admin',
'vendor/silverstripe/reports',
'vendor/silverstripe/siteconfig',
// Some vendor modules may appear here...
'vendor/othervendor/custommodule',
'vendor/silverstripe/cms',
'vendor/silverstripe/admin',
'vendor/silverstripe/assets',
'vendor/silverstripe/framework'
];

HMVC how to separate the modules?

I'm making a leave management (HRM) website. I'm using codeignitor HMVC to build this. Following features are included in this site:
A table to display a summary of leaves.
A table for leave types like annual, MC, urgent, other...
I was thinking to create two modules for leave_summary and leave_types, but my friend told me it is useless.
According to HMVC architecture we are trying to create self contained modules for reusability. If I'm creating a different module for leave types, I should be able to reuse it and module itself needs to be self containing. But I can't use leave_types module anywhere else.
My friend asked me to put all the leave related stuff in one module called leave. This sounds strange to me as I found lots of examples people are trying to separate things out.
Do we only need to separate the modules which can be reused in the future (ex: login module, image_gallery module, profile module) and keep all others things inside a one module?
(according to the above example I have to keep everything related to leave in a one module
ex: leave_type, leave_requests, leave_summary will be placed inside the leave module)
What are the benefits I will get, if I separate the leave_type, leave_requests, leave_summary etc... into separate modules?
Will I be able to reuse them? If so How?
In HMVC model classes and other assets can be exchanged among the modules, so how can I call it a self-contained module or a separate entity as it is depending on another module?
(ex: I have to call leave_type module's model class inside the leave_summary module to show the leave type name in a table.)
I'm little lost here. Please help me to understand. Thanks a lot!
As i work lot of MVC projects. And I am agree with your friend.
May times this question arise when i used join that i have to choose in which one module i should go for write query. If you write in one model may next developer will write in another one model.
So according me it is best to keep same type of tables which are handling relation and using for same behavior use this approach like leave model, profile model etc.

Codeigniter Dynamically load controller depending on url (outside routes.php)

using CodeIgniter normally one has to specify the controllers in the config/routes.php file.
This is not to handy, so I would like to be able to do something like this in a controller.
get url parts and check if the first part is specified in an array
if so, load the specified controller, if not, load default controller.
It basically mimics the behavior of the routes file, but there is no need to specify the wildcards before. I am using a base controller I extend with every controller, but I would like to have this controller just load (or include) the needed controller.
Does anyone have any idea how I can do this in a good way?
Thanks in advance.
// Edit
Okay, so here is my scenario.
I have cms and users can choose to include modules (e.g. a gallery).
I need to inlcude all the gallery php scripts without having to have "gallery" in the url.
I figured it would work if I use a "main controller" which loads another controller depending on the modules chosen. I realize this might not be the best way, so if there is a "clean" way to do it, please tell me.
As far as I know models are just for database stuff, so putting a whole gallery in there is not right either. The Plugin itself will of course be a library, but there is going to be some code to load the libs depending on the demands, get the database data, etc.
Thanks
The way you're doing this is incorrect. You never should take over the routing function to do this. What you need is to use some kind of module functionality to include the required methods and models; a module doesn't require to have route-accessible methods, so it's basically a "library" with a model and views.
If I remember correctly there are several plugins that provide this, One was HMVC (google it).
The ideal form would be to load the "Module" on demand from your controller, like you do with the core CodeIgniter Libraries; so lets say you're inside the blog controller action and you want to include the comment module which is used on gallery and on images, you just include the module and call it's methods to get the data which you can then pass to the view as needed; you can even render partials and store them into a variable to pass to your master controller.
Hope this is enough to get you on the right track :)
I may be misunderstanding your question but you want to load your controllers if you go to them and if not you want to go to your default.
If I am understanding correctly you can do a couple things in your routes have a route that takes everything to your default controller.
In your controller have an array of all your controllers then implode the array to a regular expression
$array = [c1, c2, c3, c4];
$str = implode('|', $array);
$regex = "($str)"
now just add your regex to a route
now redirect as you see fit.
But this is really what the routes file is for you you are just dancing around something that should be used.

How to serve a MVC-view with image paths from directory?

I'm kind of new to the whole MVC concept, since I just recently started developing a web site using CakePHP framework. Therefore I turn to you asking for how to achieve the following in a best-practice-way.
I want to be able to place a number of pictures in a directory, which then is scanned for all filenames in it. These filenames should afterwards be passed to an arbitrary view, which then loops through all filenames making img tags of them.
It would be nice if this could be done in a general way, so that I could reuse the code for same task but with a different directory name.
I have already tried the following two approaches. Nevertheless, non of these felt like the best way to do it, for some reason.
Create a model with $useTable=false.
Create an ordinary class and import it as a vendor.
What is the best way to achieve what I describe above?
I'm thinking your original idea is the better one, use the Model to traverse/read/write the directory. Think of the File structure as your data source. You can pass the dirname to the model with $this->data and then let it use the File class to retrieve what you need. This would make it portable across Controllers (with loadModel())
Later on down the road if you move your image paths into a DB you only have to re-write the model to take that into account.
I've done the following before: create an e.g ImageManager class and pass it as an IImageManager to the constructor of your e.g ImageController instead of passing a repository. The ImageManager could then do all the work that you mentioned.
EDIT: I did that in .net mvc and don't have experience of CakePHP, but I guess there's a place where you can register the concrete implementation of IImageManager as ImageManager so the framework would know what to pass to the controller's constructor
I would create a helper for this purpose.
Edit: And for trawling through the filesystem use the Folder class from within your helper.

Resources