SVN分支与合并

1.创建分支的意义

创建分支的意义,比如我们在一个基础平台上进行开发,每个技术小组负责一个子项目,而基础平台也是有可能会继续更改的,这个时候,如果不创建分支,子项目之间会相互影响,影响最大的就是后期的测试和版本发布,子项目A已经结束,但测试却受到正在进行的子项目B的影响,测试通不过,就别说版本发布了。所以,我们需要从目前的项目(主干trunk)中创建分支(branch),隔离子项目间的相互影响。

2.svn创建分支原理

在svn中,创建分支,实际上就是一个版本拷贝(对应copy to…注意:绝不是简单在客户端上copy一个目录,而是svn仓库中copy,文件版本号会增加。),两边做任何修改发生的版本变化,是一套机制。举例:目前主干版本是100,分支版本是101,主干中增加一个文件,版本为102,分支中再增加一个文件,版本就为103了。两边的版本号是一套,不会重复。

3.svn创建分支的方法

TortoiseSVN:右键点击工程目录->TortoiseSVN->Branch/tag..菜单,From WC at Url自动为工程svn url,比如https://localhost:8443/svn/fbysss/prj1/trunk,to Url填写https://localhost:8443/svn/fbysss/prj1/branches/branch1。点OK按钮,分支就创建好了。

Subclipse:Team->Branch/tag..,跟上面类似.

SVN命令模式:svn copy trunk_path  branch_path  -m ‘描述’

举例:svn copy https://localhost:8443/svn/fbysss/prj1/trunk 

https://localhost:8443/svn/fbysss/prj1/branches/branch1 -m “第一个分支”

注意一点:trunk和branch不能互为子目录,否则就乱套了。

4.分支合并

1)从分支合并到主干

分支开发结束之后,往往需要合并回主干去测试、发布,但分支和主干可能有很多冲突的地方,在合并时经常需要手工解决。

被操作对象:主干

From主干的打出分支时的版本

To:分支的Head版本(最新版本)

 

怎么理解这个From和To呢?似乎跟我们的想当然不太一样:因为我们理解,把分支合并到主干,肯定是From分支,To主干。怎么搞反了呢?

实际上,Svn认为,我们要合并的,是从主干的某个版本开始,到分支的某个版本结束。两边的版本号实际上是一套系统,不会有重复。

2)从主干合并到分支

试想这样的情况:一个项目里面,要独立出来一个子项目,需要单独发布版本,用到了基础框架代码,而基础框架在主干中不断修改完善,这就需要从主干合并到分支。

被操作对象:分支

From:分支的第一个版本(最旧版本)

To:主干的Head版本(最新版本)

相当于从分支的第一个版本开始一直到主干最后一个版本结束合并之后,替换分支。

3)从分支合并到分支

有这样的需求:一个项目中有很多分支,这些分支需要分期上线,有多个工作并行,但每一期之间不能相互影响,这就可以打出几个tag(也是分支),从主干copy而来。其他主干根据排期分别合并到这些tag中来。比如有prjTag1和prjTag2,model1、model2需要合并到prjTag1中,model3、model4需要合并到prjTag2中。拿prjTag1举例:

在prjTag1的work copy中,merge

 

From主干的打出分支时的版本

To:分支的Head版本(最新版本)

注意:From不是本Tag的某个版本,而是之前主干打出分支时的版本,最终Merge到prjTag1的work copy,而prjTag1是找不到当初打分支时的版本的。

原文

关于面试

好的面试可以将人的缺点暴露无疑,在关于我的页面上,今天加上这条:

curious about everything, but have no patience to insist on one!

CSS Position的使用

前几天微博上一位前端界的大牛吐槽面试的时候问一个position的问题能刷掉一半人,然后引发了一次关于面试和面试题的风波。作为PHPER表示很淡定,但是本PHPER志在成为一个comprehensive and professional web-develop engineer,所以呢,不管前端后端,数据库服务器,我都是想深入搞定的。至于这个position的问题,个人用的不深,但是目前来看平时做布局的时候只要注意absolute和fixed这两个属性即可,absolute如果在父元素没有relative或者absolute的情况想是相对body定位的,否则相对父元素定位,fixed在IE6不能用。这两点至少能解决我目前90%以上的问题了。下面转一博文,基本写到了。

——————————————————————–分割线—————————————————————————————–

CSS的很多其他属性大多容易理解,比如字体,文本,背景等。有些CSS书籍也会对这些简单的属性进行大张旗鼓的介绍,而偏偏忽略了对一些难缠的属性讲解,有避重就轻的嫌疑。CSS中主要难以理解的属性包括盒型结构,以及定位。正如positioniseverything,本文将主要讲述关于position的理解,力求让您看完本文后对position有着最全面的认识。

position的四个属性值:

  1. relative
  2. absolute
  3. fixed
  4. static

下面分别讲述这四个属性。

<div id=”parent”>
<div id=”sub1″>sub1</div>
<div id=”sub2″>sub2</div>
</div>

1. relative

relative属性相对比较简单,我们要搞清它是相对哪个对象来进行偏移的。答案是它本身的位置。在上面的代码中,sub1和sub2是同级关系,如果设定sub1一个relative属性,比如设置如下CSS代码:

#sub1
{
position: relative;
padding: 5px;
top: 5px;
left: 5px;
}

我们可以这样理解,如果不设置relative属性,sub1的位置按照正常的文档流,它应该处于某个位置。但当设置sub1为的position为relative后,将根据top,right,bottom,left的值按照它理应所在的位置进行偏移,relative的“相对的”意思也正体现于此。

对于此,您只需要记住,sub1如果不设置relative时它应该在哪里,一旦设置后就按照它理应在的位置进行偏移。

随后的问题是,sub2的位置又在哪里呢?答案是它原来在哪里,现在就在哪里,它的位置不会因为sub1增加了position的属性而发生改变。

如果此时把sub2的position也设置为relative,会发生什么现象?此时依然和sub1一样,按照它原来应有的位置进行偏移。

注意relative的偏移是基于对象的margin的左上侧的。

2. absolute

这个属性总是有人给出误导。说当position属性设为absolute后,总是按照浏览器窗口来进行定位的,这其实是错误的。实际上,这是fixed属性的特点。

当sub1的position设置为absolute后,其到底以谁为对象进行偏移呢?这里分为两种情况:

(1)当sub1的父对象(或曾祖父,只要是父级对象)parent也设置了position属性,且position的属性值为absolute或者relative时,也就是说,不是默认值的情况,此时sub1按照这个parent来进行定位。

注意,对象虽然确定好了,但有些细节需要您的注意,那就是我们到底以parent的哪个定位点来进行定位呢?如果parent设定了margin,border,padding等属性,那么这个定位点将忽略padding,将会从padding开始的地方(即只从padding的左上角开始)进行定位,这与我们会想当然的以为会以margin的左上端开始定位的想法是不同的。

接下来的问题是,sub2的位置到哪里去了呢?由于当position设置为absolute后,会导致sub1溢出正常的文档流,就像它不属于 parent一样,它漂浮了起来,在DreamWeaver中把它称为“层”,其实意思是一样的。此时sub2将获得sub1的位置,它的文档流不再基于 sub1,而是直接从parent开始。

(2)如果sub1不存在一个有着position属性的父对象,那么那就会以body为定位对象,按照浏览器的窗口进行定位,这个比较容易理解。

3. fixed

fixed是特殊的absolute,即fixed总是以body为定位对象的,按照浏览器的窗口进行定位。

4. static

position的默认值,一般不设置position属性时,会按照正常的文档流进行排列。

 

来源

dropbox客户端实时同步

环境1:

win7, dropbox windows客户端

环境2:

ubunt12.04, dropbox linux客户端

问题描述:

在环境1的dropbox目录某同步文件夹内同步一个文件,在环境2的同一同步文件夹中没有实时文件的更新同步

问题原因:

dropbox文件更新的通知请求被狗日的gfw屏蔽,环境2中的客户端没有收到有更新的通知,自然不会去启动同步

解决办法:

上代理,在prefrence->proxy菜单中修改,改成可以翻墙的代理即可。我这边是走的ssh隧道,用的socket5代理。

开启代理测试后在几秒内就会开始同步了!

Zend Framework Coding Style

绪论

适用范围

本文档提供的代码格式和文档的指南是给参与 Zend Framework 的个人和团队使用的,许多使用 Zend Framework 的开发者 也发现编码标准很有用,因为他们的代码风格和 Zend Framework 的代码保持一致。值得注意的是它要求切实努力来全面 详细说明编码标准。 注:有时候开发者认为在最详细的设计级别上标准的建立比标准所建议的更重要。Zend Framework 编码标准的指南 实践上很好地工作于 ZF 项目。你可以根据我们的 » license 中的条款来修改或使用它们。

ZF 编码标准的话题包括:

  • PHP File 文件格式
  • 命名约定
  • 编码风格
  • 注释文档

目标

编码标准对任何开发项目都很重要,特别是很多开发者在同一项目上工作。编码标准帮助确保代码的高质量、少 bug 和容易维护

 

PHP File 文件格式

常规

对于只包含有 PHP 代码的文件,结束标志(”?>”)是不允许存在的,PHP自身不需要(”?>”), 这样做, 可以防止它的末尾的被意外地注入相应。

重要: 由 __HALT_COMPILER() 允许的任意的二进制代码的内容被 Zend Framework 中的 PHP 文件或由它们产生的文件禁止。 这个功能的使用只对一些安装脚本开放。

缩进

缩进由四个空格组成,禁止使用制表符 TAB 。

行的最大长度

一行 80 字符以内是比较合适,就是说,ZF 的开发者应当努力在可能的情况下保持每行代码少于 80 个字符,在有些情况下,长点也可以, 但最多为 120 个字符。

行结束标志

行结束标志遵循 Unix 文本文件的约定,行必需以单个换行符(LF)结束。换行符在文件中表示为 10,或16进制的 0x0A。

注:不要使用 苹果操作系统的回车(0x0D)或 Windows 电脑的回车换行组合如(0x0D,0x0A)。

 

命名约定

Zend Framework 的类命名总是对应于其所属文件的目录结构的,ZF 标准库的根目录是 “Zend/”,ZF 特别(extras)库的根目录是 “ZendX/”,所有 Zend Framework 的类在其下按等级存放。

类名只允许有字母数字字符,在大部分情况下不鼓励使用数字。下划线只允许做路径分隔符;例如 Zend/Db/Table.php 文件里对应的类名称是 Zend_Db_Table。

如果类名包含多个单词,每个单词的第一个字母必须大写,连续的大写是不允许的,例如 “Zend_PDF” 是不允许的,而 “Zend_Pdf” 是可接受的。

这些约定为 Zend Framework 定义了一个伪命名空间机制。如果对开发者在他们的程序中切实可行,Zend Framework 将采用 PHP 命名空间特性(如果有的话)。

参见在标准和特别库中类名作为类名约定的例子。 重要: 依靠 ZF 库展开的代码,但又不是标准或特别库的一部分(例如程序代码或不是 Zend 发行的库),不要以 “Zend_” 或 “ZendX_” 开头。

文件名

对于其它文件,只有字母数字字符、下划线和短横线(”-“)可用,空格是绝对不允许的。

包含任何 PHP 代码的任何文件应当以 “.php” 扩展名结尾,众所周知的视图脚本除外。下面这些例子给出 Zend Framework 类可接受的文件名:

Zend/Db.php

Zend/Controller/Front.php

Zend/View/Helper/FormRadio.php

文件名必须遵循上述的对应类名的规则。

函数和方法

函数名只包含字母数字字符,下划线是不允许的。数字是允许的但大多数情况下不鼓励。

函数名总是以小写开头,当函数名包含多个单词,每个子的首字母必须大写,这就是所谓的 “驼峰” 格式。

我们一般鼓励使用冗长的名字,函数名应当长到足以说明函数的意图和行为。

这些是可接受的函数名的例子:

filterInput()

getElementById()

widgetFactory()

对于面向对象编程,实例或静态变量的访问器总是以 “get” 或 “set” 为前缀。在设计模式实现方面,如单态模式(singleton)或工厂模式(factory), 方法的名字应当包含模式的名字,这样名字更能描述整个行为。

在对象中的方法,声明为 “private” 或 “protected” 的, 名称的首字符必须是一个单个的下划线,这是唯一的下划线在方法名字中的用法。声明为 “public” 的从不包含下划线。

全局函数 (如:”floating functions”) 允许但大多数情况下不鼓励,建议把这类函数封装到静态类里。

变量

变量只包含数字字母字符,大多数情况下不鼓励使用数字,下划线不接受。

声明为 “private” 或 “protected” 的实例变量名必须以一个单个下划线开头,这是唯一的下划线在程序中的用法,声明为 “public” 的不应当以下划线开头。

对函数名(见上面 3.3 节)一样,变量名总以小写字母开头并遵循“驼峰式”命名约定。

我们一般鼓励使用冗长的名字,这样容易理解代码,开发者知道把数据存到哪里。除非在小循环里,不鼓励使用简洁的名字如 “$i” 和 “$n” 。如果一个循环超过 20 行代码,索引的变量名必须有个具有描述意义的名字。

常量

常量包含数字字母字符和下划线,数字允许作为常量名。

常量名的所有字母必须大写。

常量中的单词必须以下划线分隔,例如可以这样 EMBED_SUPPRESS_EMBED_EXCEPTION 但不许这样 EMBED_SUPPRESSEMBEDEXCEPTION

常量必须通过 “const” 定义为类的成员,强烈不鼓励使用 “define” 定义的全局常量。

 

编码风格

PHP 代码划分(Demarcation)

PHP 代码总是用完整的标准的 PHP 标签定界:

<?php

?>

短标签( )是不允许的,只包含 PHP 代码的文件,不要结束标签 (参见 常规)。

字符串

字符串文字

当字符串是文字(不包含变量),应当用单引号( apostrophe )来括起来:

$a = 'Example String';

包含单引号(’)的字符串文字

当文字字符串包含单引号(apostrophe )就用双引号括起来,特别在 SQL 语句中有用:

$sql = "SELECT `id`, `name` from `people` WHERE `name`='Fred' OR `name`='Susan'";

在转义单引号时,上述语法是首选的,因为很容易阅读。

变量替换

变量替换有下面这些形式:

$greeting = "Hello $name, welcome back!";

$greeting = "Hello {$name}, welcome back!";

为保持一致,这个形式不允许:

$greeting = "Hello ${name}, welcome back!";

字符串连接

字符串必需用 “.” 操作符连接,在它的前后加上空格以提高可读性:

$company = 'Zend' . ' ' . 'Technologies';

当用 “.” 操作符连接字符串,鼓励把代码可以分成多个行,也是为提高可读性。在这些例子中,每个连续的行应当由 whitespace 来填补,例如 “.” 和 “=” 对齐:

$sql = "SELECT `id`, `name` FROM `people` "
     . "WHERE `name` = 'Susan' "
     . "ORDER BY `name` ASC ";

数组

数字索引数组

索引不能为负数

建议数组索引从 0 开始。

当用 array 函数声明有索引的数组,在每个逗号的后面间隔空格以提高可读性:

$sampleArray = array(1, 2, 3, 'Zend', 'Studio');

可以用 “array” 声明多行有索引的数组,在每个连续行的开头要用空格填补对齐:

$sampleArray = array(1, 2, 3, 'Zend', 'Studio',
                     $a, $b, $c,
                     56.44, $d, 500);

关联数组

当用声明关联数组,array 我们鼓励把代码分成多行,在每个连续行的开头用空格填补来对齐键和值:

$sampleArray = array('firstKey'  => 'firstValue',
                     'secondKey' => 'secondValue');

类的声明

用 Zend Framework 的命名约定来命名类。

花括号应当从类名下一行开始(the “one true brace” form)。

每个类必须有一个符合 PHPDocumentor 标准的文档块。

类中所有代码必需用四个空格的缩进。

每个 PHP 文件中只有一个类。

放另外的代码到类里允许但不鼓励。在这样的文件中,用两行空格来分隔类和其它代码。

下面是个可接受的类的例子: // 459 9506 - 441 9658 下次从这里开始

/**
 * Documentation Block Here
 */
class SampleClass
{
    // 类的所有内容
    // 必需缩进四个空格
}

类成员变量

必须用Zend Framework的变量名约定来命名类成员变量。

变量的声明必须在类的顶部,在方法的上方声明。

不允许使用 var (因为 ZF 是基于 PHP 5 的 ),要用 private、 protected 或 public。 直接访问 public 变量是允许的但不鼓励,最好使用访问器 (set/get)。

函数和方法

函数和方法声明

必须用Zend Framework的函数名约定来命名函数。

在类中的函数必须用 private、 protected 或 public 声明它们的可见性。

象类一样,花括号从函数名的下一行开始(the “one true brace” form)。

函数名和括参数的圆括号中间没有空格。

强烈反对使用全局函数。

下面是可接受的在类中的函数声明的例子:

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * Documentation Block Here
     */
    public function bar()
    {
        // 函数的所有内容
        // 必需缩进四个空格
    }
}

注: 传址(Pass-by-reference)是在方法声明中允许的唯一的参数传递机制。

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * Documentation Block Here
     */
    public function bar(&$baz)
    {}
}

传址在调用时是严格禁止的。

返回值不能在圆括号中,这妨碍可读性而且如果将来方法被修改成传址方式,代码会有问题。

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * WRONG
     */
    public function bar()
    {
        return($this->bar);
    }

    /**
     * RIGHT
     */
    public function bar()
    {
        return $this->bar;
    }
}

函数和方法的用法

函数的参数应当用逗号和紧接着的空格分开,下面可接受的调用的例子中的函数带有三个参数:

threeArguments(1, 2, 3);

传址方式在调用的时候是严格禁止的,参见函数的声明一节如何正确使用函数的传址方式。

带有数组参数的函数,函数的调用可包括 “array” 提示并可以分成多行来提高可读性,同时,书写数组的标准仍然适用:

threeArguments(array(1, 2, 3), 2, 3);

threeArguments(array(1, 2, 3, 'Zend', 'Studio',
                     $a, $b, $c,
                     56.44, $d, 500), 2, 3);

控制语句

if/Else/Elseif

使用 if and elseif 的控制语句在条件语句的圆括号前后都必须有一个空格。

在圆括号里的条件语句,操作符必须用空格分开,鼓励使用多重圆括号以提高在复杂的条件中划分逻辑组合。

前花括号必须和条件语句在同一行,后花括号单独在最后一行,其中的内容用四个空格缩进。

if ($a != 2) {
    $a = 2;
}

对包括”elseif” 或 “else”的 “if” 语句,和 “if” 结构的格式类似, 下面的例子示例 “if” 语句, 包括 “elseif” 或 “else” 的格式约定:

if ($a != 2) {
    $a = 2;
} else {
    $a = 7;
}

if ($a != 2) {
    $a = 2;
} elseif ($a == 3) {
    $a = 4;
} else {
    $a = 7;
}

在有些情况下, PHP 允许这些语句不用花括号,但在(ZF) 代码标准里,它们(”if”、 “elseif” 或 “else” 语句)必须使用花括号。”elseif” 是允许的但强烈不鼓励,我们支持 “else if” 组合。

Switch

在 “switch” 结构里的控制语句在条件语句的圆括号前后必须都有一个单个的空格。

“switch” 里的代码必须有四个空格缩进,在”case”里的代码再缩进四个空格。

switch ($numPeople) {
    case 1:
        break;

    case 2:
        break;

    default:
        break;
}

switch 语句应当有 default

注: 有时候,在 falls through 到下个 case 的 case 语句中不写 break or return 很有用。 为了区别于 bug,任何 case 语句中,所有不写break or return 的地方应当有一个 “// break intentionally omitted” 这样的注释来表明 break 是故意忽略的。

注释文档

格式

所有文档块 (“docblocks”) 必须和 phpDocumentor 格式兼容,phpDocumentor 格式的描述超出了本文档的范围,关于它的详情,参考:» http://phpdoc.org/

所有类文件必须在文件的顶部包含文件级 (”file-level”)的 docblock ,在每个类的顶部放置一个 “class-level” 的 docblock。下面是一些例子:

文件

每个包含 PHP 代码的文件必须至少在文件顶部的 docblock 包含这些 phpDocumentor 标签:

/**
 * 文件的简短描述
 *
 * 文件的详细描述(如果有的话)... ...
 *
 * LICENSE: 一些 license 信息
 *
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/3_0.txt   BSD License
 * @version    $Id:$
 * @link       http://framework.zend.com/package/PackageName
 * @since      File available since Release 1.5.0
*/

每个类必须至少包含这些 phpDocumentor 标签:

/**
 * 类的简述
 *
 * 类的详细描述 (如果有的话)... ...
 *
 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/   BSD License
 * @version    Release: @package_version@
 * @link       http://framework.zend.com/package/PackageName
 * @since      Class available since Release 1.5.0
 * @deprecated Class deprecated in Release 2.0.0
 */

函数

每个函数,包括对象方法,必须有最少包含下列内容的文档块(docblock):

  • 函数的描述
  • 所有参数
  • 所有可能的返回值

因为访问级已经通过 “public”、 “private” 或 “protected” 声明, 不需要使用 “@access”。

如果函数/方法抛出一个异常,使用 @throws 于所有已知的异常类:

@throws exceptionclass [description]

PHP Coding Style

PSR-0

下面描述了关于自动加载器特性强制性要求:

强制性

  • 一个完全标准的命名空间必须要有以下的格式结构\<Vendor Name>\(<Namespace>\)*<Class Name>
  • 命名空间必须有一个顶级的组织名称 (“Vendor Name”).
  • 命名空间中可以根据情况使用任意数量的子空间
  • 从文件系统中加载源文件的时,命名空间中的分隔符将被映射为 DIRECTORY_SEPARATOR
  • 命名空间中的类名中的_没有特殊含义,也将被作为DIRECTORY_SEPARATOR对待.
  • 标准的命名空间和类从文件系统加载源文件时只需要加上.php后缀即可
  • 组织名,空间名,类名都可以随意使用大小写英文字符的组合

示例

  • \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
  • \Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
  • \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
  • \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php

命名空间和类名中的下划线

  • \namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php
  • \namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

以上是我们为轻松实现自动加载特性设定的最低标准。你可以利用下面这个可以自动加载 PHP 5.3 类的SplClassLoader来测试你的代码是否符合以上这些标准。

实例

下面是一个函数实例简单展示如何使用上面建议的标准进行自动加载

<?php

function autoload($className)
{
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
}

SplClassLoader实现

下面的gist是一个可以按照上面建议的自动加载特性来加载类的SplClassLoader实例。这也是我们当前在PHP5.3中依据以上标准加载类时推荐的方。

 

PSR-1

基本代码规范

本节标准包含了成为标准代码所需要的基本元素,以确保开源出来的PHP代码之间有较高度的技术互用性。

在 RFC 2119中的特性关键词”必须”(MUST),“不可”(MUST NOT),“必要”(REQUIRED),“将会”(SHALL),“不会”(SHALL NOT),“应当”(SHOULD),“不应”(SHOULD NOT),“推荐”(RECOMMENDED),“可以”(MAY)和“可选”(OPTIONAL)在这文档中将被用来描述。

1. 大纲

  • 源文件必须只使用 <?php 和 <?= 标签。
  • 源文件中必须只使用不带BOM的UTF-8作为PHP代码。
  • 源文件应当只声明符号(类,函数,常量等…)或者引起副作用(例如:生成输出,修改.ini配置等),但不应同时做这两件事。
  • 命名空间和类必须遵守 PSR-0
  • 类名必须使用骆驼式StudlyCaps写法 (译者注:驼峰式的一种变种,后文将直接用StudlyCaps表示)。
  • 类中的常量必须使用全大写和下划线分隔符。
  • 方法名必须使用驼峰式cameCase写法(译者注:后文将直接用camelCase表示)。

2. 文件

2.1. PHP标签

PHP代码必须只使用长标签<?php ?>或者短输出式<?= ?>标签;它不可使用其他的标签变种。

2.2. 字符编码

PHP代码必须只使用不带BOM的UTF-8。

2.3. 副作用

一个文件应当声明新符号 (类名,函数名,常量等)并且不产生副作用,或者应当执行有副作用的逻辑,但不能同时做这两件事。

短语”副作用”意思是不直接执行逻辑的类,函数,常量等 仅包括文件

“副作用”包含但不局限于:生成输出,显式地使用requireinclude,连接外部服务,修改ini配置,触发错误或异常,修改全局或者静态变量,读取或修改文件等等

下面是一个既包含声明又有副作用的示例文件;即应避免的例子:

<?php
// side effect: change ini settings
ini_set('error_reporting', E_ALL);

// side effect: loads a file
include "file.php";

// side effect: generates output
echo "<html>\n";

// declaration
function foo()
{
    // function body
}

下面是一个仅包含声明的示例文件;即需要提倡的例子:

<?php
// declaration
function foo()
{
    // function body
}

// conditional declaration is *not* a side effect
if (! function_exists('bar')) {
    function bar()
    {
        // function body
    }
}

3. 命名空间和类名

命名空间和类名必须遵守 PSR-0.

这意味着每个类必须单独一个源文件,并且至少有一级命名空间:顶级的组织名。

类名必须使用骆驼式StudlyCaps写法。

PHP5.3之后的代码必须使用正式的命名空间 例子:

<?php
// PHP 5.3 and later:
namespace Vendor\Model;

class Foo
{
}

PHP5.2.x之前的代码应当用伪命名空间Vendor_作为类名的前缀

<?php
// PHP 5.2.x and earlier:
class Vendor_Model_Foo
{
}

4. 类常量,属性和方法

术语“类”指所有的类,接口和特性(traits)

4.1. 常量

类常量必须使用全大写,并使用分隔符作为下划线。 例子:

<?php
namespace Vendor\Model;

class Foo
{
    const VERSION = '1.0';
    const DATE_APPROVED = '2012-06-01';
}

4.2. 属性

本手册有意避免推荐使用$StulyCaps$camelCase或者unser_score作为属性名字

不管名称如何约定,它应当在一个合理范围内保持一致。这个范围可能是组织层,包层,类层,方法层。

4.3. 方法

方法名必须用camelCase()写法。

 

PSR-2

代码样式规范

本手册是 PSR-1基础代码规范的继承和扩展

本指南的意图是为了减少不同开发者在浏览代码时减少认知的差异。 为此列举一组如何格式化PHP代码的共用规则。

各个成员项目的共性组成了本文的样式规则。当不同的开发者在不同的项目中合作时,将会在这些不同的项目中使用一个共同的标准。 因此,本指南的好处不在于规则本身,而在于共用这些规则。

在 RFC 2119中的特性关键词”必须”(MUST),“不可”(MUST NOT),“必要”(REQUIRED),“将会”(SHALL),“不会”(SHALL NOT),“应当”(SHOULD),“不应”(SHOULD NOT),“推荐”(RECOMMENDED),“可以”(MAY)和“可选”(OPTIONAL)在这文档中将被用来描述。

1. 大纲

  • 代码必须遵守 PSR-1
  • 代码必须使用4个空格的缩进,而不是制表符。
  • 一行代码长度不应硬性限制;软限制必须为120个字符;也应当是80个字符或者更少。
  • namespace声明下面必须有一个空行,并且use声明代码块下面也必须有一个空行。
  • 类的左花括号必须放到下一行,右花括号必须放在类主体的下一行。
  • 方法的左花括号必须放在下一行,右花括号必须放在方法主体下面。
  • 所有的属性和方法必须有可见性(译者注:Public, Protect, Private)声明;abstractfinal声明必须在可见性之前;static声明必须在可见性之后。
  • 控制结构的关键词必须在后面有一个空格; 方法和函数不可有。
  • 控制结构的左花括号必须放在同一行,右花括号必须放在控制主体的下一行。
  • 控制结构的左括号后面不可有空格,右括号之前不可有空格。

1.1. 示例

本示例包含上面的一些规则简单展示:

<?php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{
    public function sampleFunction($a, $b = null)
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // method body
    }
}

2. 概括

2.1 基础代码规范

代码必须遵守 PSR-1 的所有规则。

2.2 文件

所有的PHP文件必须使用Unix LF(换行)作为行结束符。

所有PHP文件必须以一个空行结束。

纯PHP代码的文件关闭标签?>必须省略

2.3. 行

行长度不可有硬限制。

行长度的软限制必须是120个字符;对于软限制,自动样式检查器必须警告但不可报错。

行实际长度不应超过80个字符;较长的行应当被拆分成多个不超过80个字符的后续行。

在非空行后面不可有空格。

空行可以用来改善可读性和区分相关的代码块。

一行不应多于一个语句。

2.4. 缩进

代码必须使用4个空格的缩进,并且不可使用制表符作为缩进。

注意:只用空格,不和制表符混合使用,将会对避免代码差异,补丁,历史和注解中的一些问题有帮助。使用空格还可以使调整细微的缩进来改进行间对齐变得非常简单。

2.5. 关键词和 True/False/Null

PHP keywords 必须使用小写。

PHP常量truefalsenull必须使用小写。

3. Namespace和Use声明

如果存在,namespace声明之后必须有一个空行。

如果存在,所有的use声明必须放在namespace声明的下面。

一个use关键字必须只用于一个声明。

use声明代码块后面必须有一个空行。

示例:

<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

// ... additional PHP code ...

4. 类,属性和方法

术语“类”指所有的类,接口和特性(traits)。

4.1. 扩展和继承

一个类的extendsimplements关键词必须和类名在同一行。

类的左花括号必须放在下面自成一行;右花括号必须放在类主体的后面自成一行。

<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // constants, properties, methods
}

implements一个列表可以被拆分为多个有一次缩进的后续行。如果这么做,列表的第一项必须要放在下一行,并且每行必须只有一个接口。

<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // constants, properties, methods
}

4.2. 属性

所有的属性必须声明可见性。

var关键词不可用来声明属性。

一个语句不可声明多个属性。

属性名称不应使用单个下划线作为前缀来表明保护或私有的可见性。

一个属性声明看起来应该下面这样的。

<?php
namespace Vendor\Package;

class ClassName
{
    public $foo = null;
}

4.3. 方法

所有的方法必须声明可见性。

方法名不应只使用单个下划线来表明是保护或私有的可见性。

方法名在声明之后不可跟随一个空格。左花括号必须放在下面自成一行,并且右花括号必须放在方法主体的下面自成一行。左括号后面不可有空格,右括号前面不可有空格。

一个方法定义看来应该像下面这样。 注意括号,逗号,空格和花括号:

<?php
namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
        // method body
    }
}

4.4. 方法参数

在参数列表中,逗号之前不可有空格,逗号之后必须要有一个空格。

方法中有默认值的参数必须放在参数列表的最后面。

<?php
namespace Vendor\Package;

class ClassName
{
    public function foo($arg1, &$arg2, $arg3 = [])
    {
        // method body
    }
}

参数列表可以被分为多个有一次缩进的多个后续行。如果这么做,列表的第一项必须放在下一行,并且每行必须只放一个参数。

当参数列表被分为多行,右括号和左花括号必须夹带一个空格放在一起自成一行。

<?php
namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // method body
    }
}

4.5. abstractfinal和 static

如果存在,abstractfinal声明必须放在可见性声明前面。

如果存在,static声明必须跟着可见性声明。

<?php
namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
        // method body
    }
}

4.6. 调用方法和函数

要调用一个方法或函数,在方法或者函数名和左括号之间不可有空格,左括号之后不可有空格,右括号之前不可有空格。函数列表中,逗号之前不可有空格,逗号之后必须有一个空格。

<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

参数列表可以被拆分成多个有一个缩进的后续行。如果这么做,列表中的第一项必须放在下一行,并且每一行必须只有一个参数。

<?php
$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);

5. 控制结构

对于控制结构的样式规则概括如下:

  • 控制结构关键词之后必须有一个空格
  • 左括号之后不可有空格
  • 右括号之前不可有空格
  • 在右括号和左花括号之间必须有一个空格
  • 代码主体必须有一次缩进
  • 右花括号必须主体的下一行

每个结构的主体必须被括在花括号里。这结构看上去更标准化,并且当加新行的时候可以减少引入错误的可能性。

5.1. ifelseifelse

一个if结构看起来应该像下面这样。注意括号,空格,花括号的位置;并且elseelseif和前一个主体的右花括号在同一行。

<?php
if ($expr1) {
    // if body
} elseif ($expr2) {
    // elseif body
} else {
    // else body;
}

关键词elseif应该替代else if使用以保持所有的控制关键词像一个单词。

5.2. switchcase

一个switch结构看起来应该像下面这样。注意括号,空格和花括号。case语句必须从switch处缩进,并且break关键字(或其他中止关键字)必须case主体缩进在同级。如果一个非空的case主体往下落空则必须有一个类似// no break的注释。

<?php
switch ($expr) {
    case 0:
        echo 'First case, with a break';
        break;
    case 1:
        echo 'Second case, which falls through';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Third case, return instead of break';
        return;
    default:
        echo 'Default case';
        break;
}

5.3. whiledo while

一个while语句看起来应该像下面这样。注意括号,空格和花括号的位置。

<?php
while ($expr) {
    // structure body
}

同样的,一个do while语句看起来应该像下面这样。注意括号,空格和花括号的位置。

<?php
do {
    // structure body;
} while ($expr);

5.4. for

一个for语句看起来应该像下面这样。注意括号,空格和花括号的位置。

<?php
for ($i = 0; $i < 10; $i++) {
    // for body
}

5.5. foreach

一个foreach语句看起来应该像下面这样。注意括号,空格和花括号的位置。

<?php
foreach ($iterable as $key => $value) {
    // foreach body
}

5.6. trycatch

一个try catch语句看起来应该像下面这样。注意括号,空格和花括号的位置。

<?php
try {
    // try body
} catch (FirstExceptionType $e) {
    // catch body
} catch (OtherExceptionType $e) {
    // catch body
}

6. 闭包

闭包在声明时function关键词之后必须有一个空格,并且use之前也需要一个空格。

左花括号必须在同一行,右花括号必须在主体的下一行。

参数列表和变量列表的左括号之后不可有空格,其右括号之前也不可有空格。

在参数列表和变量列表中,逗号之前不可有空格,逗号之后必须有空格。

闭包带默认值的参数必须放在参数列表后面。

一个闭包声明看起来应该像下面这样。注意括号,空格和花括号的位置。

<?php
$closureWithArgs = function ($arg1, $arg2) {
    // body
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // body
};

参数和变量列表可以被分成多个带一次缩进的后续行。如果这么做,列表的第一项必须放在下一行,并且一行必须只放一个参数或变量。

当最终列表(不管是参数还是变量)被分成多行,右括号和左花括号必须夹带一个空格放在一起自成一行。

下面是一个参数和变量列表被分割成多行的示例。

<?php
$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
   // body
};

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
   // body
};

$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // body
};

注意如果在函数或者方法中把闭包作为一个参数调用,如上格式规则同样适用。

<?php
$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // body
    },
    $arg3
);

7. 结论

在该指南中有很多风格的元素和做法有意被忽略掉。这些包括但不局限于:

  • 全局变量和全局常量的声明
  • 方法声明
  • 操作符和赋值
  • 行间对齐
  • 注释和文档块
  • 类名给你前缀和后缀
  • 最佳实践

以后的建议可以修改和扩展该指南以满足这些或其他风格的元素和实践。

 

PSR-3

日志接口

本文档用来描述日志类库的通用接口。

主要目标是让类库获得一个Psr\Log\LoggerInterface对象并且使用一个简单通用的方式来写日志。有自定义需求的框架和CMS可以根据情况扩展这个接口,但应当保持和该文档的兼容性,这将确保使用第三方库和应用能统一的写应用日志。

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

关键词实现者在这个文档被解释为:在日志相关的库和框架实现LoggerInterface接口的人。用这些实现的人都被称作用户

1. 规范

1.1 基础

  • LoggerInterface暴露八个接口用来记录八个等级(debug, info, notice, warning, error, critical, alert, emergency)的日志。
  • 第九个方法是log,接受日志等级作为第一个参数。用一个日志等级常量来调用这个方法的结果必须和调用具体等级方法的一致。如果具体的实现不知道传入的不按规范的等级来调用这个方法必须抛出一个Psr\Log\InvalidArgumentException。用户不应自定义一个当前不支持的未知等级。

1.2 消息

  • 每个方法都接受字符串,或者有__toString方法的对象作为消息。实现者可以对传入的对象有特殊的处理。如果不是,实现者必须将它转换成字符串。
  • 消息可以包含可以被上下文数组的数值替换的占位符。

    占位符名字必须和上下文数组键名对应。

    占位符名字必须使用使用一对花括号为分隔。在占位符和分隔符之间不能有任何空格。

    占位符名字应该A-Za-z0-9,下划线_和句号.。其它的字符作为以后占位符规范的保留。

    实现者可以使用占位符来实现不同的转义和翻译日志成文。用户在不知道上下文数据是什么的时候不应提前转义占位符。

    下面提供一个占位符替换的例子,仅作为参考:

    /**
    * Interpolates context values into the message placeholders.
    */
    function interpolate($message, array $context = array())
    {
      // build a replacement array with braces around the context keys
      $replace = array();
      foreach ($context as $key => $val) {
          $replace['{' . $key . '}'] = $val;
      }
    
      // interpolate replacement values into the message and return
      return strtr($message, $replace);
    }
    
    // a message with brace-delimited placeholder names
    $message = "User {username} created";
    
    // a context array of placeholder names => replacement values
    $context = array('username' => 'bolivar');
    
    // echoes "Username bolivar created"
    echo interpolate($message, $context);

1.3 上下文

  • 每个方法接受一个数组作为上下文数据,用来存储不适合在字符串中填充的信息。数组可以包括任何东西。实现者必须确保他们对上下文数据足够的掌控。在上下文中一个给定值不可抛出一个异常,也不可产生任何PHP错误,警告或者提醒。
  • 如果在上下文中传入了一个异常对象,它必须以exception作为键名。记录异常轨迹是通用的模式,如果日志底层支持这样也是可以被允许的。实现者在使用它之前必须验证exception的键值是不是一个异常对象,因为它可以允许是任何东西。

1.4 助手类和接口

  • Psr\Log\AbstractLogger类让你非常简单的实现和扩展LoggerInterface接口以实现通用的log方法。其他八个方法将会把消息和上下文转发给它。
  • 类似的,使用Psr\Log\LoggerTrait只需要你实现通用的log方法。记住traits不能实现接口前,你依然需要implement LoggerInterface
  • Psr\Log\NullLogger是和接口一个提供的。它可以为使用接口的用户提供一个后备的“黑洞”。如果上下文数据非常重要,这不失为一个记录日志更好的办法。
  • Psr\Log\LoggerAwareInterface只有一个setLogger(LoggerInterface $logger)方法可以用来随意设置一个日志记录器。
  • Psr\Log\LoggerAwareTraittrait可以更简单的实现等价于接口。通过它可以访问到$this->logger
  • Psr\Log\LogLevel类拥有八个等级的常量。

2. 包

作为psr/log 的一部分,提供接口和相关异常类的一些描述以及一些测试单元用来验证你的实现。

3. Psr\Log\LoggerInterface

<?php

namespace Psr\Log;

/**
 * Describes a logger instance
 *
 * The message MUST be a string or object implementing __toString().
 *
 * The message MAY contain placeholders in the form: {foo} where foo
 * will be replaced by the context data in key "foo".
 *
 * The context array can contain arbitrary data, the only assumption that
 * can be made by implementors is that if an Exception instance is given
 * to produce a stack trace, it MUST be in a key named "exception".
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * for the full interface specification.
 */
interface LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function emergency($message, array $context = array());

    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function alert($message, array $context = array());

    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function critical($message, array $context = array());

    /**
     * Runtime errors that do not require immediate action but should typically
     * be logged and monitored.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function error($message, array $context = array());

    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable things
     * that are not necessarily wrong.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function warning($message, array $context = array());

    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function notice($message, array $context = array());

    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function info($message, array $context = array());

    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function debug($message, array $context = array());

    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     * @return null
     */
    public function log($level, $message, array $context = array());
}

4. Psr\Log\LoggerAwareInterface

<?php

namespace Psr\Log;

/**
 * Describes a logger-aware instance
 */
interface LoggerAwareInterface
{
    /**
     * Sets a logger instance on the object
     *
     * @param LoggerInterface $logger
     * @return null
     */
    public function setLogger(LoggerInterface $logger);
}

5. Psr\Log\LogLevel

<?php

namespace Psr\Log;

/**
 * Describes log levels
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT     = 'alert';
    const CRITICAL  = 'critical';
    const ERROR     = 'error';
    const WARNING   = 'warning';
    const NOTICE    = 'notice';
    const INFO      = 'info';
    const DEBUG     = 'debug';
}

参考1  参考2

基于curl封装一个爬虫

<?php  
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 5.1.6 or newer
 *
 * @package		CodeIgniter
 * @author		ExpressionEngine Dev Team
 * @copyright	Copyright (c) 2008 - 2011, EllisLab, Inc.
 * @license		http://codeigniter.com/user_guide/license.html
 * @link		http://codeigniter.com
 * @since		Version 1.0
 * @filesource
 */

// ------------------------------------------------------------------------

class Crawler {
	private $_url;
	private $_handle;
	//多线程处理时一些变量
	private $_batch_config = array(
											'handle_array' => array(),
											'map_array' => array()
									);
	private $_curl_option;
	private $_single_or_multi = TRUE; //TRUE表示是单个curl句柄,FALSE表示一组批处理curl句柄(多线程操作)

	function __construct() {
		$this->_curl_option = array(
				CURLOPT_TIMEOUT => 60,
				CURLOPT_FOLLOWLOCATION => TRUE,
				CURLOPT_RETURNTRANSFER => TRUE,
				CURLOPT_HEADER => TRUE,
				CURLOPT_NOSIGNAL => TRUE,
		);
	}

	public function deal($url) {
		$this->set_url($url);
		$this->init_handle();

		return $this->get_response();
	}

	public function set_url($url) {
		$this->_url = $url;
		$this->_single_or_multi = is_array($url) ? FALSE : TRUE;
	}

	public function set_curl_option($option) {
		$this->_curl_option = $option;
	}

	public function init_handle() {
		if(is_array($this->_url)) {
			$this->_handle = curl_multi_init();
			foreach ($this->_url as $id=>$s_url) {
				$ch = curl_init($s_url);
				$this->_batch_config['handle_array'][] = $ch;
				curl_setopt_array($ch, $this->_curl_option);

				curl_multi_add_handle($this->_handle, $ch);
				$this->_batch_config['map_array'][(string)$ch] = $id;
// 				print_r($ch);
// 				echo "\n" . (string)$ch . "\n";
			}
			print_r($this->_batch_config);
		}
		else {
			$this->_handle = curl_init($this->_url);
			curl_setopt_array($this->_handle, $this->_curl_option);
		}
	}

	public function get_response() {
		if($this->_single_or_multi) {
			$response = curl_exec($this->_handle);
			curl_close($this->_handle);

			return $response;
		}
		else {
			$responses = array();
			do
			{
				while(($code = curl_multi_exec($this->_handle , $active)) == CURLM_CALL_MULTI_PERFORM);
				if($code != CURLM_OK)
				{
					break;
				}

				// a request was just completed -- find out which one
				while($done = curl_multi_info_read($this->_handle))
				{

					// get the info and content returned on the request
					$content = curl_multi_getcontent($done['handle']);
					$responses[$this->_batch_config['map_array'][(string) $done['handle']]] = $content;//$this->parseHead($content);

					// remove the curl handle that just completed
					curl_multi_remove_handle($this->_handle , $done['handle']);
					curl_close($done['handle']);
				}

				// Block for data in / output; error handling is done by
				// curl_multi_exec
				if($active > 0)
				{
					curl_multi_select($this->_handle , 0.5);
				}
			}
			while($active);

			return $responses;
		}
	}
}

今天在CI下写一个爬虫库,此爬虫支持单url抓取和多线程批量url抓取,以及自定义正则匹配所需要的内容。

未完成

===========2013.05.06============

完成多线程部分,类代码待完善

Apache虚拟主机中NameVirtualHost指令

说明 为一个基于域名的虚拟主机指定一个IP地址(和端口)
语法 NameVirtualHost addr[:port]
作用域 server config
状态 核心(C)
模块 core

如果您要配置基于域名的虚拟主机,NameVirtualHost指令就是您必须的指令之一。

尽管addr参数可以使用主机名,但建议您还是使用IP地址。比如:

NameVirtualHost 111.22.33.44

使用NameVirtualHost指令,您可以指定一个基于域名的虚拟主机将使用哪个IP地址来接受请求。在一个防火墙或是其它代理接受了请求并把它转到服务器所在的另外一个IP地址上的情况下,您必须指定伺服请求的机器物理界面上的IP地址。如果您对于多个地址使用了多个基于域名的虚拟主机,您应该为每个地址使用这个指令。

注意

“主服务器”和任何其它”_default_“服务器都不会伺服发送到NameVirtualHost IP地址的请求。(除非您指定了NameVirtualHost,但没有为这个地址指定任何VirtualHost)。

另外,您还可以为您使用的基于域名的虚拟主机指定一个端口号。比如:

NameVirtualHost 111.22.33.44:8080

IPv6地址必须封装在一对方括号内,如下例所示:

NameVirtualHost [2001:db8::a00:20ff:fea7:ccea]:8080

为了接受所有界面的请求,您可以使用”*“:

NameVirtualHost *

<VirtualHost>指令的参数

请注意,<VirtualHost>指令的参数必须与NameVirtualHost指令的参数完全匹配。

NameVirtualHost 1.2.3.4
<VirtualHost 1.2.3.4>
# ...
</VirtualHost>

[来源]

ubuntu和centos下关于lamp的一些常规操作

本文中centos环境是在root账户下操作的

安装Apache, MySQL, PHP

sudo apt-get install apache2 mysql-server-5.0 php5 libapache2-mod-php5 php5-mysql ...(需要别的模块自己添加)
yum -y install httpd php mysql mysql-server php-mysql httpd-manual mod_ssl mod_perl mod_auth_mysql php-mcrypt php-gd php-xml php-mbstring php-ldap php-pear php-xmlrpc mysql-connector-odbc mysql-devel libdbi-dbd-mysql...(相关模块自己取舍,需要再加)

重启apache服务(其他服务类似)

sudo /etc/init.d/apache2 restart(或sudo service apache2 restart)
/etc/init.d/httpd restart(或 service httpd restart)

Apache相关配置

路径:

/etc/apache2/apache2.conf
/etc/httpd/conf/httpd.conf

虚拟主机配置

可以直接写到上述配置文件中,也可以单独写,我在centos中是直接写到apache主配置文件的,在ubuntu中,配置文件同路径中有两个文件夹,分别是

sites-available和sites-enabled,具体作用不言而喻(同目录中的mods-available和mods-enable文件夹也类似)

在sites-available中配好相关虚拟主机,我一般单独文件一个主机,然后运行

sudo a2ensite 虚拟主机配置文件名

然后restart或者reload apache服务都可以使配置生效。

用户和组

centos下一般是apache:apache

ubuntu下一般是www-data:www-data

Ubuntu 12.04下新建快捷方式

[Desktop Entry]
Name=ZendStudio
Exec=/usr/local/ZendStudio/ZendStudio
Icon=/usr/local/ZendStudio/icon.xpm
Terminal=false
StartupNotify=true
Type=Application
Categories=Development;

把程序包放在/usr/local下面