Setting Sun's Blog – 残阳 彪悍的人生不需要解释~~

29六/101

针对浏览器vim插件的研究

If you're new here, you may want to subscribe to my RSS feed. Thanks for visiting!

firefox就不说了Vimperator,哥一直在用,谁用谁知道 最近使用了一个chrome我被他的运行速度震精了,当时我就湿了 于是很自然的想到有没有vim插件 我找到了三个来代替 Shortcut Manager、Vimlike Smooziee、Vrome(前者的升级) 我先说一下Shortcut Manager 他的优点是可以自定义各种快捷键 缺点是内置系统功能偏少,不得不用javascript去自己实现 如果你设置的快捷键和系统冲突了,他会优先系统(orz,用户至上啊,大老) 但是基本的h、j、k、l、d、o、t用他来实现还是不错的 我已经写了一些快捷键的设置如下

// ==UserScript==
// @ShortcutManager
// @name Scroll down by 200 pixels
// @namespace COXhleP4izwk
// @key j
// @include *
// @execute ScrollDown(["200"])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Scroll left by 150 pixels
// @namespace COXhleP4izwk
// @key h
// @include *
// @execute ScrollLeft(["150"])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Scroll up by 200 pixels
// @namespace COXhleP4izwk
// @key k
// @include *
// @execute ScrollUp(["200"])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Open a new tab last
// @namespace COXhleP4izwk
// @key t
// @include *
// @execute OpenTabLast([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Scroll left by 150 pixel
// @namespace COXhleP4izwk
// @key l
// @include *
// @execute ScrollRight(["150"])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Select the left tab
// @namespace COXhleP4izwk
// @key Alt+h
// @include *
// @execute SelectLeftTab([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Select the right tab
// @namespace COXhleP4izwk
// @key Alt+l
// @include *
// @execute SelectRightTab([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Close the current tab
// @namespace COXhleP4izwk
// @key d
// @include *
// @execute CloseTab([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Go to head of a line
// @namespace COXhleP4izwk
// @key g g
// @include *
// @execute GoToLineHead([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Go to end of a line
// @namespace COXhleP4izwk
// @key Shift+g
// @include *
// @execute GoToLineEnd([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Reload
// @namespace COXhleP4izwk
// @key r
// @include *
// @execute Reload([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Duplicate the current tab
// @namespace COXhleP4izwk
// @key p
// @include *
// @execute DuplicateTab([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Upper directory
// @namespace COXhleP4izwk
// @key u
// @include *
// @execute UpperDirectory([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Focus on the next input element
// @namespace COXhleP4izwk
// @key a
// @include *
// @execute FocusNextElement([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name Focus on the previous input element
// @namespace COXhleP4izwk
// @key s
// @include *
// @execute FocusPrevElement([])
// ==/UserScript==

// ==UserScript==
// @ShortcutManager
// @name View source
// @namespace COXhleP4izwk
// @key f g
// @include *
// @execute ViewSource([])
// ==/UserScript==

因为Vimlike Smooziee、Vrome是升级关系我就挑后面的说了

他基本上已经实现了两种模式的快捷键及insert模式、normal模式
我用的一下除了buffer不用能、QuickHint和Search 比较卡之外,其他目前我还没遇到什么问题

初始化的设置j、k的值太小为15(我了个擦,你想累死人啊)
修改方法为C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\Extensions\godjoomfiimiddapohpmfklhgmbfffjj\0.5.7\frontend\modules\scroll.js
把15改为500
var vertical_moment = 500;
var horizontal_moment = 500;

等待他的更新(不给力啊老湿)

如有新的内容我补上

5三/102

windows下的nginx+php5.3+php-cgi+mysql

引子:

由于工作需要 

准备工作:

1、首先下载最新的nginx http://nginx.org/download/nginx-0.8.34.zip
2、下载PHP5.3 http://windows.php.net/downloads/releases/php-5.3.2-Win32-VC9-x86.zip
3、下载MYSQL http://download.mysql.cn/download_file/zip/5.0/mysql-5.0.22-win32.zip 


配置PHP:

把下载完的php解压到:D:\php 。备份php.ini-development,并将其重命名为php.ini。然后编辑php.ini。

	documentroot.doc_root = ""
	本来我写的是我的项目根目录的,本来发现是错误的,这个稍后在说
	扩展存放目录 extension_dir——更改为真实的扩展存放地址。extension_dir = “ext”
	默认时区更改——在[Date]里面增加:date.timezone = PRC 

因为nginx需要的是cgi方式的php,所以如下几个地方是重点,否则nginx无法打开php文件:

	这里我是copy的别人的,反正我自己使用正常
	enable_dl = On
	cgi.force_redirect = 0
	cgi.fix_pathinfo=1
	fastcgi.impersonate = 1
	cgi.rfc2616_headers = 1 

5.3版本我没有发现php5ts.dll和libmysql.dll两个文件,就不管他了

配置nginx:

将下载下来的nginx解压到D:\nginx目录中,我给conf目录做了些工作,一会直接上配置文件。

nginx.conf 内容详情

	#user  nobody;
	#启动进程
	worker_processes  1; 

	#错误日志及PID文档
	error_log  logs/error.log crit;
	pid        logs/nginx.pid;

	#工作模式及连接数上限
	events {
	    #use epoll;  #windows下好像会出错
	    worker_connections  1024;
	}

	#设定http服务器
	http {
	    #设定负载均衡的服务器列表>#设定负载均衡的服务器列表
	    upstream phpfastcgi {
		server 127.0.0.1:9000 weight=1;
		#server 127.0.0.1:9001 weight=1;
	    }

	    #设定mime类型
	    include       mime.types;
	    default_type  application/octet-stream;
	    charset utf-8;

	    server_names_hash_bucket_size 128;
	    client_header_buffer_size 32k;
	    large_client_header_buffers 4 32k;
	    client_max_body_size 8m;

	    sendfile on;
	    tcp_nopush     on;
	    keepalive_timeout 60;
	    tcp_nodelay on;

	    fastcgi_connect_timeout 300;
	    fastcgi_send_timeout 300;
	    fastcgi_read_timeout 300;
	    fastcgi_buffer_size 64k;
	    fastcgi_buffers 4 64k;
	    fastcgi_busy_buffers_size 128k;
	    fastcgi_temp_file_write_size 128k;

	    #开启gzip模块
	    gzip on;
	    gzip_min_length 1k;
	    gzip_buffers     4 16k;
	    gzip_http_version 1.0;
	    gzip_comp_level 2;
	    gzip_types       text/plain application/x-javascript text/css application/xml;
	    gzip_vary on;

	    #设定日志格式
	    log_format access '$remote_addr - $remote_user [$time_local] "$request" '
	                        '$status $body_bytes_sent "$http_referer" '
	                        '"$http_user_agent" $http_x_forwarded_for';

	    #加载虚拟主机
	    include nginx.servers.conf;
	}

nginx.servers.conf 内容详情

	server
	{
	    listen 80;
	    server_name test.cc;
	    root D:/www/test/webroot;
	    include nginx.location.conf;
	}

nginx.location.conf 内容详情

	index index.html index.htm index.php;
	location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
	    expires 30d;
	}

	location ~ .*\.(js|css)$ {
	    expires 1h;
	}

	location ~ \.php$ {
	    fastcgi_pass phpfastcgi;
	    fastcgi_index index.php;
	    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	    include fastcgi_params;
	}

附送两个.bat

start_php.bat 内容详情

	@ECHO OFF
	ECHO Starting PHP FastCGI
	RunHiddenConsole.exe D:\php\php-cgi.exe -b 127.0.0.1:9000 -c d:\php\php.ini

stop_php.bat 内容详情

	@ECHO OFF
	ECHO Stopping nginx...
	taskkill /F /IM nginx.exe > nul
	echo Stopping PHP FastCGI...
	taskkill /F /IM php-cgi.exe > nul
	exit

一个小工具

http://redmine.lighttpd.net/attachments/660/RunHiddenConsole.zip

还记得我在php.ini说在doc_root写入项目目录地址会问题么,我的问题就是

出现No input file specified.

写空反而没事了

好了就写到这了。

参考文章:

http://www.xiaoxiaozi.com/2009/09/23/1485/

21二/100

使用Locator获取对象实例

一个高效、易懂、便于管理的加载方法,在开发过程中会方便不少。 下面我来说一个比较简单的方法。 首先我们创建一个抽象类LocatorAbs.php

abstract class LocatorAbs
{
	/**
	 * 初始化的对象
	 *
	 * @var array
	 */
	private $_objects = array();

	/**
	 * 魔术方法实现getXXX得到对象
	 *
	 * @param string $name
	 * @param array $arguments
	 * @return object
	 */
	public function __call($name, $arguments)
	{
		$pos = strpos($name, 'get');

		if($pos === false)
		{
			throw new Exception('invalid class name of ' . $name);
		}

		$className = substr($name, 3);
		return $this->get($className);
	}

	/**
	 * 根据一个传入的类名取得实例
	 *
	 * @param string $className
	 * @return object
	 */
	protected function get($className)
	{
		if(array_key_exists($className, $this->_objects))
		{
			return $this->_objects[$className];
		}

		$object = new $className();
		$this->_objects[$className] = $object;

		return $object;
	}
}

这是我们写了一个魔术方法和一个get方法
get方法是用来得到实例对象的,均采用单例模式来实例
魔术方法我们一会才会用到,先不说了。

随后我们创建一个ServiceLocator用来管理我们的业务实例

require_once ROOT_PATH . DIRECTORY_SEPARATOR . 'LocatorAbs.php';
class ServiceLocator extends LocatorAbs
{
	private static $instance;
	private function __construct()
	{}

	/**
	 * 得到ServiceLocator对象实例
	 *
	 * @return ServiceLocator
	 */
	public static function getInstance()
	{
		if(!self::$instance)
		{
			self::$instance = new ServiceLocator();
		}

		return self::$instance;
	}

	/**
	 * 根据一个类名取得一个实例对象
	 *
	 * @param string $className
	 * @return object
	 */
	protected function get($className)
	{
		require_once SERVICE_PATH . DIRECTORY_SEPARATOR . $className . '.php';
		return parent::get($className);
	}

	/**
	 * 取得NiubilityService对象实例
	 *
	 * @return NiubilityService
	 */
	public function getNiubilityService()
	{
		return $this->get('NiubilityService');
	}
}

我们把构造方法私有化,使之不能实例,采用单例模式来实例,是为了确保LocatorAbs中的objects不会丢失
在ServiceLocator中我们有一个方法getNiubilityService,其实可以不用写(因为在LocatorAbs中有个魔术方法可以自动帮助我们做这些事情),但是为了IDE联想忍了。

下面我们来创建两个业务文件
NiubilityService.php

class NiubilityService
{
	public function __construct()
	{}

	public function aa()
	{
		echo "哥的博客 http://www.setting.cc/blog\n";
	}
}

TestService.php

class TestService
{
	/**
	 * ServiceLocator对象实例
	 *
	 * @var ServiceLocator
	 */
	private $serviceLocator;

	public function __construct()
	{
		$this->serviceLocator = ServiceLocator::getInstance();
	}

	public function test()
	{
		echo '感受哥体内的和谐之力吧,P民的世界与哥何干~';
		echo "\n------------华丽的分割线------------\n";

		$niubilityService = $this->serviceLocator->getNiubilityService();
		$niubilityService->aa();
	}
}

现在准备工作已经完成,让我们来看看他是怎么工作的吧!!!

test.php

define(ROOT_PATH, realpath('.'));
define(SERVICE_PATH, realpath('.'));

require_once ROOT_PATH . DIRECTORY_SEPARATOR . 'ServiceLocator.php';

$serviceLocator = ServiceLocator::getInstance();

$niubilityService = $serviceLocator->getNiubilityService();
$niubilityService->aa();

$testService = $serviceLocator->getTestService();
$testService->test();

打印结果如下:

哥的博客 http://www.setting.cc/blog
感受哥体内的和谐之力吧,P民的世界与哥何干~
------------华丽的分割线------------
哥的博客 http://www.setting.cc/blog

我们可以看到,他轻松的完成了各各业务之间的那啥。

$testService由于没有在ServiceLocator中写getTestService方法,所以IDE没有相关的联想

哥刚看完 《看你妹之XXXX》感触颇深,怕被和谐,全名我就不写了。哦一西吧!!!!!

13一/104

便捷的IP数据存储和查询

首先我们需要一个功能健全、容错率高的得到IP方法

    /**
     * 获取客户端IP
     *
     * @return string
     */
    function getClientIP()
    {
        if (isset($_SERVER))
        {
            if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
            {
                $realip = $_SERVER["HTTP_X_FORWARDED_FOR"];
            }
            else if (isset($_SERVER["HTTP_CLIENT_IP"]))
            {
                $realip = $_SERVER["HTTP_CLIENT_IP"];
            }
            else
            {
                $realip = $_SERVER["REMOTE_ADDR"];
            }
        }
        else
        {
            if (getenv("HTTP_X_FORWARDED_FOR"))
            {
                $realip = getenv("HTTP_X_FORWARDED_FOR");
            }
            else if (getenv("HTTP_CLIENT_IP"))
            {
                $realip = getenv("HTTP_CLIENT_IP");
            }
            else
            {
                $realip = getenv("REMOTE_ADDR");
            }
        }

        return addslashes($realip);
    }

如果你只要知道IP地址那么以上代码就可以完成。存储即可。

如果你的需求想要知道这个IP的IP段列表或区域列表,那么恭喜你你杯具了。所以好的数据库设计还是必要的。

PHP自带的函数非常好用,ip2long,long2ip 可以自己去查下手册,保存成int整形入库。

//IP段
$sql = 'select * from `table` where `ip` >= ' . ip2long('10.4.0') . ' AND `ip` <= ' . ip2long('10.4.20.200');

对于没有函数支持的可以用下面方法实现。


function getIp2Long($ip)
{
        $ipList = explode('.', $ip);

        return 16777216 * intval($ipList[0]) + 65536 * intval($ipList[1]) + 256 * intval($ipList[2]) + intval($ipList[3]);
}

function getLong2Ip($ipLong)
{
        $ipList = array();

        for($i = 3 ; $i >= 0 ; $i--)
        {
                $ip = intval($ipLong / pow(256, $i));
                $ipList[] = $ip;
                $ipLong -= pow(256, $i) * $ip;
        }

        return implode('.', $ipList);
}

就先写到这里吧,纯真数据就是这个规则。

17十二/090

使用 PHP 解决机率和权重问题

在程序设计中我们经常会碰到要解决机率或权重相关的问题,例如经常碰到的中奖问题。 有一个百货公司办了一个抽奖活动,一等奖的中奖率是3%,二等奖是5%,三等奖是10%,纪念奖是20%。 处理这个需求,一般的程序员会采用如下的逻辑:

$randKey = mt_rand(1, 100);
$prizeLevel = 0;

if ($randKey <= 3)
{
	$prizeLevel = 1;
}
elseif ($randKey <= 3 + 5)
{
	$prizeLevel = 2;
}
elseif ($randKey <= 3 + 5 + 10)
{
	$prizeLevel = 3;
}
elseif ($randKey <= 3 + 5 + 10 + 20)
{
	$prizeLevel = 4;
}

这段程序似乎有些复杂,我们可以简化一下它:

$prizeInfo = array(
	0 => 62,
	1 => 3,
	2 => 5,
	3 => 10,
	4 => 20
);

$randKey = mt_rand(1, 100);
$radix = 0;

foreach ($prizeInfo as $prizeLevel => $prizeOdds)
{
	$radix += $prizeOdds;

	if ($randKey <= $radix)
	{
		break;
	}
}

权重和机率类似,只是概率总值不固定,我们只想直观的用一个数字的大小来表示想给它多大的机会。 我们修改一下需求,一等奖的权重是5,二等奖是10,三等奖是20,纪念奖是50,没有奖励是100。 实际上,稍微修改一下逻辑,我们就可以处理这个问题了:

$prizeInfo = array(
	0 => 100,
	1 => 5,
	2 => 10,
	3 => 20,
	4 => 50
);

$randKey = mt_rand(1, array_sum($prizeInfo));
$radix = 0;

foreach ($prizeInfo as $prizeLevel => $prizeOdds)
{
	$radix += $prizeOdds;

	if ($randKey <= $radix)
	{
		break;
	}
}

但是实际上,我们在处理更复杂的需求时会发现,即使我们使用了 PHP 中号称更好用线性分布更平均的 mt_rand,统计结果看起来,也不是那么随机,或许这是源于 PHP 本身的问题。 我在设计杀死怪物时按照权重掉落物品的逻辑时,就遇到了这样的问题。 稍作处理后,结果稍微满意了些,基本上,我只是扩大了随机范围,扰乱了权重的顺序。

$prizeInfo = array(
	0 => 100,
	1 => 5,
	2 => 10,
	3 => 20,
	4 => 50
);

$prizeLevels = array_keys($prizeInfo);
shuffle($prizeLevels);

$randKey = rand(1, array_sum($prizeInfo));
$radix = 0;

foreach ($prizeLevels as $prizeLevel)
{
	$radix += $prizeInfo[$prizeLevel];

	if ($randKey <= $radix)
	{
		break;
	}
}

这段逻辑基本上可以应付大多数的权重和机率问题! 当然,如果你有更复杂更精确的需求,你可能需要自己设计一个特别的算法。

转自:http://zivn.me/archives/58

16十二/090

使用 GetText 扩展实现国际化支持

首先,我们构建一个简单的 I18n 工具类 I18n.php:

class I18n
{
    /**
     * 默认语言
     *
     * @var string
     */
    const DEFAULT_LOCALE = 'zh_CN';
    /**
     * 默认编码
     *
     * @var string
     */
    const DEFAULT_CHARSET = 'UTF-8';

    /**
     * 单实例对象序列
     *
     * @var array
     */
    private static $instances = array();
    /**
     * 当前语言
     *
     * @var string
     */
    private static $locale;
    /**
     * 当前域
     *
     * @var string
     */
    private $domain;

    /**
     * 格式化索引
     *
     * @param string $key
     * @return string
     */
    public static function quote($key)
    {
    	return '/\{'.$key.'\}/';
    }

    /**
     * 构造函数
     *
     * @param string $domain
     */
    private function __construct($domain)
    {
    	$this->domain = $domain;

    	bind_textdomain_codeset($this->domain, self::DEFAULT_CHARSET);
    	bindtextdomain($this->domain, LOCALE_DIR);
    }

    /**
     * 获取格式化后的文本
     *
     * @param string $key
     * @param array $params
     * @return string
     */
    public function _($key, $params = null)
    {
        $text = dgettext($this->domain, $key);

        if (empty($params))
        {
        	return $text;
        } else {
        	return preg_replace(
        		array_map('I18n::quote', array_keys($params)),
        		array_values($params),
        		$text
        	);
        }
    }

    /**
     * 取得一个单实例I18n对象
     *
     * @param string $domain
     * @return I18n
     */
    public static function getInstance($domain)
    {
    	if (empty(self::$locale))
    	{
    		self::setLocale(self::DEFAULT_LOCALE);
    	}

    	if (!array_key_exists($domain, self::$instances))
        {
            self::$instances[$domain] = new I18n($domain);
        }

        return self::$instances[$domain];
    }

    /**
     * 设置I18n语言
     *
     * @param string $locale
     */
    public static function setLocale($locale)
    {
    	self::$locale = $locale;
        setlocale(LC_ALL, $locale);
    }
}

然后我们再生成 2 个用于测试的 po 文件。

首先是中文的语言文件 locale\zh_CN\LC_MESSAGES\message.po:

msgid ""
msgstr ""
"Project-Id-Version: message\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2008-06-12 17:26+0800\n"
"PO-Revision-Date: 2009-12-15 20:39+0800\n"
"Last-Translator: Zivn \n"
"Language-Team: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Chinese\n"
"X-Poedit-Country: CHINA\n"
"X-Poedit-SourceCharset: utf-8\n"

msgid "testMsg"
msgstr "这是一条测试信息!你好,{name}!"

msgid "userName"
msgstr "火星梅梅"

然后是英文的语言文件 locale\en_US\LC_MESSAGES\message.po:

"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2008-06-12 17:26+0800\n"
"PO-Revision-Date: 2009-12-15 20:40+0800\n"
"Last-Translator: Zivn \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: English\n"
"X-Poedit-Country: AMERICAN SAMOA\n"
"X-Poedit-SourceCharset: utf-8\n"

msgid "testMsg"
msgstr "This is a test message!Hello,{name}!"

msgid "userName"
msgstr "zivn"

记得要生成二进制的 mo 文件哦。

好了,最后是我们用来测试的主文件:

define('ROOT_PATH', realpath('.'));
define('LOCALE_DIR', ROOT_PATH . DIRECTORY_SEPARATOR . 'locale');

$i18n = I18n::getInstance('message');

// Output: 这是一条测试信息!你好,火星梅梅!
echo $i18n->_('testMsg', array('name' => $i18n->_('userName')))."\n";

// Change Locale
I18n::setLocale('en_US');

// Output: This is a test message!Hello,zivn!
echo $i18n->_('testMsg', array('name' => $i18n->_('userName')))."\n";

转载自http://zivn.me/archives/43

3十二/092

php5.3新加正则功能

$p = "/^(?.*) (?

可以指定返回数组key了

标签: , 2 评论
15十一/091

博客在今天重生了

前些日子博客挂了,一直没有时间重新弄。。

后来有时间了,发现备份有问题,真是杯具啊。。

既然如此就一切重新开始吧。

打造高品质博文~~~~

标签: 1个评论