根据日期取得当前的星期

PHP的date函数是有时间范围区间的,即只能从1970~2038年,因此在这个区间范围之外的算法都是不准的。那倒底怎么算呢?其实是有一个公式的:

蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1

公 式中的符号含义如下,w:星期;c:世纪-1;y:年(两位数);m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的 13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算);d:日;[ ]代表取整,即只要整数部分。(C是世纪数减一,y是年份后两位,M是月份,d是日数。1月和2月要按上一年的13月和 14月来算,这时C和y均按上一年取值。)

算出来的W除以7,余数是几就是星期几。如果余数是0,则为星期日。【膘叔备注,如果小于0,则先+7再取余数

以2049年10月1日(100周年国庆)为例,用蔡勒(Zeller)公式进行计算,过程如下:
蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
=49+[49/4]+[20/4]-2×20+[26× (10+1)/10]+1-1
=49+[12.25]+5-40+[28.6]
=49+12+5-40+28
=54 (除以7余5)
即2049年10月1日(100周年国庆)是星期5。

你的生日(出生时、今年、明年)是星期几?不妨试一试。
但其实上面的并不是特别准,我根据上面的公式写了一段代码。。。

//蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
function getDayofWeek ( $datetime , $delimiter = '-' )
{
        //其实这个explode,可以参考split函数,它的分隔支持类似正则的批量处理,比如split("[/.-]",$datetime),可以查一下手册
	list($year,$month,$day) = explode( $delimiter, $datetime );
	if(strLen( $year ) == 2 && $year < 50){
		$century = 20;	//世纪数为当前世纪数-1
	}else{
		$century = subStr( $year, 0,2 ) ;
		$year = subStr( $year, -2 );
	}
	$week = ( $year + floor($year/4) + floor($century / 4) - 2*$century + floor( 26*($month+1)/10)+$day-1 ) % 7; //floor($year/4),代表不取小数点后的值,即,不四舍五入
	return ($week + 7 ) % 7;	//如果有负数出现,则转为正数再取模,就是正常的星期了。
}

echo( getDayofWeek( '1999-05-02') );

上面部分文字来自于http://www.neatstudio.com/show-1174-1.shtml

jQuery图片自动缩放

半年前写的代码,现在看看也不算太差就放上来了

$(document).ready(function(){
    $('div').autoResize({height:50});  //用法
});  

jQuery.fn.autoResize = function(options)
{
    var opts = {
        'width' : 400,
        'height': 300
    }
    var opt = $.extend(true, {},opts,options || {});
    width = opt.width;
    height = opt.height;
    $('img',this).each(function(){
        var image = new Image();
        image.src = $(this).attr('src');
        //开始检查图片
        if(image.width > 0 && image.height > 0 ){
            var image_rate = 1;
            if( (width / image.width) < (height / image.height)){
                image_rate = width / image.width ;
            }else{
                image_rate = height / image.height ;
            }
            if ( image_rate <= 1){
                $(this).width(image.width * image_rate);
                $(this).height(image.height * image_rate);
            }
        }
    });
}

用法也写在上面了。可以直接使用。。。

为Zend的table加上prefix

我不知道别人是怎么做的。我做的很累啊。。。明明在继承Zend_Db_Table_Abstract的类中打印getAdapter方法时,有_config变量,但是,它是protected的,没有找到合适的方法调用。
于是没办法。到bootstrap.php文件里加了一个方法。

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected $_bootConfig;

    public function  __construct( $application ) {
        parent::__construct($application);
        $this->_bootConfig = new Zend_Config_Ini( APPLICATION_PATH . '/configs/application.ini' );
        Zend_Registry::set('config', $this->_bootConfig);
    }
}

这样。我在bootstrap中也能直接使用 $this->_bootConfig 的变量。因为我使用了smarty,而且用的不是继承的方法。所以直接在__construct方法中把config变量赋值出来也有一定的方便之处。
就象这样:

    public function _initView()
    {
        require_once ('Smarty/Smarty.class.php');
        $tpl = new Smarty();
        $tplSettings = $this->_bootConfig->staging->smarty->toArray();
        foreach( $tplSettings as $key=>$value){
            $tpl->$key = $value;
        }
        Zend_Registry::set( 'tpl', $tpl);
    }

这样 _initView 之后,一定要在 application.ini里设置
resources.frontController.noViewRenderer = 1
不过这样就没有办法用zend_view的layout 。。。
于是我现在就在Zend_Db_Table_Abstract的继承类里用 init方法加了简单的处理

    public function init(){
        $config = Zend_Registry::get('config')->toArray();
        if(isset( $config['production']['resources']['db']['params']['prefix'] )){
            $prefix = strval( $config['production']['resources']['db']['params']['prefix'] );
            $this->_name =  $prefix . $this->_name ;
        }
    }

Over。解决。。。。

简单学习一下Zend_ACL

如果不想用rbac那么,简单权限管理ACL,应该是最方便的了。简要说一下原理吧。。
这个文件是放在/application/models/目录下的Acl.php,调用的时候就直接

$identity = Zend_Auth::getInstance()->getIdentity();
$acl = new Application_Model_Acl();
//然后判断
if( $acl->isAllowed( $identity['Role'] , 'xxxxx' ,'yyyy' )); //xxxx是controller名,yyyy是controller里的action名称。不用额外加action。。。
class Application_Model_Acl extends Zend_Acl
{

	public function __construct()
	{
		/*
		 *  第一次添加权限 "guest" ,支持查看所有的内容
		 */
		$this->addRole(new Zend_Acl_Role('guest'));

		/*
		 * 添加 'user' 组权限,权限大于 guest
		 * 用户组能够发表回复
		 */
		$this->addRole(new Zend_Acl_Role('user'), 'guest');

		/*
		 * 添加一个auth组
		 * auth用户权限基于user,并且可以发表文章
		 */
		$this->addRole(new Zend_Acl_Role('auth'), 'user');

		/*
		 * 添加admin组权限,可以做任何事情
		 */
		$this->addRole(new Zend_Acl_Role('admin'), 'blogger');

		//添加允许使用的Resource(也就是controller名啦),这是posts controller
		$this->add(new Zend_Acl_Resource('posts'));

		//添加允许使用的Resource(也就是controller名啦),这是comments controller
		$this->add(new Zend_Acl_Resource('comments'));

		//最后,添加权限,guest用户组可以执行posts controller下的view方法
		$this->allow('guest', 'posts', 'view');

		//User组可以执行 comments controller下的Add 方法
		$this->allow('user', 'comments', 'add');

		// auth 除了上面的功能外还能够支持 posts controller 中的Edit和add方法
		$this->allow('auth', 'posts', 'edit');
		$this->allow('auth', 'posts', 'add');
	}

}

是不是很方便?ACL就是这样的方便 。。

QeePHP中的优秀函数(三)

这几个函数还是来自于QeePHP的核心类Q中。不过,我是自认为,我的configure类有部分写的比他好,不过我没有考虑删除之类的。呵呵。

    /**
     * 获取指定的设置内容
     *
     * $option 参数指定要获取的设置名。
     * 如果设置中找不到指定的选项,则返回由 $default 参数指定的值。
     *
     * @code php
     * $option_value = Q::ini('my_option');
     * @endcode
     *
     * 对于层次化的设置信息,可以通过在 $option 中使用“/”符号来指定。
     *
     * 例如有一个名为 option_group 的设置项,其中包含三个子项目。
     * 现在要查询其中的 my_option 设置项的内容。
     *
     * @code php
     * // +--- option_group
     * //   +-- my_option  = this is my_option
     * //   +-- my_option2 = this is my_option2
     * //   \-- my_option3 = this is my_option3
     *
     * // 查询 option_group 设置组里面的 my_option 项
     * // 将会显示 this is my_option
     * echo Q::ini('option_group/my_option');
     * @endcode
     *
     * 要读取更深层次的设置项,可以使用更多的“/”符号,但太多层次会导致读取速度变慢。
     *
     * 如果要获得所有设置项的内容,将 $option 参数指定为 '/' 即可:
     *
     * @code php
     * // 获取所有设置项的内容
     * $all = Q::ini('/');
     * @endcode
     *
     * @param string $option 要获取设置项的名称
     * @param mixed $default 当设置不存在时要返回的设置默认值
     *
     * @return mixed 返回设置项的值
     */
    static function ini($option, $default = null)
    {
        if ($option == '/') return self::$_ini;

        if (strpos($option, '/') === false)
        {
            return array_key_exists($option, self::$_ini)
                ? self::$_ini[$option]
                : $default;
        }

        $parts = explode('/', $option);
        $pos =& self::$_ini;
        foreach ($parts as $part)
        {
            if (!isset($pos[$part])) return $default;
            $pos =& $pos[$part];
        }
        return $pos;
    }

    /**
     * 修改指定设置的内容
     *
     * 当 $option 参数是字符串时,$option 指定了要修改的设置项。
     * $data 则是要为该设置项指定的新数据。
     *
     * @code php
     * // 修改一个设置项
     * Q::changeIni('option_group/my_option2', 'new value');
     * @endcode
     *
     * 如果 $option 是一个数组,则假定要修改多个设置项。
     * 那么 $option 则是一个由设置项名称和设置值组成的名值对,或者是一个嵌套数组。
     *
     * @code php
     * // 假设已有的设置为
     * // +--- option_1 = old value
     * // +--- option_group
     * //   +-- option1 = old value
     * //   +-- option2 = old value
     * //   \-- option3 = old value
     *
     * // 修改多个设置项
     * $arr = array(
     *      'option_1' => 'value 1',
     *      'option_2' => 'value 2',
     *      'option_group/option2' => 'new value',
     * );
     * Q::changeIni($arr);
     *
     * // 修改后
     * // +--- option_1 = value 1
     * // +--- option_2 = value 2
     * // +--- option_group
     * //   +-- option1 = old value
     * //   +-- option2 = new value
     * //   \-- option3 = old value
     * @endcode
     *
     * 上述代码展示了 Q::changeIni() 的一个重要特性:保持已有设置的层次结构。
     *
     * 因此如果要完全替换某个设置项和其子项目,应该使用 Q::replaceIni() 方法。
     *
     * @param string|array $option 要修改的设置项名称,或包含多个设置项目的数组
     * @param mixed $data 指定设置项的新值
     */
    static function changeIni($option, $data = null)
    {
        if (is_array($option))
        {
            foreach ($option as $key => $value)
            {
                self::changeIni($key, $value);
            }
            return;
        }

        if (!is_array($data))
        {
            if (strpos($option, '/') === false)
            {
                self::$_ini[$option] = $data;
                return;
            }

            $parts = explode('/', $option);
            $max = count($parts) - 1;
            $pos =& self::$_ini;
            for ($i = 0; $i < = $max; $i ++)
            {
                $part = $parts[$i];
                if ($i < $max)
                {
                    if (!isset($pos[$part]))
                    {
                        $pos[$part] = array();
                    }
                    $pos =& $pos[$part];
                }
                else
                {
                    $pos[$part] = $data;
                }
            }
        }
        else
        {
            foreach ($data as $key => $value)
            {
                self::changeIni($option . '/' . $key, $value);
            }
        }
    }

    /**
     * 替换已有的设置值
     *
     * Q::replaceIni() 表面上看和 Q::changeIni() 类似。
     * 但是 Q::replaceIni() 不会保持已有设置的层次结构,
     * 而是直接替换到指定的设置项及其子项目。
     *
     * @code php
     * // 假设已有的设置为
     * // +--- option_1 = old value
     * // +--- option_group
     * //   +-- option1 = old value
     * //   +-- option2 = old value
     * //   \-- option3 = old value
     *
     * // 替换多个设置项
     * $arr = array(
     *      'option_1' => 'value 1',
     *      'option_2' => 'value 2',
     *      'option_group/option2' => 'new value',
     * );
     * Q::replaceIni($arr);
     *
     * // 修改后
     * // +--- option_1 = value 1
     * // +--- option_2 = value 2
     * // +--- option_group
     * //   +-- option2 = new value
     * @endcode
     *
     * 从上述代码的执行结果可以看出 Q::replaceIni() 和 Q::changeIni() 的重要区别。
     *
     * 不过由于 Q::replaceIni() 速度比 Q::changeIni() 快很多,
     * 因此应该尽量使用 Q::replaceIni() 来代替 Q::changeIni()。
     *
     * @param string|array $option 要修改的设置项名称,或包含多个设置项目的数组
     * @param mixed $data 指定设置项的新值
     */
    static function replaceIni($option, $data = null)
    {
        if (is_array($option))
        {
            self::$_ini = array_merge(self::$_ini, $option);
        }
        else
        {
            self::$_ini[$option] = $data;
        }
    }

    /**
     * 删除指定的设置
     *
     * Q::cleanIni() 可以删除指定的设置项目及其子项目。
     *
     * @param mixed $option 要删除的设置项名称
     */
    static function cleanIni($option)
    {
        if (strpos($option, '/') === false)
        {
            unset(self::$_ini[$option]);
        }
        else
        {
            $parts = explode('/', $option);
            $max = count($parts) - 1;
            $pos =& self::$_ini;
            for ($i = 0; $i < = $max; $i ++)
            {
                $part = $parts[$i];
                if ($i < $max)
                {
                    if (!isset($pos[$part]))
                    {
                        $pos[$part] = array();
                    }
                    $pos =& $pos[$part];
                }
                else
                {
                    unset($pos[$part]);
                }
            }
        }
    }

QeePHP中的优秀函数(二)

这两个函数来自于Helper_Array,我觉得是非常常用的方法,功能也比较强大。适合大家使用。

    /**
     * 将一个平面的二维数组按照指定的字段转换为树状结构
     *
     * 用法:
     * @code php
     * $rows = array(
     *     array('id' => 1, 'value' => '1-1', 'parent' => 0),
     *     array('id' => 2, 'value' => '2-1', 'parent' => 0),
     *     array('id' => 3, 'value' => '3-1', 'parent' => 0),
     *
     *     array('id' => 7, 'value' => '2-1-1', 'parent' => 2),
     *     array('id' => 8, 'value' => '2-1-2', 'parent' => 2),
     *     array('id' => 9, 'value' => '3-1-1', 'parent' => 3),
     *     array('id' => 10, 'value' => '3-1-1-1', 'parent' => 9),
     * );
     *
     * $tree = Helper_Array::tree($rows, 'id', 'parent', 'nodes');
     *
     * dump($tree);
     *   // 输出结果为:
     *   // array(
     *   //   array('id' => 1, ..., 'nodes' => array()),
     *   //   array('id' => 2, ..., 'nodes' => array(
     *   //        array(..., 'parent' => 2, 'nodes' => array()),
     *   //        array(..., 'parent' => 2, 'nodes' => array()),
     *   //   ),
     *   //   array('id' => 3, ..., 'nodes' => array(
     *   //        array('id' => 9, ..., 'parent' => 3, 'nodes' => array(
     *   //             array(..., , 'parent' => 9, 'nodes' => array(),
     *   //        ),
     *   //   ),
     *   // )
     * @endcode
     *
     * 如果要获得任意节点为根的子树,可以使用 $refs 参数:
     * @code php
     * $refs = null;
     * $tree = Helper_Array::tree($rows, 'id', 'parent', 'nodes', $refs);
     *
     * // 输出 id 为 3 的节点及其所有子节点
     * $id = 3;
     * dump($refs[$id]);
     * @endcode
     *
     * @param array $arr 数据源
     * @param string $key_node_id 节点ID字段名
     * @param string $key_parent_id 节点父ID字段名
     * @param string $key_childrens 保存子节点的字段名
     * @param boolean $refs 是否在返回结果中包含节点引用
     *
     * return array 树形结构的数组
     */
    static function toTree($arr, $key_node_id, $key_parent_id = 'parent_id',
                           $key_childrens = 'childrens', & $refs = null)
    {
        $refs = array();
        foreach ($arr as $offset => $row)
        {
            $arr[$offset][$key_childrens] = array();
            $refs[$row[$key_node_id]] =& $arr[$offset];
        }

        $tree = array();
        foreach ($arr as $offset => $row)
        {
            $parent_id = $row[$key_parent_id];
            if ($parent_id)
            {
                if (!isset($refs[$parent_id]))
                {
                    $tree[] =& $arr[$offset];
                    continue;
                }
                $parent =& $refs[$parent_id];
                $parent[$key_childrens][] =& $arr[$offset];
            }
            else
            {
                $tree[] =& $arr[$offset];
            }
        }

        return $tree;
    }

    /**
     * 将树形数组展开为平面的数组
     *
     * 这个方法是 tree() 方法的逆向操作。
     *
     * @param array $tree 树形数组
     * @param string $key_childrens 包含子节点的键名
     *
     * @return array 展开后的数组
     */
    static function treeToArray($tree, $key_childrens = 'childrens')
    {
        $ret = array();
        if (isset($tree[$key_childrens]) && is_array($tree[$key_childrens]))
        {
            $childrens = $tree[$key_childrens];
            unset($tree[$key_childrens]);
            $ret[] = $tree;
            foreach ($childrens as $node)
            {
                $ret = array_merge($ret, self::treeToArray($node, $key_childrens));
            }
        }
        else
        {
            unset($tree[$key_childrens]);
            $ret[] = $tree;
        }
        return $ret;
    }

不过显而易见,这两个函数,都不需要多介绍,tree2list,list2tree,想想也知道怎么用,再加上注释又比较全。
可惜QeePHP不再开发,而ThinkPHP积下来的问题又很多,改动起来也非常痛苦。所以我开始慢慢分析一下。

QeePHP中的优秀函数(一)

基类Q中的normalize。

    /**
     * 对字符串或数组进行格式化,返回格式化后的数组
     *
     * $input 参数如果是字符串,则首先以“,”为分隔符,将字符串转换为一个数组。
     * 接下来对数组中每一个项目使用 trim() 方法去掉首尾的空白字符。最后过滤掉空字符串项目。
     *
     * 该方法的主要用途是将诸如:“item1, item2, item3” 这样的字符串转换为数组。
     *
     * @code php
     * $input = 'item1, item2, item3';
     * $output = Q::normalize($input);
     * // $output 现在是一个数组,结果如下:
     * // $output = array(
     * //   'item1',
     * //   'item2',
     * //   'item3',
     * // );
     *
     * $input = 'item1|item2|item3';
     * // 指定使用什么字符作为分割符
     * $output = Q::normalize($input, '|');
     * @endcode
     *
     * @param array|string $input 要格式化的字符串或数组
     * @param string $delimiter 按照什么字符进行分割
     *
     * @return array 格式化结果
     */
    static function normalize($input, $delimiter = ',')
    {
        if (!is_array($input))
        {
            $input = explode($delimiter, $input);
        }
        $input = array_map('trim', $input);
        return array_filter($input, 'strlen');
    }

看到这个方法,其实应该感觉得到它的用户,确实,大多数情况下,我们都是用explode来分割字符串的,但事实上,你不能保证别人给你的字符串有没有多余的空格,或者无效的字符串,因此,通过这个函数,就可以去除掉很无效的值 。建议使用它来代替explode,但,如果确实是很规则的,还是用explode吧,毕竟,如果这个分割出来的数组很大,效率肯定比explode低很多了。

Google maps API开发(一)

由于自己想在mzditu.com上运用google maps api进行开发,在看到这篇相对比较简单的介绍文章时,就下载下来进行了学习,现在贴上分析代码。

一、加载 Google maps API的JS文件

很明显的,你可以看到,我们加载的JS文件来自于http://ditu.google.com,而后面的apikey则需要到http://code.google.com/intl/zh-CN/apis/maps/signup.html注册申请。(因为,它需要绑定自己的域名,否则不能被正确使用)

二、创建一个简单的应用

1、加载Google地图

//声明一个GMap2全局变量
var map;
function load()
{
    //检查浏览器的兼容性.
    if (GBrowserIsCompatible())
    {
        map = new GMap2(document.getElementById("map")); //加载地图
        map.addControl(new GLargeMapControl()); //增加全功能控件
        map.addControl(new GMapTypeControl()); //设置地图类型
        map.enableScrollWheelZoom(); //设置地图支持滚轮
        map.setCenter(new GLatLng(39.990168, 116.295304), 10); //设置地图的中心坐标
        map.enableDoubleClickZoom(); //开启双击google map会自动放大.
        map.enableScrollWheelZoom(); //开启滚动鼠标自动放大和缩小.
          //
    }
}

2、添加一个创建GMarker的方法

function createMarker(baseIcon, point, html)
{
    var icon = new GIcon(baseIcon);
    var marker = new GMarker(point, icon);
    GEvent.addListener(marker, "click", function() { marker.openInfoWindowHtml(html); });
    return marker;
}

3、调用GMarker方法

var icon = new GIcon(G_DEFAULT_ICON);
var point = new GPoint(116.429114, 39.934322);
var html = '
HelloWorld!
'; var marker = createMarker(icon, point, html); map.addOverlay(marker);

这样一个简单的HelloWorld就显示出来了
通过这个例子我们可以了解到GMap2、GMarker、GIcon这几个核心类的基本应用,现在让我们运行一下这段代码看看实际效果先。

【由于我的runcode插件有问题,请直接到这里下载并测试吧:http://files.cnblogs.com/cyan/01.rar
原文请参考:http://www.cnblogs.com/cyan/archive/2010/03/15/1685867.html

测试最简单的插件

尝试使用wordpress的时候,看了一下插件的简要信息,说白了,就是一个add_filter在调用相关信息。于是参照hello_dolly插件写了一个最简单的插件,也就是在文章内容后面加上一个版权信息。好象除了默认的模版外,其他就没有这样的提示了。所以,我就开始这样的尝试。

/**
 * @package NeatCN Copyright
 * @author neatcn / gouki
 * @version 0.1
 */
/*
Plugin Name: NeatCN WordPress Copyright
Plugin URI: http://neatcn.com/#
Description: 显示文章的版权信息
Author: NeatCN / gouki
Version: 0.1
Author URI: http://neatcn.com/
*/
function neatCopyRight ( $content )
{
	$content .= < <

于是在文章内容结束后就有了这一行信息。当然上面仅仅是测试,我不会满足这点的。于是我对neatCopyRight进行了改进,插件也就变成了0.2版了。

/*
  说明,the_time,the_category这些函数在文章里居然没有输出值,所以还需要研究一下
  0.2是个失败的作品,晚上回家继续研究
 */
function neatCopyRight ( $content )
{
	$postTime = the_time('l, F jS, Y') . the_time();
	$currentCate = the_category(', ');
	$rssLink = post_comments_feed_link('RSS 2.0');
	$content .= < <

本文发表于 $postTime , 隶属于 $currentCate 分类,你可以订阅本文的评论:$rssLink 

EOT;
	echo( $content );
}

第一个插件,连配置啥的都没有。只能算是一个尝试,尝试了一下add_filter函数而己

采用 CURL登录量子统计(二)

本文就全是代码了。。。

$cookiefile = tempnam( './log/' , 'cookie' );//设定cookie文件的路径 。
$ch = curl_init();
$header[]="Content-Type: application/x-www-form-urlencoded";
curl_setopt($ch, CURLOPT_URL, 'http://www.linezing.com/login.php');  //登录地址
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);  //发送header ,其实这个header可以不发送
curl_setopt($ch, CURLOPT_POST, 1);  //这是POST数据
curl_setopt($ch, CURLOPT_POSTFIELDS, 'referer=&webname=index&username=用户名&password=密码&submit=%E7%99%BB%E5%BD%95');//http_build_query( $postData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  //这个是代表curl_exec后取返回成字符串,而不是象WEB一样跳转
curl_setopt($ch, CURLOPT_HEADER, 0);  //curl返回的时候,默认都是带有header信息的,所以这里设为0,代表返回的时候不要header信息
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); //这是在用sniff抓包的时候发现用了gzip,deflate的encoding,
curl_setopt($ch, CURLOPT_REFERER, 'http://www.linezing.com/');//记录来源的Referer
curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefile);
curl_setopt($ch, CURLOPT_COOKIEJAR,$cookiefile);
curl_exec($ch);  //我这里并没有取返回值,主要是把cookie记录下来

curl_setopt($ch, CURLOPT_URL, 'http://www.linezing.com/router.php');  //登录后跳转的网址
//curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefile); 原先我在这里也记录cookie了,但事实上,我这样做之后,反而会把第一次登录时的cookie覆盖了。。。郁闷
//curl_setopt($ch, CURLOPT_COOKIEJAR,$cookiefile);
curl_setopt($ch, CURLOPT_REFERER, 'http://www.linezing.com/');
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_COOKIESESSION,1);
$res = curl_exec($ch);  

curl_setopt($ch, CURLOPT_URL, 'http://tongji.linezing.com/welcome.html');  //welcome页还会再判断是否登录,如果没有登录,会是一段JS跳到www.linezing.com
//curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefile);
//curl_setopt($ch, CURLOPT_COOKIEJAR,$cookiefile);
curl_setopt($ch, CURLOPT_REFERER, 'http://www.linezing.com/');
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_COOKIESESSION,1);
curl_exec($ch);  

curl_setopt($ch, CURLOPT_URL, 'http://tongji.linezing.com/mystat.html');
curl_setopt($ch, CURLOPT_COOKIEFILE,$cookiefile);
curl_setopt($ch, CURLOPT_COOKIEJAR,$cookiefile);
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_COOKIESESSION,1);
$res = curl_exec($ch);  //这里获取返回值,我是想看一下是不是正确。。。
curl_close($ch);
echo htmlSpecialChars( $res );

因为是临时写的代码,所以没有封装,但也算是尽量做了注释。。