Is there a way to catch the event when the customer verifies it's account? I need this feature to enable user's access to other integrated subsystem
Since confirmAction() doesnt seem to fire any events in
/app/code/core/Mage/Customer/controllers/AccountController.php
You could do either
Overriding Frontend Core Controllers to create you own event using Mage::dispatchEvent() or add code directly to confirmAction in AccountController.php
Use #Pavel Novitsky answer but you may need to check that you are on the confirm account controller or check for the changing of email verification flag, because this event will trigger every time a customer information is change/updated
eg
public function myObserver(Varien_Event_Observer $observer)
{
if(Mage::app()->getRequest()->getControllerName() == '....account_confirm'){
$customer = $observer->getCustomer();
....
}
}
Every model has standard load_before, load_after, save_before, save_after, etc. events. Look at the Mage_Core_Model_Abstract to get the list of all predefined events.
For customers you can use customer_save_after event. In observer check original data vs new data:
public function myObserver(Varien_Event_Observer $observer)
{
$customer = $observer->getCustomer();
$orig_active_flag = $custoner->getOrigData('is_active');
$new_active_flag = $customer->getData('is_active');
// do something here …
return $this;
}
Even you can create your own event after customer vefication using below code.
Mage::dispatchEvent('Yuor_Unique_Event_Name', array());
Now using this event you can do anything you want.
Related
So I've run into this issue a few times and now I've decided that I want to find a better solution.
For examples sake, I have two models, Order & Product. There is a many to many relation so that an order can have multiple products and a product can of course have multiple orders. Table structure looks like the below -
orders
id
more fields...
products
id
more fields...
product_orders
order_id
product_id
So when an order is created I run the following -
$order = Order::create($request->validated())
$order->products()->attach([1,2,3,4...]);
So this creates an order and attaches the relevant products to it.
However, I want to use an observer, to determine when the order is created and send out and perform related tasks off the back (send an order confirmation email, etc.) The problem being, at the time the order created observer is triggered, the products aren't yet attached.
Is there any way to do the above, establishing all the many to many relationships and creating the order at the same time so I can access linked products within the Order created observer?
Use case 1
AJAX call hits PUT /api/order which in turn calls Order::place() method. Once an order is created, an email is sent to the customer who placed the order. Now I could just put an event dispatch within this method that in turn triggers the email send but this just feels a bit hacky.
public static function place (SubmitOrderRequest $request)
{
$order = Order::create($request->validated());
$order->products()->attach($request->input('products'));
return $order;
}
Use case 2
I'm feature testing to make sure that an email is sent when an order is created. Now, this test passes (and email sends work), but it's unable to output the linked products at this point in execution.
/**
* #test
**/
public function an_email_is_sent_on_order_creation()
{
Mail::fake();
factory(Order::class)->create();
Mail::assertSent(OrderCreatedMailable::class);
}
Thanks,
Chris.
I think the solution to your problem could be transaction events as provided by this package from fntneves.
Personally, I stumbled upon the idea of transactional events for another reason. I had the issue that my business logic required the execution of some queued jobs after a specific entity had been created. Because my entities got created in batches within a transaction, it was possible that an event was fired (and the corresponding event listener was queued), although the transaction was rolled back because of an error shortly after. The result were queued listeners that always failed.
Your scenario seems comparable to me as you don't want to execute your event listeners immediately due to missing data which is only attached after the model was actually created. For this reason, I suggest wrapping your order creation and all other tasks that manipulate the order within a transaction. Combined with the usage of said package, you can then fire the model created event as the actual event listener will only be called after the transaction has been committed. The code for all this basically comes down to what you already described:
DB::transaction(function() {
$order = Order::create($request->validated());
$order->products()->attach($request->input('products'));
});
In your model, you'd simply define an OrderCreated event or use an observer as suggested in the other answer:
class Order
{
protected $dispatchesEvents = [
'created' => OrderCreated::class,
];
}
class OrderCreated implements TransactionalEvent
{
public $order;
/**
* Create a new event instance.
*
* #param \App\Order $order
* #return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
}
You can redefine boot method in your model, if product ids is static
class Order extends Eloquent {
protected static function boot() {
parent::boot();
static::saving(function ($user) {
$this->products()->attach([1,2,3,4...]);
});
}
}
Or use observers
class OrderObserver
{
public function created($model)
{
//
}
}
And register this
class EventServiceProvider extends ServiceProvider
{
public function boot(DispatcherContract $events)
{
parent::boot($events);
Order::observe(new OrderObserver());
}
}
I've created an observer for customer_registration_success, but I need to listen to the event that is triggered on one page checkout, when a user chooses to register. http://cl.ly/image/2F3L0s1E3g1e
Any thoughts on what event this might be?
You could create your own 'custom event' using the logic below to check which method they use to check out on success.phtml or incorporate it in sales_order_place_after
$quoteId = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId())->getQuoteId();
$quote = Mage::getModel('sales/quote')->load($quoteId);
$method = $quote->getCheckoutMethod(true);
if ($method == 'register'){
//the customer registered...do your stuff
}
Source : http://www.magentocommerce.com/boards/viewthread/273690/#t375160
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 made the authorization and authentication via facebook like here:
http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html
and it works
Now I want to make my own event, this event will do something when the user authenticates using facebook. For example-will redirect the user to the home page.
I did it like this
http://symfony.com/doc/current/components/event_dispatcher/introduction.html
So I have this class
http://pastebin.com/2FTndtL4
I do not know how to implement it, what am I supposed to pass as an argument to the constructor
It's really simple. Symfony 2 event system is powerful, and service tags will do the job.
Inject the dispatcher into the class where you want to fire the event. The service id is event_dispatcher;
Fire the event with $this->dispatcher->dispatch('facebook.post_auth', new FilterFacebookEvent($args)) when needed;
Make a service that implements EventSubscriberInterface, defining a static getSubscribedEvents() method. Of course you want to listen to facebook.post_auth event.
So your static method will look like:
static public function getSubscribedEvents()
{
return array(
'facebook.post_auth' => 'onPostAuthentication'
);
}
public function onPostAuthentication(FilterFacebookEvent $event)
{
// Do something, get the event args, etc
}
Finally register this service as a subscriber for the dispatcher: give it a tag (eg. facebook.event_subscriber), then make a RegisterFacebookEventsSubscribersPass (see this tutorial). You compiler pass should retrieve all tagged services and inside the loop should call:
$dispatcher = $container->getDefinition('event_dispatcher');
$subscribers = $container->findTaggedServiceIds('facebook.event_subscriber');
foreach($subscribers as $id => $attributes) {
$definition->addMethodCall('addSubscriber', array(new Reference($id)));
}
This way you can quick make a subscriber (for logging, for example) simply tagging your service.
Event object is just some kind of state/data storage. It keeps data that can be useful for dispatching some kind of events via Subscribers and/or Listeners. So, for example, if you wanna pass facebook id to your Listener(s) - Event is the right way of storing it. Also event is the return value of dispatcher. If you want to return some data from your Listener/Subscriber - you can also store it in Event object.
When I look at the event checkout_onepage_controller_success_action and works, but I can not get the Id of the newly created order.
Anyone have any idea??
Use magento-1.4.1.0
Thanks
The event is dispatched like this:
Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($lastOrderId)));
So to get the last orderId, simply make your observer method like this:
public function orderSuccessEvent($observer)
{
$observer->getData('order_ids'));
}
This is an answer provided by Branko Ajzele and I've just successfully tested:
$order = new Mage_Sales_Model_Order();
$incrementId = Mage::getSingleton('checkout/session')->getLastRealOrderId();
$order->loadByIncrementId($incrementId);
Thanks to him and hope it'll work.
That event probably gets called before the action itself executes. Can you use sales_order_save_after instead?
EDIT: Here's your ID code. In your observer:
public function setLinkStatus($observer) {
$order = $observer->getEvent()->getOrder();
$id = $order->getId();
// do something useful
}
The Onepage Checkout controller in the Magento version 1.4.1 is not updated to have functions that can obtain the Order ID and thus you cant have the order object and data from the event observer. To have this working in Magento 1.4.1 simply update your OnepageController with the necessary functions.
The best approach would be to create your own module and override the core controller.
Add this in the config xml of your module so that your controller is called before the core OnepageController.
<frontend><routers><checkout><use>standard</use><args><modules><MyCompany_MyModule before="Mage_Checkout">MyCompany_MyModule</MyCompany_MyModule></modules></args></checkout></routers></frontend>
Hope this helps