466页,安装xdebug。原文“就像APD一样,你可以运行pear install xdebug 从PECL安装Xdebug。”

这里的pear有误,应当是pecl。

正确方法: pecl install xdebug。

Controlling how web pages are cached is basically done using 2 kind of headers: Expires and Cache-Control

Using the Expire header is really simple. It tells when the page the browser or the proxy downloaded should be fetched again from the web server. In order to use it in your CGI or PHP page, just after the Content-type, you can add the the expire header as shown below:

// calc an offset of 24 hours
$offset = 3600 * 24;
// calc the string in GMT not localtime and add the offset
$expire = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
//output the HTTP header
Header($expire);

The Cache-Control HTTP Headers is part of the HTTP 1.1 standard. Here you are an example:

  Cache-Control: max-age=3600, must-revalidate

It has a certain number of parameters that can be used:

  • max-age=seconds - the number of seconds from the time of the request you wish this objcet to be keep into the cache;
  • s-maxage=seconds - like max-age but it only applies to proxy;
  • public - tell to handle the content has cacheable even if it would normally be uncacheable, it is used for example for authenticated pages;
  • no-cache - force both proxy and browser to validate the document before to provide a cached copy;
  • must-revalidate - tell the browser to obey to any information you give them about a webpage;
  • proxy-revalidate - like must-revalidate but applies to proxy;

More Headers

But that's not all, you have to consider other 2 headers: Content-Length and Last-Modified.

The Last-Modified is the easier, you just have to output a date in GMT for example:

        $gmt_mtime = gmdate('D, d M Y H:i:s', time() ) . ' GMT';
header("Last-Modified: " . $gmt_mtime );

Content-Lenght is the harder because you don't know how long is a php page before processing it. If you output a file, for example and image or a PDF, it is simple because before of starting the output you can read the filesize. With dynamic page you have to use the special OB library, see the example:

	ob_start();
... your php code ...
... your php code ...
... your php code ...
header('Content-Length: ' . ob_get_length());
ob_end_flush();

The advantage is that you can use:

	ob_start('ob_gzhandler');
to have automatically compressed pages in output for faster downloading.

Usefull Links

Finally if you want to check the cacheability of your pages there are some urls available:

原文地址:

http://bbs.chinaunix.net/viewthread.php?tid=661015&extra=page%3D1%26amp%3Bfilter%3Ddigest&page=1 

[学习] PHP中的(伪)多线程与多进程

    已经因为没怎么需要,所以没有查这个的资料。最近有一个项目却是需要这样子的功能。

    查看了PHP的手册和他人的例子,了解到基本的两种方法:

(伪)多线程:借助外力
    利用WEB服务器本身的多线程来处理,从WEB服务器多次调用我们需要实现多线程的程序。
    以下转载自:http://www.laikan8.com/21/118472.html

QUOTE:
我们知道PHP本身是不支持多线程的, 但是我们的WEB服务器是支持多线程的.

也就是说可以同时让多人一起访问. 这也是我在PHP中实现多线程的基础.

假设我们现在运行的是a.php这个文件. 但是我在程序中又请求WEB服务器运行另一个b.php

那么这两个文件将是同时执行的.

(PS: 一个链接请求发送之后, WEB服务器就会执行它, 而不管客户端是否已经退出)

有些时候, 我们想运行的不是另一个文件, 而是本文件中的一部分代码.该怎么办呢?

其实可是通过参数来控制a.php来运行哪一段程序.

下面看一个例子:

//a.php


PHP代码:--------------------------------------------------------------------------------

<?php
    function runThread()
    {
        $fp = fsockopen('localhost', 80, $errno, $errmsg);
        fputs($fp, "GET /a.php?act=brnrn");        //这里的第二个参数是HTTP协议中规定的请求头
                                //不明白的请看RFC中的定义
        fclose($fp);
    }

    function a()
    {
        $fp = fopen('result_a.log', 'w');
        fputs($fp, 'Set in ' . Date('h:i:s', time()) . (double)microtime() . "rn");
        fclose($fp);        
    }

    function b()
    {
        $fp = fopen('result_b.log', 'w');
        fputs($fp, 'Set in ' . Date('h:i:s', time()) . (double)microtime() . "rn");
        fclose($fp);        
    }
    if(!isset($_GET['act'])) $_GET['act'] = 'a';
    if($_GET['act'] == 'a')
    {
        runThread();
        a();
    }
    else if($_GET['act'] == 'b') b();
?>

--------------------------------------------------------------------------------


打开result_a.log 和 result_b.log 比较一下两个文件的中访问的时间. 大家会发现, 这两个的确是在不同线程中运行的.
有些时间完全一样.

上面只是一个简单的例子, 大家可以改进成其它形式.


既然PHP中也能多线程了, 那么问题也来了, 那就是同步的问题. 我们知道 PHP本身是不支持多线程的. 所以更不会有什么像

Java 中synchronize的方法了. 那我们该如何做呢.

1. 尽量不访问同一个资源. 以避免冲突. 但是可以同时像数据库操作. 因为数据库是支持并发操作的. 所以在多线程的PHP中

不要向同一个文件中写入数据. 如果必须要写的话, 用别的方法进行同步.. 如调用 flock对文件进行加锁等. 或建立临时文件

并在另外的线程中等待这个文件的消失 while(file_exits('xxx')); 这样就等于这个临时文件存在时, 表示其实线程正在操作

如果没有了这个文件, 说明其它线程已经释放了这个.

2. 尽量不要从runThread在执行fputs后取这个socket中读取数据. 因为要实现多线程, 需要的用非阻塞模式. 即在像fgets这

样的函数时立即返回.. 所以读写数据就会出问题. 如果使用阻塞模式的话, 程序就不算是多线程了. 他要等上面的返回才执行

下面的程序. 所以如果需要交换数据最后利用外面文件或数据中完成. 实在想要的话就用socket_set_nonblock($fp) 来实现.


说了这么多, 倒底这个有没有实际的意义呢? 在什么时候需要这种用这种方法呢 ?

答案是肯定的. 大家知道. 在一个不断读取网络资源的应用中, 网络的速度是瓶颈. 如果采多这种形式就可以同时以多个线程对

不同的页面进行读取.

本人做的一个能从8848、soaso这些商城网站搜索信息的程序。还有一个从阿里巴巴网站上读取商业信息和公司目录的程序也用到

了此技术。 因为这两个程序都是要不断的链接它们的服务器读取信息并保存到数据库。 利用此技术正好消除了在等待响应时的瓶

颈。

多进程:使用PHP的Process Control Functions(PCNTL/线程控制函数)
    函数参考可见:http://www.php.net/manual/zh/ref.pcntl.php
    只能用在Unix Like OS,Windows不可用。
    编译php的时候,需要加上--enable-pcntl,且推荐仅仅在CLI模式运行,不要在WEB服务器环境运行。
    以下为简短的测试代码:

<?php
declare(ticks=1);
$bWaitFlag = FALSE; /// 是否等待进程结束
$intNum = 10;           /// 进程总数
$pids = array();        ///  进程PID数组

echo ("Startn");

for($i = 0; $i < $intNum; $i++) {

  $pids[$i] = pcntl_fork();/// 产生子进程,而且从当前行之下开试运行代码,而且不继承父进程的数据信息

  if(!$pids[$i]) {
    // 子进程进程代码段_Start
    $str="";
    sleep(5+$i);
    for ($j=0;$j<$i;$j++) {$str.="*";}
    echo "$i -> " . time() . " $str n";
    exit();
    // 子进程进程代码段_End
  }

}
if ($bWaitFlag)
{
  for($i = 0; $i < $intNum; $i++) {
    pcntl_waitpid($pids[$i], $status, WUNTRACED);
    echo "wait $i -> " . time() . "n";
  }
}
echo ("Endn");
?>

运行结果如下:

[qiao@oicq qiao]$ php test.php        
Start
End
[qiao@oicq qiao]$ ps -aux | grep "php"
qiao     32275  0.0  0.5 49668 6148 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32276  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32277  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32278  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32279  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32280  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32281  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32282  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32283  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32284  0.0  0.5 49668 6152 pts/1    S    14:03   0:00 /usr/local/php4/b
qiao     32286  0.0  0.0  1620  600 pts/1    S    14:03   0:00 grep php
[qiao@oicq qiao]$ 0 -> 1133503401  
1 -> 1133503402 *
2 -> 1133503403 **
3 -> 1133503404 ***
4 -> 1133503405 ****
5 -> 1133503406 *****
6 -> 1133503407 ******
7 -> 1133503408 *******
8 -> 1133503409 ********
9 -> 1133503410 *********

[qiao@oicq qiao]$

如果$bWaitFlag=TURE,则结果如下:

[qiao@oicq qiao]$ php test.php        
Start
0 -> 1133503602  
wait 0 -> 1133503602
1 -> 1133503603 *
wait 1 -> 1133503603
2 -> 1133503604 **
wait 2 -> 1133503604
3 -> 1133503605 ***
wait 3 -> 1133503605
4 -> 1133503606 ****
wait 4 -> 1133503606
5 -> 1133503607 *****
wait 5 -> 1133503607
6 -> 1133503608 ******
wait 6 -> 1133503608
7 -> 1133503609 *******
wait 7 -> 1133503609
8 -> 1133503610 ********
wait 8 -> 1133503610
9 -> 1133503611 *********
wait 9 -> 1133503611
End
[qiao@oicq qiao]$

从 多进程的例子可以看出,使用pcntl_fork()之后,将生成一个子进程,而且子进程运行的代码,从pcntl_fork()之后的代码开始,而子进 程不继承父进程的数据信息(实际上是把父进程的数据做了一个全新的拷贝),因而使用if(!$pids[$i]) 来控制子进程实际运行的代码段。

    更详细的研究出于时间关系,暂时没有进行,你可以参考我给出的手册的链接。

升级到PHP 5.2.2后,出现session_start写入权限问题。

提示信息如下:

Warning: session_start() [function.session-start]: SAFE MODE Restriction in effect. The script whose uid is 2023 is not allowed to access /var/tmp/ owned by uid 0 in /configs/config.inc.php on line 9

Fatal error: session_start() [<a href='function.session-start'>function.session-start</a>]: Failed to initialize storage module: files (path: ) in /configs/config.inc.php on line 9

 

 后来在php5的changelog里找到一个bug报告。里面提到一个安全模式的bug。默认session的save_path是/var/tmp,这样会要校验权限。在php.ini文件里,显式指定session的save_path为/tmp,重启web服务就解决了。

今天摆弄起dia来,用它画UML。但是光画成UML,不能导出生成代码,仍然是个痛苦的事情。

为此想用umbrello来着,可是我用的 桌面环境,不支持KDE,无法安装umbrello。只好作罢。

 

找到uml2php,能够将dia生成PHP代码。遗憾的是只有LINUX版本。 后来找到了dia2code这个好东西。他支持导出多种代码。


 # dia2code
dia2code version 0.8.2, Copyright (C) 2000-2001 Javier O'Hara
Dia2Code comes with ABSOLUTELY NO WARRANTY
This is free software, and you are welcome to redistribute it
under certain conditions; read the COPYING file for details.

Usage: dia2code [-h|--help] [-d <dir>] [-nc] [-cl <classlist>]
       [-t (ada|c|cpp|idl|java|php|php5|python|shp|sql|csharp)] [-v]
       [-l <license file>] [-ini <initialization file>]<diagramfile>

 


要将dia文件生成PHP代码,很简单:

 

 # dia2code -t php test.dia

 

有很多Apache的虚拟主机,若要我一个一个的转换成为Lighttpd的虚拟主机,那太痛苦了。

于是用PHP写成这个小程序。

 查看全文