Tag: magento

  • Magento speed optimisation

    诚然,我接触Magento时间不短了,但直到最近才开始研究Magento的速度,因为我的一个Magento项目已经上马了。

    通常Magento要比Zencart, osCommerce, VirtueMart for Joomla跑得慢,但这个没有吓退我。我坚信Magento是我的方向,是因为Magento的ecommerce功能是其它软件望尘莫及的,况且我拥有让Magento加速的硬件资源。(这世界上没有什么是最好的,适合自己的就是最好的)。

    我认为选择Magento,首先得有一台独立服务器。虽然我曾成功地在shared hosting环境里运行了Magento,但一个没有速度优化潜力的Magento,就算能跑,又有什么用?Magento内置了很多SEO特性,但如果页面loading time过长,Google也不会喜欢。VPS理论上也能为Magento做速度优化,但一台入门级的独立服务器与一台高性能的VPS价格相当,我会选择前者,以确保所有的优化可能。

    其次得有1G以上内存,CPU差一点没关系,因为Magento的速度瓶颈在硬盘,优化手法中很多就用内存代替硬盘。

    有了以上两个硬件资源,剩下的就是进行一些软件环境设置。

    首先,得是Linux环境。我不是说Magento在Windows下跑不起来,我是说网上大部分建议都是针对Linux提的,除非你有一个Microsoft专家在你旁边,每当你给他一个Linux配置文件,他能为你写一个Windows下的对应文件。

    其次,给MySQL Server分配更多的内存。

    再次,启用Cache。Cache分三种,一是Magento data cache,Magento系统菜单的Cache Management指的就是这个,默认已经启用。据我观察,data cache单独使用时,对速度提升没多大帮助。二是Linux in-memory file cache,把magento/var/cache指到或软连接到tmpfs。三是php byte cache,开源世界里主要有三种选择,php APC, eAccelerator, xCache。孰优孰劣尚无定论,我看了一些测试结果,我的结论是:小访问量时选php APC,访问量达到负载容量50%以上的选xCache,Magento的开发小组说eAccelerator在处理magento异常时会出错,我就把它剔除了。

    如果以上优化都做过了,速度应该很理想了。经济条件许可的话,买多点内存,搞个SCSI, RAID硬盘,换个四核CPU,我就不信Magento会比谁慢。

  • Magento new version notification is annoying

    It is exciting to see Magento new versions keep coming out once after a while. Magento notify administrator upon login, and administrator upgrades it, then Magento should stop notifying until another new version is available. The logic should be as simple as that.

    However, currently Magento message is always active even after upgrading. It only disappears when administrator marks it read or deletes it. Very annoying, isn’t it?

  • Magento sub category url at level 1

    Although Google said it does not matter if you put pages at deep level, it would be quite nice to put all category pages at level 1. I have not found a way to achieve it in Magento.

    I have a strong reason to put sub category url at level 1 besides of SEO – Sometime I need reorganise the category hierarchy. If moving category around changes its url, the site will produce 404 error if the visitor visiting the site via bookmark or search engine cached url.

    Magento takes care of product pages very well. It asks you whether to use categories path for product URLs. However, Magento does not ask the same question for sub category pages. If a sub category is at level 3 from root category, its url will be sub-category-level-1/sub-category-level-2/sub-category-level-3. That is too long. If you can make sure each category (no matter which category it belongs to) url identifier identical, why Magento not simply use sub-category-level-3 as url?

  • Is Magento is_in_stock an attribute

    is_in_stock在magento export products时会是其中一列,但我在attributes里怎么也找不到它,它到底是什么?

  • Magento 1.2.0.1 is out

    今天很欣喜地发现Magento 1.2.0出来了,赶紧用magento connect upgrade了一下,结果升级失败,前台出不来,后台也进不去。

    我只好手动安装了一下,原先php环境设置前台safe_mode on,只对后台safe_mode off,安装了magento 1.2.0以后,前台出现了错误提示 Warning: set_time_limit() [function.set-time-limit]: Cannot set time limit in safe mode。magento对php环境要求越来越高了,我只好把safe_mode 前台、后台统统off。这下就没问题了。

    在我成功把magento 1.2.0运行起来后,发现1.2.0.1发布了,才几个小时啊,magento更新真够快了。我猜想1.2.0.1是针对safe_mode苛刻要求发布的小补丁,因为我又把magento 1.2.0更新成1.2.0.1,试着把php safe_mode恢复原先的设置,一切正常!

  • Change csv export file enclosed-by sign

    Excel另存为CSV (comma separator)格式时,不带字段的限定符(enclosed-by sign)。

    因为magento import csv前特别提醒,限定符不得为空,所以我就想着怎么把Excel CSV指定限定符为双引号。可以左找右找Excel本身不能设置限定符(连修改默认的逗号分隔符都很麻烦,要在Excel以外,Windows Control Panel->Regional Setting那里修改),倒有人提供了一个宏代码,用起来也很方便。

    将Excel文件导出为逗号分隔、双引号限定的CSV文件的宏代码如下:

    Sub CSVFile()

    Dim SrcRg As Range
    Dim CurrRow As Range
    Dim CurrCell As Range
    Dim CurrTextStr As String
    Dim ListSep As String
    Dim FName As Variant
    FName = Application.GetSaveAsFilename("", "CSV File (*.csv), *.csv")

    If FName <> False Then
    ListSep = Application.International(xlListSeparator)
    If Selection.Cells.Count > 1 Then
    Set SrcRg = Selection
    Else
    Set SrcRg = ActiveSheet.UsedRange
    End If
    Open FName For Output As #1
    For Each CurrRow In SrcRg.Rows
    CurrTextStr = ""
    For Each CurrCell In CurrRow.Cells
    CurrTextStr = CurrTextStr & """" & CurrCell.Value & """" & ListSep
    Next
    While Right(CurrTextStr, 1) = ListSep
    CurrTextStr = Left(CurrTextStr, Len(CurrTextStr) - 1)
    Wend
    Print #1, CurrTextStr
    Next
    Close #1
    End If
    End Sub

  • Magento user defined attributes in product list

    Magento内置的产品属性与自定义的产品属性可访问范围不同。默认设置下,自定义的产品属性只能在product view取值,如在product view以外则取不到值;内置的产品属性则没有这种限制。

    为了让自定义产品属性能在Magento前端(比如product list, product new, 或者自己写一个product featured)随意取值,至少有三种方法可以更改默认设置。

    最简单的办法是创建一个config.xml(文件名任意),放在app/etc/modules/下:

    <?xml version="1.0"?>
    <config>
        <frontend>
            <product>
                <collection>
                    <attributes>
                        <attributeyouwant/>
                    </attributes>
                </collection>
            </product>
        </frontend>
    </config>
    

    以后有空再讲其他两种办法。记得一定要刷新Magento cache才能让设置生效!

  • Clear Magento cache is essential after layout xml update

    说来懊恼,为了让Magento product list能够显示自定义属性的值,我查看了magento wiki 和 forum 上几十个帖子,众说纷纭,我也不知道哪个是对的,或者哪个针对当前1.1.8可用。一个个实验下来,排列组合了不下100种可能,比如:

    • 有人说layout add this line: my_attribute,另有人说是my_attribute
    • 有人说要用$_product->getMyAttribute(),也有人说用$_product->getAttribute(‘my_attribute’),也有人说用$_product->getData(‘my_attribute’),也有人说用$_product->getAdditionalData(‘my_attribute’),还有人说用$_product->getResource()->getAttribute(‘my_attribute’)->getFrontend()->getValue($_product))
    • 还有人说Create separate module for your customization, Name it ‘Mycustomization’
      (can be changed).
      Then do this:
      1. Create file app/etc/modules/Mycustomization.xml

      <?xml version="1.0"?>
      <config>
      <modules>
      <Mycustomization>
      <active>
      true
      </active>
      <codePool>
      local
      </codePool>
      </Mycustomization>
      </modules>
      </config>
      

      2. Create folder app/code/local/Mycustomization and inside it app/code/local/Mycustomization/etc/

      3. Create file
      app/code/local/Mycustomization/etc/config.xml

      <?xml version="1.0"?>
      <config>
      <modules>
      <Mycustomization>
      <version>
      0.0.1
      </version>
      </Mycustomization>
      </modules>
      <frontend>
      <product>
      <collection>
      <attributes>
      <designer/>
      </attributes>
      </collection>
      </product>
      </frontend>
      </config>
      

      Once done on the frontend in all product collections you will have designer attribute loaded automatically.

    • 还有Create a file app/etc/modules/category_product_attributes.xml with the following:
      <?xml version="1.0"?>
      <config>
      <frontend>
      <product>
      <collection>
      <attributes>
      <attributeyouwant/>//This is your attribute
      </attributes>
      </collection>
      </product>
      </frontend>
      </config>
      
    • 等等

    最后发现所有组合都不起作用,除非清除magento cache 让 layout xml 生效。

  • Update proof way to customise Magento code

    如果直接修改Magento的文件,Magento每次升级后,又要重新修改,所以这肯定不是个办法。以我最近一次修改/app/code/core/Mage/Core/Model/Email/Template.php为例,修改后Magento使用gmail smtp server来发送邮件。以下我使用update proof way重作一遍。(当前Magento版本是1.1.8)

    1. 不直接修改/app/code/core/Mage/Core/Model/Email/Template.php,而是新建一个/app/code/local/(MyNameSpace)/Core/Model/Email/Template.php,其中(MyNameSpace)可以随意命名。

    /app/code/local/(MyNameSpace)/Core/Model/Email/Template.php 是 /app/code/core/Mage/Core/Model/Email/Template.php的子类,其中我只重载了send方法,所以,/app/code/local/(MyNameSpace)/Core/Model/Email/Template.php不需要拷贝其他部分,它完整的内容是:

    class (MyNameSpace)_Core_Model_Email_Template extends Mage_Core_Model_Email_Template {
    public function send($email, $name=null, array $variables = array())
    {
    if(!$this->isValidForSend()) {
    return false;
    }

    if (is_null($name)) {
    $name = substr($email, 0, strpos($email, ‘@’));
    }

    $variables[’email’] = $email;
    $variables[‘name’] = $name;

    $mail = $this->getMail();
    if (is_array($email)) {
    foreach ($email as $emailOne) {
    $mail->addTo($emailOne, $name);
    }
    } else {
    $mail->addTo($email, ‘=?utf-8?B?’.base64_encode($name).’?=’);
    }

    $this->setUseAbsoluteLinks(true);
    $text = $this->getProcessedTemplate($variables, true);

    if($this->isPlain()) {
    $mail->setBodyText($text);
    } else {
    $mail->setBodyHTML($text);
    }

    $mail->setSubject(‘=?utf-8?B?’.base64_encode($this->getProcessedTemplateSubject($variables)).’?=’);
    $mail->setFrom($this->getSenderEmail(), $this->getSenderName());

    $config = array(
    ‘ssl’ => ‘ssl’, //optional
    ‘port’ => 465, //optional – default 25
    ‘auth’ => ‘login’,
    ‘username’ => ‘your_email’,
    ‘password’ => ‘your_password’);

    $transport = new Zend_Mail_Transport_Smtp(‘smtp.gmail.com’, $config);

    try {
    $mail->send($transport); //add $transport object as parameter
    $this->_mail = null;
    }
    catch (Exception $e) {
    return false;
    }

    return true;
    }
    }

    2. 新建一个/app/code/local/(MyNameSpace)/Core/etc/config.xml,内容是

    <?xml version=”1.0″?>
    <config>
    <modules>
    <(MyNameSpace)_Core>
    <version>1.0.0</version>
    </(MyNameSpace)_Core>
    </modules>
    <global>
    <models>
    <core>
    <rewrite>
    <email_template>(MyNameSpace)_Core_Model_Email_Template</email_template>
    </rewrite>
    </core>
    </models>
    </global>
    </config>

    据说因为Zend Framework的一个bug,tag <email_template>必须在一行内封闭,其间不得有多余的white space。我试过,确实如此。

    3. 最后,在Magento注册本次重载:新建一个/app/etc/modules/(MyNameSpace)_Core.xml,内容是:

    <?xml version=”1.0″?>
    <config>
    <modules>
    <(MyNameSpace)_Core>
    <active>true</active>
    <codePool>local</codePool>
    </(MyNameSpace)_Core>
    </modules>
    </config>

    我只是以重载一个model class为例,重载block class也是同样步骤。按Magento的说法,重载controller class有点区别,我尚未亲试。

  • Send mail using Gmail SMTP in Magento

    我能想到的也是大部分人能想到的——我想用gmail smtp server代替magento内置的sendmail,这么做的好处是用gmail sent mail log all emails sent out by magento。gmail smtp server是我所知的唯一一个能记录发送邮件的smtp服务器(感谢google)。

    Magento默认使用MTA发送邮件,后台configuration可以设置使用smtp发送邮件,但仅限于未使用ssl的smtp服务器,看来只能修改程序才能让Magento用上gmail ssl smtp server了。

    似乎有很多人有这个想法但无法成功完成程序的修改。我参照了Use any smtp to send email (even gmail)的代码,但发现它无法连接gmail smtp server (可能以前可以,但gmail smtp server改了设置?)。

    经我修改,在magento 1.1.8版测试可行的代码方案是:

    修改/app/code/core/Mage/Core/Model/Email/Template.php, 找到public function send($email, $name=null, array $variables = array()),删掉此函数中最后几句:

    try {
    $mail->send(); // Zend_Mail warning..
    $this->_mail = null;
    }
    catch (Exception $e) {
    return false;
    }
    return true;

    替换为:

    $config = array(
    'ssl' => 'ssl',
    'port' => 465,
    'auth' => 'login',
    'username' => 'your_email',
    'password' => 'your_password');

    $transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config);

    try {
    $mail->send($transport); //add $transport object as parameter
    $this->_mail = null;
    }
    catch (Exception $e) {
    return false;
    }
    return true;

    除此之外无需任何其他修改。赶紧试一下吧。

    原贴主要的误导之处是一个错误的$config:

    $config = array(
    'ssl' => 'tls',
    'port' => 465,
    'auth' => 'login',
    'username' => 'your_email',
    'password' => 'your_password');

    其实,如果非要使用tls的话,相应的port应该是587。tls+587的搭配虽然能发邮件,但编码不对,我想应该在程序其他地方相应调整。这个我就没去研究了,ssl+465已能正常发送邮件,我的想法已经实现了。