I'm developing a Magento extension that deals with analytics. One of the things it needs to do is pass events (such as checkout_cart_add_product_complete and catalog_controller_product_view) from the backend PHP observer class to the frontend javascript.
I have the events working in myextension's config.xml:
<events>
...
<catalog_controller_product_view>
<observers>
<myextension>
<type>model</type>
<class>myextension/observer</class>
<method>productViewContent</method>
</myextension>
</observers>
</catalog_controller_product_view>
<checkout_cart_add_product_complete>
<observers>
<myextension>
<type>model</type>
<class>myextension/observer</class>
<method>productAddToCart</method>
</myextension>
</observers>
</checkout_cart_add_product_complete>
...
</events>
I have the Observer.php model implemented to write to the log currently:
public function productViewContent($observer) {
$product = $observer->getProduct();
Mage::log('('.$product->getId() .') '. $product->getName().' has been viewed.', null, 'product.log');
}
public function productAddToCart($observer) {
$product = $observer->getProduct();
Mage::log('('.$product->getId() .') '. $product->getName().' has been added to cart.', null, 'product.log');
}
and I'm seeing the correct product details in the product.log.
Now where I am stuck is in this class:
class Mynamespace_Myextension_Block_Html_Head extends Mage_Page_Block_Html_Head {
// some session code here
$this->addJs('myextension/file.js');
}
I've successfully detected that myextension/file.js is loading, but I need to be able to pass dynamic event info to the JS file. I was hoping to be able to do something like:
class Mynamespace_Myextension_Block_Html_Head extends Mage_Page_Block_Html_Head {
// some session code here
$this->addRawHTML('<script>var myevent='addtocart';var myproduct=$product_id</script>');
$this->addJs('myextension/file.js');
}
...so that myevent and myproduct are available to the code that runs in file.js. Obviously there is no such method addRawHTML.
Hopefully that makes sense. I tried
echo "<script>alert('add_to_cart');</script>";
in the my extension's Head.php block and I get the alert as expected, but it of course is printed before the first line of the html which is not the correct way to do it.
Also, I am currently using the session to write details about the event from the Observer so that the _prepareLayout method in Mynamespace_Myextension_Block_Html_Head can read them and forward them on to the JS in the layout. Is there a better way?
In a nutshell, I'm not able to modify layout.xml/theme.xml because this is an extension, and I'm not able to use addJs alone because I need the JS file to be dynamically generated or detect JS variables written dynamically into the page.
Is it considered bad practice to call add JS with a PHP file?
$this->addJs('myextension/file.php?myevent=add_to_cart&product_id='.$product_id);
and render the JS file dynamically using PHP? That might work but it seems like a hack.
Thanks for your advice.
UPDATE: I have managed to get something working, but in a "non-magento-way". I followed something like this answer, basically generating Javascript on the fly from the observer directly:
public function generateLayout($observer)
{
// I do this if there's an event in a custom session variable
$layout = $observer->getEvent()->getLayout();
$headBlock = $layout->getBlock('head');
$block = $layout->getBlock('head');
$block->setText("
<script>
var myevent = '$event';
var myproduct = '$product';
</script>
");
$headBlock->append($block);
}
I would still like to approach it properly using Magento best practice.
As you might know, Magento uses a javascript variable var spConfig (in view pages) for storing product data to be used in javascript for changing prices and other thigs.
Can't you use such a js variables that store product/cart info and use them in js file that you are including (that is file.js)
Related
I need popup with custom content after customer successfully login.
In content I need to set customer name, customer group and some other text.
Use the event customer_login
<customer_login>
<observers>
<yourobservername>
<type>model</type>
<class>yourmodule/path_to_class</class>
<method>customerLogin</method>
</yourobservername>
</observers>
</customer_login>
Your observer class would look like this and you can call here your popup .phtml file
class YourCompany_YourModule_Model_Observer
{
public function customerLogin($observer)
{
$customer = $observer->getCustomer();
}
}
You will need to work on events and observers in magento.
First you will need to observe customer_login event and set some custom value in session.
Next you will need to observe event like controller_action_layout_load_before or controller_front_init_before. In this observer function you will need to check value of session which you had set in previous step. If value is found then use code like:
$layout = $observer->getEvent()->getLayout();
$layout->addHandle('some_handle')->removeHandle('some_other_handle');
and after setting layout handle, you will need to unset session value which you had set in first step.
Please try to implement it and let me know if you find any problem.
I need to access it in an observer just before collectTotals() is run. I'm using the sales_quote_collect_totals_before observer and it seems to be doing everything else I need it to do. I want to be able to access this attribute when the event is triggered
You can use this sales_quote_address_collect_totals_before event in your module. like this:
<events>
<sales_quote_address_collect_totals_before>
<observers>
<namespace_your_modulename_custom_event>
<class>your_observer_class</class>
<method>yourObserverMethod</method>
</namespace_your_modulename_custom_event>
</observers>
</sales_quote_address_collect_totals_before>
</events>
In your observer model the method should look like this:
public function yourObserverMethod(Varien_Event_Observer $observer)
{
// code goes to here
}
I want to update customer cart on login.I have created an observer in folder
local/goodahead/customer/etc/cofig.xml
<customer_login>
<observers>
<updatelogincart_observer>
<type>singleton</type>
<class>goodahead_customer/observer</class>
<method>customerLogin</method>
</updatelogincart_observer>
</observers>
</customer_login>
and in Observer at path local/goodahead/customer/Model/Observer.php ,i have created the function customerLogin
class Goodahead_Customer_Model_Observer
{
public function customerLogin($observer)
{
$customer = $observer->getCustomer();
mail('muemailaddress#gmail.com','hello','test');
}
}
But i am not getting any mail.
How can i do this?
First of all, why are you using an email to test if your observer works? That seems so incredibly error-prone, it's almost insane. If you don't have a debugger or something, at least use something simple like die('IT WORKS!'); to see if your Observer is called, it's really impossible to miss.
Secondly, did you properly configure your model in the config.xml?
I want to make my site private only to registered users. If any one try to access my homepage. the login screen should come first. People should register or login to enter into my site.
How to do this? Any Suggestion from magento experts?
If you do programming then simple logic would be checking if user is logged in or not else redirect them to the login page using event: controller_action_predispatch.
1> In your config.xml add the following xml code:
...
<frontend>
<events>
<controller_action_predispatch>
<observers>
<yourmodule_controller_action_predispatch>
<class>yourmodule/observer</class>
<method>checkForLogin</method>
</yourmodule_controller_action_predispatch>
</observers>
</controller_action_predispatch>
</events>
</frontend>
...
2> Create a Observer.php in your Module's Model/ directory.
Here is the basic code that you need to use in your Observer class:
<?php
class YourCompany_Yourmodule_Model_Observer extends Varien_Object{
public function checkForLogin(Varien_Event_Observer $observer){
if(!Mage::getSingleton('customer/session')->isLoggedIn() && $observer->getControllerAction()->getFullActionName() != 'customer_account_login') {
Mage::app()->getResponse()->setRedirect(Mage::getUrl('customer/account/login'))->sendResponse();
exit;
}
}
}
If you are interested with more robust solution with much more features ready to use for your B2B store then here is an awesome Magento Extension called 'Store Restriction Pro':
http://www.magepsycho.com/store-restriction-pro.html
Good Luck
Update (13-11-27), JSOV
In order to allow the forgot password, login access and default funcionality, you can add an array of the default pages you want to give permissions, and then validate and redirect.
ex:
...
$allow = array('customer_account_login','customer_account_forgotpassword','customer_account_resetpassword','customer_account_loginpost','customer_account_forgotpasswordpost','customer_account_resetpasswordpost');
if(!Mage::getSingleton('customer/session')->isLoggedIn() && !in_array(strtolower($observer->getControllerAction()->getFullActionName()),$allow) ) {
...
I'm working on an extension that will receive product information from Magento when saved and do custom processing on the product.
I've spent 2 days until now trying to figure out why Magento is not triggering the event "catalog_product_status_update".
Simply, I change product status by going to Catalog->Manage Products, then select one or more products and use the "Actions" field above the products grid to change product(s) status to "disabled".
When I do that, the product(s) status changes just fine, but the problem is that I don't receive the event for it.
Here's the code I use:
<?xml version="1.0"?>
<config>
<global>
<models>
<mage4ucustomredirect>
<class>Mage4u_Customredirect</class>
</mage4ucustomredirect>
</models>
<events>
<catalog_product_save_after>
<observers>
<abc>
<type>singleton</type>
<class>Mage4u_Customredirect_Model_Observer</class>
<method>on_catalog_product_save_after</method>
</abc>
</observers>
</catalog_product_save_after>
<catalog_product_status_update>
<observers>
<abc>
<type>singleton</type>
<class>Mage4u_Customredirect_Model_Observer</class>
<method>on_catalog_product_status_update</method>
</abc>
</observers>
</catalog_product_status_update>
</events>
</global>
</config>
And this is the observer:
class Mage4u_Customredirect_Model_Observer
{
public function on_catalog_product_status_update(Varien_Event_Observer $observer)
{
Mage::log( "on_catalog_product_status_update" );
}
public function on_catalog_product_save_after(Varien_Event_Observer $observer)
{
Mage::log( "on_catalog_product_save_after" );
}
}
?>
Strange enough, when I try to save a product manually, I receive the event "on_catalog_product_save_after" which tells me that my code is working fine, but it doesn't work for this "on_catalog_product_status_update" event.
Any help is appreciated!
NOTE: I'm using Magento v1.6.2.0
I believe your problem is that the update status option at the top of the grid doesn't use any models to achieve the task, it access the database directly. If you look at the updateAttributes method in Mage_Catalog_Model_Product_Action and Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Action respectively, you will see that no product or product_status model is loaded.
Unfortunately for you, at a quick glance I don't see any events that you can hook into to capture this. It might require rewriting of the model.
Your two observers have the same name "abc". This should be unique inside Magento observers list.
Try changing one of them to "abc1", refresh your cache and it should work.
This question was asked somewhere in 2012, but in more recent Magento versions, the mass action update for the product grid is processed by the catalog/product_action model its updateAttributes method:
Mage_Catalog_Model_Product_Action::updateAttributes()
An event is dispatched there:
Mage::dispatchEvent('catalog_product_attribute_update_before', array(
'attributes_data' => &$attrData,
'product_ids' => &$productIds,
'store_id' => &$storeId
));
attributes_data is a key-value list with data to be stored for product_ids in the store_id scope. In your observer for catalog_product_attribute_update_before you can check if the status attribute is being updated:
$event = $observer->getEvent();
$attributesData = $event->getData('attributes_data');
if (! isset($attributesData['status'])) {
// we are not updating the status
return;
}
// do something, for example - if the product will be disabled
if ($attributesData['status'] != Mage_Catalog_Model_Product_Status::STATUS_ENABLED) {
// api call
}
Hope this helps for anyone who tries to intercept a mass status update.