Blog

  • Magento code snippet

    Magento provide a beautiful GUI, which let you setup or change nearly everything. However, occasionally you prefer do it with php code. Here are a collection of codes for various functionalities. I will keep editing this post to add new methods.

    Read if a product attribute is “Use Default Value” in a Store View:

    Assume the storeview ID is $storeId, the product attribute code is $attributeCode;

    $result = Mage::getModel(‘catalog/product’)->setStoreId($storeId)->getAttributeDefaultValue($attributeCode);

    $result === false when the attribute IS “Use Default Value”;

    $result === Mage::getModel(‘catalog/product’)->setStoreId(0)->getAttributeDefaultValue($attributeCode) when the attribute HAS storeview specific value.

    Please note even if the attribute is “Yes/No” choice type, the attribute value is 1 or 0. So there is no conflict – when getAttributeDefaultValue returns false means “Use Default Value”; when it returns 0 means “default value is No”.

    Read storeview specific value to a product attribute:

    public function getAttributeOptionValue($optionId, $storeId = 0, $attributeId = null)
    {
    	$valuesCollection = Mage::getResourceModel('eav/entity_attribute_option_collection')
    		->setStoreFilter($storeId, false)
    		->addFieldToFilter('main_table.option_id', $optionId)
    		->setAttributeFilter($attributeId);
            return $valuesCollection->getFirstItem()->getValue();
    }
    

    CRUD manipulation on entity attributes, such as product attribute

    All need to do is construct an array in the right structure, add to the attribute, and save. Do not operate on ‘eav/entity_attribute_option’ directly. It won’t work because relationship between table eav_attribute_option and eav_attribute_option_value is not set in this model.

    Add options to attribute

    $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $attributeCode);
    $data = array(
    	'option' => array(
    		'value' => array(
    			$optionId => array(
    				$storeId => $value
    			)
    		)
    	)
    );
    $attribute->addData($data)->save();
    

    Bear in mind, as this is to add a new option, you do not need to specify an actual $optionId. It can be any string which, if convert to number, must be 0. If $optionId’s numeric value is positive, and if that option does not exist or does not belong to the $attribute, it will throw exception like:

    SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails.

    You can construct an array with more than one option ID’s and store ID’s inside to add multiple options or give option values to multiple stores at a time.

    Read options

    $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $attributeCode);
    $optionCollection = Mage::getResourceModel('eav/entity_attribute_option_collection')
    	->setStoreFilter($storeId, false)
    	->setAttributeFilter($attribute->getId());
    foreach ($optionCollection as $option) {
    	echo $option->getValue();
    }
    

    The code is straight forward. I did not find another way retrieving options. I tried
    $attribute->getOptions() and $attribute->getOption(). Neither worked.

    Delete options

    $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $attributeCode);
    $data = array(
    	'option' => array(
    		'value' => array(
    			$optionId => ''
    		),
    		'delete' => array(
    			$optionId => 1
    		)
    	)
    );
    $attribute->addData($data)->save();
    

    The tricky thing is: the $optionId to delete must exist in both ‘value’ and ‘delete’, although the value itself is not critical (because it will be deleted).

    Update options

    $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $attributeCode);
    $data = array(
    	'option' => array(
    		'value' => array(
    			$optionId => array(
    				$storeId => $value
    			)
    		)
    	)
    );
    $attribute->addData($data)->save();
    

    It is the same code as adding options. The difference is in $optionId. You need work out the existing option ID.

    CRUD manipulation does not need to construct $data with the complete list of existing options. Any options not in $data is untouched.

  • Magento extension: Root Category As Homepage

    It is my first time publish an Magento extension – Qian_Rcah. By default, Magento prevent root category from being shown at frontend, not to say use it as homepage. I do not see significant security leaks if showing root category. There are some benefits using root category as homepage:

    • Layered navigation starts with a complete product collection on site.
    • Selective products show on homepage without prerequisite knowledge of cms block.

    Download RootCategoryAsHomepage.tar.gz

    How to install:
    Copy the whole “app” folder to magento/app. That’s it.

    How to use:
    Log in Magento backend, go to System -> Configuration -> General -> Web -> Default Pages, change “Default web URL” to “rcah” (default is cms). Besides of root category, this module can load an arbitrary category page as homepage. In this case, change “Default web URL” to “rcah/index/index/id/ARBITRARY_CATEGORY_ID”.

    How is it created:
    This module is created by koukou1985’s module creator (http://www.magentocommerce.com/wiki/custom_module_with_custom_database_table). Thanks to koukou1985.

    How good is it:
    This module does not override any Mage classes. It is safe to use with other extensions as long as namespace and module name do not conflict.

  • How can Magento generate sitemap.xml belongs to root?

    今天看到 magento 目录下的 sitemap.xml 的属主和属组分别是 root:root,属性是644,而这一台的 webserver 是以 apache:apache 身份运行的,所以我觉得很奇怪:

    • apache 怎么能建立一个 root:root 的文件?
    • 如果这个文件不是 apache 建的,apache 怎么有权去更新它(最近更新就在今天)?

    想了好一会明白过来,sitemap.xml 是 cron job 建的,crontab 这么写

    */10 * * * * /usr/bin/php -f /path/to/magento/cron.php

    那么 sitemap.xml 归 root:root 所有就不奇怪了。

    我想这样写会好些:

    */10 * * * * sudo -u apache -g apache /usr/bin/php -f /path/to/magento/cron.php

    2010年6月29日更新:上行命令不对,设想在 cron job 里以 apache 身份运行 cron.php,但出错。正确的写法应该是:

    */10 * * * * su -c '/usr/bin/php -f /path/to/magento/cron.php' -s /bin/bash apache

  • CNVD-2010-00979

    互联网是一个很容易以讹传讹的地方,这大概是人们不满意 google 的地方,要搞个知识搜索取而代之。

    最近金山毒霸和360杀毒口水之争,我无意关心了一把。看到被多家网站(包括人民网)转发的金山网盾再陷新的诚信危机“漏洞门”,其中提到

    5月24日,中国国家信息安全漏洞库证实金山网盾存在一个高危的内核本地提权漏洞(国家漏洞库编号:CNVD-2010-00979),并公布了该漏洞利用相关细节。同一天,国外权威漏洞机构Secunia研究并收录了金山网盾这一漏洞,同时对该漏洞进行了自己的解释和归类(SA ID:SA39916)。国内外两大权威安全机构同时证实金山网盾存在高危漏洞,把此前一直高调否认软件有漏洞的金山公司置于非常尴尬的境地。

    我好奇了一下,上 cnvd 和 secunia 去查了一下,CNVD-2010-00979 和 SA ID:SA39916 讲的是多个供应商”rpc.pcnfsd”整数溢出漏洞,跟金山网盾无关,真不知道这个刹有其事的报导从何而来。

    虽然CNVD-2010-00979 跟金山网盾无关,但我有感觉无风不起浪,因为这是在 cnvd 上搜索金山网盾的结果:

    Google search result cached something
    Google search result cached something

    但实际查看被缓存的页面却什么也没有:

    Nothing on cached page
    Nothing on cached page

    或许 cnvd 只把详细信息公开给了 google spider;或许这其中有太多的内幕是我们常人无法知道的……

  • Google do not need windows. Neither do I

    Magento grid is flexible to customise. A lot of options can be controlled by addColumn(). I knew the parameters could be header, width, type, index, but I just found a new one sortable. I am thinking where I can get a complete list of parameters for addColumn(). The best way I can imagine is searching magento source and find the file which contains all words of “header width type index sortable”. File search in eclipse can not do this kind search, so I am thinking google desktop search.

    I have not used google desktop search for a while. Last time I used it, it only has windows version. Today I am glad find google desktop search linux version is available. Up to now, my favourite google programmes, chrome, picasa, and google desktop, all embrace linux users.

    It reminds me a piece of news that google stop offering staff windows as operation system. I regard this is competition between google and microsoft, none of my business. However, google makes programmes independent of windows, which really benefits me.

    What else left in windows which has to be in windows?

    • IE: it is shame our Chinese banks’ website only support IE;
    • MS Office: how many advanced users are using Office features which are exclusive to MS Office? Not many.
    • Photoshop: it’s a pity Gimp still can not beat photoshop at moment.
  • Best place to put module installation scripts in Magento

    Magento module 中,在哪里放置安装脚本比较好?

    当然,把它放在 sql/$resourceName 目录下 $resModel.’-‘.$actionType.’-(.*)\.(sql|php) 文件里是不错的。安装脚本通常是修改数据库结构,所以放在.sql文件理所当然。但如果安装脚本跟数据库无关,放在.sql略显勉强,为此,我找了一个更好的地方。

    首先在 config.xml 声明一个 setup 类:

    
    <config>
    
    <resources>
    <mymodule_setup>
    <setup>
    <module>Mynamespace_Mymodule</module>
    <class>Mynamespace_Mymodule_Model_Setup</class>
    </setup>
    </mymodule_setup>
    </resources>
    </config>
    
    

    这个类只要 extends Mage_Core_Model_Abstract,不一定得 extends Mage_Core_Model_Resource_Setup。

    然后在该类里放置 applyUpdates() 方法,把安装脚本都写到这个方法里就可以了。模块在安装时就是执行这个方法,而且是在 .sql 执行之前。

  • Dabs bundle irrelevant products together

    I am searching for a high resolution LCD/LED monitor. So when dabs send me an eshot promoting Samsung 23″ Wide SM2333SW 5ms DVI TFT Gloss Black, I open it up.

    I am very excited to see “Get A 2m HDMI Cable FREE! Use Bundle Option 1!” on the product page. It makes me think Samsung SM2333SW support HDMI, and stimulates me to buy it. Then suddenly I am very disappointed after reading its specifications:

    Signal Input
    DVI-D, VGA

    Where is HDMI? No, there isn’t one. Why bundle HDMI cable with a monitor does not support HDMI? Who knows!

  • Problemic boc.cn

    今天上中行的网站,本来是找信息的,却发现了很多大问题,比如:

    • DNS 只解析 www.boc.cn,不解析 boc.cn
    • 供下载的申请表竟然用 rar 打包,是不是在考验申请人的计算机操作能力?
    • 网银操作依赖于 IE
    • 安全增强依赖于 ActiveX
    • SSL 证书只是基本型的,而不是银行业界普及的增强型
    • 网页用 gb2312 编码,而非最适合国际公司的 utf-8
    • 网页申明为 xhtml,但显然不知 xhtml 为何物
    • table 布局

    小问题肯定数都数不过来,我也没心情帮他们去纠错。

  • 1and1 waste me two days

    订了一个 1&1 Cloud Server,两天了还没法用。在 1&1 control panel 里一点那个 cloud server,就抛给我一个 500 Internal Server Error。这是在 1&1 control panel 里的错误,不是我订的 cloud server 上的错误。

    一开始我还以为下订单时某个环节没做到,我拼命发 email,拼命打电话(电话很长时间才有人接,接了也会被掐,还是email support 好一些),辗转了 N 个来回以后被告知,1&1 的程序有个错误,让我耐心等。晕啊,浪费我两天时间。

  • What if I change the EAV attribute backend type in Magento?

    The question is raised because in my catalog_category, I have a user attribute originally 255 length varchar. Now I am told by users it was not long enough for block text. I want to change it to text type in mysql to solve the problem.

    I know EAV attributes use different tables for different type. My worry is moving attribute value from varchar table to text table when changing the EAV attribute backend type. Anyway, I have to try before I know. Here is my steps:

    1. go to table magento_eav_attribute, find the attribute, change backend_type from varchar to text
    2. (what’s next?) I am about to change something else, but surprisingly, nothing else! All done after step 1.

    I do not need to move old values from magento_catalog_category_entity_varchar to magento_catalog_category_entity_text. After change attribute’s backend_type, Magento can still read existing value from magento_catalog_category_entity_varchar, but if I save the category, the value will save to magento_catalog_category_entity_text. Old value is not deleted from magento_catalog_category_entity_varchar, but it does no harm.

    I am curious at how Magento did it – Does Magento go through 5 tables (datetime, decimal, int, text, varchar) to get a value? Or Magento cache attributes’ backend type (so even I make changes in magento_eav_attribute, Magento still have records of old type)?