Magento错误 - Notice: Undefined index:***app\code\core\Mage\Core\Model\Mysql4\Config.php on line 92的解决办法

今天拷站架Magento
站,又碰到了这种错:

a:4:{i:0;s:116:"Notice: Undefined index
:  0  in ***\app\code\core\Mage\Core\Model\Mysql4\Config.php on line 92
";i:1;s:681:"#0 ***\app\code\core\Mage\Core\Model\Mysql4\Config.php(92): mageCoreErrorHandler(8, 'Undefined index...', 'D:\chen\www\mym...', 92, Array)
#1 ***\app\code\core\Mage\Core\Model\Config.php(344): Mage_Core_Model_Mysql4_Config->loadToXml(Object(Mage_Core_Model_Config))

好吧,抽时间总结一下。。

问题原因

Mysql使用工具
(如PhpMyAdmin / MySQL-Front / Navicat for MySQL / SQLyogEnt等)重载转储文件(也就是重导.sql文件)的时候,默认在执行过程中遇到0值一般会生成新的序列号。

Magento的core_store表的admin的store_id为0;core_store_group表的Default的group_id也为0。

在导入.sql文件的时候,原本的0变成了新的序列号,破坏了Magento原有的数据。

解决办法

1,

执行一遍下面语句。
SET FOREIGN_KEY_CHECKS=0;
update `core_store` set store_id = 0 where code='admin';
update `core_store_group` set group_id = 0 where name='Default';
update `core_website` set website_id = 0 where code='admin';
update `customer_group` set customer_group_id = 0 where customer_group_code='NOT LOGGED IN';
SET FOREIGN_KEY_CHECKS=1;

2,

在导的.sql文件最前面加入:SET SQL_MODE = NO_AUTO_VALUE_ON_ZERO;

补充,

Mysql的模式:NO_AUTO_VALUE_ON_ZERO
这个项影响
AUTO_INCREMENT
列的处理。
正常情况下,当我们向
AUTO_INCREMENT
列插入0或NULL的时候,会产生下一个序列号。
而mode = NO_AUTO_VALUE_ON_ZERO的时候,只有NULL才产生新的序列号,屏蔽了0。

如此,像遇到Magento报错 - Notice: Undefined index :  \app\code\core\Mage\Core\Model\Mysql4\Config.php on line 92
这种问题就解决了。

Magento 多货币设置,Magento显示多货币

本文针对Magento 1.4.0.1,其他版本未测试。

顺便提提Magento后台设置多货币

System - Configuration - Currency Setup
在右边Currency Options里的Allowed currencies勾选,

然后 System - Manage Currency Rates
点击Import自动设置汇率或者自己手动输入,然后保存。

(像Magento安装IPS支付通道就需要先设置人民币CNY的汇率)

如此Magento后台设置多货币的处理就OK了。

<?php if($this->getCurrencyCount()>1): ?>
        <div id="currency_html" style="display:none">
        <?php foreach ($this->getCurrencies() as $_code => $_name): ?>
            <input type="radio" name="currency_radio" id="currency_radio" onclick="changeCurrency('<?php echo $_code ?>')" value="<?php echo $_code ?>"<?php if($_code==$this->getCurrentCurrencyCode()): ?> checked <?php endif; ?>>
                <?php echo $_code ?>
        <?php endforeach; ?>
       </div>
<script type="text/javascript">
//<![CDATA[
function changeCurrency(sObject){
    if(sObject){
        setLocation('<?php echo $this->helper('directory/url')->getSwitchCurrencyUrl() ?>currency/'+sObject);
    }
}
//]]>
document.getElementById('currency_display').innerHTML=document.getElementById('currency_html').innerHTML;
</script>
<?php endif; ?>

Magento前台自定义显示多货币选项

假定用的主题是:app/design/frontend/base/default/
这个,

修改模板文件template/directory/currency.phtml
这个改为以上内容:

然后在头部位置:template/page/html/header.phtml
挑个位置加入以下内容:

<div id="currency_display" ></div>

接着修改布局文件,要加的内容(代号A)都是:

<block type="directory/currency" name="right_currency" before="-" template="directory/currency.phtml"/>

首页显示多货币选项
更改default/layout/cms.xml
,在<cms_page translate="label">这个位置里的<reference name="content">里面加上代号A。

目录页和商品详细页面显示多货币选项
default/layout/catalog.xml
这个文件里的<default><reference name="left">里加入代号A。

后台清空Cache。

重新刷新访问,Magento显示多货币选项如预期的实现了。

有问题留言一起讨论~

PHP - 读取操作IP地址数据库文件QQWry.dat

首先看看QQWry.Data文件的内容结构
,以及解读方式

一、文件结构
文件主要分三个结构
1、文件头,8个字节;
2、数据记录区,不定长度;
3、索引区,长度为 7 的整数倍;

二、文件头
文件头的8个字节分两部分,每个部分4个字节,分别指定了索引区的开始地址和结束地址。所以可以通过两个地址的差值 除 7 后 加 1 可以计算出总的记录数。

二、记录区
记录区的数据需要通过索引区的数据来获得各个数据的起始位置;本区数据记录了IP地址的结束地址和地区字符串;所有地区字符串都以 0×00 为结束。

三、索引区
检索IP对应的地区,关键就是找到IP起始地址对应的索引内容。一个IP索引数据包含7个字节,前4个字节是IP地址起始值,后3个字节是对应的IP数据 记录在文件内的偏移地址;IP数据记录中,前 4 个字节是IP结束地址;紧跟的数据有两种模式: 0×01 模式 和 0×02 模式。

0×01模式,即在IP数据的第5个字节是 0×01,则在后面的 3 个字节是国家地区数据的偏移地址;国家地区数据包括国家和地区这两个字符串。即
—————————————————————
4字节 | 3字节 重定向 0x NN NN NN -> 国家地区数据的文件偏移地址
—————————————————————

0×02模式,即在IP数据的第5个字节是 0×02,则在后面的 3 个字节是国家数据的偏移地址,地区数据是再往后的字符串,以 0×00 截至。即
—————————————————————————–
4字节 | 3字节 重定向 0x NN NN NN -> 国家数据的文件偏移地址 | 地区字符串 | 0×00
—————————————————————————–

对于 0×01 模式所得到的 国家地区数据中,它可能又带有一个重定向结构,即
————————————–
国家字符串 | 0×00 | 地区字符串 | 0×00
————————————–

————————————————————————-
国家字符串 | 0×00 | 0×02 | 3字节 0x NN NN NN -> 地区字符串的文件偏移地址
————————————————————————-

对于前一种情况,比较简单,直接读出两个字符串数据就可以了;对于后一种情况,需要再次重定向到地区字符串的偏移地址,然后读取到 0×00 为字符串结尾。

对于这种采取地址映射实际字符串值的方式,主要作用是避免重复记录字符串值。在整个IP地址库文件中,有太多相同字符串记录了,采用 3 字节的映射地址要比重复记录字符串值节省太多空间了。

PHP代码读取操作QQWry.dat文件

function bin2ip($bin){
	$ip = '';
	$bd = str_split($bin, 1);
	for($i = 4; $i > 0; $i--){
		$ip .= "." . sprintf("%03d", implode('', unpack('s', $bd[$i-1] . chr(0))));
	}
	return substr($ip, 1);
}

//--------------------------------------------------
$f = fopen('QQWry.Dat', 'r');
$c = fread($f, 4);
$d = fread($f, 4);

$index_begin	= implode('', unpack('L', $c));
$index_end		= implode('', unpack('L', $d));
if($index_begin < 0) $index_begin += pow(2, 32);
if($index_end < 0) $index_end += pow(2, 32);

$ip_num = ($index_end - $index_begin) / 7 + 1;

echo "index begin at: $index_begin\n";
echo "index end at: $index_end\n";
echo "ip data count : $ip_num\n";

$output = '';

for($i = 0; $i < $ip_num; $i++){

	//文件指针指到每个IP数据文件的索引取得索引数据(7字节)上
	fseek($f, $i * 7 + $index_begin);
	$ip4 = fread($f, 4); //IP起始地址
	if(strlen($ip4) < 4) exit('data file error');

	$ip3 = fread($f, 3); //IP记录偏移地址
	if(strlen($ip3) < 3) exit('data file error');

	$dataseek = implode('', unpack('L', $ip3 . chr(0)));
	if($dataseek < 0) $index_ip_record += pow(2, 32);

	//指向记录区 $dataseek 位置查找记录
	fseek($f, $dataseek);
	$ipdata = fread($f, 4); //IP结束地址
	if(strlen($ipdata) < 4) exit('data file error');

	$area = '';
	$country = '';

	//读一个标记位
	$flag = fread($f, 1);
	if($flag == chr(1)){ //国家名偏移标记位 模式一 0x01
		$area1seek = fread($f, 3);
		if(strlen($area1seek) < 3) exit('data file error');
		$area1seek = implode('', unpack('L', $area1seek . chr(0)));
		fseek($f, $area1seek);
		$flag = fread($f, 1); //可能又是标记位
	}
	if($flag == chr(2)){ //国家地区 重定向
		$area1seek = fread($f, 3);
		if(strlen($area1seek) < 3) exit('data file error');
		$area1seek = implode('', unpack('L', $area1seek . chr(0)));
		$flag = fread($f, 1);
		if($flag == chr(2)){
			$area2seek = fread($f, 3);
			$area2seek = implode('', unpack('L', $area2seek . chr(0)));
			fseek($f, $area2seek);
		}else{
			fseek($f, -1, SEEK_CUR);
		}
		while(($c = fread($f, 1)) != chr(0)) $area .= $c;
		fseek($f, $area1seek);
		while(($c = fread($f, 1)) != chr(0)) $country .= $c;
	}else{
		fseek($f, -1, SEEK_CUR);
		while(($c = fread($f, 1)) != chr(0)) $country .= $c;

		$flag = fread($f, 1); //如果地区是重定向的
		if($flag == chr(2)){
			$area2seek = fread($f, 3);
			$area2seek = implode('', unpack('L', $area2seek . chr(0)));
			fseek($f, $area2seek);
		}else{
			fseek($f, -1, SEEK_CUR);
		}
		while(($c = fread($f, 1)) != chr(0)) $area .= $c;
	}
	$adata = trim($country) . trim($area); //$country是国家字符串 , $area 是地区字符串
}
fclose($f);

顺便附上QQWry.dat文件下载地址

QQ IP数据库 纯真版20100815
IP数据记录:380573条
数据库大小:7919KB

PHP - 增强性mhash函数

今天使用php的加密函数mhash
的时候,报错: Fatal error
: Call to undefined function mhash()

mhash是php的内置函数但是使用却报错..

一番研究总结两种方法:

1,导入php_mhash.dll扩展文件,除此之外还要导入 libmhash.dll (mhash 库的载入依赖这个文件) ,

在 Apache 的配置文件 Httpd.conf 中加载   LoadFile C:/php/libmhash.dll” 。

2,使用自定义的mhash增强函数。

function hmac_md5($key, $data)
{
    if (extension_loaded('mhash'))
    {
        return bin2hex(mhash
(MHASH_MD5, $data, $key));
    }

    $b = 64;
    if (strlen($key) > $b)
    {
        $key = pack('H*', md5($key));
    }
    $key  = str_pad($key, $b, chr(0x00));
    $ipad = str_pad('', $b, chr(0x36));
    $opad = str_pad('', $b, chr(0x5c));

    $k_ipad = $key ^ $ipad;
    $k_opad = $key ^ $opad;

    return md5($k_opad . pack('H*', md5($k_ipad . $data)));
}

hmac_md5
函数里的参数$key和$data对应mhash原有的3,2参数。

这两个方法都可以顺利的使用上php
mhash
加密函数

Magento调试 - 页面空白,打开错误报告的方法

问题:Magento页面一片空白
没显示什么东西,无法判断是否程序错误,所以要把错误显示打开使之能调试

解决:

1. 在网站根目录的.htaccess文件里加上

php_flag display_errors on
php_value error_reporting 2039
详情看另外一篇文章:(用.htaccess设置 PHP错误显示
)

2. 然后找到/errors/local.xml.sample这个文件,改成/errors/local.xml

3. 接着找到lib/Zend/Cache/Backend/File.php

查找 protected $_options = array( ’cache_dir’ => ‘null’,

替换成 protected $_options = array( ’cache_dir’ => ‘tmp/’,

4. 最后在/index.php文件里把error_reporting(E_ALL | E_STRICT)
;和ini_set('display_errors', 1)
;注释取消。可以再加上Mage::setIsDeveloperMode(true)
;这句配合第二点把magento的开发模式打开

这几步下来Magento的错误报告
就打开啦!

解决jQuery插件Uploadify上传中文文件出现乱码的问题

jQuery.Uploadify是一个方便的jqyery文件上传插件

今天项目需要拿来使用,

但是出现了个问题:上传中文文件的时候会出现乱码

 

通过一番研究,最终解决:

修改uploadify.php文件,

把move_uploaded_file($tempFile,$targetFile); 

改为 move_uploaded_file($tempFile,iconv("UTF-8","gb2312", $targetFile)); 即可。