PHP ActiveRecord

tablepre = TABLE_PREFIX;
        $this->class = get_class($this);
        $this->table = $this->tablepre . strtolower($this->class);
        $this->data = array();
        $this->connect();
    }

    private function connect() {
        if(!self::$link) {
            self::$link = mysql_connect(DBHOST, DBUSER, DBPASS);
            mysql_select_db(DBNAME);
        }
        return self::$link;
    }

    public function __set($name, $value) {
        $this->data[$name] = $value;
    }

    private function implodefields($cond) {
        $fields = array();
        foreach($cond as $key => $value) {
            $value = mysql_real_escape_string($value);
            $fields[] = "`$key`='$value'";
        }
        return implode(', ', $fields);
    }

    public function add() {
        $fields = $this->implodefields($this->data);
        $sql = "INSERT INTO `{$this->table}` SET $fields";
        $this->query($sql);
    }

    public function findById($id) {
        $sql = "SELECT * FROM `{$this->table}` WHERE `{$this->primaryKey}`='$id' LIMIT 1";
        $data = $this->getOne($sql);
        return $this->makeObjFromArray($data);
    }

    private function makeObjFromArray($data) {
        $obj = new $this->class;
        foreach($data as $key => $value) {
            $obj->$key = $value;
        }
        return $obj;
    }

    private function query($sql) {
        echo $sql . "\n";
        return mysql_query($sql, self::$link);
    }

    private function getOne($sql) {
        $data = $this->query($sql);
        if($data) {
            $item = mysql_fetch_assoc($data);
            return $item;
        }
        return false;
    }
}

class User extends ActiveRecord {
    var $primaryKey = 'id';
}

$user = new User();
$user->name = 'Woody';
$user->email = 'xxx@hotmail.com';
$user->add();

$user = $user->findById(1);
print_r($user);

原文地址:  http://www.phpig.net/showthread.php?tid=310

使用PHPDocumentor来生成API文档

使用PHPDocumentor来生成API文档

(一)什么是PHPDocumentor

PHPDocumentor是使用PHP开发的一款API文档生成工具, 相对于有规范注视的程序, 可以使用它快速的生成具有相互参照,索引等功能的API文档, 大概就是这么一个东西, 如果你还不了解. 请继续往下看.

(二)安装PHPDocumentor

安装方式有两种

  1. 手动安装

www.phpdoc.org下载, 然后解压即可

  1. 通过pear自动安装

命令行下输入: pear install PhpDocumentor

(三)使用PHPDocumentor

1.命令行方式

在PHPDocumentor目录下找到phpdoc.bat文件进行编辑. 查找SET phpCli=这句将=号后面的值设置为你的phpcli所在路径, 一般都在你的PHP安装目录下. 比如我的就设置为SET phpCli=C:\wamp\bin\php\php5.3.0\php.exe,保存退出. 在命令行方式下进入PHPDocument目录. 输入phpdoc –h 会出现一大堆参数的介绍, 这里我们只会用到.

-f 要进行分析的文件名称,多个文件用,号分割

-d 要进行分析的目录, 多个目录用,号分割

-t 分析后的文件存放路径

-o 输出文档的格式, 列如: -o HTML:frames:default, 这里你可以打开PHPDocumentor目录下的phpDocumentor/Converters/目录查看. 像上面这个就是对应的phpDocumentor/Converters/HTML/frames/templates/default目录

下面我们写一个文件来测试一下.

Demo.php文件

然后我们打开命令行, 进入PHPDocumentor目录, 输入以下内容

phpdoc -f E:/www/demo.php -t E:/www/demo -o HTML:frames:def

ault

然后打开E:/www/demo/目录打开index.html文件看看. 是不是demo.php文件中的类以及方法全列出来了. 弄到这你已经会使用PHPDocumentor了.  细心的你可能发现demo.php文件中的中文显示出来全乱码了, 是的, 我们还需要做下面的事.

打开 phpDocumentor/Converters/HTML/frames/templates/default/templates/目录中的header.tpl以及top_frame.tpl文件将其中的charset=iso-8859-1改为charset=utf-8,保存文件退出, 重新运行一次phpdoc -f E:/www/demo.php -t E:/www/demo -o HTML:frames:default, 再次浏览生成的文件. 乱码问题就解决了, 你还可以更改模板文件, 把生成的页面弄的更好看..

还有一种方式为web页面生成, 很简单这里不在讲述, 我们主要看看phpdocumentor的注释语法

注释规则:

所有注释已/**开始, 第一行为功能简述,第二行为详细说明,第三行为标记tag.

例如:
/**
     * hello函数
	 *
	 * 传入你的名字, 想你问好.
	 *
	 * @param	string	$name	你的名字
*/
function hello($name)
{
	echo ‘hell’. $name;
}

这样就是一个标准的注释格式了

在上面出现了@param这样的关键字, 这个是用来描述一个参数的. 类似的关键字还有

@access
@author
@copyright
@example
@const
@final
@filesource
@global
@link
@package
@abstruct
@return
@param
@static
@var
@version
@todo

常用的大概就这些, 具体函数请google一下..

PHPDocumentor能够识别的PHP关键字:

Include,include_once
Request,request_once
Define
Function
Global
Class

也就是说你在上面这些列出的关键字前书写规范的注释PHPDocumentor都能进行解析. 都能生成对应的文档, 还等什么自己写个文件试试吧..

GPC的思考:$_REQUEST、$_GET、$_POST、$_COOKIE 的关系和区别

原文地址:http://www.phpig.net/showthread.php?tid=206&pid=548#pid548

GPC的优先级在PHP.INI里可以设置,variables_order = “GPCS”

测试开始。
测试1:

echo '
';//源格式打印
//URL加上m=xxoo来测试$_GET
    print_r($_REQUEST);//首先打印内容
    print_r($_GET);

    $_REQUEST = array();//清空$_REQUEST
    echo $_GET['m'];
echo '

';

测试结果:$_GET['m']的值是xxoo。

测试2:

echo '
';//源格式打印
//URL加上m=xxoo来测试$_GET
    print_r($_REQUEST);
    print_r($_GET);

    $_GET = array();//清空
    print_r($_REQUEST);
echo '

';

测试结果:$_REQUEST['m']的值是xxoo。

结论:对$_REQUEST的操作没有影响到$_GET,反之亦然。$_REQUEST只是包含了一个$_GET的副本(the same as $_POST 哈哈)。

————————————华丽的分隔线 —————————————————
好。继续
测试3:

//POST-GET重名测试
//从其他页面POST传送一个m的值为post,action地址加上m=get
    print_r($_REQUEST);
    print_r($_GET);
    print_r($_POST);

结果:$_REQUEST['m'] == ‘post’。
结论:同时提交GET和POST且同名,$_REQUEST取的是POST的值。(可能是POST优先级更高。)

测试4

//cookie与post\get 重名测试
setcookie('m', 'cookie', time()+3600);//先把COOKIE种上,名字为m,值为cookie。然后刷新。(COOKIE要刷新才生效)

//从其他页面POST传送一个m的值为post,action地址加上m=get
print_r($_REQUEST);

结果:$_REQUEST['m'] == ‘cookie’。结论:COOKIE的优先级最高。

总结:
$_REQUEST、$_GET、$_POST、$_COOKIE 的关系和区别。
1.关系:$_REQUEST包含了$_GET、$_POST、$_COOKIE的所有内容,是它们的集合体。
2.$_GET、$_POST、$_COOKIE在$_REQUEST中都有一个副本。改变$_REQUEST的值不影响$_GET等,反之亦然。
3.GET和POST同名的情况下,$_REQUEST取的是POST的值。COOKIE与GET或POST重名的情况下,$_REQUEST取的是COOKIE的值。COOKIE的优先级最高。

pack/unpack 实现简单的文件数据库

dbhandler) {
            return $this->dbhandler;
        }
        $this->dbhandler = fopen($this->dbfile, "ab+");
        flock($this->dbhandler, LOCK_EX);
        if (!$this->dbhandler) {
            trigger_error("Connot open file {$file}", E_USER_ERROR);
        }
        return $this->dbhandler;
    }

    /**
     * 写入数据
     *
     * @access  public
     * @param   string $str    数据已空格( )分割自断
     * @return  integer
     */
    public function write($str)
    {
        if (!$this->dbhandler) {
            trigger_error('Not open the database', E_USER_ERROR);
        }
        $data  = explode(' ', $str);
        $name  = pack('a8', $data['0']); //a这里用a是为0保证 不管数据多长或多短都格式化为一个长度为8的字符串
        $age   = pack('S', $data['1']); //16位无符合短整数, 总是16位
        $site  = pack('a30', $data['2']); //同理
        return fwrite($this->dbhandler, $name . $age . $site);
    }

    /**
     * 读取数据
     *
     * @access  public
     * @param   integer $row    读取行数 -1为全部读取
     * @return  array
     */
    public function read($row = 0)
    {
        if (!$this->dbhandler) {
            trigger_error('Not open the database', E_USER_ERROR);
        }
        rewind($this->dbhandler);
        if ($row == -1) { /* 读取所有 */
            $res = array();
            fseek($this->dbhandler, 0, SEEK_END);
            $len = ftell($this->dbhandler);
            $len = $len / 40;
            for ($i = 0; $i < $len;$i++) {
                $res[] = $this->read($i);
            }
            return $res;
        } else {
            /* 读取一行 */
            fseek($this->dbhandler, 40 * $row);
            $res = array();
            $res[] = array_shift(unpack('a8', fread($this->dbhandler, 8)));
            $res[] = array_shift(unpack('S', fread($this->dbhandler, 2)));
            $res[] = array_shift(unpack('a30', fread($this->dbhandler, 30)));
            return $res;
        }
    }

    /**
     * 删除记录
     *
     * @access  public
     * @param   integer $row    删除的行数
     * @return  boolean
     */
    public function remove($row)
    {
        $res    = $this->read(-1);
        $status = false;
        if (isset($res[$row])) {
            unset($res[$row]);
            $status = true;
        }
        $len = count($res);
        $this->truncate(); //清空数据库
        for ($i = 0; $i < $len; $i++) {
            isset($res[$i]) && $this->write(join(' ', $res[$i])); //重新写入数据
        }
        return $status;
    }

    /**
     * 清空数据库
     *
     * @access  public
     * @return  void
     */
    public function truncate()
    {
        $this->close();
        unlink($this->dbfile);
        $this->open();
    }

    /**
     * 关闭数据库
     *
     * @access  public
     * @return  boolean
     */
    public function close()
    {
        if (!$this->dbhandler) {
            trigger_error('Not open the database', E_USER_ERROR);
        }
        return fclose($this->dbhandler);
    }
}

$db = new DataBase();
$db->open(); //打开数据库
$db->write('xiaokai 18 www.youyuge.com'); //写入数据
$db->write('likai 18 www.youyuge.com');
$db->read(0); //读取第一条数据
$res = $db->read(-1); //读取所有数据
$db->remove(0); //删除第一条数据
$db->truncate(); //清空数据库
$db->close(); //关闭数据库

为了更了解pack/unpack这两个函数, 仿照别人的例子, 自己添加了些功能…

PHP pack/unpack 的格式字符详细

手册上解释的不是很清楚, 所以网上找了下, 记录下来, 用得着..

string pack ( string $format [, mixed $args [, mixed $...]] )

  • a 一个填充空的字节串
  • A 一个填充空格的字节串
  • b 一个位串,在每个字节里位的顺序都是升序
  • B 一个位串,在每个字节里位的顺序都是降序
  • c 一个有符号 char(8位整数)值
  • C 一个无符号 char(8位整数)值;关于 Unicode 参阅 U
  • d 本机格式的双精度浮点数
  • f 本机格式的单精度浮点数
  • h 一个十六进制串,低四位在前
  • H 一个十六进制串,高四位在前
  • i 一个有符号整数值,本机格式
  • I 一个无符号整数值,本机格式
  • l 一个有符号长整形,总是 32 位
  • L 一个无符号长整形,总是 32 位
  • n 一个 16位短整形,“网络”字节序(大头在前)
  • N 一个 32 位短整形,“网络”字节序(大头在前)
  • p 一个指向空结尾的字串的指针
  • P 一个指向定长字串的指针
  • q 一个有符号四倍(64位整数)值
  • Q 一个无符号四倍(64位整数)值
  • s 一个有符号短整数值,总是 16 位
  • S 一个无符号短整数值,总是 16 位,字节序跟机器芯片有关
  • u 一个无编码的字串
  • U 一个 Unicode 字符数字
  • v 一个“VAX”字节序(小头在前)的 16 位短整数
  • V 一个“VAX”字节序(小头在前)的 32 位短整数
  • w 一个 BER 压缩的整数
  • x 一个空字节(向前忽略一个字节)
  • X 备份一个字节
  • Z 一个空结束的(和空填充的)字节串
  • @ 用空字节填充绝对位置

一些规则:

1.每个字母后面都可以跟着一个数字,表示 count(计数),如果 count 是一个 * 表示剩下的所有东西。
2.如果你提供的参数比 $format 要求的少,pack 假设缺的都是空值。如果你提供的参数比 $format 要求的多,那么多余的参数被忽略。

echo pack('c', 65); //A
echo pack('c', 65, 97); //A 但是会报错, 因为多了一个参数
echo pack('c2', 65, 97);// Aa
echo pack('c*', 65, 97, 59, 97, 65); // Aa;aA *就是来多少填充多少..

冻结和解冻的PHP对象

之前无意间看到了 Freezing and Thawing PHP Objects 这篇文章翻译过来就是 冻结和解冻的PHP对象 感觉挺新鲜的, 然后花了点时间研究了下。

代码如下:

getProperties() as $attr) {

            $attr->setAccessible(true); //设置属性为访问级别public
            //ReflectionProperty::getName() 获取属性名
            //ReflectionProperty::getValue() 获取属性的值
            $state[$attr->getName()] = $attr->getValue($object) + 1;
        }
        return array('className' => get_class($object), 'state' => $state);
    }

    //解冻
    public static function thaw(array $frozenObject) {
        if(!class_exists($frozenObject['className'])) {
            throw new RuntimeException(sprintf('Class "%s could not be found"', $frozenObject['className']));
        }

        $object = unserialize(sprintf('O:%d:"%s":0:{}', strlen($frozenObject['className']), $frozenObject['className']));
        $reflector = new ReflectionObject($object);

        foreach ($frozenObject['state'] as $name => $value) {
            $attr = $reflector->getProperty($name);
            $attr->setAccessible(true);
            $attr->setValue($object, $value);
        }
        return $object;
    }
}

class Foo {

    public $a;
    protected $b;
    private $c;

    public function __construct($a, $b, $c) {
        $this->a = $a;
        $this->b = $b;
        $this->c = $c;
    }
}
$object = new Foo(1, 2, 3);
var_dump($object);
/* 输出结果
object(Foo)[1]
  public 'a' => int 1
  protected 'b' => int 2
  private 'c' => int 3
*/

$frozenObject =  ObjectFreezer::freeze($object);
var_dump($frozenObject);
/* 输出结果
array
  'className' => string 'Foo' (length=3)
  'state' =>
    array
      'a' => int 2
      'b' => int 3
      'c' => int 4
*/

$object = ObjectFreezer::thaw($frozenObject);
var_dump($object);
/* 输出结果
object(Foo)[5]
  public 'a' => int 2
  protected 'b' => int 3
  private 'c' => int 4
*/
?>

第一次就是输出了 $object 的所有字段信息

第二次经过调用 ObjectFreezer::freeze($object); 也就是冻结 $object 对象返回了一个数组

className没啥说的 $object 的类名

state是经过冻结后的 $object 对象的属性这里给他每个值加1

第三次通过 ObjectFreezer::thaw($frozenObject); 也就是解冻,返回了一个对象

可以看到这个对象中的属性值已经改变了.

这就是所谓的冻结与解冻php对象. 但是具体用到哪, 暂时还我也不清楚, 相信以后总有地方会用到.. ^_^

对了setAccessible是5.3才有的哦..

在看完 Freezing and Thawing PHP Objects 萌生了个想法, 使用php自带的serialize/unserialize这两个函数也许也能实现这样的功能啊..

然后动手试了下, 果然如此.

a = $a;
        $this->b = $b;
        $this->c = $c;
    }

    function show() {
        echo sprintf('$a=%d, $b=%d, $c=%d', $this->a, $this->b, $this->c);
    }

}
?>

注意一下字段的修饰符

show();
$string = serialize($foo);
$foo    = unserialize(str_replace(2, 20, $string)); //这里吧 $foo->b的值替换为20
//这里因为序列化后 protected和private字段 的表示方法不一样, 所以就好用替换了.. - -
$foo->show();
?>

输出结果
$a=1, $b=2, $c=3
$a=1, $b=20, $c=3

很明显, 这里也修改成功了..

PHP还提供了实现类似映射的一些函数

class_ exists
get_ called_ class
get_ class_ methods
get_ class_ vars
get_ class
get_ declared_ classes
get_ declared_ interfaces
get_ object_ vars
get_ parent_ class
interface_ exists
method_ exists
property_ exists

感叹下PHP真TMD强大..

牛X的PHP(用于坚定信念)

1.序言
定义:PHP是一种简单的,面向对象的,解释型的,健壮的,安全的,性能非常之高的,独立于架构的,可移植的,动态的脚本语言。PHP具有和JAVA类似的Class关键字。因为不需要虚拟机,以致速度比JAVA快5倍。PHP正迅速变成一种标准的,多用途的,面向对象的脚本语言。PHP不仅可用来开发Web应用程序,也可以开发普通应用程序。

PHP是一种功能强大的脚本语言。PHP将击败PERL/Python并取而代之。PHP是下一代的PERL/Python脚本。PHP可以胜任任何PERL/Python做的工作,并且做的更多,更好,更简洁!!

PHP是Hypertext Pre-Processor(超文本预处理器)的缩写,它是一种服务器端的HTML脚本/编程语言。PHP语法上与C相似,可运行在Apache, Netscape/iPlanet, 和 Microsoft IIS Web 服务器上。PHP作为一种工具,可以让你创建动态的Web页面。应用PHP的网页与常规的HTML页面并无二致,你可以用同样的方式来创建、编辑它们。PHP允许你直接在HTML文件里写入简单的脚本,这一点与Javas cript非常相似。而不同的是,PHP不依赖于浏览器,是服务器端的语言,而Javas cript却是一种客户端的嵌在HTML中的语言。概念上,PHP与Netscape的LiveWire Pro产品,Microsoft的ASP以及SunMicrosystem 的JSP相似。

PHP不仅可以用来创建Web应用程序,也可以用来开发普通的单机应用程序。

PHP的强劲之处在于:

·PHP是一项最优秀的技术。其它技术,如PERL,Python, Tcl, VB s cript, ASP 相对来说,都是陈旧低劣的。即使是Java/JSP,也在PHP之下。

·开放源码

·广泛的数据库连接

·大量的扩展库

·作为一种多用途的脚本语言,比PERL,VB s cript, ASP, JSP都要优秀。

为什么选择PHP?因为PHP是最好的,原因如下:

·PERL“味道不好”,因为其程序不易阅读和维护,且不是面向对象的。把PERL忘了,转向PHP吧。PERL程序员将抛弃PERL,因为他们爱上了PHP! PHP实际上就是“现代版的PERL”,只是名称不同而已。

·Java 是面向对象的,但速度很慢。Java程序远行起来很慢,对它唯一的抱怨就是——“Java,真是慢的糟糕”。而且十分复杂(具有许多层,如JVM,JIT 等等)。这往往诱发问题。既然有了Linux,为什么还要Java呢?

·Python“不错”,但没有C语言中的括号和大括号,而这在vi编辑器中对*控代码非常有用。如果不能利用vi/emacs编辑器搜索括号/大括号的命令迅速*控代码,那么就好象断了手一样。PHP在技术上比Python更加先进。

·PHP是最好的,因为它面向对象,并且吸收了C/C++/Java/PERL的精华。PHP可以替代PERL,Python, Java, C, C++, awk, Unix shell 脚本,Visual Basic 和其它语言!!

PHP直接运行,而且是由C写成的。

·每一个电脑程序员都知道PHP是最好的,不信问一下你旁边的程序员。

·只有PHP才能称雄于21世纪、22世纪以及更远的将来。

·为什么我们认为PERL,Python和Java程序员会将归附PHP,这里有一个很重要的原因。

以前,世界上许多公司都把PHP当作是一个“高度机密,严格保密”的电脑程序语言,但是现在它已经变成最为著名的,在Web, Internet, E-commerce以及 B2B等诸多项目上应用最广泛的面向对象的脚本语言。即使是在今天,仍有许多竞争性(competing)公司把PHP当作是高度机密的东西,决不向外界(竞争对手)透露半点。

PHP将如同暴风雨一般席卷整个世界,IT工业将为之震惊。PHP的力量在于它是跨平台的,可以运行在任何地方。如Linux,Windows 95/98/NT/2000/XP, Solaris, HPUX 以及各种UNIX。PHP只需写一次,就可以配置在任何地方。PHP可以运行在Apache,Microsoft IIS等多种Web服务器上。

PHP比Java快5到20倍!!实际的比较测试显示,PHP的运行速度是Java3.7倍左右。PHP太容易使用了,你可以用它在非常短的时间里,非常迅速的开发出非常复杂的web,e-commerce和一般的单机应用程序。(在将来,PHP将会模仿Java大多数的功能,相信Java程序员也会喜欢上它。PHP将包含Java中的关键字,如class, extends,interface, implements, public,protected, private 等等等等。)

PHP具有面向对象特性,它吸收了Java, C++, PERL 和C的最优秀的部分。PHP可以说是所有脚本/编程语言中的宝石。不久,它就会成为全世界程序员的“麦加圣地”。PHP即可以运行在Window95/NT/2000/XP上,也可以运行在各种UNIX上。

我们将大吃一惊——PHP极有可能成为21世纪的电脑编程语言。

可以使用Zend Optimizer对PHP进行编译和优化,从而使它运行的更快。PHP4.0中已经集成了Zend Optimizer。 首先,你在开发、测试、除错过程中,用PHP脚本语言编写你的应用程序。一旦项目完成,你便可以用Zend编译器,将PHP文件编译成运行速度更快的可执行程序。

对于电子商务项目,你一般需要综合使用PHP(70%),HTML/DHTML/XML(25%)和5%的Javas cript(客户端验证)。

Simple cookie method

/**
 * simple cookie method
 *
 * @access  public
 * @param   string    $name
 * @param   mixed   $value  when $value=null the remove cookie
 * @param   integer $expire
 * @param   string  $path
 * @param   string  $domain
 * @return  mixed
 */
function cookie($name, $value = '', $expire = null, $path = null, $domain = null)
{
    if (empty($value)) {
        if (is_null($value)) {
            //remove cookie
            if (isset($_COOKIE[$name])) {
                setcookie($name, $value, time()-3600, $path, $domain);
                unset($_COOKIE[$name]);
                return true;
            }
        }
        //get cookie
        $value = isset($_COOKIE[$name]) ? $_COOKIE[$name] : null;
        return unserialize($value);
    }
    //set cookie
    $expire = is_null($expire) ? $expire : time() + $expire;
    $value  = serialize($value);
    return setcookie($name, $value, $expire, $path, $domain);
}