记录一下,2016最后一天把本站从wordpress转到了Magento,从国外转回了国内

WordPress的确是个很不错的blog系统,只是本站的一些内容需要magento系统配合来做演示。再说了,玩得是magento,索性就转到magento来了,保留了原来wordpress的URL 结构,用Bootstrap简单做了个模板。。如你所见的样子了,后面的慢慢折腾完善。

原来网站是放在linode的日本东京机房,速度跟稳定性最近是没法接受了,已经彻底放弃了linode。一些不重要的小站放到了阿里云HK 机房,国内速度还不错。Mageoo.com要认真搞,就去备案了,广东地区的备案速度还算可以,备案很多次基本都是5工作日完成。备案期间网站没完全关闭,蜘蛛放行,广东地区的IP给屏蔽了。反正就这么过关了。

现在网站是放到阿里云深圳的机房,服务器配置是最基本了1核1G的,反正运行起来无压力。带宽太小,用了百度的CDN,按流量付费,现在网站没什么流量一个月也就几块钱的样子。

话说现在网站是  百度CDN ->Nginx(https)->Varnish->Apache  这纯属瞎折腾了,但这也是我改用magento的原因:就是折腾!

Nginx使用CloudFlare CDN加速后获取真实客户端IP

Nginx使用CloudFlare CDN加速后,如果不做处理,通过 $SERVER[“REMOTEADDR”> 获取到的IP会是 CloudFlare的服务器IP Nginx 需要启用http_realip_module目录,
编译的时候带上 –with-http_realip_module
Nginx 配置加上

set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;

# use any of the following two
#real_ip_header CF-Connecting-IP;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

如果 nginx 前面还有一层varnish的话 还要加上varnish的IP

set_real_ip_from   127.0.0.1/32;#与nginx同服务器的情况
set_real_ip_from   具体varnish服务器的ip;#与nginx不同服务器的情况

php通过 $SERVER[“REMOTEADDR”> 就能获取到真实的用户IP

相关文档 :https://support.cloudflare.com/hc/en-us/articles/200170706-How-do-I-restore-original-visitor-IP-with-Nginx-

Magento的Prototype与Bootstrap冲突问题及解决

Magento引入Bootstrap的时候,会产生冲突问题,最明显的就是dropdown等控件在选择的时候会把整个控件给hide了

解决办法

修改 prototype.js 文件,最开头加入下面代码

var isBootstrapEvent = false;
if (window.jQuery) {  
  jQuery('*').on('hide.bs.dropdown', function( event ) {
    isBootstrapEvent = true;
  });
  jQuery('*').on('hide.bs.collapse', function( event ) {
    isBootstrapEvent = true;
  });
  jQuery('*').on('hide.bs.modal', function( event ) {
    isBootstrapEvent = true;
  });
}

大概1931行 修改为

    if(!isBootstrapEvent){
        element.style.display = 'none';
    }

使用Full Page Cache插件Lesti_Fpc加速magento

Magento Full Page Cache插件很多,这里介绍Lesti_Fpc这个免费全页缓存插件。

插件安装

插件下载:https://github.com/GordonLesti/Lesti_Fpc 安装完成后到Cache Management你们可以看到Fpc 这栏。 然后开启它

使用设置

Lesti_Fpc 的后台配置在:ADVANCED > System > Lesti FPC 这里主要说下Lesti_Fpc处理一些动态内容block的问题,例如显示购物车数量的block,这个是不能缓存的。 动态内容的block只需要把布局配置文件layout里面的block name 填入设置的Lazy Blocks中即可。 默认设置的那几个block是magento自带的模板里面的动态内容block。 例如里面的 minicart_head 这个是 rwd模板 右上角 显示 购物车内容的 block 其名称来自文件:/app/design/frontend/rwd/default/layout/checkout.xml

<reference name="header">
            <block type="checkout/cart_minicart" name="minicart_head" template="checkout/cart/minicart.phtml" before="-">
                <block type="checkout/cart_sidebar" name="minicart_content" template="checkout/cart/minicart/items.phtml">
                ...

看了上面的代码,应该是很容易理解了。需要用这个Full Page Cache插件的话就这样根据你的模板来配置。

缓存配置

参考app/etc/fpc.xml.sample 的文件,可以把配置直接放入local.xml文件的节点

Redis

            <backend>Cm_Cache_Backend_Redis</backend>
            <backend_options>
                <server>127.0.0.1</server>
                <port>6379</port>
                <persistent>cache-fpc</persistent>
                <database>1</database>
                <password></password>
                <force_standalone>1</force_standalone>
                <connect_retries>1</connect_retries>
                <lifetimelimit>86400</lifetimelimit>
                <read_timeout>10</read_timeout>
                <compress_data>1</compress_data>
                <compress_tags>1</compress_tags>
                <compress_data>gzip</compress_data>
            </backend_options>

注意设置persistent 的值 ,避免同一个 redis database安装了多个magento造成的冲突

apc

            <backend>apc</backend>
            <prefix>LESTI_FPC_</prefix-->

memcached

<backend>memcached</backend>
            <memcached>
                <servers>
                    <server>
                        <host><![CDATA[127.0.0.1]]></host>
                        <port><![CDATA[11211]]></port>
                        <persistent><![CDATA[1]]></persistent>
                    </server>
                </servers>
                <compression><![CDATA[0]]></compression>
                <cache_dir><![CDATA[]]></cache_dir>
                <hashed_directory_level><![CDATA[]]></hashed_directory_level>
                <hashed_directory_umask><![CDATA[]]></hashed_directory_umask>
                <file_name_prefix><![CDATA[]]></file_name_prefix>
            </memcached>

Magento从当前控制器中获取另外一个控制器中的方法

首先,正常人类是不会这么操作的。当然了,特殊的情况还是会存在的。 Mage.php 文件里面 实例化类的方法 getControllerInstance

    /**
     * Retrieve Controller instance by ClassName
     *
     * @param string $class
     * @param Mage_Core_Controller_Request_Http $request
     * @param Mage_Core_Controller_Response_Http $response
     * @param array $invokeArgs
     * @return Mage_Core_Controller_Front_Action
     */
    public static function getControllerInstance($class, $request, $response, array $invokeArgs = array())
    {
        return new $class($request, $response, $invokeArgs);
    }

这里我们用下面代码获取控制器类的时候会报错

Fatal error: Class 'Mage_Customer_AccountController' not found

$controller = Mage::getControllerInstance('Mage_Customer_AccountController', null, null);

原因是没有加载这个Mage_Customer_AccountController类的php文件。 现在先看看路由的时候怎么加载控制器的Class 的 Mage_Core_Controller_Varien_Router_Standard

public function match(Zend_Controller_Request_Http $request){
            ...
            $controllerClassName = $this->_validateControllerClassName($realModule, $controller);
            if (!$controllerClassName) {
                continue;
            }

        // instantiate controller class
        $controllerInstance = Mage::getControllerInstance($controllerClassName, $request, $front->getResponse());
        ...
}

到了_validateControllerClassName()里面的 _includeControllerClass 才具体include 控制器类文件

    /**
     * Include the file containing controller class if this class is not defined yet
     *
     * @param string $controllerFileName
     * @param string $controllerClassName
     * @return bool
     */
    protected function _includeControllerClass($controllerFileName, $controllerClassName)
    {
        if (!class_exists($controllerClassName, false)) {
            if (!file_exists($controllerFileName)) {
                return false;
            }
            include $controllerFileName;

        if (!class_exists($controllerClassName, false)) {
            throw Mage::exception('Mage_Core', Mage::helper('core')->__('Controller file was loaded but class does not exist'));
        }
    }
    return true;
}

到这里就很明了了。Magento从当前控制器中获取另外一个控制器中的方法就是得先include其他控制的类php文件,后面就是操作一个php类了 这种反人类的做法会不会是我想多了,本文也是为写而写了,实际应用中不建议做这种操作。有错误请帮忙指出。

Magento订单邮件发送给多个收件人的问题

Magento1.9后订单邮件是通过计划任务cron job 发送,待发的邮件都保存到了core_email_queue表里,收件人则保存到了core_email_queue_recipients这个表。 通过计划任务定时发送邮件 和清理已经发送了的邮件。清理的时候是删除了core_email_queue表里的已发送邮件,通过外键约束同时把对应的core_email_queue_recipients表里的收件人 也清理了。 然,有些情况下会碰到Magento订单邮件发送给多个收件人的问题。这个就是外键约束丢失了。

修复代码

注意:这里直接清空了这2个表,要保留未发送邮件的需要自己清理错误的收件人,再修复表即可。

SET FOREIGN_KEY_CHECKS=0;
TRUNCATE `core_email_queue`;
TRUNCATE `core_email_queue_recipients`;
#约束 同时删除,避免重复发错邮件
ALTER TABLE core_email_queue_recipients ADD FOREIGN KEY(message_id) REFERENCES core_email_queue(message_id) ON DELETE CASCADE;
SET FOREIGN_KEY_CHECKS=1;

Magento后台Configuration encrypted 配置加密和解密

后台配置设置的时候有时候需要加密保存,如一些关键的账号密码就不应该明文保存到数据库和显示在前台。 配置代码如下面 后台Configuration encrypted 配置加密的代码

            <app_secret translate="label"> 
              <label>app_secret</label>  
              <frontend_type>password</frontend_type>  
              <backend_model>adminhtml/system_config_backend_encrypted</backend_model>  
              <sort_order>2</sort_order>  
              <show_in_default>1</show_in_default>  
              <show_in_website>1</show_in_website>  
              <show_in_store>0</show_in_store> 
            </app_secret>  

获取值得代码

        $appSecret = Mage::getStoreConfig('facebook_login/setting/app_secret', $storeId);

直接拿getStoreConfig 获取到的值是经过加密的,还需要解密才能用。 解密代码

        $appSecret = Mage::helper('core')->decrypt($appSecret);

其他问题,配置文件中设置<frontend_type>password</frontend_type>的时候,前台还是能看到明文字符的。 frontend-type-password 要不显示明文字符,配置文件中设置<frontend_type>obscure</frontend_type>即可。

frontend-type-obscure

Magento2.x中文语言包及安装使用

本站版本的 Magento2.x中文语言包 还在整理中,先把一份[作者:木瓜]的共享出来。 如果需要最新Magento1.x中文语言包请到这里 magento1.x中文语言包下载地址

下载

magento2中文语言包

安装

上传到mage2.store/app/i18n/Magento/zh_Hans_CN文件夹 【备注:mage2.store/vendor/magento/language-zh_hans_cn】 运行脚本命令:

bin/magento setup:static-content:deploy zh_Hans_CN

使用

后台显示中文界面

编辑后台用户账号,把Interface Locale 设为中文。如下图: magento2-chinese-lang-1 magento2-chinese-lang-2  

前台使用中文

修改店铺配置,把Locale Options 下面的locale 设为中文,如下图: magento2-chinese-lang-4 magento2-chinese-lang-3

Magento中文语言包

长期维护Magento中文语言包,Magento新版本发布后会及时把对应的更新放出来。

本语言包特点:
– 在目前网上流传的中文语言包的基础上,修正了很多翻译,尤其是一些完全错误的翻译。
– 语言包管理做成了Magento 的一个插件,能及时发现新增翻译字段,也方便翻译调试。

不足之处是 没有100%的翻译成中文,也不打算这么干。

Magento 1.x 中文语言包下载地址

Magento 1.9.3.2 翻译就多了一个字段,忽略不计了。

  1. Mage_Page.csv  © 2017 Magento Demo Store. All Rights Reserved.

Magento 1.9.3.1 中文语言包无新增翻译字段

Magento 1.9.3 中文语言包
Magento1.9.3最新中文语言包-20161030

Magento 2.x 中文语言包下载地址

如果需要最新Magento1.x中文语言包请到这里 magento2.x中文语言包下载地址