过去一年了

突然发现这个blog有一年多没更新了,懒啊~~懒啊~~

以后争取更新有时间就更新下…挨踢员,blog不能停啊

.htaccess 语法配置

在 Windows 资源管理器里面不允许你建立 .htaccess 这样只有扩展名的文件。

用记事本编写好内容后,保存时,文件名要输入为 ”.htaccess”

或者先将文件保存为其他名字,例如 app.htaccess。

然后进入命令行窗口(通过开始菜单运行 cmd.exe 程序即可),

输入 ren app.htaccess .htaccess 命令来对文件改名。

 

1. .htaccess最简单的地址转向设置,文件里只有下面一句话

Redirect permanent /test/soap05/test01.php   http://www.baidu.com/

2. .htaccess 用到的正则表达式

元字符^(和数字6在同一个键位上的符号)和$都匹配一个位置,这和\b有点类 似 ,^匹配你要用来查找的字符串的开头 $匹配结尾。

比如一个网站如果要求你填写的QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$。 \b代表着单词的开头或结尾,也就是单词的分界处,它只匹配一个位置。

\d是个新的元字符,匹配一位数字(0,或1,或2,或……)。

例:0\d{2}-\d{8} 匹配这样的字符串:以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(也就是中国的电话号码。当然,这个例子只能匹配区号为3位的情形)。

\s匹配任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等。

\w匹配字母或数字或下划线或汉字

\来取消字符的特殊意义。可使用\.和\*。要查找\本身,也得用\\.

[ ] 匹配没有预定义元字符的字符集合,在方括号里列出它们就行了

例: [aeiou]就匹配任何一个英文元音字母,[.?!]匹配标点符号(.或?或!) [0-9]代表的含意与\d就是完全一致的:一位数字;
同理[a-z0-9A-Z_]也完全等同于\w
.匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]‘ 的模式。
例子:\(?0\d{2}[) -]?\d{8}。 像(010)88886666,或022-22334455,02912345678等。
分析:首先是一个转义字符\(,它能出现0次或1次(?), 然后是一个0,后面跟着2个数字(\d{2}), 然后是)或-或空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8})。
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

 

3. .htaccess 语法简介
RewriteEngine ON  RewriteCond %{HTTP_HOST} ^abc.com$  [OR] 
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^(.*)$ http://www.999.com/ [R=301,L]
RewriteEngine on RewriteCond %{ HTTP_HOST } ^888.com
RewriteRule ^(.*)$ http://888.com/hot$1 [R=301,L]
RewriteCond %{ HTTP_HOST } ^www.888.comRewriteRule ^(.*)$ http://www.888.com/hot$1 [R=301,L]
RewriteCond的语法如下:       RewriteCond  TestString  CondPattern  [Flags]       其中的TestString是指一个文本格式的条件,例子中用的是环境变量名HTTP_HOST所包含的内容(Name= Value),这是一个map(键值对)格式的数据类型。       CondPattern是条件参数,这儿以第一个例子为例,就是abc.com。       Flags标识是是第三个参数,可以用来紧跟下一个条件,这儿用OR表示或者,如果没有[Flags],则用隐含的AND,表示并且。其它的还可以NC等等,表示忽略大小写
RewriteRule的语法如下:       RewriteRule  Pattern  Substitution [Flags]       其中的Pattern就是参数,一般为一些文件的扩展名,Substitution是用来替换前面用的,这儿的Flags,常用的R表示redirect(强制重定向),F表示forbidden(禁止访问),L表示last(最后),通常当你希望停止重写操作而立即重定向时,可用它。
**防止访问者看到你的.htaccess文件,把下面几行放到你的文件中
(Files .htaccess) order allow,deny deny from all (/Files)
**防止访问者看到你的.htaccess文件,把下面一行放到你的文件中;
AddHandler cgi-script htaccess

Zend Encoder加密PHP源码和如何运行加密代码

前言:

因为php是脚本语言,发布后源码容易暴露,尤其是在使用虚拟主机的时候,如果用Zend Encoder加密后,相当于在源码上加了一层保护,而且据说还加快了程序的运行速度,我们为什么不使用它呢!

教程:

安装软件时,在选择安将目录后会有一个对话框让你选择许可证的地址,这里我们选择下面的在本地磁盘查找,然后在接 下的的对话框中输入我们下载到的许可证文件“zend_encoder.dat”的路径(压缩包的“crack”文件夹里)。(下载Zend Encoder的地址很多,可以从网上搜索)

软 件的使用方法非常的简单,首先选择“File->NewProject”新建一个项目,然后在该项目下添加你要加密的文件或文件夹。在右边的 “Target Directory”选项里输入保存加密PHP文件的路径。然后点“Encode”按钮就可以对当前项目中的PHP文件进行加密了。你还可以将当前项目保 存起来,以便你的PHP文件更新后重新加密。PHP文件加密后,文件大小也变得小多了,以前一个30K的文件加密后只有14K。

技巧:在“Tools->Settings”对话框的“Extensions to Encoder”文本框中你可以对要加密的文件扩展名进行指定(多个扩展名用空格分隔),使Zend Encoder只对这些文件进行加密。

加密后的PHP文件需要服务器上有“ZendOptimizer”才能正常显示,而一般在“Zend Encoder”压缩包的“optimizer_packages”目录中都能够找到该文件,如果没有的话可以到www.zend.com免费下载。安装完成后重新启动WEB服务器就可以正常浏览加密的PHP文件了。而一般的PHP空间都是应该支持“ZendOptimizer”的。

小知识点:zend encoder和zend safeguard有什么区别?

Zend   SafeGuard   Suite   是加密编写的PHP程序,保护源代码的完全解决方案,是一个包括了
Zend   Encoder   +   Zend   License   Manager   的工具套装。

php发送get、post请求获取内容的几种方法

方法1: 用file_get_contents 以get方式获取内容

1
2
3
4
5
<?php
$url='http://www.domain.com/';
$html = file_get_contents($url);
echo $html;
?>

方法2: 用fopen打开url, 以get方式获取内容

1
2
3
4
5
6
7
8
9
10
<?php  
$fp = fopen($url, 'r');  
//返回请求流信息(数组:请求状态,阻塞,返回值是否为空,返回值http头等)
stream_get_meta_data($fp);  
while(!feof($fp)) {  
$result .= fgets($fp, 1024);  
}  
echo "url body: $result";  
fclose($fp);  
?>

方法3:用file_get_contents函数,以post方式获取url

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php  
$data = array ('foo' => 'bar');
//生成url-encode后的请求字符串,将数组转换为字符串  
$data = http_build_query($data);  
$opts = array (  
<span style="white-space:pre">  </span>'http' => array (  
<span style="white-space:pre">      </span>'method' => 'POST',  
<span style="white-space:pre">      </span>'header'=> "Content-type: application/x-www-form-urlencoded\r\n" .  
<span style="white-space:pre">      </span>"Content-Length: " . strlen($data) . "\r\n",  
<span style="white-space:pre">      </span>'content' => $data  
<span style="white-space:pre">  </span>)  
);
//生成请求的句柄文件  
$context = stream_context_create($opts);  
$html = file_get_contents('http://localhost/e/admin/test.html', false, $context);  
echo $html;  
?>

方法4:用fsockopen函数打开url,以get方式获取完整的数据,包括header和body,fsockopen需要 PHP.ini 中 allow_url_fopen 选项开启

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    <?php  
    function get_url ($url,$cookie=false)  
    {  
    $url = parse_url($url);  
    $query = $url[path]."?".$url[query];  
    echo "Query:".$query;  
    $fp = fsockopen( $url[host], $url[port]?$url[port]:80 , $errno, $errstr, 30);  
    if (!$fp) {  
    return false;  
    } else {  
    $request = "GET $query HTTP/1.1\r\n";  
    $request .= "Host: $url[host]\r\n";  
    $request .= "Connection: Close\r\n";  
    if($cookie) $request.="Cookie:   $cookie\n";  
    $request.="\r\n";  
    fwrite($fp,$request);  
    while()) {  
    $result .= @fgets($fp, 1024);  
    }  
    fclose($fp);  
    return $result;  
    }  
    }  
    //获取url的html部分,去掉header  
    function GetUrlHTML($url,$cookie=false)  
    {  
    $rowdata = get_url($url,$cookie);  
    if($rowdata)  
    {  
    $body= stristr($rowdata,"\r\n\r\n");  
    $body=substr($body,4,strlen($body));  
    return $body;  
    }  
        return false;  
    }  
    ?>

方法5:用fsockopen函数打开url,以POST方式获取完整的数据,包括header和body

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    <?php  
    function HTTP_Post($URL,$data,$cookie, $referrer="")  
    {  
        // parsing the given URL  
    $URL_Info=parse_url($URL);  
        // Building referrer  
    if($referrer=="") // if not given use this script as referrer  
    $referrer="111";  
        // making string from $data  
    foreach($data as $key=>$value)  
    $values[]="$key=".urlencode($value);  
    $data_string=implode("&",$values);  
        // Find out which port is needed - if not given use standard (=80)  
    if(!isset($URL_Info["port"]))  
    $URL_Info["port"]=80;  
        // building POST-request:  
    $request.="POST ".$URL_Info["path"]." HTTP/1.1\n";  
    $request.="Host: ".$URL_Info["host"]."\n";  
    $request.="Referer: $referer\n";  
    $request.="Content-type: application/x-www-form-urlencoded\n";  
    $request.="Content-length: ".strlen($data_string)."\n";  
    $request.="Connection: close\n";  
        $request.="Cookie:   $cookie\n";  
        $request.="\n";  
    $request.=$data_string."\n";  
        $fp = fsockopen($URL_Info["host"],$URL_Info["port"]);  
    fputs($fp, $request);  
    while(!feof($fp)) {  
    $result .= fgets($fp, 1024);  
    }  
    fclose($fp);  
        return $result;  
    }  
    ?>

方法6:使用curl库,使用curl库之前,可能需要查看一下php.ini是否已经打开了curl扩展

1
2
3
4
5
6
7
8
9
10
<?php  
$ch = curl_init();  
$timeout = 5;  
curl_setopt ($ch, CURLOPT_URL, 'http://www.domain.com/');  
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);  
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);  
$file_contents = curl_exec($ch);  
curl_close($ch);  
echo $file_contents;  
?>

数据表的设计指南及在YII中的应用

使用单数而不是使用复数来命名表名

我们认为 SQL 表 包含很多记录,一个模型(model) 只是其中的一个,在任何地方使用 $model = new Comments() 来表示再次定义关系时感觉非常奇怪.

命名您的表名为 comment 而不是 comments,invoice 而不是 invoices 等等。对于的模型(model)类名也是一样(Comment,Invoice等等).

如果你不可以改变数据库的模式,但至少在适当的情况下你可以改变 Yii 模型类(model class)的名称,在这种不匹配的情况下你应该在代码中添加一个额外的注释 //COMMENT 来提醒用户.

 

不要在字段名前面加上表名

下面的做法是在传统 SQL 设计模式上非常常见的,但是它在于 ActiveRecord 结合时时冗长复杂的。在 category 表中:

– 不可取 — 可取
create table category ( create table category(
category_id INTEGER …, id INTEGER …,
category_name VARCHAR …, name VARCHAR …,
category_value INTEGER value INTEGER
); );
// 不友好的 // 友好的
$model->category_id $model->id
$model->category_name $model->name
$model->category_value $model->value

不要在模型类(model class)的类名中出现表名的前缀

Yii 支持表前缀,表前缀被用在 所有 应用放到共享的主机并且共享一个数据库的环境中. 你的博客表前缀为 blog_,计时应用的表前缀为 time_等等. 它们存在于同一个数据库中而互相不起冲突.

前缀 tbl_ 在很多教程和例子中经常看到。

但是类不需要包含这些前缀,因为没有必要避免冲突:你的博客应用和你的计时应用时两个不同的应用.

class TblComment extends CActiveRecord { // 不可取
class Comment extends CActiveRecord { // 可取

在代码中看到无处不见的前缀使人们非常反感.

 

确保每个表的主键为 id

大多数表都有一个唯一主机,命名主键为 id(而不是 commentid、postid) 会使你的工作更加顺手.

虽然无论你是否访问数据库 Yii 都可以通过读取数据结构来得到它的主键,但是系统的其他部分可能不会这样做,并且它们依赖的主键为 id.

例子:CArrayDataProvider 默认的主键为 id, 虽然你可以重写它的属性 ‘keyField’, 但是把这放到第一位是很不方便的.

显而易见,当使用复合主键时这将不能工作,但是这毕竟是少数.

 

避免特殊意义的主键名

一个经典的设计错误是创建的表的主键有实际意义. 在下面的列子中 用户(user)表使用的用户名(name)作为主键:

– 不要这么做!
CREATE TABLE user (
name VARCHAR(16) PRIMARY KEY, — bad idea
email VARCHAR…

这样做引发了两个问题:This presents two difficulties:

  1. 当在其他地方 引用 时,它的效率大大降低,因为它包含16个字符而不是4个字节的整数.当大量的 引用 时性能大大降低。
  2. 当系统中存在外键约束时用户想 修改用户名 是很困难的:表中的字段和引用都必须在同一时间改变,这样做的代价时昂贵的。

最好的解决办法时创建一个整型字段作为主键,并设置 name 字段为 unique:

– much better
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(32) NOT NULL UNIQUE,
email …
);

这种方式在用户更新用户名时只修改了一条记录.

 

确认在数据库结构中定义的外键关系

大多数的数据支持定义表之间的关系,一个表中的字段指向另一个表的主键。这些外键帮助保证了数据的完整性当有记录执行某条记录时不允许你删除它.

MySQL的InnoDB 强制使用外键约束,而 MyISAM 允许你 定义 它们,但不会 强制 使用. Yii 知道怎么处理这些关系,并且可以使用 Gii或Giix 自动生成关系.

抛开 Yii ,外键是维护数据库完整性的重要部分,在网络上有许多学习它的教程.

 

使用 “id” 作为外键字段的结尾

通过以上的说明,如果你有一个字段指向一个用户(user),命名这个字段为 userid 而不是 user. 原因是你肯定要为表中的每一个外键定义一个 关系.

在 Yii、类变量、数据字段、虚拟属性、关系共享一个命名空间(namespace), 所以不可能通过 $model->user 的方式来 同时 访问表的外键 关系.

通过外键 userid, $model->user 形式的 BELONGS_TO 关系可以轻松自然的使用:

class Post extends CActiveRecord {
public function relations()
{
return array(
‘user’ => array(self::BELONGS_TO, ‘User’, ‘userid’)
);
}

注意: 有很多人喜欢用 Id 或 _id 来代替 id.这只是个人爱好问题,意义是一样的.

 

在关系的名称(name)上体现它们的单数或复数的特性

继续我们的主题一致性和代码易于阅读,关系应当在名称上体现它们代表的为单数还是复数.

  • HAS_ONE – 返回一个模型(model): 单数
  • BELONGS_TO – 返回一个模型(model): 单数
  • HAS_MANY – 返回一个由多个模型(model)组成的数组: 复数
  • MANY_MANY – 返回一个由多个模型(model)组成的数组: 复数

注意: 对于返回一个数组的关系,它们可能只包含一个模型,但事实上它们是通过复数名称方式认证来的 数组

你只需要通过看关系的名称就会知道它返回的是一个数组还是一个模型:

$model->post
$model->comments
$model->author
$model->members

如果你必须通过查看代码才会知道,那这将会让你的代码更加难以阅读和维护.

YII页面缓存的设置

在YII设置页面缓存主要分为两步:

1. 在config文件加入缓存组件.

‘cache’ => array (

‘class’ => ‘system.caching.CFileCache’,

‘directoryLevel’ => 2,

),

class标识需要使用的缓存媒介,用途比较广的类型基本都有支持:

CMemCache: 使用 PHP memcache 扩展.

CApcCache: 使用 PHP APC 扩展.

CDbCache: 使用一张数据库表来存储缓存数据。

CFileCache: 使用文件来存储缓存数据。 特别适用于大块数据(例如页面)。

 

2. 在要做缓存的控制器里定义过滤器。

public function filters() {

return array (

array (

‘COutputCache + post, list’,

‘duration’ => 3600,

‘varyByParam’ => array(‘id’,'page’),

‘dependency’ => array(

‘class’=>’CDbCacheDependency’,

‘sql’=>’SELECT MAX(id) FROM k1029_article’,

)

);

}

COutputCache 是用于处理缓存的类,如果只填’COutputCache’,则控制器里所有action都会通过缓存过滤,定义’COutputCache + post, list’,表示只对以下方法进行缓存:actionPost, actionList

duration 是缓存的时间,单位是秒,

varyByParam 是指定一系列GET参数名称列表, 使用相应的值去确定缓存内容的版本,即同一个action用于区分是不同页面的的参数,此处我以id和page来区分不同页面。

除varyByParam以外,还可以采用其他的条件来区分页面:

varyByExpression:指定缓存内容通过自定义的PHP表达式的结果而变化

varyByRoute:指定缓存内容基于请求的路由不同而变化 (controller 和 action)

varyBySession:指定是否缓存内容. 因用户session不同而变化

dependency’指定缓存失效依赖关系:可指定文件或数据库;本文采用的是数据库依赖CDbCacheDependency;

本例指定的是数据库,通过数据表的某个值的变化来确定缓存是否失效。例如,如果在表中新增了一条k1029_article记录,即使缓存才过了2分钟(<3600),仍然判断为失效,从而查询数据库,生成整个页面,再次缓存;

 

去年今日

去年的今天,本博客开通了.10月29日也是本人的生日,今天在这里做个纪念,希望每天都要有个新的开始!

php的pathinfo的版本差异

今天用pathinfo的时候,发现在php版本5.2.0前后返回的结果有所不同:

php5.2.0之前,pathinfo返回的结果只包含三项

<?php
$path_parts = pathinfo(“/www/htdocs/index.html”);
echo $path_parts["dirname"] . “/n”;
echo $path_parts["basename"] . “/n”;
echo $path_parts["extension"] . “/n”;
?>

php5.2.0之后,pathinfo返回的结果加入了filename项

<?php
$path_parts = pathinfo(‘/www/htdocs/inc/lib.inc.php’);
echo $path_parts['dirname'], “/n”;
echo $path_parts['basename'], “/n”;
echo $path_parts['extension'], “/n”;
echo $path_parts['filename'], “/n”; // since PHP 5.2.0
?>

YII cookie和session的使用方法

设置cookie:
//首先新建cookie
$cookie = new CHttpCookie(‘mycookie’, ‘this is my cookie’);
//定义cookie的有效期
$cookie->expire = time()+60*60*24*30;  //有限期30天
//把cookie写入cookies使其生效
Yii::app()->request->cookies['mycookie']=$cookie;

注意:CHttpCookie定义的cookie名”mycookie”与Yii::app()->request->cookies['mycookie']中的”mycookie”必须一致,即每次添加cookie值都要写两次cookie名

读取cookie:
$cookie = Yii::app()->request->getCookies();
echo $cookie['mycookie']->value;

销毁cookie:
$cookie = Yii::app()->request->getCookies();
unset($cookie[$name]);

 

 
设置session变量:
Yii::app()->session['var']=’value’;
使用: echo Yii::app()->session['var'];
移除: unset(Yii::app()->session['var']);
更为复杂一点的使用时如何配置你的session
配置项可设在 protected/config/main.php的components中:
‘session’=>array(
‘autoStart’=>false(/true),
‘sessionName’=>’Site Access’,
‘cookieMode’=>’only’,
‘savePath’='/path/to/new/directory’,
),

YII模块绑定二级域名方法

在配置文件设置
‘urlManager’ => array(
‘urlFormat’ => ‘path’,
‘showScriptName’ => false, //注意false不要用引号括上
‘urlSuffix’ => ‘.html’,
‘rules’ => array(
‘http://blog.k1029.com’=>array(‘/blog’, ‘urlSuffix’=>”, ‘caseSensitive’=>false),
),

//blog 为一个模块 ,如果在blog模块下还存在第二个控制器(这里以comment为例),则需要多写一个规则,如下

‘urlManager’ => array(
‘urlFormat’ => ‘path’,
‘showScriptName’ => false, //注意false不要用引号括上
‘urlSuffix’ => ‘.html’,
‘rules’ => array(
‘http://blog.k1029.com’=>array(‘/blog’, ‘urlSuffix’=>”, ‘caseSensitive’=>false),
‘http://blog.k1029.com/comment-<id:\w+>’=>array(‘/blog/comment/’, ‘urlSuffix’=>’.html’, ‘caseSensitive’=>false),
),

//如要访问blog下的某一条评论的URL会是:http://blog.k1029.com/comment-1.html

如果是本在地服务器
一、当然,在YII配置中设置了还不够的,还需要在DNS服务器中把blog.k1029.com二级域名解析到程序服务器,可以在hosts中的最后加入
127.0.0.1       www.k1029.com     blog.k1029.com

二、还需要在apache服务器的http.conf中添加
NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin  kane@k1029.com
DocumentRoot E:/wamp/www/k1029
ServerName blog.k1029.com
ErrorLog logs/blog.k1029.com-error_log
CustomLog logs/blog.k1029.com-access_log common
</VirtualHost>

//如果需要绑定多个二级域名,则只要重复添加即可.

 

如果是在虚拟服务器上,一般会有服务器的GUI设置界面,在上面进行操作就可以了.较本地设置还方便快捷.