I'm trying to write an observer that will export order data when an order is placed. I haven't written any modules before. Basing my implementation on this article: http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/customizing_magento_using_event-observer_method
so far I'm just trying to trigger some dummy code to write to a file. I'm not getting anything showing in my log, and the file's not being modified. The apache user has permission for the directory. I've disabled configuration caching in the Magento settings. I'm a little confused on some of the naming conventions; I just tried to follow the example. Anyone know where I'm going wrong?
in magento/app/etc/modules/Feed.xml:
<?xml version="1.0"?>
<config>
<modules>
<Feed_Sales>
<codePool>local</codePool>
<active>true</active>
</Feed_Sales>
</modules>
</config>
in magento/app/code/local/Feed/Sales/etc/config.xml:
<?xml version="1.0"?>
<config>
<global>
<models>
<feedsales>
<class>Feed_Sales_Model</class>
</feedsales>
</models>
<events>
<sales_order_place_after>
<observers>
<feed_sales_order_observer>
<type>singleton</type>
<class>sales/order_observer</class><!-- I've also tried Feed_Sales_Model_Order_Observer here -->
<method>export_new_order</method>
</feed_sales_order_observer>
</observers>
</sales_order_place_after>
</events>
</global>
</config>
in magento/app/code/local/Feed/Sales/Model/Order/Observer.php:
<?php
class Feed_Sales_Model_Order_Observer
{
public function __contruct()
{
}
/**
* Exports new orders to an xml file
* #param Varien_Event_Observer $observer
* #return Feed_Sales_Model_Order_Observer
*/
public function export_new_order($observer)
{
Mage::log("reached export_new_order");
try
{
$dumpFile = fopen('/home/jorelli/new_orders/testdump', 'w+');
fwrite($dumpFile, 'this is a test!');
}
catch (Exception $e)
{
Mage::log("order export failed.\n");
}
return $this;
}
}
?>
Magento 1.4 on Debian Lenny with Apache2 if it should matter for any reason.
Read my articles, they'll help you understand what's going on from a naming convention standpoint and get you grounded in some of Magento's conventions/assumptions.
Looking at the samples above, you have a few things not quite right.
First, your file in the etc folder is named wrong
magento/app/etc/modules/Feed.xml
This file needs to be named Packagename_Modulename, so you probably want
magento/app/etc/modules/Feed_Sales.xml
Look at System -> Configuration -> Advanced to see if your module shows up. If it does, you'll have named this file correctly. Without this, the module you created isn't being loaded into the system, and your code never has a chance to run.
Next, you're specifying the class incorrectly. You say
sales/order_observer
but that first part of the URI (sales) is incorrect. You defined your models section as
<models>
<feedsales> <!-- this is your model part -->
<class>Feed_Sales_Model</class>
</feedsales>
</models>
which means you want
feedsales/order_observer
Checkout the Class/URI tab of Commerce Bug and try entering some URIs (like sales/order) to get a better idea of what's going on here.
Another quick tip, when you're trying to get your handler setup, do it for an event that fires on every page load. Then, once you have your method being called, you can switch it to the specific event you want and not have to go through the entire purchase process.
Finally, and I realize you were copying examples, consider putting your module in a folder named something other than Sales. I find mimicking the names of Magento core folders only add an extra layer of confusion, which is not what you need while you're learning the system.
The problem seems to be with your observer declaration. Give this a try:
<events>
<sales_order_place_after>
<observers>
<feed_sales_order_observer>
<type>singleton</type>
<class>feedsales/order_observer</class>
<method>export_new_order</method>
</feed_sales_order_observer>
</observers>
</sales_order_place_after>
</events>
Holy crap. I was stupid. I tested it out with a command line script, like I do with a lot of things, but that particular file was only writeable by the command line interpreter, not the Apache interpreter. I should have left the office earlier last night.
Well for the record, this is how you trigger an action on order placement. I'll leave it up for posterity.
better use this event instead of sales_order_save_after and checkout_onepage_controller_success_action
checkout_submit_all_after
it will work even site not redirected to success page because of some errors like internet issue and all.
try to use below code my requirement also same
namespace Custom\Checkout\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Simplexml\Element as SimpleXMLElement;
class Afterplaceorder implements ObserverInterface
{
protected $_request;
protected $_layout;
protected $_dir;
protected $jsonHelper;
protected $timezone;
protected $_io;
protected $_RandomBytes;
public function __construct(
\Magento\Framework\View\Element\Context $context,
\Magento\Framework\Filesystem\DirectoryList $dir,
\Magento\Framework\Json\Helper\Data $jsonHelper,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone,
\Magento\Framework\Filesystem\Io\File $io,
\Magento\Framework\Math\Random $RandomBytes
){
$this->_layout = $context->getLayout();
$this->_request = $context->getRequest();
$this->_dir = $dir;
$this->jsonHelper = $jsonHelper;
$this->timezone = $timezone;
$this->_io = $io;
$this->_RandomBytes = $RandomBytes;
}
/**
* #param \Magento\Framework\Event\Observer $observer
* #return void
*/
public function execute(EventObserver $observer)
{
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/orderdata.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$order = $observer->getData('order');
$quote = $observer->getQuote();
try{
// function defination to convert array to xml
function array_to_xml( $data, &$xml_data ) {
foreach( $data as $key => $value ) {
if( is_numeric($key) ){
$key = 'item'.$key; //dealing with <0/>..<n/> issues
}
if( is_array($value) ) {
$subnode = $xml_data->addChild($key);
array_to_xml($value, $subnode);
} else {
$xml_data->addChild("$key",htmlspecialchars("$value"));
}
}
}
$data = array('total_stud' => 500);
// creating object of SimpleXMLElement
$xml_data = new SimpleXMLElement('<?xml version="1.0"?><order></order>');
// function call to convert array to xml
array_to_xml($orderDeatails,$xml_data);
//saving generated xml file;
if ( ! file_exists($this->_dir->getPath('var').'/api/order')) {
$this->_io->mkdir($this->_dir->getPath('var').'/api/order', 0775);
}
$result = $xml_data->asXML($this->_dir->getRoot().'/var/api/order/order_'.$order->getIncrementId().'.xml');
}catch(\Exception $e){
$logger->info(print_r('error-> '.$e->getMessage(),true));
}
}
}
hope it will help you!
Happy Coding!!
Related
I have written a payment plugin in magento and it works (almost) flawlessly. Frontend payments are getting through I thought everything is done. But now I stumbled upon an issue.
I am using own autoloader and the registering event is controller_front_init_before which works fine. When I create a script calling Mage::app(); and then when I try to edit the orders I get from Mage::getModel("sales/order")->getCollection(); I get an error that my classes aren't loaded. I tried changing the event even to resource_get_tablename but the error persists. The only way to fix this error was to register the same autoloader I use in my plugin in the small script and this is an issue for me. Script follows
require_once "app/Mage.php";
Mage::app();
$orders = Mage::getModel("sales/order")->getCollection();
foreach ($orders as $order) {
echo "ORDER id " . $order->getId() . " #" . $order->getIncrementId()."\n";
$order->setData('status',Mage_Sales_Model_Order::STATE_COMPLETE);
$order->save();
}
Is anybody here who knows maybe which event to use so that this script works without needing to use spl_autoload_register... method?
Thanks!
EDIT
code/communinty/Payment/Module/config.xml
<config>
<global>
<events>
<resource_get_tablename>
<observers>
<payment_module>
<class>Payment_Module_Model_Autoloader</class>
<method>addAutoloader</method>
<type>singleton</type>
</payment_module>
</observers>
</resource_get_tablename>
</events>
</global>
</config>
code/community/Payment/Module/Model/Autoloader.php
class Payment_Module_Model_Autoloader extends Mage_Core_Model_Observer
{
protected static $registered = false;
public function addAutoloader(Varien_Event_Observer $observer)
{
if (self::$registered) {
return;
}
spl_autoload_register(array($this, 'autoload'), false, true);
self::$registered = true;
}
public function autoload($class)
{
$classFile = COMPILER_INCLUDE_PATH . DIRECTORY_SEPARATOR . $class . '.php';
include $classFile;
}
}
how do i start ? hrmmmm.
ok , right now Im trying to extend the mage_sales_mode_order . but this error appear.
Fatal error: Call to a member function load() on a non-object in /app/code/core/Mage/Adminhtml/controllers/Sales/OrderController.php on line 74
i don't know what is the problem because i already try using the same code extend different magento site but is working.
but below is what that i do and thanks in advance.
MageCustom/Sales/Model/Order.php
class MageCustom_Sales_Model_Order extends Mage_Sales_Model_Order
{
public function queueNewOrderEmail($forceMode = false)
{
$storeId = $this->getStore()->getId();
if (!Mage::helper('sales')->canSendNewOrderEmail($storeId)) {
return $this;
}
// Get the destination email addresses to send copies to
$copyTo = $this->_getEmails(self::XML_PATH_EMAIL_COPY_TO);
$copyMethod = Mage::getStoreConfig(self::XML_PATH_EMAIL_COPY_METHOD, $storeId);
// Start store emulation process
/** #var $appEmulation Mage_Core_Model_App_Emulation */
$appEmulation = Mage::getSingleton('core/app_emulation');
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($storeId);
try {
// Retrieve specified view block from appropriate design package (depends on emulated store)
$paymentBlock = Mage::helper('payment')->getInfoBlock($this->getPayment())
->setIsSecureMode(true);
$paymentBlock->getMethod()->setStore($storeId);
$paymentBlockHtml = $paymentBlock->toHtml();
} catch (Exception $exception) {
// Stop store emulation process
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
throw $exception;
}
// Stop store emulation process
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
// Retrieve corresponding email template id and customer name
if ($this->getCustomerIsGuest()) {
$templateId = Mage::getStoreConfig(self::XML_PATH_EMAIL_GUEST_TEMPLATE, $storeId);
$customerName = $this->getBillingAddress()->getName();
} else {
$templateId = Mage::getStoreConfig(self::XML_PATH_EMAIL_TEMPLATE, $storeId);
$customerName = $this->getCustomerName();
}
/** #var $mailer Mage_Core_Model_Email_Template_Mailer */
$mailer = Mage::getModel('core/email_template_mailer');
/** #var $emailInfo Mage_Core_Model_Email_Info */
$emailInfo = Mage::getModel('core/email_info');
$emailInfo->addTo($this->getCustomerEmail(), $customerName);
if ($copyTo && $copyMethod == 'bcc') {
// Add bcc to customer email
foreach ($copyTo as $email) {
$emailInfo->addBcc($email);
}
}
$mailer->addEmailInfo($emailInfo);
// Email copies are sent as separated emails if their copy method is 'copy'
if ($copyTo && $copyMethod == 'copy') {
foreach ($copyTo as $email) {
$emailInfo = Mage::getModel('core/email_info');
$emailInfo->addTo($email);
$mailer->addEmailInfo($emailInfo);
}
}
// Set all required params and send emails
$mailer->setSender(Mage::getStoreConfig(self::XML_PATH_EMAIL_IDENTITY, $storeId));
$mailer->setStoreId($storeId);
$mailer->setTemplateId($templateId);
$mailer->setTemplateParams(array(
'order' => $this,
'billing' => $this->getBillingAddress(),
'payment_html' => $paymentBlockHtml
));
/** #var $emailQueue Mage_Core_Model_Email_Queue */
$emailQueue = Mage::getModel('core/email_queue');
$emailQueue->setEntityId($this->getId())
->setEntityType(self::ENTITY)
->setEventType(self::EMAIL_EVENT_NAME_NEW_ORDER)
->setIsForceCheck(!$forceMode);
//$mailer->setQueue($emailQueue)->send();
$mailer->send();
Mage::log('new order trigger email', null, 'email.log');
$this->setEmailSent(true);
$this->_getResource()->saveAttribute($this, 'email_sent');
return $this;
}
MageCustom/Sales/etc/config.xml
<config>
<modules>
<MageCustom_Sales>
<version>0.1.0</version>
</MageCustom_Sales>
</modules>
<global>
<models>
<MageCustom_Sales>
<class>MageCustom_Sales_Model</class>
</MageCustom_Sales>
<sales>
<rewrite>
<order>MageCustom_Sales_Model_Order</order>
</rewrite>
</sales>
</models>
</global>
</config>
MageCustom_Sales.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<MageCustom_Sales>
<active>false</active>
<codePool>local</codePool>
</MageCustom_Sales>
</modules>
</config>
Problem
Your class and configuration are all correct assuming they exist in app/code/local, except for the active setting in MageCustom_Sales.xml:
<active>false</active>
Turn it on, clear your cache and try again :)
Testing
> With Magerun
If you've got magerun, you can use it to test your rewrite:
n98-magerun.phar dev:class:lookup model sales/order
# Model sales/order resolves to MageCustom_Sales_Model_Order
If you don't see the above resolution, you may have conflicts with the rewrite, but it's more likely that your rewrite configuration is wrong.
If you don't have Magerun - get it! You won't regret it.
> Without Magerun
You can drop a custom script into the root directory of your Magento project just to test the class alias:
<?php
include 'app/Mage.php';
Mage::app();
var_dump(get_class(Mage::getModel('sales/order')));
Run it from command line via php myTestFile.php, or from browser via http://magento.local/myTestFile.php.
If it works, you should see string(28) "MageCustom_Sales_Model_Order". If it doesn't you'll see bool(false).
Hope this helps.
Make it sure that you have your custom module inside the local folder and enable your module by inserting true inside the active tag.
<active>true</active>
I am overriding the Mage_Core_Model_Encryption in my module to override hash, getHash, and validateHash methods.
Since urls in the admin side of things use hashing as well, I am overriding the Mage_Adminhtml_Model_Url getSecretKey method so that it will use (faster) md5 hashing in the urls.
The problem I have noticed is that when I clear my cache (config only is enabled) and load the admin/index my encyptor is not registered. It takes until the third request for it to be seen.
I have debugging statements in Mycompany_Encryption_Adminhtml_Url which show that it is immediately loaded with the module. After clearing my cache, I can see my debug statements are working.
When I use the following statement:
var_dump('Class name: '.get_class(Mage::helper('core')->getEncryptor() ) );
I see returned to admin/index (upon refreshing the page) that the class name is Mage_Core_Model_Encryption, then on the third refresh it shows me my class, Mycompany_Encryption_Model_Encryption.
Why does this take three requests? I have been searching all over and haven't found/figured out the problem yet. By all appearances, I have this configured correctly ( and have experimented with a bunch of alternatives).
Can anyone help me solve this issue?
(Below are config, Url class, and Encryption class snippets). Big thanks in advance for any help.
Update, am using modman, here is my modman too:
# Modman file allows Modman to generate links in Magento.
code app/code/local/Mycompany/Encryption/
Mycompany_Encryption.xml app/etc/modules/Mycompany_Encryption.xml
Here is my config:
<config>
<modules>
<Mycompany_Encryption>
<version>0.1</version>
<depends>
<Mage_Core />
</depends>
</Mycompany_Encryption>
</modules>
<phpunit>
<suite>
<modules>
<Mycompany_Encryption />
</modules>
</suite>
</phpunit>
<global>
<helpers>
<core>
<encryption_model>
<class>Mycompany_Encryption_Model_Encryption</class>
</encryption_model>
</core>
</helpers>
<models>
<mycompany_encryption>
<class>Mycompany_Encryption_Model</class>
</mycompany_encryption>
<core>
<rewrite>
<encryption>Mycompany_Encryption_Model_Encryption</encryption>
</rewrite>
</core>
<adminhtml>
<rewrite>
<url>Mycompany_Encryption_Model_Adminhtml_Url</url>
</rewrite>
</adminhtml>
</models>
</global>
</config>
Url class:
class Mycompany_Encryption_Model_Adminhtml_Url extends Mage_Adminhtml_Model_Url
{
/**
* Generate secret key for controller and action based on form key
*
* #param string $controller Controller name
* #param string $action Action name
* #return string
*/
public function getSecretKey($controller = null, $action = null)
{
$salt = Mage::getSingleton('core/session')->getFormKey();
$p = explode('/', trim($this->getRequest()->getOriginalPathInfo(), '/'));
if (!$controller) {
var_dump('Not Controller');
$controller = !empty($p[1]) ? $p[1] : $this->getRequest()->getControllerName();
}
if (!$action) {
var_dump('Not Action');
$action = !empty($p[2]) ? $p[2] : $this->getRequest()->getActionName();
}
$secret = $controller . $action . $salt;
// Here are my debug statements showing when class/method become available.
var_dump('Method exists: '.method_exists(Mage::helper('core')->getEncryptor(), 'urlHash'));
var_dump('Class name: '.get_class(Mage::helper('core')->getEncryptor() ) );
/* This is what I want to return - but sends error 500 until instantiated. */
//return Mage::helper('core')->getEncryptor()->urlHash($secret);
return false;
}
}
Encryption class:
class Mycompany_Encryption_Model_Encryption extends Mage_Core_Model_Encryption
{
public function hash($data)
{
return password_hash($data, PASSWORD_BCRYPT);
}
public function validateHash($password, $hash)
{
return password_verify($password, $hash);
}
public function getHash($value)
{
return $this->hash($value);
}
public function urlHash($value)
{
return md5($value);
}
}
Using the n98-magerun tool, I was able to config:dump and search for the global/helpers/core node.
With the above configuration, I was getting this badly formed config dump:
$ n98-magerun config:dump |cat |grep -A1 -B2 encryption_model
<helpers>
<core>
<encryption_model>Mage_Core_Model_Encryption<class>Mycompany_Encryption_Model_Encryption</class></encryption_model>
</core>
It appears to clear up if I remove the <class> tags in my config.xml:
<helpers>
...
<core>
<!-- Class tags were surrounding my encryption_model value before -->
<encryption_model>Mycompany_Encryption_Model_Encryption</encryption_model>
</core>
...
</helpers>
With this change, I clear cache and get a better config dump:
$ n98-magerun cache:clean config
config cache cleaned
$ n98-magerun config:dump |cat |grep -A1 -B2 encryption_model
<helpers>
<core>
<encryption_model>Mycompany_Encryption_Model_Encryption</encryption_model>
</core>
Please comment with a doc link or provide info if you know why this was happening! Thanks!
I have made a custom module with layout in magento. its shows customer's information of a particular customer group.
its url is
www.mysite.com/profile/index/index/mayank
Where profile is my modulename, index is controller name, 2nd index is index controller's method and mayank is customer's username (a unique field or attribute).
What i need is.
Make this url like this:-
www.mysite.com/mayank
Firstly, Magento URLs tend to put the field name before the value. So I expect the long URL to actually look like this:
www.mysite.com/profile/index/index/name/mayank
This would allow for a neat retrieval in the controller,
public function indexAction() {
$name = $this->getRequest()->get('name');
}
“Is there anyway we can do like 'if no route found then magento calls our module's controller..?”
I've wrestled with routers before and in my opinion they are unnecessary unless absolutely necessary. When the number of possible URLs is finite then it is easier to save a rewrite in advance. The best time to do this is whenever a username changes.
To listen for a change add this to your module's config.xml:
<global>
<events>
<customer_save_after>
<observers>
<mayank_profile>
<type>singleton</type>
<class>mayank_profile/observer</class>
<method>customerSaveAfter</method>
</mayank_profile>
</observers>
</customer_save_after>
<customer_delete_after>
<observers>
<mayank_profile>
<type>singleton</type>
<class>mayank_profile/observer</class>
<method>customerDeleteAfter</method>
</mayank_profile>
</observers>
</customer_delete_after>
</events>
</global>
In your module's Model folder create Observer.php:
class Mayank_Profile_Model_Observer {
public function customerSaveAfter(Varien_Event_Observer $observer) {
$customer = $observer->getCustomer();
// username is not a standard attribute, hopefully you have created it
if ($customer->dataHasChangedFor('username')) {
$this->remove($customer->getOrigData('username'));
$this->add($customer->getData('username'));
}
}
public function customerDeleteAfter(Varien_Event_Observer $observer) {
$customer = $observer->getCustomer();
$this->remove($customer->getOrigData('username'));
}
protected function remove($username) {
// this does nothing if rewrite doesn't exist
Mage::getModel('core/url_rewrite')
->loadByIdPath('profile/'.$username);
->delete();
}
protected function add($username) {
if ($this->isValidUsername($username)) {
$storeId = Mage::app()->getDefaultStoreView()->getId();
Mage::getModel('core/url_rewrite')
->setIsSystem(0)
->setStoreId($storeId)
// IdPath is used by remove() function
->setIdPath('profile/'.$username)
// TargetPath is your controller/action
->setTargetPath('profile/index/index/name/'.$username)
// RequestPath is what the browser sees
->setRequestPath($username)
->save();
}
}
protected function isValidUsername($username) {
// feel free to add more checks here
// start with existing rewrites
$rewrite = Mage::getModel('core/url_rewrite')
->loadByRequestPath($username);
if (!$rewrite->isObjectNew()) {
return false;
}
// scan known frontNames
$frontNames = Mage::getConfig()->getXPath('*/routers/*/args/frontName');
foreach ($frontNames as $name) {
if ($username == (string) $name) {
return false;
}
}
return true;
}
}
It's quite a bit of work but the advantage here is the following code correctly looks up the path earlier saved as "RequestPath":
echo Mage::getUrl('profile', array(
'name' => $username,
'_use_rewrite' => true
));
Here is a much simpler way which only works for URLs that cannot clash with other modules. Add this to your config.xml:
<global>
<rewrite>
<mayank_profile>
<from><![CDATA[#^/profile/#]]></from>
<to><![CDATA[/profile/index/index/name/]]></to>
<complete>1</complete>
</mayank_profile>
</rewrite>
</global>
When outputting an URL you need to concatenate the path yourself. e.g.
echo Mage::getUrl('', array(
// Use _direct here to avoid a trailing solidus
'_direct' => 'profile/' . $username
));
You can try to solve this with a htaccess rewriterule
Or
create an observer on controller_action_layout_load_before and fetch the REQUEST_URI and use it for your case.
Good luck
Heyo, been working on a magento theme for a little while now (... and my understanding of the system is slowly but steadily growing). I need to start working on some custom modules soon, and so I'm starting with this little project to get my bearings:
I found a little bit of code to manage a specific task that I have been copying and pasting into template files:
<?php
$ids = $_product->getCategoryIds();
$cat = Mage::getModel('catalog/category')->load($ids[0]);
$isFF = false;
foreach ($ids as $key=>$val) {
$cat = Mage::getModel('catalog/category')->load($val);
$name = $cat->getName();
if ( $name === 'Fast Fulfillment' ) {
$isFF = true;
}
}
if ($isFF) { echo '<span class="ff-logo"></span>'; }
?>
Very simple. I'm just checking to see if a product is in a specific category, and producing an element if it is. (I know there are about 5 solid ways of doing this... this is the one I went with).
I need to test this every time a product block is displayed, and have, up till now, been replicating this code to make it work. It does work, but is backasswards (I shouldn't be putting logic into the view layer).
Ok - so, lets make a simple module to share the functionality:
local/WACI/ProductFlag/etc/config.xml
<config>
<modules>
<WACI_ProductFlag>
<version>0.1.0</version>
</WACI_ProductFlag>
</modules>
<global>
<blocks>
<WACI_ProductFlag>
<class>WACI_ProductFlag_Block_View</class>
</WACI_ProductFlag>
</blocks>
</global>
</config>
etc/modules/WACI_All.xml
<config>
<modules>
<WACI_CustomPageLayouts>
<codePool>local</codePool>
<active>true</active>
</WACI_CustomPageLayouts>
</modules>
<modules>
<WACI_ProductFlag>
<codePool>local</codePool>
<active>true</active>
</WACI_ProductFlag>
</modules>
</config>
Now, for the Class ... I'm not really sure if a Block or a Helper is appropriate. I went with Block, but - idk... I'm probably wrong (tutorials for this stuff vary wildly).
local/WACI/ProductFlag/Block/View.php
<?php
/**
* WACI
*
* #codepool Local
* #category View
* #package WACI
* #module ProductFlag
*/
class WACI_ProductFlag_Block_View extends Mage_Core_Block_Template
{
private $_focus;
private $_isFF = false;
public function getIsFF( $product ){
$this->_focus = "FF";
$isFF = false;
$ids = $product->getCategoryIds();
$cat = Mage::getModel('catalog/category')->load($ids[0]);
foreach ($ids as $key=>$val) {
$cat = Mage::getModel('catalog/category')->load($val);
$name = $cat->getName();
if ( $name === 'Fast Fulfillment' ) {
$isFF = true;
}
}
}
protected function _toHtml(){
$html = parent::_toHtml();
if ($this->_focus === "FF") {
if ($this->_isFF){
$html .= '<span class="ff-logo"></span>';
}
}
return $html;
}
}
?>
Hopefully its clear that I only want to output a string based on the input of any given product. Should I be overriding the _toHtml() to deliver the string? Again. Probably not...
in my local.xml I reference the block:
<catalog_product_view>
<reference name="content">
<reference name="product.info">
<block type="WACI/ProductFlag" name="product.flag" as="productFlag" output="toHtml" />...
... I'm not clear if this instantiates this class? I don't think so. I'm not really sure how to address it in my product/view/media.phtml anyway, given that I need to call a method with a parameter.
I don't think I need a template file, given that I'm just outputting a string, but I don't think I've seen block modules without an associated template. Maybe a helper class is appropriate then?
Whatever the case, it ain't workin.
I either get a fatal error saying my media class has no getIsFF() method (not surprising), or just nothing shows up. My config files are correct, but that's about it, I think.
Jebus. I'm all turned around.
Can someone with Mage skillz clarify this simple issue and point me in the right direction?
Cheers!
No advice? Well = I sussed out this slightly modified and working solution:
local/WACI/ProductFlag/etc/config.xml
<config>
<modules>
<WACI_ProductFlag>
<version>0.1.0</version>
</WACI_ProductFlag>
</modules>
<global>
<blocks>
<productflag>
<class>WACI_ProductFlag_Block</class>
</productflag>
</blocks>
<helpers>
<productflag>
<class>WACI_ProductFlag_Helper</class>
</productflag>
</helpers>
</global>
</config>
local/WACI/ProductFlag/Helper/Flag.php
class WACI_ProductFlag_Helper_Flag extends Mage_Core_Helper_Abstract
{
private $_isFF = false;
public function getIsFF( $product ){
$html = '';
$ids = $product->getCategoryIds();
$cat = Mage::getModel('catalog/category')->load($ids[0]);
foreach ($ids as $key=>$val) {
$cat = Mage::getModel('catalog/category')->load($val);
$name = $cat->getName();
if ( $name === 'Fast Fulfillment' ) {
$this->_isFF = true;
}
}
if($this->_isFF) {
$html = '<span class="ff-logo"></span>';
}
return $html;
}
}
and call it up in any template file via the simple:
<?php echo $this->helper('productflag/flag')->getIsFF($_product); ?>
I'm still not sure if this is exactly appropriate to the magento way of doing things - ie the model calls, I think, should be relegated to their own class and dropped in a Model folder.
Whatever the case - and for anyone else trying to figure this stuff out - as I monkeyed around with it I slowly realized the intent of the config.xml file is to add available factory classes to the blocks/helpers/model pools - and that the path is to the containing directory. The helper call in the template file, then, identifies the "short name" of the directory and then the actual class name.
ie - You could have multiple classes of helpers:
<?php echo $this->helper('productflag/class_one')->someMethod($_product); ?>
<?php echo $this->helper('productflag/class_two')->someOtherMethod($_product); ?>
<?php echo $this->helper('productflag/class_three')->yetAnotherMethod($_product); ?>
So... One step closer.