phper10问10答
在PPC看到这样一篇,觉得很有感触,很多东西都有些忘了,有些东西是不能放的,其地址为:http://bbs.phpchina.com/viewthread.php?tid=174331
其内容及答案如下:
1.首先看了PHP的源码API函数,对于许多口水仗的争论一笑而过,只是停留在脚本级别上的什么效率,安全。。。之争完全就是无稽之谈,没有深入理解API,所有的争论都是臆测和不科学的态度。你做了吗?
答:没有
2.不再把PHP看作一门后台语言,而是一门类似JS的脚本,页面表现级的语言,更多的是尝试使用一种软件来做后台,PHP做前台,尝试真正的B/S开发。你的看法呢?
答:我认为PHP会有更好的发展,我始终坚信这一点!
3.知识更新。PHP中的接口你懂了吗?反射你听过吗?JS中的事件冒泡你懂了吗?原型链知道吗?一切函数都是对象,你能理解否?MYSQL里面的视图,存储过程你尝试过么有?
答:已经2年没写过JS了该忘的不该忘的已经全忘了。。。反射在用。JS PASS吧。。不知道。。可以理解。。目前还没用过视图和存储过程,我不推荐用mysql 来做过程
4.扎实的学知识。你是不是离开了JQ框架就连个DOM操作的原生JS都不会写了?你是不是离开了DB类,就连个简单的查询都不会写了?你是不是离开了IDE,连个表格都画不出来?你是不是到现在多表查询,子查询都还不会?你是不是到现在就只知道索引是用来加快查询的?
你是不是到现在连个PHP5的稍微复杂点的OO类都还不会写?你会正则吗?你的E文水平咋样?
答:JS继续PASS吧。。不会DB操作曾经在纸上写到吐我感觉我这辈子都忘不了。。同上写到吐(这算不算基础扎实,自嘲一下)。。继续同上。。目前对于索引我知道的确实不多
5.扎实的算法基础。你知道选择排序,插入排序,冒泡排序,二分排序,希尔排序并且能写出来吗?你知道怎么遍历二叉树吗?知道霍夫曼吗?你知道图吗?你知道龙格-库塔,迭代,插值,雅戈尔,牛顿下山法吗?知道ZIP压缩原理吗?你是不是可爱到以为加减乘除加上循环判断就搞定了算法?你知道概率论,微积分,线性方程组在算法中是非常非常基础的吗?
答:在做游戏中学到了比较多的算法,但是对于题目上的好像80%没用过,也没有了解过
6.学习的主动性。你是不是自己的网站连个拿的出手的JS都没有写过?你网站的效果是不是都是你下载的JQ插件弄出来的?到现在都还没有看过JQ的代码?你现在的模板引擎是谁的?DB类是谁的?框架是谁的?你是不是一直都很鄙视重复造轮子的事情,就像中国现在,“拿来主义”,永远是MADE IN CHINA,而不是Created in China?
答:JS继续PASS吧。。PASS。。模板引擎是smarty。。。DB类是主程写的(写的真的很风骚)。。主程。。。我很鄙视重复造轮子,我是拿来主义者,其实写框架在中国已经变味了我感觉,拼的无非就是utils\helper
7.广泛的基础。你会汇编吗?那C总该会点吧。。那C++呢,那简单的JAVA总该会吧。。。那。。那傻瓜化的VB,NET,PY。。。?什么,你只会PHP?其他啥都不会?JS总该会吧?啊,不会,只会用网上下来的JQ?你除了PHP还会点啥?那假如PHP垮台了或者你所在的公司不用PHP了你吃什么?如果老板让你学J2SE你怕不怕?
答:不会。。不会。。想往游戏圈深入发展,所以目前在学习C++中。。python会一点。。。好吧JS继续pass吧
8.你是不是就准备一辈子做个coder?你的知识如果让你传授给别人的话,能支撑三个月吗?三个月后你还能讲得出点其他的东西吗?
答:争取做到每天学习,摄取新知识。。后面这个我无法估计
9.你现在的水平和你刚开始学的时候进步了多少?你有过自己的作品吗?有多少代码是你自己写的?你认为是不是只要会写PHP代码就够了?这样的话一个初中生三个月后也就能达到你的水平了,你认为呢?你准备一直停留在这个水平吗?
答:准确的说我曾经有过1年时间丝毫没有一点进步,来京之后进入了一家游戏公司技术得到飞速的提升,但是那一年让我的基本功做的非常扎实!其实我更加想做一个管理者!我不知道我的IT激情还能燃烧多久,如果没有了燃料我可能会转型到其他行业吧!
10.最后一问,你除了会写仅会的PHP代码,还会点其他的吗?你有把握做其他工作吗?你能养活自己老婆孩子吗?能给他们幸福吗?
答:我在努力,我觉得只有在逆境中才会有进步!老天赐给我一个妞吧!!!
建议其它的phper也可以问下自己
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.
写空反而没事了
好了就写到这了。
使用 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;
}
}
这段逻辑基本上可以应付大多数的权重和机率问题! 当然,如果你有更复杂更精确的需求,你可能需要自己设计一个特别的算法。
使用 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";