Magento Helper Directory Structure - magento

I have a custom module and everything works fine. I'm adding and admin panel portion to the module and would like a separate admin helper. I know I can create and call my admin helper like this:
app/code/local/namespace/module/helper/Admin.php
class Namespace_Module_Helper_Admin extends Mage_Core_Helper_Abstract....
$helper = Mage::helper('namespace_module/admin');
And everything works great.
I was really wanting the structure for my admin helper to be something like this:
app/code/local/namespace/module/helper/admin/Data.php
But can't figure out the how to set that up in config.xml and then call the helper.
My initial thought was to setup the config like this:
...
<helper>
<namespace_module>
<class>Namespace_Module_Helper</class>
</namespace_module>
<namespace_module_admin>
<class>Namespace_Module_Admin_Helper</class>
</namespace_module_admin>
</helper>
...
Then call the helper like this:
$helper = Mage::helper('namespace_module_admin');
But this doesn't work.
Is it possible to have a second helper for my module in a helper directory child directory? If so could someone point me in the right direction.
Thanks for the help!

Yes, it is possible to do this but I think you have some typos. I was able to register a new helper using your approach with settings like this:
<helpers>
<namespace_module>
<class>Namespace_Module_Helper</class>
</namespace_module>
<namespace_module_admin>
<class>Namespace_Module_Helper_Admin</class>
</namespace_module_admin>
</helpers>
The helper file itself was at the path: app/code/local/Namespace/Module/Helper/Admin/Data.php
The helper class looks like this:
class Namespace_Module_Helper_Admin_Data extends Mage_Core_Helper_Abstract
{
public function test()
{
return 'test';
}
}
And I was able to invoke it with the syntax:
Mage::helper('namespace_module_admin')->test();
So it is possible that your issue is due to your file/class name not matching up with the location Magento’s autoloader was expecting. For example your <class>Namespace_Module_Admin_Helper</class> should map to the (improper) directory app/code/local/Namespace/Module/Admin/Helper rather than the expected app/code/local/Namespace/Module/Helper/Admin.

Your approach looks fine and absolutely right. You have only one mistake in config.xml. You should name node <helpers> instead of <helper>

Related

Error extends AccountController.php in magento

I'm trying to extend the core AccountController.php -> app/code/core/Mage/Customer copied it to app/code/local/Mage/ and add a log to see which extends properly.
In the file AccountController.php (app/code/local/Mage/Customer/controllers)
...
...
public function createPostAction() {
Mage::log('In app/code/local/Mage/', null, 'test.log', true);
...
...
AND CORE (only test)
In the file AccountController.php (app/code/core/Mage/Customer/controllers)
...
...
public function createPostAction() {
Mage::log('In app/code/core/Mage/', null, 'test.log', true);
...
...
And does not go through code/local/ Mage but by CORE.
I need to configure something or it fails?
The logic through which controller class definitions are loaded builds the path to the file above the explicit include paths on which the autoloader relies. This means no local vs. core precedence.
You need to creat a controller rewrite by specifying a directory under the xpath frontend/routers/customer/args/modules/your_module
The latter node needs the before attribute set to Mage_Customer and you will need to create an AccountController.php with a createPostAction() method. Depending on your needs you may or may not need to extend from and require the core account controller class.
I guess you need to require the original controller:
require_once Mage::getModuleDir('controllers', 'Mage_Customer').DS.'AccountController.php';
Normally you need to do this with rewriting a controller the xml way...i havent checked in code, but maybe this is the problem.
I would recommend to do it the regular way via config.xml
http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/how_to_overload_a_controller

Magento Observer Destination

I have wrote 2 Magento observers and they both do exactly what I want with the exception that they end on the wrong page. In other words, they write the log files, modify the databases, and talk with other servers, but they modify the page to page routing. For example, I have an observer that I used at login that modifies a database, writes a cookie, and writes to a log, but it changes the post log-in page to
http://www.my-web-site.com/index.php/customer/login/post/
and then gives me a 404 error. If I hit "Ctrl" + 'r' then I am logged in at
http://www.my-web-site.com/index.php/customer/account/index/
which is correct. If I change, app/code/local/my_module/my_model/etc/config.xml to
app/code/local/my_module/my_model/etc/config.xml.1 (in other words take out the observer), then Magento routes to the correct page,
I'm thinking that I need router information in config.xml. My current config.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<!-- The root node for Magento module configuration -->
<config>
<!-- The module's node contains basic information about each Magento module -->
<modules>
<!-- This must exactly match the namespace and module's folder
names, with directory separators replaced by underscores -->
<MyCompany_LogIn>
<!-- The version of our module, starting at 0.0.0 -->
<version>0.0.0</version>
</MyCompany_LogIn>
</modules>
<!-- Configure our module's behavior in the global scope -->
<global>
<!-- Defining models -->
<models>
<!-- Unique identifier in the model's node.
By convention, we put the module's name in lowercase. -->
<mycompany_login>
<!-- The path to our models directory,
with directory separators replaced by underscores -->
<class>MyCompany_LogIn_Model</class>
</mycompany_login>
</models>
</global>
<frontend>
<!-- Defining an event observer -->
<events>
<!-- The code of the event we want to observe -->
<customer_login>
<!-- Defining an observer for this event -->
<observers>
<!-- Unique identifier within the catalog_product_save_after node.
By convention, we write the module's name in lowercase. -->
<mycompany_login>
<!-- The model to be instantiated -->
<class>mycompany_login/observer</class>
<!-- The method of the class to be called -->
<method>wrtLogInCookie</method>
<!-- The type of class to instantiate -->
<type>singleton</type>
</mycompany_login>
</observers>
</customer_login>
</events>
</frontend>
</config>
I'm guessing that the login inside Magento uses an observer, and I'm interfering with it.
Besides the , I'm guessing that I could also accomplish a similar thing in the PHP Observer code. My observer is:
<?php
/**
* Our class name should follow the directory structure of
* our Observer.php model, starting from the namespace,
* replacing directory separators with underscores.
* i.e. /www/app/code/local/MyCompany/LogIn/Model/Observer.php
*/
class MyCompany_LogIn_Model_Observer extends Varien_Event_Observer
{
/**
* Magento passes a Varien_Event_Observer object as
* the first parameter of dispatched events.
*/
public function wrtLogInCookie(Varien_Event_Observer $observer)
{
// Retrieve the product being updated from the event observer
$customer = $observer->getEvent()->getCustomer();
$email = $customer->getEmail();
Mage::log('The E-mail is: ' . $email);
$ran_nmbr = rand();
Mage::log('The random number is: ' . $ran_nmbr);
$crnt_dat = date("m-d-Y::H:i:s");
Mage::log('The date is: ' . $crnt_dat);
return $this;
}
}
?>
I have read about routers, but the articles discussed it in terms of landing on some page before the extension is executed. As you can see, I need to land on the right page after the extension is executed.
Inside the PHP observer, I also tried redirects. For example,
Mage::app()->getResponse()->setRedirect(Mage::getUrl('customer/account/login'));
Maybe I need a full URL address or something. I'm sure this is easy to fix, but my ignorance seems to be following me around. Please help if you know something about this.
Unfortunately, it's not quite as simple as an easy fix. You see, if we look at app/code/core/Mage/Customer/controllers/AccountController.php, in the loginPostAction(), we see that the customer/session singleton triggers the customer_login call. However, what is causing the trip-up here is that after that is called, back in the controller, the controller calls $this->_loginPostRedirect(), so all of your rerouting work that you did is overwritten.
How to fix:
After saying it isn't all that simple, I did happen to see a cheat that we can take advantage of:
$session = Mage::getSingleton('customer/session');
$session->setBeforeAuthUrl($forwardToUrl);
You're partially right. The problem you're running into is Magento's redirect mechanism works with a "last one to say something" wins philosophy. If you look at the standard login code in
app/code/core/Mage/Customer/controllers/AccountController.php
You'll see the loginPostAction method ends with a call to
$this->_loginPostRedirect();
which (ultimately) ends up calling some code that looks like this
$this->getResponse()->setRedirect($url);
This may be the code that's causing you a problem, or it may be something else. The general problem is the final call to the response object's setRedirect method will win.
My usual solution to this is setting some sort of global flag (static variable on a class, a flag set with Mage::register) when I want to perform a redirect, and then creating an additional observer for controller_action_postdispatch. In this observer I look for the global flag I set, and if I find it, set the redirect there.
This handled 99% of redirect situations, and should handle yours. The times this won't work are with some admin login cases, as well as URL rewrites.
The admin login contains some redirect code that doesn't use Magento response object
#File: app/code/core/Mage/Admin/Model/Session.php
...
header('Location: ' . $requestUri);
exit;
...
If this redirect is causing you a problem, create a listener for admin_session_user_login_success that uses PHP header redirects before Magento's does.
Similarly, if Magento's using a rewrite object, the following code might run
#File: app/code/core/Mage/Core/Model/Url/Rewrite.php
if ($isPermanent) {
header('HTTP/1.1 301 Moved Permanently');
}
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('Pragma: no-cache');
header('Location: ' . $url);
exit;
(that said, the rewrite code will rarely be your problem, as in standard Magento operation is runs before controller dispatch)

magento how to call custom model

How can I call model in a custom module? Lets assume that model is really simple one and returns just arrays of static data.
I have a directory structure similar to this:
app
local
Mypackage
Module
Models
Model1.php
How can I include Model1.php inside controller? If I go with Mage::getModel('Mypackage/Modul/Model1) it returns error since it searches model inside Mage/Module/Model/Model1.php
Thanks!
Mage::getModel('mypackage_module/modeltest) should work. But first check your config.xml.
You should have declared it like so:
<models>
<mypackage_module>
<class>Mypackage_Module_Model</class>
<resourceModel>modeltest_mysql4</resourceModel>
</mypackage_module>
<modeltest_mysql4>
<class>Mypackage_Module_Model_Mysql4</class>
<entities>
<modeltest>
<table>mypackage_module</table>
</modeltest>
</entities>
</modeltest_mysql4>
</models>
Mage::getModel('modulename/modelname')->modelmethod();
i.e.
Mage::getModel('catalog/product')->getName();
Hope this help you
This should work:
Mage::getModel('module/model_model1')->modelmethod();
Please note that the model folder should be "Model" not "Models"
Hello you can try this but I have not tested it
$collection = Mage::getModel('Module/Model1')->getCollection();

Magento Router Url - Need Hyphnated Path Name

Let's say I use a custom controller to have a url path/frontend name of
/customcategory
Well, obviously if I have a controller file named 'TestController.php' and indexAction
the url path would be
/customcategory/test/index
What I am trying to figure out is how I do re-name the Test Controller, or modify the config xml file, so I can have a hyphenated url from a controller file such as
/customcategory/test-section/index
I know that if I want /customcategory to be hyphenated, I can just modify the frontend tag in the config file. But the site I am building would benefit from a hyphenated controller route, the part that comes after /customcategory with keywords and I cannot get it to work nor can I find an example on google - as crazy as that may seem.
Thanks for your time.
What you are trying to do is possible using global rewrite in your custom module. You could pass all incoming request for /customcategory/* to a specific controller action. But you would have to manage your own route (base on the depth of your url path).
e.g www.MageIgniter.com/customcategory/path1/path2
config.xml
<global>
<rewrite>
<fancy_url>
<from><![CDATA[/customcategory\/(.*)/]]></from>
<to><![CDATA[customcategory/index/processroute/tagname/$1/]]></to>
<complete>1</complete>
</fancy_url>
<rewrite>
</global>
<frontend>
<routers>
<tagseo>
<use>standard</use>
<args>
<frontName>customcategory</frontName>
</args>
</tagseo>
</routers>
class MageIgniter_Customcategory_IndexController extends Mage_Core_Controller_Front_Action
{
public function processRoute(){
print_r($requestUri = Mage::app()->getRequest()->getRequestUri()); //path1/path2
print_r($this->getRequest()->getParam('tagname')); // path1
print_r($this->getRequest())
// do you custom logic here base on about request path explode('/', trim($requestUri,'/'))
}
...
For a working example see "Product Tags" section # http://www.contempospace.com/bedroom-furniture/wardrobe-closets/custom-closet-systems/isa-closet-system-shelves-hanging-walk-in-reach-in-closet.html
As far as I am aware you cannot add hypens in the url to match up to a filename. If you are trying to get a folder structure you can just add more paths to it.
For example if you wanted:
Namespace/CustomCategory/controller/test/SectionController.php
you could do:
/customcategory/test_section/index

Magento - module with system config, how do I do something on save?

I have a simple module created with the Magento Module Creator with a couple of settings in admin->system->config.
When I go to these settings and choose the enable/disable option, the settings get saved - which is great - however, I want to run my own code after that, i.e. on the save action, once the data has been saved.
In your etc/system.xml add a backend model descended from Mage_Core_Model_Config_Data and use it's _afterSave() method to run your code.
although it isnt a good idea but you can achieve it by observers:
<controller_action_postdispatch_adminhtml_mymodule_mycontroller_myaction>
replace the my-s with module_controller_action, and most likely you want to put it in this event:
<controller_action_postdispatch_adminhtml_system_config_save>
in your config xml as follows:
<controller_action_postdispatch_adminhtml_system_config_save>
<observers><myobserver>
<type>singleton</type>
<class>mymodule/observer</class>
<method>mymethod</method>
</myobserver></observers>
</controller_action_postdispatch_adminhtml_system_config_save>
and in mymodule, as in your module have a class observer in mymodule/Model/Observer.php
and declare the observer as
class modules_mymodule_observer {
public function myfunction(Varien_Event_Observer $observer){
//do your stuffs
}
}

Resources