存档

‘zencart项目’ 分类的存档

解决bluehost主机同域邮件无法发送的问题

2011年11月9日 1 条评论

bluehost主机,用php自带的mail函数给同域的邮件发送邮件的时候会有个问题,比如我的域名是anfirst.com,如果给info@anfirst.com就会失败,原因很简单,因为bluehost本身自带了smtp服务,如果给同域名的邮箱发送邮件,bluehost就错误的以为这个邮箱的服务器就是localhost,即使这个域名的真实mx记录不是这台服务器。
解决办法也很简单,我们要修改bluehost的默认配置。
在cpanel配置面板,从mail下面的mx entry下面进去,从上面的下拉框里选择相应域名,再下面的 MX (Mail Exchanger) 项,点击下面的小小的more链接

在出现的单选列表中,选择 Remote Mail Exchanger 点击change按钮保存。

到此为止,这个问题就已经解决了

有关IIS下zencart的伪静态设置

2010年1月16日 没有评论

公司的zencart 项目放在了window2003的服务器上,为了seo的考虑,开启了搜索引擎优化模块,可是碰到了一个问题,url的伪静态是通过网站根目录下的.htaccess文件来实现的,这需要apache的rewrite模块,可是iis中怎么实现?其实可以通过iis的ISAPI_Rewrite扩展来实现,下载一个ISAPI Rewrite的安装包,Lite免费版本ISAPI_Rewrite Lite (freeware)即可。安装运行后,打开IIS,在网站单击右键选属性,就可以看到ISAPI_Rewrite已经被加入到了ISAPI筛选器中。在ISAPI_Rewrite的安装目录下,找到 httpd.ini 在此文件中输入Rewrite的规则即可,这里的规则基本跟apache的rewrite差不多,不过在我的测试过程中,发现了一些问题,例如http.ini中不能使用%{QUERY_STRING}这样的服务器变量,也不知道是不是我服务器配置的原因,这里我对 zencart 里的.htaccess文件需要经过一些修改解决了这个问题

RewriteRule ^(.*)-p-(.*).html$ index\.php?main_page=product_info&products_id=$2&%{QUERY_STRING} [L]

修改为,无非是一个简单的正则替换

RewriteRule ^(.*)-p-(.*).html(\?(.*))?$ index\.php?main_page=product_info&products_id=$2&$4 [L]

有关zen cart集成支付宝借口时提示ILLEGAL_SIGN 错误解决

2010年1月8日 6 条评论

这次开发zencart的过程中要用过国内大名鼎鼎的支付宝接口,从zencart.cn上下了jack的 zen cart 支付宝模块从后台安装一切ok,可是测试购物的时候遇到了 ILLEGAL_SIGN错误,找了很多答案,仔仔细细看了阿里提供的api文档,还是找不出问题所在。看来得靠自己了,对着firebug,一个个核对网站传输给支付宝的post数据,发现多了 btn_submit.x,btn_submit.x 这两个参数,我把form 的method改成get,从地址栏中去掉这两个参数再打开,成功转向支付宝收银台页面,看来果然是两个参数搞得鬼!
google了下submit.x,得到如下答案
根据图形提交按钮行为W3C的描述 :

When a pointing device is used to click on the image, the form is submitted and the click coordinates passed to the server.
当指针设备用于在图像上点击,表单提交和点击坐标传递给服务器。

The x value is measured in pixels from the left of the image, and the y value in pixels from the top of the image.
在x值的单位是像素从左边的形象,以像素为单位从图像的顶部y值。

The submitted data includes name.x=x-value and name.y=y-value where “name” is the value of the name attribute, and x-value and y-value are the x and y coordinate values, respectively.
提交的数据包括name.x = x值和name.y = y值在“名称”的名称属性值和x值和y值是x和y坐标值。

于是这还是W3C的标准,现在的问题就是如何避免浏览器“多此一举”了,很简单,在表单添加onsubmit=”this.submit();return false;”,即修改zencart的订单确认页面模板tpl_checkout_confirmation_default.php文件中的

echo zen_draw_form(‘checkout_confirmation’, $form_action_url, ‘post’, ‘id=”checkout_confirmation” onsubmit=”submitonce();”‘);

修改为

echo zen_draw_form(‘checkout_confirmation’, $form_action_url, ‘post’, ‘id=”checkout_confirmation” onsubmit=”this.submit();return false;”‘);

javascript 图片loading的实现

2009年9月8日 2 条评论

我们在设计一些图片比较多的网页时,为了增强用户体验,希望图片加载的时候有个loading动画效果,而不是由空白到一下子出来。在zen cart的二次开发过程中同样也遇到了这个问题,下面是我的解决方案。

首页给图片设置一个默认的loading动画,再分配一个id,如<img  id=”loading1″  src=”loading.gif”>实际上加载过程通过一个函数来完成

function addListener(element, type, expression, bubbling)
{
bubbling = bubbling || false;
if(window.addEventListener)    { // Standard
element.addEventListener(type, expression, bubbling);
return true;
} else if(window.attachEvent) { // IE
element.attachEvent('on' + type, expression);
return true;
} else return false;
}

var ImageLoader = function(url){
this.url = url;
this.image = null;
this.loadEvent = null;
};

ImageLoader.prototype = {
load:function(){
this.image = document.createElement('img');
var url = this.url;
var image = this.image;
var loadEvent = this.loadEvent;
addListener(this.image, 'load', function(e){
if(loadEvent != null){
loadEvent(url, image);
}
}, false);
this.image.src = this.url;
},
getImage:function(){
return this.image;
}
};

function loadImage(objId,urls){
var loader = new ImageLoader(urls);
loader.loadEvent = function(url){
obj = document.getElementById(objId);
obj.src = url;
}
loader.load();
}

通过loadImage函数就可以为指定的图片添加加载过程,其中通过addListener 函数注册事件,使得在图片加载完成的时候能够自动替换掉loading.gif这个动画过渡图片。使用代码很简单

<img  id=”loading1″  src=”loading.gif”  />

<script language=”javascript”>

loadImage(“loading1″,”http://www.baidu.com/img/baidu_logo.gif”);

</script>

zen cart 中使用自定义 session

2009年9月5日 1 条评论

    上次给zen cart添加图片验证码功能的时候同时碰到了一个问题,自己定义的session在zen cart程序中读取不到值,后来分析了一下得出如下结论。

    zen cart自定义了session的处理函数,session_save_path设在了/cache/文件夹,在include/configure.php里有个选项 define(‘STORE_SESSIONS’, ‘db’); // use ‘db’ for best support, or ” for file-based storage 设置session的保存方式。

    不同的程序间要想共享session数据,至少要遵循以下几个条件:session_save_path 相同,session_id相同,当然session的保存方式肯定要一样,php默认的session保存方式就是文件存储,而保存目录就在系统的临时目录。

    这里我们要想zen cart 读取到我们自己定义的 session变量,就需要我们在自己的程序里把session的存储目录放到zc目录下的cache文件夹,例如 session_save_path(‘e:/zc/cache’),然后修改zc/include/configure.php文件中 define(‘STORE_SESSIONS’, ‘db’); 修改为 define(‘STORE_SESSIONS’, ”);这样就让zen cart的session也以文件形式存储,就可以实现自定义session的共享了!

    以上的原理适用于其他类似的不同程序间session共享的问题,其实 zen cart中使用自定义 session的最简单的方法是 直接在自己的程序最顶部 require进来zen cart 的application_top.php即可,简单固然简单,但了解原理更重要!

php产生验证码完整案例

2009年8月28日 没有评论

今天继续开发zen cart项目,加上了验证码的功能,考虑到需要较高的安全性,自己手工写了个小程序,功能还算全面,自动检测背景和字体,并随机选取背景图片中的一块范围,随机使用字体,显示验证字符串时随机显示字体大小,字符间距,字符颜色等。以下是程序代码。
validimg.php文件

<?php
/**
* Class for Validate image
* @author  zcs
* @version 1.0-20090828
*/

session_start();
class validimg
{
//背景图片目录
var $backgroundpath = ‘validbg’;
//生成验证码宽度
var $width =’80′;
//生成验证码高度
var $height =’25′;
//背景
var $background;
//验证文本
var $text=’abcd’;
//字体目录
var $fontpath = ‘validbg’;
//字体
var $font=’simhei.ttf’;
//字体宽度
var $font_width = ’20′;

function validimg($text)
{
$this->text = $text;
//随机选取一个背景文件
$bgdir =  @dir($this->backgroundpath);
while(false !== ($image = $bgdir ->read()))
{
if($image != ‘.’ && $image != ‘..’ && $this->checktype($image) != false)
{
$backgroundarr[] = $image;

}
}
$bgdir->close();
//随机选取一个字体文件
$fonts =  @dir($this->fontpath);
while(false !== ($font = $fonts ->read()))
{
if($font != ‘.’ && $font != ‘..’ && $this->checktype($font,’FONT’) != false)
{
$fontsarr[] = $font;
}
}
$fonts->close();
$this->font = $fontsarr[array_rand($fontsarr,1)];
$this->background = $backgroundarr[array_rand($backgroundarr,1)];

$this->output();
}

//创建背景图像handdle
function createbackground()
{
switch ($this->checktype($this->background))
{
case ‘jpg’:
$bghanddle = @imagecreatefromjpeg( $this->backgroundpath.’/’.$this->background);
break;
case ‘gif’:
$bghanddle = @imagecreatefromgif( $this->backgroundpath.’/’.$this->background);
break;
case ‘png’:
$bghanddle = @imagecreatefrompng( $this->backgroundpath.’/’.$this->background);
break;
default:
}
return $bghanddle;
}
//检查文件类型
function checktype( $image,$type = ‘IMAGE’)
{
$ext = substr( $image, strrpos($image,’.')+1);
if($type == ‘IMAGE’)
{
if ($ext == ‘jpg’ || $ext ==’gif’ || $ext ==’png’)
return $ext;
else return false;
}else if($type == ‘FONT’)
{
if ($ext == ‘ttf’)
return $ext;
else return false;
}
}
//输出
function output()
{
header(“content-type:image/png;”);
//生成图像
$img = @imagecreatetruecolor( $this->width,$this->height);
$bghanddle = $this->createbackground();
//从背景图像随机位置载入一块作为背景
if($bghanddle)
{
$randx=rand(0,(imagesx($bghanddle) – $this->width));
$randy=rand(0,(imagesy($bghanddle) – $this->height));
}
imagecopy($img,$bghanddle,0,0,$randx,$randy,$this->width,$this->height);
//随机选择角度 字体大小 坐标输出文字
for($i=0;$i<strlen($this->text);$i++)
{
$angle = rand(-30,30);
$fontsize = rand(15,20);
$x = rand($this->font_width*$i,$this->font_width*$i+10);
$color = imagecolorallocate($img, rand(0,255), rand(0,255), rand(0,255));
imagettftext($img,$fontsize,$angle,$x,20,$color,$this->fontpath.’/’.$this->font,substr($this->text,$i,1));
}
imagepng($img);
//释放资源
imagedestroy($img);
imagedestroy($bghanddle);
}
}

new validimg($_SESSION['valid']);
?>

测试文件validtest.php

<?php
/**
* 验证码测试
* @author  zcs
*/
session_start();
$_SESSION['valid']= randstr();
echo $_SESSION['valid'];

//随机生成字符串

function randstr($num=4)
{
$chars = ‘ABDEFGHJKLMNPQRSTVWXYabdefghijkmnpqrstvwxy23456789′;
$randstr=”;
for($i=0;$i<$num;$i++)
{
$randstr.=substr($chars,rand(0,strlen($chars)),1);
}
return $randstr;
}
?>
<img src=”validimg.php” />

Demo http://anfirst.cn/case/validimg/

代码包下载:validimg

zen cart 的sidebox 机制

2009年8月24日 没有评论

zen cart的左右边栏很有特色,由一块一块的sidebox拼合起来的,在模板的sidebox文件夹建立一个sidebox程序,登陆管理后台后,选择外观控制,系统会自动检测到新增加的sidebox程序,并提醒你操作。并把所有的sidebox配置信息存储在layout_boxes的表格中。

程序调用边栏是通过includes/modules 目录下的column_left.php,和column_right.php 控制。分析下源码也非常简单:首页查询layout_boxes数据表,检索出在左栏和或右栏显示的所有sidebox,再直接require 进来 layout_box_name 字段标记的sidebox名称。随便打开一个sidebox的源代码,如系统自带的includes/modules/sideboxes/banner_box.php,banner_box.php只要用来获取sidebox显示所要的数据,再通过require($template->get_template_dir(‘tpl_banner_box.php’,DIR_WS_TEMPLATE, $current_page_base,’sideboxes’),载入显示这个sidebox的模板,其实这个所谓的模板就是生成一个$content的字符串,然后再require($template->get_template_dir($column_box_default, DIR_WS_TEMPLATE, $current_page_base,’common’) . ‘/’ . $column_box_default) 再用一个显示sidebox的公共模板,在$column_box_default中打印出$content的内容,这样一个sidebox就显示完成了!

如何添加一个自己的sidebox?其实很简单,在includes/modules/sideboxes/{模板目录}/  建立一个文件,就是一个sidebox了,可以在后台控制是否显示在默认的左右边栏和排序 。在这个文件中就输出任何内容了,当然可以按照标准的模式,再在includes/templates/{模板目录}/sideboxes 下建立一个模板文件require进来,尽量做到 M/V的分离,这样以后修改也会比较方便!

zen cart的运行过程

2009年8月23日 2 条评论

zencart是典型的单入口程序,所有的程序的url都是index.php?mainpage=XX的形式,通过$_GET['mainpage']载入相应的页面程序。先说首页的输出过程如下:入口index.php->载入初始化文件application_top.php->载入首页默认变量文件mail_template_vars.php->载入公用模板控制文件tpl_main_template.php->载入方框(sidebox)控制文件column_left.php,column_left.php->载入各个sidebox的控制文件和模板->载入首页默认核心部分模板tpl_index_default.php->载入公共页面底部,到这里就完成了首页的显示。其他页面的显示则是在载入include/pages/ $_GET['mainpage']文件下的文件,基本跟首页相同,只是根据不同页面载入不同配置文件和模板。

初次接触zencart,觉得zencart的模板系统异常的复杂,其最大的特点就是覆盖机制,通过其class/template_func.php模板类的get_template_dir方法,按照预先设定的位置按顺序查找模板文件,这种机制极大的提高了模板修改的灵活性,同时避免影响其他的模板和系统程序,也方便了以后的升级,我像扩充下系统默认的模板很简单,拷贝到我自己的模板相应文件夹,想怎么改就怎么改,也不会担心会跟系统不和谐。

以上皆是根据印象所写,文件名也许错误,下次修正。