/libraries/joomla/application/component/controller.php
where this file is located in JOOMLA 3.1.5
In 3.0, it is my understanding that most of the classes autoload, so you can typically guess a files location based on the class name (since this is how the autoloader finds them!). Basically, the prefix is mapped to one or more libraries, and then each word after that represents a folder or file (for the last word of the class). If there is just a prefix and one word (like JController), controller will be both the folder and file name. Tricky? Some examples:
For these, you should note that the J prefix is mapped to several libraries: joomla, cms, and legacy.
JControllerLegacy will be defined in either libraries/joomla/controller/legacy.php, libraries/cms/controller/legacy.php, or libraries/legacy/controller/legacy.php. In this case it is the last one, the legacy library.
JController no longer refers to a class but an interface in 3.1, but still it will reside at either libraries/joomla/controller/controller.php, libraries/cms/controller/controller.php, or libraries/legacy/controller/controller.php. In this case it happens to be the first place, the joomla library.
Note in the above how controller is repeated as both the folder and the file name. They don't allow php files in the main library folder (ie. you can't do libraries/joomla/controller.php, so for short class names, you will see the name doubled.)
Finally, any class that follows this format will be autoloaded by joomla, so there is no need to include a jimport call before using the class.
Related
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'
];
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/
I'm starting my 1st CodeIgniter project and want to get some advice before i start. I'm a little confused with how the name of the controller and models work.
If i want the url to my company page to be http://example.com/Company/view
the controller needs to be called Company.php correct?
inside the company controller it would look like this:
public function viewAll()
{
$this->load->model('Companymodel');
$this->load->view('templates/header');
$data['result'] = $this->Companymodel->viewAll();
$this->load->view('company/viewAll', $data);
$this->load->view('templates/footer');
}
ok im confused here, on line 4 above:
$this->load->model('Companymodel');
this call to the company model page needs to have 1st letter capital with the rest lower case?
if that's correct, does the model file need to be called Companymodel.php and placed inside the application/models folder?
is it bad practice to call the controller and model the same
example: Company.php and place it inside /application/controller/
and then have the model called Company.php and place it inside the application/model or should the model be called Companymodel.php
I guess my ultimate question is the naming convention of the controller and model files, and whether they can be upper case or not.
URLs
Your URLs should typically be all lowercase letters. If you expect capital letters, there's a chance you could accidentally exclude their lowercase counterparts, even though they're the same URL. Example: www.example.com/controller/method/param
Controllers
Controller class names should be all lowercase, except the first letter.
If your URL is www.example.com/gallery, the controller name is Gallery.
If your URL is www.example.com/admin_folder, the controller name is Admin_folder.
Controller file names should match the class name, but be all lowercase.
Gallery :: gallery.php
Admin_folder :: admin_folder.php
Controller methods should be all lowercase as well. There is some flexibility with uppercase, but similar to URLs, there are opportunities where it can goof something up (here's an example where capital letters interfered with a form validation callback method).
Models
Models follow most of the same conventions as controllers. The only difference is with model method names, which can use your preference of capitalization. Since these methods are not tied to URLs, and are called using normal PHP OOP, you can name them as you please.
It is recommended to load models using the all lowercase version. While it is not required by CI, it can confuse some users if they load it with a capital letter, but then attempt to access it as all lowercase (this is due to native PHP being case sensitive with class properties [and variables in general], not CodeIgniter).
Model class name: Users_model (the _model suffix is also not required, but some people may use it as a personal preference, or to prevent naming conflicts with a Users controller).
Model file name: users_model.php
Model loading: $this->load->model('users_model')
Model method names (all okay): $this->users->getAll(), $this->users->find_by_name($name), etc.
Libraries
Libraries follow the same conventions except for the file name. In their case, file names should match the class name.
Similar to models, it's recommended to load libraries using the lowercase name.
These rules are the same for CI's libraries (located in application/core and application/libraries, as well as custom or third-party libraries.
Special note: when extending default CI libraries, the prefix as defined in application/config.php comes into play. This prefix typically should be all uppercase, followed by an underscore. The default is MY_.
Library class name: Photos
Library file name: Photos.php,
Library load: $this->load->library('photos')
Helpers
Helper names and loading are all lowercase. The filename consists of the helper name with _helper appended after.
Helper name: url
Helper file name: url_helper.php
Helper load: $this->load->helper('url')
Notes
CodeIgniter is somewhat inconsistent in their naming conventions, but there really aren't too many rules, so they are easy to get used to and memorize. I very rarely have issues with naming and loading in CI, and when I do, it's usually because I was just working on a Composer-related project so I got into a different habit.
The rules in this answer are for CodeIgniter 2.1.x as of this writing. There is discussion on Github for 3.0 to better and add more consistency to naming conventions, which you can read about and contribute to if you'd like.
models/admin.php
<?php
class Admin extends CI_Model {
...etc
controllers/company.php
will include the admin model with
function galleryView()
{
$this->load->model('Admin');
$numRows = $this->Admin->getPhotoNum();
... etc
To browse to galleryView the URL would be mysite.com/company/galleryView
There is very good documentation and examples on the CodeIgniter site
Many extensions (including the one's I've written) include a helper class that just extend the abstract base class without adding any functionality. The helper usually looks like this:
class MyCompany_MyModule_Helper_Data extends Mage_Core_Helper_Abstract {
}
The extended class is therefore just used for things that the abstract class provides, especially for translations. On the other hand, all Block and Controller classes in Magento inherit the __() method for translations - and in an extension I'm currently developing I don't have the need to call the helper class even once.
Can I just delete the helper class and remove it from config.xml? I've tried it and the extension seems to work fine without, but due to Magento's complexity I'm always a bit worried that there are implications I'm not aware of.
If you're creating a module from scratch, helper classes aren't strictly necessary. I usually skip creating one until it's needed.
However, if any XML file uses the module attribute to specify a translation module, that attribute needs to resolve to a valid helper. For example, in this core file
<!-- File: app/code/core/Mage/Catalog/etc/system.xml -->
<tabs>
<catalog translate="label" module="catalog">
<label>Catalog</label>
<sort_order>200</sort_order>
</catalog>
</tabs>
There's module="catalog". By specifying this attribute, the Magento system code that translates the label will look something like this
Mage::helper('catalog')->__('Label');
So, removing the helper from the catalog module would break parts of Magento.
(The single part class alias catalog is automatically converted to Mage::helper('catalog/data') by Magento system code)
This "helper to group translations" feature is used in many of Magento's XML files, not just system.xml (layout, widgets, etc.). Additionally, there are some systems in Magento that will infer and/or require the existence of a helper module for translations (Access Control, external API system,etc. )
Long Story Short: If you're creating a module from scratch, feel free to leave the helper out until you start getting errors that Magento can't instantiate a helper. Never remove an existing helper from a module, and if you want to make sure you're 100% compatible with assumptions other people might make, always include a Data.php helper class.
Magento's Helper classes contain utility methods that will allow you to perform common tasks on objects and variables. http://www.magentocommerce.com/knowledge-base/entry/magento-for-dev-part-1-introduction-to-magento#6
Assuming that the Helper file is empty with no custom methods eg.
<?php
class MagePal_SomeModule_Helper_Data extends Mage_Core_Helper_Abstract
{
}
Then some of things that may still be affected are:
system.xml - blank screen for your module in admin -> system -> config
$this->__('') - error in your .phtml template (for internationalization/translation)
So if your helper is empty, without a system config section and no translation then it 'maybe' ok to delete.
I know how to override Mage classes (any class within app/code/core)
My question is how to override Varien classes? (classes within lib/Varien)
If I want to override Mage_Adminhtml_Block_Page_Menu
I create a class MyCompany_Adminhtml_Block_Page_Menu under app/code/local/MyCompany/Adminhtml/Block/Page/Menu.php
I name it like:
class MyCompany_Adminhtml_Block_Page_Menu extends Mage_Adminhtml_Block_Page_Menu
Now Magento uses my class MyCompany_Adminhtml_Block_Page_Menu instead of Mage_Adminhtml_Block_Page_Menu
My question is: where should I put the new class, and how to name it, to override, for example Varien_Date (lib/Varien/Date.php)
Thanks
If you must, copy the file and path to the local codepool and make the necessary changes. There is no configuration mapping to change the class name.
Explanation: see the bootstrapping in app/Mage.php. There is a load order set for the codepools and libraries in the following order:
app/code/local/
app/code/community/
app/code/core/
lib/
Typically, Varien_Autoload is responsible for mapping classnames such as Varien_Data_Collection_Db, Mage_Core_Model_Abstract, or Zend_Db_Select to relative filenames (Varien/Data/Collection/Db.php, Mage/Core/Model/Abstract.php, and Zend/Db/Select.php respectively). These file locations are then passed to include(), which internally uses the load order set in the bootstrap. Therefore, if the file Varien/Data/Collection/Db.php is present under one of the "earlier" locations, that version of the class definition will be used.
These type of modifications may be justified, but they should be well-considered and documented, as the entire definition will be owned by you and any upgrades will need to be merged in the future. It would be good to know what you would like to change, as someone else may have a slightly less invasive option.