I'm working on an existing magento page. A logged in user can change his profile informamation (firstname, lastname, email, etc.) and they can change their billing and shipping addresses.
What I need to do is send notification emails whenever a customer changes their basic information or one of their addresses. I created an observer for two events:
<frontend>
<events>
<customer_save_after>
<observers>
<ext_customer_save_after>
<type>singleton</type>
<class>ext/observer</class>
<method>customerSaveAfter</method>
</ext_customer_save_after>
</observers>
</customer_save_after>
<customer_address_save_after>
<observers>
<ext_customer_save_after>
<type>singleton</type>
<class>ext/observer</class>
<method>customerAddressSaveAfter</method>
</ext_customer_save_after>
</observers>
</customer_address_save_after>
</events>
</frontend>
And in customerSaveAfter I send an email and in customerAddressSaveAfter I check if the current ID is the same as the defaultbillingaddress or the defaultshipping address and send the notification accordingly. This is working fine, until the user checks the "Set as Default Shipping Address" checkbox. In this case, I suddenly receive 5 emails:
Billing Address changed
Shipping Address changed
Shipping Address changed
Billing address changed
customer info changed
So, suddenly the events are fired multiple times and the customer_address_save_after somehow triggers the customer_save_after event. Is there a way to prevent this or to check which event triggered another event or something like this? Or are there other ways to handle this problem?
I'd be really thankful for any hints, thank you very much.
I couldn't really solve the problem, with mage_registry I alawys got an error so I decided to go for a totally different approach.
In my extension I removed the observers and instead created 2 new Controllers, AccountController and AddressController, to overwrite Magentos Standard Controllers for handling customer and address saving.
In my config.xml I added this:
<frontend>
<routers>
<customer>
<args>
<modules>
<my_ext before="Mage_Customer_AccountController">My_Ext</my_ext>
<my_ext before="Mage_Customer_AddressController">My_Ext</my_ext>
</modules>
</args>
</customer>
</routers>
</frontend>
And, for example, my AccountController looks like this:
<?php
require_once Mage::getModuleDir('controllers','Mage_Customer').DS."AccountController.php";
class My_Ext_AccountController extends Mage_Customer_AccountController{
public function editPostAction(){
//I copied the code from the Magento AccountController here and at the proper line I added my own code
}
}
And the same for my AddressController. This worked really nicely.
Thanks for your help, everyone.
I have created a custom Module,In which i am Selling Recurring Product, if Customer buy and Recurring product then after placing Order Successfully,i am making some changes in Custom database table now i want if customer suspend that recurring profile from his/her id then my custom module database table must be updated according to that. is there any event observer that i can but on suspend button ?
You can use whatever event name you want in Magento. Don't know what do you mean by "suspending recurring profile" but when this happens you can fire/dispatch your custom event, for example:
Mage::dispatchEvent('stop_recurring_orders_save_after', array(
'some_id' => &$someId,
'other_fields' => &$otherFields,
));
You can find how to handle events in Magento here on SO.
Shortly in config.xml you need something like:
<config>
<global>
<events>
<stop_recurring_orders_save_after>
<observers>
<mycustomextension>
<type>singleton</type>
<class>mycustomextension/observer</class>
<method>stopRecurringOrders</method>
</mycustomextension>
</observers>
</stop_recurring_orders_save_after>
</events>
</global>
</config>
And an observer class with the appropriate method (e.g. stopRecurringOrders):
class Mycustomextension_Model_Observer {
public function stopRecurringOrders($event) {
$id = $event->getSomeId();
// update your custom table etc.
}
}
All the Events in Magento are available at
http://www.magentocommerce.com/wiki/5_-_modules_and_development/reference/magento_events
You can check them and select which suits your requirement....
First... I'm new to this so bear with me.
I'm trying to make a module which adds custom field to newsletter using observers.
I made a column in "newsletter_subscribers" table (mysql4-install-0.1.0.php)
$installer = $this;
$installer->startSetup();
$installer->run("
ALTER TABLE {$this->getTable('newsletter_subscriber')}
ADD (user_name VARCHAR(50) NOT NULL);
");
$installer->endSetup();
Then i modified config.xml for observer
<events>
<newsletter_subscriber_save_before>
<observers>
<My_Newsletter>
<type>model</type>
<class>Newsletter_Observer</class>
<method>newsletterSubscriberSaveBefore</method>
</My_Newsletter>
</observers>
</newsletter_subscriber_save_before>
</events>
Then made an observer.php
class My_Newsletter_Model_Observer
{
public function newsletterSubscriberSaveBefore(Varien_Event_Observer $observer)
{
$subscriber = $observer->getEvent()->getSubscriber();
$name = Mage::app()->getRequest()->getParam('subscriber_name');
$subscriber->setSubscriberName($name);
return $this;
}
}
So my questions is.
What did i miss?
It doesn't work. I know I'm missing something important.
You specify
ADD (user_name VARCHAR(50) NOT NULL);
That means your code should be:
$subscriber->setUserName($name);
well easiest solution to explain would be to put a
die("TEST");
at the beginning of the method itself.
If it dies with output TEST the observer is listening to the dispatched event.
Clear the cache, because Magento doesnt know due to ddl caching, even if caching is off in admin menu.
Have you taken a look at 'newsletter_subscriber' table? Did the sql script do its job?
According to #SeanBreeden you need to call your magic setter-method via setUserName($name);
Is your observer in the right section if saved from frontend (<global> or <frontend>)?
Thanks guys. It was my fault atfer all. I put "Newsletter_Observer" class in config.xml, but my Observer.php was in Newsletter/Model/ folder.
I would like to be able to run some functionality with a module that I am building whenever a customer registers an account, but I can't seem to find any event that is fired upon a new customer registration.
Does anybody know of an event that is dispatched for that?
Whenever I'm looking for an event, I'll temporarily edit the Mage.php file to output all the events for a particular request.
File: app/Mage.php
public static function dispatchEvent($name, array $data = array())
{
Mage::log('Event: ' . $name); //not using Mage::log, as
//file_put_contents('/tmp/test.log','Dispatching '. $name. "\n",FILE_APPEND); //poor man's log
Varien_Profiler::start('DISPATCH EVENT:'.$name);
$result = self::app()->dispatchEvent($name, $data);
#$result = self::registry('events')->dispatch($name, $data);
Varien_Profiler::stop('DISPATCH EVENT:'.$name);
return $result;
}
and then perform whatever action it is I'm trying to hook into. Magento events are logically named, so scanning/sorting through the resulting logs usually reveals what I'm after.
customer_register_success is what you are looking for:
<config>
<frontend>
<events>
<customer_register_success>
<observers>
<your_module>
<type>singleton</type>
<class>your_module/observer</class>
<method>yourMethod</method>
</your_module>
</observers>
</customer_register_success>
</events>
</frontend>
</config>
I discovered how to achieve this today. It involves using one of the generic controller events. This node in the config.xml will hook into the right event:
<events>
....
<controller_action_postdispatch_customer_account_createPost>
<observers>
<your_module_here>...etc
The controller_action_postdispatch_REQUESTPATH event is thrown for every controller that extends Mage_Core_Controller_Front_Action (which is basically all of them) which makes it very easy to target. Ditto for controller_action_predispatch_REQUESTPATH.
I'm a bit surprised that none of the answers if solving the case completely.
Customer create can happen
by url customer/account/create
by register in checkout
I solved it by tracking two events:
config.xml
<events>
<controller_action_postdispatch_customer_account_createpost>
<observers>
<myextensionkey_create_account>
<class>myextensionkey/observer</class>
<method>createAccount</method>
<type>singleton</type>
</myextensionkey_create_account>
</observers>
</controller_action_postdispatch_customer_account_createpost>
<checkout_submit_all_after>
<observers>
<myextensionkey_checkout_create_account>
<class>myextensionkey/observer</class>
<method>createAccountCheckout</method>
<type>singleton</type>
</myextensionkey_checkout_create_account>
</observers>
</checkout_submit_all_after>
</events>
and in Observer.php
public function createAccount($observer) { ... } //Nothing special here
public function createAccountCheckout($observer) {
if ($observer->getQuote()->getData('checkout_method') != Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER) {
return;
}
Edit: I changed
<controller_action_predispatch_customer_account_createpost>
into
<controller_action_postdispatch_customer_account_createpost>
because on predispatch the account is not created yet. There can be an error for example if the email already exists in the shop.
There isn't a direct event for this, but you could use the customer_save_commit_after event. This event also guarantees you that the customer is save in the shop's database. The problem with this event is that is triggered twice. Bellow is an hack that allows you to use this event - the observer function is listed:
public function customer_save_commit_after($p_oObserver) {
$l_oCustomer = $p_oObserver->getCustomer();
if ($l_oCustomer->isObjectNew() && !$l_oCustomer->getMyCustomKeyForIsAlreadyProcessed()) {
$l_oCustomer->setMyCustomKeyForIsAlreadyProcessed(true);
// new customer
}
else {
// existing customer
}
return false;
}
Hope this helps someone!
You have to consider also when the user register on-the-fly on checkout: a Register on chekout. Thinking on this case, you can catch the "checkout_type_onepage_save_order_after" event with your own Observer class, and then this code...
if($observer->getEvent()->getQuote()->getCheckoutMethod(true) == Mage_Sales_Model_Quote::CHECKOUT_METHOD_REGISTER){
(...)
}
Anybody may say: Mage_Sales_Model_Quote->getCheckoutMethod() is deprecated since 1.4!!,but:
If we call the ortodox method Mage_Checkout_Model_Type_Onepage->getCheckoutMethod(), waiting for something as "METHOD_REGISTER" this is executed:
if ($this->getCustomerSession()->isLoggedIn()) {
return self::METHOD_CUSTOMER;
}
... "METHOD_CUSTOMER" is the name for a checkout with an already registrated user, not our case.... but yes!, because....
...the registration operation is perfomed before "checkout_type_onepage_save_order_after" event. Then we a have a METHOD_CUSTOMER now. Ups, something inconsistent?
Fortunatly, the Quote remains with the original value: CHECKOUT_METHOD_REGISTER
Any other idea for the registration on checkout?
You can try customer_save_after, the only thing that the registration sends this event twice
Actually there are customer_save_after and customer_save_before (magento 1.5)
If you want to modify on-the-fly some data after form post, pick customer_save_before, change the data you want and that's all (the save action come after, so your change will be taken into account).
$customer->save() just doesn't work in customer_save_after. (fatal error) Use this observer to run a code after customer creation which are NOT related to customer data.
Hope that helps!
customer_register_success
adminhtml_customer_save_after
these two are the default events when a customer is inserted into the database....
first event fires in frontend when a user registers and second event fires in the backend when a customer is created through admin panel...i hope you know how to register an observer for an event...hope this will help you...
I was looking of the same thing. I believe the event is customer_register_success.
You can find a link for all events at:
http://www.nicksays.co.uk/magento_events_cheat_sheet/
I found the event checkout_submit_all_after.
<checkout_submit_all_after>
<observers>
<my_example>
<class>my_example/observer</class>
<method>customerRegistered</method>
</my_example>
</observers>
</checkout_submit_all_after>
In my Observer.php I get the quote object that is passed in.
public function customerRegistered (Varien_Event_Observer $observer) {
$quote = $observer->getQuote();
$checkout_method = $quote->getData();
$checkout_method = $checkout_method['checkout_method'];
if ($checkout_method == Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER) {
}
Do not use $quote->getCheckoutMethod() it gives you login_in instead. Not sure why. Hope this helps.
I've discovered that the customer_login and customer_session_init events are both thrown on account create. You could register a listener for either and then check to see the create date on the account?
The answer to this question is that there isn't an event for that.
You can use the customer_register_success event. It is triggered after the customer is succesfully created. Here is the link of event cheat sheets. Hope it also helps you.
http://www.nicksays.co.uk/magento-events-cheat-sheet-1-7/
customer_register_success is the event dispatched after successful customer registration.
Here's from the code from Mage/Customer/controllers/AccountController.php::454 in magento 1.8:
protected function _dispatchRegisterSuccess($customer)
{
Mage::dispatchEvent('customer_register_success',
array('account_controller' => $this, 'customer' => $customer)
);
}
customer_save_after is the event which gets called after a new customer registration.
Read about all the events here:
http://www.magentocommerce.com/wiki/5_-_modules_and_development/reference/events
event nameļ¼customer_registration_is_allowed
I'm not sure if this is you want,you can write a observer to test
Greetings, in Magento I want to trigger an event, once an order has been set to processing (by gateway confirmation or manually) that, example: If a general customer (id 1) spends over 100$ and the payment has been confirmed, set his group id to 4 (silver VIP, which by promotion rule gets 2% discount globally)
I would give a bounty to this, but I'd like the answer before 2 days O_o
EDIT: the answer I received so far is only a partial answer, also I find the links very confusing, I'm not clear on what is the minimal setup, what do i have to configure create etc... Also I'm trying to find out how to get the paying customers id/model.
You should start by creating your own module in app/code/local.
Create for example the directories Moak/Vip. It will be the root of your module.
In order for Magento to know it exists, create a file named Moak_Vip.xml in etc/modules, with the following content :
<?xml version="1.0"?>
<config>
<modules>
<Moak_Vip>
<active>true</active>
<codePool>local</codePool>
<self_name>Moak VIP module</self_name>
</Moak_Vip >
</modules>
</config>
Then, in your module directory, you need the following structure and files :
etc/config.xml
Model/Observer.php
The config.xml defines your module and declares your event listener for a given event (checkout_onepage_controller_success_action is sent when onepage checkout process is complete, sales_order_payment_pay is sent when the payment has been confirmed).
You don't need any DB setup since you will not save any new entity.
So your config file should look something like the following :
<?xml version="1.0"?>
<config>
<modules>
<Moak_Vip>
<version>0.1.0</version>
</Moak_Vip>
</modules>
<global>
<models>
<moak>
<class>Moak_Vip_Model</class>
</moak>
</models>
<events>
<sales_order_payment_pay>
<observers>
<moak_observer>
<type>singleton</type>
<class>moak/observer</class>
<method>checkVipCustomer</method>
</moak_observer>
</observers>
</sales_order_payment_pay >
</events>
</global>
</config>
Now, your Observer method checkVipCustomer should receive an event object from which you can retrieve all information about the order, the customer... and perform the modifications you like.
Have a look at Magento model classes in app/code/core/Mage/.../Model/...
to see how to navigate through those objects.
Example :
<?php
class Moak_Vip_Model_Observer
{
public function checkVipCustomer($event)
{
$order = $event->getInvoice()->getOrder(); // Mage_Sales_Model_Order
/*
- Check order amount
- Get customer object
- Set Group id
- $customer->save();
*/
return $this;
}
}
Note I've not tested any of the code I wrote here, so handle with care !
Hope it helped, Magento has a hard learning curve...
Good luck !
You can create an observer for the "sales_order_payment_pay" event. Here is a cheatsheet of the events in magento 1.3.
And an explanation of how to create observer methods. Links courtesy of the excellent activecodeline and inchoo sites.