I've made controller_front_init_routers event observer, which retrieves data from a REST service to construct a menu.
All was ok until I discovered that the observer generates errors in the backend (no way to save products for example) and also in the rest services.
I am struggling for any conclusions, So I raised some interrogations.
I tried to make a condition in order to trigger my Observer
methods in case we are in frontend only. But Magento considers that we are
always in frontend area.
(var_dump(Mage::app()->getStore()->isAdmin()) return always false
and the same with var_dump(Mage::getDesign()->getArea() ==
'adminhtml'))
Can anyone explain what's happened ?
Also one solution is to place the event observer in frontend
area in the config.xml and to load it with
Mage::app()->loadArea($this->getLayout()->getArea()); but where should I
place this piece of code ? in a new observer ? Is that the most
appropriate process ?
Is it a way to listen once an event then to pause the listener?
(once my menu is registered, I don't need to listen to the event any more)
Is the use of controller_front_init_routers event the best choice ?
Who has ever seen that kind of problem ?
I work on Magento ver. 1.12.0.2
Here the config.xml
<globals>
....
<events>
<controller_front_init_routers>
<observers>
<connector_services_observer>
<type>singleton</type>
<class>Connector_Services_Model_Observer</class>
<method>getEvent</method>
</connector_services_observer>
</observers>
</controller_front_init_routers>
</events>
</globals>
Here the function getEvent in my model observer
public function getEvent($observer){
//model which do post or get requests and return xml and menu
$_getRest = Mage::getModel('connector_services/RestRequest');
//the paths
$_menu_url = Mage::getStoreConfig('connector_service_section/connector_service_url/service_menu_url');
//put a store config
$path_nlist = 'veritas-pages-list.xml';
$_isAdmin = Mage::helper('connector_services');
$currentUrl=Mage::helper("core/url")->getCurrentUrl();
//the way I found to trigger methods only in frontend
//that's not very beautiful I know
$admin = preg_match("#/admin/#",$currentUrl);
$api = preg_match("#/api/#",$currentUrl);
//
if ( !$admin && ! $api ){
$_menuXml = $_getRest->postRequest($_menu_url);
if( $_menuXml )
{
$_menu = $_getRest->makeMenu($_menuXml);
Mage::register('menu',$_menu);
}
}
You should be able to pass a querystring to the rest service, similar to how you'd just type it out in the address bar. Magento will forward it on to the observer, and you can use it as a flag.
Add something like the following to your code:
const USE_FRONTEND = 'usefront';
public function getEvent($observer){
this->request = $observer->getEvent()->getData('front')->getRequest();
// If the constant is in the query string
if ($this->request->{self::USE_FRONTEND}) {
// Do code related to this request
die('Frontend flag detected');
}
}
Call to your site like this and pass the querystring
http://www.yourmagentosite.com/?usefront=true
I am not extremely familiar with Magento's new REST api, but I know it works in the browser. Maybe this explanation can help you out.
Related
I would like to know if I can change the theme based on url parameter (or if it's too late) and if it is possible which is the right event to observe
I have only found a guy who was talking about observing controller_action_predispatch but with this event I can't still access to the parameters url (based on this answer https://stackoverflow.com/a/19214765/1139052)
Yes, you could do that a number of different ways. That answer is not saying the URL params are inaccessible in the controller_action_predispatch event, however you might want to do it during an event like controller_action_layout_load_before instead and create custom layout handles from your param value. You can get them in your observer like this:
public function getExampleParam(Varien_Event_Observer $observer)
{
$request = $observer->getControllerAction()->getRequest();
$param = $request->getParam('example');
return $this;
}
I would like to add a static link at the navigation bar that can link directly to a specific product.
As I only have one product listing under category "pillow", I wish to set it to go into the product directly, skipping the catalog view.
I am aware of two methods, being URL rewrite management and static block, however I experience problem with both.
For "URL rewrite", it worked but once I update something at the category (e.g. moving the position), the system generate a new "URL rewrite" and delete the my custom one.
For "static block", I do not know what code to put in it. My guess was to add below code, but it doesn't work.
{{block type="catalog/product_view" product_id="896" template="catalog/category/view.phtml"}}
How do I get it done? Thanks in advance.
I have taken a different approach to the problem which may be helpful. It seems like your end goal is to skip the category view if a category only contains one product. So rather than fussing with hard coding templates or trying to clobber the category with URL rewrite, you can accomplish this using an event observer.
The approach will listen for the <catalog_controller_category_init_after> event to fire and check whether the category only has one product. If so it will send the request directly to the product. You will need to add a new extension or modify an existing one.
etc/config.xml
Create a new node under config/frontend/events:
<catalog_controller_category_init_after>
<observers>
<redirectSingleProduct>
<class>My_MyExtension_Model_Observer</class>
<method>redirectSingleProduct</method>
</redirectSingleProduct>
</observers>
</catalog_controller_category_init_after>
Model/Observer.php
Create the corresponding method to handle the event:
class My_MyExtension_Model_Observer
{
/**
* Check whether a category view only contains one product, if so send the request directly to it.
* #param Varien_Event_Observer $observer
* #return $this
*/
public function redirectSingleProduct(Varien_Event_Observer $observer)
{
$category = $observer->getCategory();
if ($category->getProductCount() == 1) {
$product = $category->getProductCollection()->addUrlRewrite()->getFirstItem();
$url = $product->getProductUrl();
$observer->getControllerAction()->getResponse()->setRedirect($url);
}
return $this;
}
}
I am trying to redirect specific users in Magento to the products.html page after logging in. Most every way I attempt to do this (setRedirect, header) results in a loop due to too many redirects.
Currently, I am trying to use an observer to setParam('return_url', "$customerRedirectUrl") as described in this rather popular post - Magento - Redirect Customer from Observer Method. The variable $customerRedirectUrl represents logic that together reliably creates the url I know I want the page to be. My relevant code looks like this.
public function redirect(Varien_Event_Observer $observer)
{
$helper = Mage::helper('personal_order');
$isPersonalOrderStore = $helper->isPersonalOrderStore(null);
$session = Mage::getSingleton('customer/session');
if ($isPersonalorderStore){
if(!$session->isLoggedIn()) {
$targetUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB).'customer/account/login';
Mage::app()->getResponse()->setRedirect($targetUrl);
} else {
$baseUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
$storeName = strtolower(Mage::app()->getStore()->getName());
$storeName = str_replace(' ', '', $storeName);
$customerRedirectUrl = "$baseUrl$storeName/products.html";
$observer->getRequest()->setParam('return_url',"$customerRedirectUrl");
}
}
The important part for my purposes now is the else statement, the rest of the function works fine. However, the call to setParam results in the following error:
Fatal error: Call to a member function setParam() on a non-object...
What about the Magento - Redirect Customer from Observer Method post am I not getting (there is a good chance I'm just oblivious to something due to being a fairly new user)? The observer is laid out in the relative config file under controller_action_postdispatch and is in an observer model. What is the context for getting setParam to operate correctly?
Thanks to any and all for your help!
I know this post is a bit old but I see have it worked out for a module of my own.
I run the redirect on 2 different events. When the customer registers or when a customer logs in.
<customer_register_success>
<observers>
<redirectAfterRegister>
<class>businessdirectory/profile_observer</class>
<method>redirectAfterRegister</method>
</redirectAfterRegister>
</observers>
</customer_register_success>
<customer_login>
<observers>
<redirectAfterLogin>
<class>businessdirectory/profile_observer</class>
<method>redirectAfterLogin</method>
</redirectAfterLogin>
</observers>
</customer_login>
I edited this answer because after testing I realized that two separate observers are needed for the two events. The good news is that you do not need to override files or rewrite controllers.
For the customer_register_success event, all you need to do is set the success_url param to whatever you want the url to be.
For the customer_login event, you will notice in your controller customer/account/_loginPostRedirect that the redirect URLs are being set on the customer session. As you can see in the second observer method below, all you need to do is grab the customer session and set the URL. For my purposes, I set the BeforeAuthUrl and AfterAuthUrl.
public function redirectAfterRegister($observer)
{
if(Mage::app()->getRequest()->getParam('listing_id') || Mage::app()->getRequest()->getParam('directory_id')){
$_session = Mage::getSingleton('customer/session');
$action = $_session->getDirectoryAction();
if(Mage::app()->getRequest()->getParam('listing_id')){
$listingId = Mage::app()->getRequest()->getParam('listing_id');
Mage::app()->getRequest()->setParam('success_url',Mage::getUrl($action,array('listing_id'=>$listingId)));
}elseif(Mage::app()->getRequest()->getParam('directory_id')){
$directoryId = Mage::app()->getRequest()->getParam('directory_id');
Mage::app()->getRequest()->setParam('success_url',Mage::getUrl($action,array('directory_id'=>$directoryId)));
}
}
}
public function redirectAfterLogin($observer)
{
if(Mage::app()->getRequest()->getParam('listing_id') || Mage::app()->getRequest()->getParam('directory_id')){
$_session = Mage::getSingleton('customer/session');
$action = $_session->getDirectoryAction();
if(Mage::app()->getRequest()->getParam('listing_id')){
$listingId = Mage::app()->getRequest()->getParam('listing_id');
$url = Mage::getUrl($action,array('listing_id'=>$listingId));
$_session->setBeforeAuthUrl($url);
$_session->setAfterAuthUrl($url);
}elseif(Mage::app()->getRequest()->getParam('directory_id')){
$directoryId = Mage::app()->getRequest()->getParam('directory_id');
$url = Mage::getUrl($action,array('directory_id'=>$directoryId));
$_session->setBeforeAuthUrl($url);
$_session->setAfterAuthUrl($url);
}
}
}
When you have a problem instantiating an object with $observer->getRequest(), try using $observer->getEvent()->getFront()->getResponse() instead. I believe this differs depending on what event the observer is listening to.
I have a special case where users have to sign up for an account via the account sign up page (e.g. /customer/account/create/). Upon completion, and in the event that they have a product in the cart, I need to redirect them back to the checkout screen.
I currently have an observer in place that listens to the customer_register_success event. The observer upgrades the users account to a membership group via this code:
class Hatclub_MembershipHandler_Model_Observer {
// members group id
const GROUP_ID = 4;
// called when a customer registers for the site
public function registrationSuccess(Varien_Event_Observer $observer) {
// extract customer data from event
$customer = $observer->getCustomer();
// a cookie should have been set with the membership id
if (isset($_COOKIE['membership_account_id'])) {
$customer
->setGroupId(self::GROUP_ID)
->setRmsId($_COOKIE['membership_account_id']);
}
return $this;
}
}
Is there another event that I can listen to that is better suited for what I want to do? I have a redirect_to cookie that is available as well if that helps.
After much trial and error, I came across a solution. Since I'm already using the customer_register_success event and modifying user data with my observer, I had to use another event called customer_save_after and it worked like a charm.
config.xml event block
<customer_save_after>
<observers>
<customer_session_observer>
<class>hatclub_membership_handler/observer</class>
<method>customerSave</method>
<type>singleton</type>
</customer_session_observer>
</observers>
</customer_save_after>
observer.php method
public function customerSave() {
// set redirect url from cookie, default to null
$redirect_url = (isset($_COOKIE['redirect_url']))
? isset($_COOKIE['redirect_url']) : null;
// if a redirect url was specified
if (isset($redirect_url)) {
// remove cookie to prevent infinite loop
unset($_COOKIE['redirect_url']);
// redirect to provided url
Mage::app()->getResponse()
->setHeader('Location', $redirect_url)
->sendHeaders();
}
}
The redirect within an observer was a bit of a struggle, but I managed to accomplish it using
Mage::app()->getResponse()
->setHeader('Location', $redirect_url)
->sendHeaders();
Suggestions and criticism welcome.
Why are there no events dispatched on or around the newsletter subscription/un-subscription process either in the customer or newsletter modules.
The only alternative i am faced with at the moment is to use a rewrite for the subscriber model to fit some code in around here.
Does anyone else have a good alternative to this - or am I missing something
I encountered a situation where I needed to listen for subscription/unsubscription events. I encountered this question and thought I would leave this solution here for anyone that may need it:
By adding an observer to the event newsletter_subscriber_save_before in your config.xml:
<global>
....
<events>
....
<newsletter_subscriber_save_before>
<observers>
<your_unique_event_name>
<class>yourgroupname/observer</class>
<method>newsletterSubscriberChange</method>
</your_unique_event_name>
</observers>
</newsletter_subscriber_save_before>
</events>
</global>
You can then call getSubscriber() (in the context of $observer->getEvent(), see next code block) in your observer to get the Mage_Newsletter_Model_Subscriber model that allows you get data about the subscriber. This works for occurrences of subscription and unsubscriptions.
public function newsletterSubscriberChange(Varien_Event_Observer $observer) {
$subscriber = $observer->getEvent()->getSubscriber();
//now do whatever you want to do with the $subscriber
//for example
if($subscriber->isSubscribed()) {
//...
}
//or
if($subscriber->getStatus() == Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED) {
//...
} elseif($subscriber->getStatus() == Mage_Newsletter_Model_Subscriber::STATUS_UNSUBSCRIBED) {
//..
}
}
So it turns out this is really easy. These model events are super powerful and let you do things like this super easily. Can't turn down free functionality!
For quick reference, here is what data the Mage_Newsletter_Model_Subscriber model provides (1.7)
Here's what just worked for me on 1.7.0.2. I know this thread is old, but posting it here in case it can help anyone (since there's not a lot of info about this event out there):
*NOTE: Replace myco_myextension with your extension's unique name:*
In config.xml:
<newsletter_subscriber_save_commit_after>
<observers>
<myco_myextension_model_observer>
<class>Myco_Myextension_Model_Observer</class>
<method>subscribedToNewsletter</method>
</myco_myextension_model_observer>
</observers>
</newsletter_subscriber_save_commit_after>
In Observer.php:
public function subscribedToNewsletter(Varien_Event_Observer $observer)
{
$event = $observer->getEvent();
$subscriber = $event->getDataObject();
$data = $subscriber->getData();
$statusChange = $subscriber->getIsStatusChanged();
// Trigger if user is now subscribed and there has been a status change:
if ($data['subscriber_status'] == "1" && $statusChange == true) {
// Insert your code here
}
return $observer;
}
The newsletter/subscriber model is a normal Magento model from the looks of it, so it should still dispatch some events from the upstream classes. Take a look at something like newsletter_subscriber_create_after and newsletter_subscriber_delete_after for some possible event hooks to use.
the newsletter modul hooks to event: customer_save_after