Event only runs once. I am adding custom value in quote after product add in cart through observer on event checkout_quote_init
it works fine but if customer is logged in and place order then in first order value is inserted well in quote but in second time observer is not runing.
<checkout_quote_init>
<observers>
<youva_custom>
<type>singleton</type>
<class>custom/observer</class>
<method>setqoutevalue</method>
</youva_custom>
</observers>
</checkout_quote_init>
public function setqoutevalue($observer) {
$event = $observer->getEvent();
$_quote = $event->getQuote();
$_quote->setCustomevalue($customevalue);
$_quote->save();
}
If you take a look at the code that dispatches the event you are using you will see this (Mage_Checkout_Model_Session::getQuote()):
if (!$this->getQuoteId()) {
if ($customerSession->isLoggedIn() || $this->_customer) {
$customer = ($this->_customer) ? $this->_customer : $customerSession->getCustomer();
$quote->loadByCustomer($customer);
$this->setQuoteId($quote->getId());
} else {
$quote->setIsCheckoutCart(true);
Mage::dispatchEvent('checkout_quote_init', array('quote'=>$quote));
}
}
This means that the event is dispatched only when the quote is created. and only when the user is not logged in. This means that if there is already a quote id in the session the event won't get dispatched.
You may want to use a different event. For example checkout_cart_product_add_after
Related
I'm reposting this from magento.stackexchange because of practically no views/answers there.
We have an observer that modifies final price, that's triggered on the event catalog_product_get_final_price. Problem is, when you retrieve products via collection with addAttributeToSelect("*"), they come back with a final_price already set, and the product getFinalPrice function merely returns what's in the database instead of recalculating (and running the observers for) the final price.
Mage_Catalog_Model_Product
public function getFinalPrice($qty=null)
{
// *** Collection items already have a 'final_price' from flat tables
// but it's wrong because observers haven't run yet ***
$price = $this->_getData('final_price');
if ($price !== null) {
return $price;
}
return $this->getPriceModel()->getFinalPrice($qty, $this);
}
I've also noticed that all of our custom attributes are also not being interpreted (we save things as JSON but decode into objects them on product load before using them).
This behavior doesn't happen when you load the product directly -- all the observers and models are interpreted when the product is loaded.
Is there a way to ensure the data we're retrieving from a collection matches in format and value the data we would retrieve if we load the product directly?
I know I can just load the product individually to trigger all of the events that go along with it, but in the case of 3rd party software, that might not always be the case and the final price is wrong.
We're on version 1.7 if it helps.
Set up an event
<catalog_product_collection_load_after>
<observers>
<modulename>
<type>singleton</type>
<class>Seamus_Module_Model_Observer</class>
<method>changePrice</method>
</modulename>
</observers>
</catalog_product_collection_load_after>
On your observer do something like...
public function changePrice($observer)
{
$event = $observer->getEvent();
$products = $observer->getCollection();
foreach( $products as $product )
{
$product->setFinalPrice( $this->getPriceLogic($product) );
}
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.
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.
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