Day: December 13, 2008

  • No deplicate posts any more in WordPress

    刚用上WordPress后,我发现WordPress一个不足之处——同一个post_id的post,可以用不同的url来访问。

    以此blog为例,我设置permanent link structure为/%post_id%/%postname%/。我认为post_id查询最快,postname又是meaningful string,最有利seo,所以我把两者结合起来了(后来据说顶层目录的文件最利于seo,所以我更喜欢设置permanent link structure为/%postname%_%post_id%.html,但据说Google不吃这一套,那我就没必要为一些小引擎去劳师动众修改现有的blog,扯远了)。

    当permanent link structure存在post_id和postname两个参数时,post_id起决定作用。早期版本会完全忽略postname,造成只要post_id是正确的,任何杜撰的postname都会被承认。设想一下,如果我发布了一个post以后修改了postname,搜索引擎读到不同url上的相同内容,肯定会降低对此blog的评价。

    所以,当时我想改一下WordPress程序逻辑,当post_id存在但url中的postname不等于数据库中的postname时,返回404页。但是我还没来得及做这个修改,今天惊喜发现WordPress 2.6 (可能更早的版本已经实现了这个修改) 已经会把/(post_id)/(incorrect_postname) 301跳转到 /(post_id)/(postname),这应该比我设计的方案更完好,我非常喜欢WordPress的体贴。

  • 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已能正常发送邮件,我的想法已经实现了。