阿辉的博客

系统 网络 集群 数据库 分布式云计算等 研究

PHP版3DES加解密类,可与java的3DES(DESede)加密方式兼容

<?php

/**
*
* PHP版3DES加解密类
*
* 可与java的3DES(DESede)加密方式兼容
*
* @Author: Luo Hui (farmer.luo at gmail.com)
*
* @version: V0.1 2008.12.04
*
*/

class Crypt3Des
{   
    public $key    = "01234567890123456789012345678912";
    public $iv    = "23456789"; //like java: private static byte[] myIV = { 50, 51, 52, 53, 54, 55, 56, 57 };
   
    //加密
    public function encrypt($input)
    {
        $input = $this->padding( $input );
        $key = base64_decode($this->key);
        $td = mcrypt_module_open( MCRYPT_3DES, ”, MCRYPT_MODE_CBC, ”);
        //使用MCRYPT_3DES算法,cbc模式
        mcrypt_generic_init($td, $key, $this->iv);
        //初始处理
        $data = mcrypt_generic($td, $input);
        //加密
        mcrypt_generic_deinit($td);
        //结束
        mcrypt_module_close($td);
        $data = $this->removeBR(base64_encode($data));
        return $data;
    }
   
    //解密
    public function decrypt($encrypted)
    {
        $encrypted = base64_decode($encrypted);
        $key = base64_decode($this->key);
        $td = mcrypt_module_open( MCRYPT_3DES,”,MCRYPT_MODE_CBC,”);
        //使用MCRYPT_3DES算法,cbc模式
        mcrypt_generic_init($td, $key, $this->iv);
        //初始处理
        $decrypted = mdecrypt_generic($td, $encrypted);
        //解密
        mcrypt_generic_deinit($td);
        //结束
        mcrypt_module_close($td);
        $decrypted = $this->removePadding($decrypted);
        return $decrypted;
    }
   
    //填充密码,填充至8的倍数
    public function padding( $str )
    {
        $len = 8 – strlen( $str ) % 8;
        for ( $i = 0; $i < $len; $i++ )
        {
            $str .= chr( 0 );
        }
        return $str ;
    }
   
    //删除填充符
    public function removePadding( $str )
    {
        $len = strlen( $str );
        $newstr = "";
        $str = str_split($str);
        for ($i = 0; $i < $len; $i++ )
        {
            if ($str[$i] != chr( 0 ))
            {
                $newstr .= $str[$i];
            }
        }
        return $newstr;
    }
   
    //删除回车和换行
    public function removeBR( $str )
    {
        $len = strlen( $str );
        $newstr = "";
        $str = str_split($str);
        for ($i = 0; $i < $len; $i++ )
        {
            if ($str[$i] != ‘n’ and $str[$i] != ‘r’)
            {
                $newstr .= $str[$i];
            }
        }
   
        return $newstr;
    }

}

//test
$input = "1qaz2ws";
echo "plainText:" . $input."<br/>";
$crypt = new Crypt3Des();
echo "Encode:".$crypt->encrypt($input)."<br/>";
echo "Decode:".$crypt->decrypt($crypt->encrypt($input));
?>

结果:

plainText:1qaz2ws
Encode:0GsXgYA8BuM=
Decode:1qaz2ws

PHP 实现多服务器共享 SESSION 数据

肖理达 (KrazyNio AT hotmail.com), 2005.09.13, 转载请注明出处

一、问题起源

稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套 用户名、密码在整个网站的各个模块中都是可以登录使用的。各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接 口对用户数据进行访问即可。但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这就是一次登录,全部通 行的问题,映射到技术上,其实就是各个服务器之间如何实现共享 SESSION 数据的问题。

二、PHP SESSION 的工作原理

在解决问题之前,先来了解一下 PHP SESSION 的工作原理。在客户端(如浏览器)登录网站时,被访问的 PHP 页面可以使用 session_start() 打开 SESSION,这样就会产生客户端的唯一标识 SESSION ID(此 ID 可通过函数 session_id() 获取/设置)。SESSION ID 可以通过两种方式保留在客户端,使得请求不同的页面时,PHP 程序可以获知客户端的 SESSION ID;一种是将 SESSION ID 自动加入到 GET 的 URL 中,或者 POST 的表单中,默认情况下,变量名为 PHPSESSID;另一种是通过 COOKIE,将 SESSION ID 保存在 COOKIE 中,默认情况下,这个 COOKIE 的名字为 PHPSESSID。这里我们主要以 COOKIE 方式进行说明,因为应用比较广泛。

那么 SESSION 的数据保存在哪里呢?当然是在服务器端,但不是保存在内存中,而是保存在文件或数据库中。默认情况下,php.ini 中设置的 SESSION 保存方式是 files(session.save_handler = files),即使用读写文件的方式保存 SESSION 数据,而 SESSION 文件保存的目录由 session.save_path 指定,文件名以 sess_ 为前缀,后跟 SESSION ID,如:sess_c72665af28a8b14c0fe11afe3b59b51b。文件中的数据即是序列化之后的 SESSION 数据了。如果访问量大,可能产生的 SESSION 文件会比较多,这时可以设置分级目录进行 SESSION 文件的保存,效率会提高很多,设置方法为:session.save_path="N;/save_path",N 为分级的级数,save_path 为开始目录。当写入 SESSION 数据的时候,PHP 会获取到客户端的 SESSION_ID,然后根据这个 SESSION ID 到指定的 SESSION 文件保存目录中找到相应的 SESSION 文件,不存在则创建之,最后将数据序列化之后写入文件。读取 SESSION 数据是也是类似的操作流程,对读出来的数据需要进行解序列化,生成相应的 SESSION 变量。

三、多服务器共享 SESSION 的主要障碍及解决办法

通过了解 SESSION 的工作原理,我们可以发现,在默认情况下,各个服务器会各自分别对同一个客户端产生 SESSION ID,如对于同一个用户浏览器,A 服务器产生的 SESSION ID 是 30de1e9de3192ba6ce2992d27a1b6a0a,而 B 服务器生成的则是 c72665af28a8b14c0fe11afe3b59b51b。另外,PHP 的 SESSION 数据都是分别保存在本服务器的文件系统中。如下图所示:

image

确定了问题所在之后,就可以着手进行解决了。想要共享 SESSION 数据,那就必须实现两个目标:一个是各个服务器对同一个客户端产生的 SESSION ID 必须相同,并且可通过同一个 COOKIE 进行传递,也就是说各个服务器必须可以读取同一个名为 PHPSESSID 的 COOKIE;另一个是 SESSION 数据的存储方式/位置必须保证各个服务器都能够访问到。简单地说就是多服务器共享客户端的 SESSION ID,同时还必须共享服务器端的 SESSION 数据。

第一个目标的实现其实很简单,只需要对 COOKIE 的域(domain)进行特殊地设置即可,默认情况下,COOKIE 的域是当前服务器的域名/IP 地址,而域不同的话,各个服务器所设置的 COOKIE 是不能相互访问的,如 www.aaa.com 的服务器是不能读写 www.bbb.com 服务器设置的 COOKIE 的。这里我们所说的同一网站的服务器有其特殊性,那就是他们同属于同一个一级域,如:aaa.infor96.com 和 www.infor96.com 都属于域 .infor96.com,那么我们就可以设置 COOKIE 的域为 .infor96.com,这样 aaa.infor96.com、www.infor96.com 等等都可以访问此 COOKIE。PHP 代码中的设置方法如下:


<?php
ini_set('session.cookie_domain', '.infor96.com');
?>

这样各个服务器共享同一客户端 SESSION ID 的目的就达到了。

第二个目标的实现可以使用文件共享方式,如 NFS 方式,但设置、操作上有些复杂。我们可以参考先前所说的统一用户系统的方式,即使用数据库来保存 SESSION 数据,这样各个服务器就可以方便地访问同一个数据源,获取相同的 SESSION 数据了。

解决办法如下图所示:

image

四、代码实现

首先创建数据表,MySQL 的 SQL 语句如下:

CREATE TABLE `sess` (
`sesskey` varchar(32) NOT NULL default ”,
`expiry` bigint(20) NOT NULL default ‘0’,
`data` longtext NOT NULL,
PRIMARY KEY (`sesskey`),
KEY `expiry` (`expiry`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

sesskey 为 SESSION ID,expiry 为 SESSION 过期时间,data 用于保存 SESSION 数据。

默认情况下 SESSION 数据是以文件方式保存,想要使用数据库方式保存,就必须重新定义 SESSION 各个操作的处理函数。PHP 提供了session_set_save_handle() 函数,可以用此函数自定义 SESSION 的处理过程,当然首先要先将 session.save_handler 改成 user,可在 PHP 中进行设置:


<?php
session_module_name('user');
?>

接下来着重讲一下 session_set_save_handle() 函数,此函数有六个参数:

session_set_save_handler ( string open, string close, string read, string write, string destroy, string gc )

各个参数为各项操作的函数名,这些操作依次是:打开、关闭、读取、写入、销毁、垃圾回收。PHP 手册中有详细的例子,在这里我们使用 OO 的方式来实现这些操作,详细代码如下:


<?php
define('MY_SESS_TIME', 3600);   //SESSION 生存时长
//类定义
class My_Sess
{
     function init()
     {
        $domain = '.infor96.com';
        //不使用 GET/POST 变量方式
        ini_set('session.use_trans_sid',    0);
        //设置垃圾回收最大生存时间
        ini_set('session.gc_maxlifetime',   MY_SESS_TIME);

        //使用 COOKIE 保存 SESSION ID 的方式
        ini_set('session.use_cookies',      1);
        ini_set('session.cookie_path',      '/');
        //多主机共享保存 SESSION ID 的 COOKIE
        ini_set('session.cookie_domain',    $domain);

        //将 session.save_handler 设置为 user,而不是默认的 files
        session_module_name('user');
        //定义 SESSION 各项操作所对应的方法名:
        session_set_save_handler(
             array('My_Sess', 'open'),   //对应于静态方法 My_Sess::open(),下同。
            array('My_Sess', 'close'),
             array('My_Sess', 'read'),
             array('My_Sess', 'write'),
             array('My_Sess', 'destroy'),
             array('My_Sess', 'gc')
         );
     }   //end function

    function open($save_path, $session_name) {
         return true;
     }   //end function

    function close() {
         global $MY_SESS_CONN;

         if ($MY_SESS_CONN) {    //关闭数据库连接
            $MY_SESS_CONN->Close();
         }
         return true;
     }   //end function

    function read($sesskey) {
         global $MY_SESS_CONN;

        $sql = 'SELECT data FROM sess WHERE sesskey=' . $MY_SESS_CONN->qstr($sesskey) . ' AND expiry>=' . time();
        $rs =& $MY_SESS_CONN->Execute($sql);
         if ($rs) {
             if ($rs->EOF) {
                 return ";
             } else {    //读取到对应于 SESSION ID 的 SESSION 数据
                $v = $rs->fields[0];
                $rs->Close();
                 return $v;
             }   //end if
        }   //end if
        return ";
     }   //end function

    function write($sesskey, $data) {
         global $MY_SESS_CONN;
        
        $qkey = $MY_SESS_CONN->qstr($sesskey);
        $expiry = time() + My_SESS_TIME;    //设置过期时间
        
         //写入 SESSION
        $arr = array(
            'sesskey' => $qkey,
            'expiry'  => $expiry,
            'data'    => $data);
        $MY_SESS_CONN->Replace('sess', $arr, 'sesskey', $autoQuote = true);
         return true;
     }   //end function

    function destroy($sesskey) {
         global $MY_SESS_CONN;

        $sql = 'DELETE FROM sess WHERE sesskey=' . $MY_SESS_CONN->qstr($sesskey);
        $rs =& $MY_SESS_CONN->Execute($sql);
         return true;
     }   //end function

    function gc($maxlifetime = null) {
         global $MY_SESS_CONN;

        $sql = 'DELETE FROM sess WHERE expiry<' . time();
        $MY_SESS_CONN->Execute($sql);
        //由于经常性的对表 sess 做删除操作,容易产生碎片,
         //所以在垃圾回收中对该表进行优化操作。
        $sql = 'OPTIMIZE TABLE sess';
        $MY_SESS_CONN->Execute($sql);
         return true;
     }   //end function
}   ///:~

//使用 ADOdb 作为数据库抽象层。
require_once('adodb/adodb.inc.php');
//数据库配置项,可放入配置文件中(如:config.inc.php)。
$db_type = 'mysql';
$db_host = '192.168.212.1';
$db_user = 'sess_user';
$db_pass = 'sess_pass';
$db_name = 'sess_db';
//创建数据库连接,这是一个全局变量。
$GLOBALS['MY_SESS_CONN'] =& ADONewConnection($db_type);
$GLOBALS['MY_SESS_CONN']->Connect( $db_host, $db_user, $db_pass, $db_name);
//初始化 SESSION 设置,必须在 session_start() 之前运行!!
My_Sess::init();
?>

五、遗留问题

如果网站的访问量很大的话,SESSION 的读写会频繁地对数据库进行操作,这样效率就会明显降低。考虑到 SESSION 数据一般不会很大,可以尝试用 C/Java 写个多线程的程序,用 HASH 表保存 SESSION 数据,并通过 socket 通信进行数据读写,这样 SESSION 就保存在内存中,读写速度应该会快很多。另外还可以通过负载均衡来分担服务器负载。不过这些都只是我自己的一些想法和假设,并没有实践过 :( 。。。。。。

延长session失效时间从24分钟到4小时

UTBlog写文章,最后提交的关头,有时候会出现“认证错误”信息,提示再次登陆,再不可能“退回”到刚才编辑的页面,结果是刚才的心血全部白费,痛哉!

究其原因,是因为php session有一个GC功能,就是Garbage Collector。这个GC启动的时候,会清除那些已经“超时”的session。它的工作原理是这样的(以utblog.com为例):

  1. 用户访问并登陆网站http://www.utblog.com,这时候后台会调用session_start来尝试生成一个会话(如果已经有会话,则相当于一次有效会话请求)
  2. 对于这样的每一次有效会话请求(Request),apache的php模块会根据session相关的全局变量gc_probability/gc_divisor =>计算出启动GC的概率,并由此概率来决定在这次请求中是否应该启动GC。举例来说,session.gc_probability的缺省值为1,session.gc_divisor的缺省值为100,则启动“垃圾回收”器的概率是1%,这就意味着在每100次请求中,会有可能清理一次过期会话
  3. 如果GC启动,则GC会扫描当前会话所 在路径(session.save_path)下的所有会话文件,并根据另外一个全局变量session.gc_maxlifetime的多少来判断哪些 session已经过期(“当前时间”与“会话文件的atime或者mtime”之间的差大于gc_maxlifetime:过期),并删除这些过期的 session
  4. 如果你在一个session启动后,长时间没有任何交互操作(譬如,不停地码字,没有提交或者保存为草稿),那么你 的保存在后台的会话文件将得不到机会被修改或者访问,在gc_maxlifetime(缺省值1440秒=24分钟)时间后,它有可能因失效而被清理,这 以后你再提交,就会因为会话失效而报错

由此可见,gc_maxlifetime设置为24分钟,对于写某些文章来说还不够。这 是一个原因,另外,session.save_path的缺省路径在linux上是/tmp,很少有程序会修改这个设置。如果这台服务器上有多个虚拟主 机,那么,/tmp目录下会存放许多不同session_name的会话文件。糟糕的是,php的GC不区分会话归属,它会根据它取得的 gc_maxlifetime来清理这个目录下的所有过期session文件。

据以上分析,解决方案是:UTBLOG在.htaccess文件内添加了一条语句,将session.gc_maxlifetime的local value扩大为14400(4小时),同时在后台将session.save_path设置为/tmp/utblog,这样,utblog的会话文件就不受其他网站干扰了,而4小时的失效时间,我想,无论如何应该够用了。

测试下来,一切如我所愿。

另, 如果直接改动/etc/php.ini当然也可以。如果没有权限改动php.ini,也没有权限改动apache的conf文件,.htaccess被禁 止,那么直接修改plog的sessionmanager.class.php文件,在session_start行前添加 ini_alter("session.gc_maxlifetime", 14400)亦可。plog结构良好,只有这一处调用session_start,所以也只有这一处需要修改。我在本地做过测试,可以工作。

高级权限管理系统的设计 转

          在任何系统中,权限设计是最基础的东西,一个好的权限系统,可以为开发人员提高开发进度;而且,又可以为用户提供完美的可扩展权限管理,而非简单的权限定制。
本文实现功能:实现基于角色+模块+权限粒度的权限管理
相关概念:
(1)角色:是一类功能的集合,比如新闻编辑这个角色,他可能有起草新闻、编辑新闻等功能集合,而责任编辑他可能就有更多的权限,比如除了新闻编辑的功能,还有审核新闻、删除新闻等粒度级别操作;这个可以理解为程序设计中的组.
(2)权限粒度:它是最小的单位,比如起草新闻、编辑新闻、审核新闻、删除新闻等
(3)用户:就是一个系统的最终使用用户(包括管理人员和被管理人员)
(4)资源:管理的对象

下面模拟对一个信息系统的控制数据:

(图一. 权限示意图)

用户信息表:

UserID

UserName

U1

张三

U2

李四

角色表:

RoleID

RoleName

R1

新闻编辑

R2

责任编辑

角色用户表:

RoleID

UserID

R1

U1

R2

U2

权限粒度表:

PrivilegeID

ResourceType

PrivilegeTitle

P1

NTA

起草新闻:分类A

P2

NTA

编辑新闻:分类A

P3

NTA

审核新闻:分类A

P4

NTA

删除新闻:分类A

P1

NTB

起草新闻:分类B

P2

NTB

编辑新闻:分类B

P3

NTB

审核新闻:分类B

P4

NTB

删除新闻:分类B

注意:这个表里面添加有资源(模块)信息

角色权限表:

RoleID

PrivilegeID

R1

P1

R1

P2

R2

P1

R2

P2

R2

P3

R2

P4

判断一个用户具有某个模块权限实现:
#获取权限(Privileges)的语句:
Select PrivilegeID + `,` + ResourceType From 角色权限表 Where RoleID In (Select RoleID From 用户角色表 Where UserID=’U1′)

#权限的判断
Privileges.Contain(‘F1,NTA’);

在新添加一个分类的时候,同时也在权限表中增加相应的记录(当然不是在数据库里面直接添加,由和权限相关的函数来添加)。
使用这种解决方案可以简单地对有分类的应用(比如论坛系统)的每个分类实行不同的控制(比如VIP板块,就只能拥有VIP角色的用户才能浏览、发表等,而其他板块只要是注册用户就可以使用了)。

在实际应用中PrivilegeID并不是随便的一个字符串,而是进行了编码,其编码中包含了模块 ID以及能够体现出父子关系,举个例子来说:对于论坛系统,我们给它一个模块ID为”30”,论坛的权限我们先分成2类,一类是管理类(比如删除帖子), 一类是使用类(比如发帖、回帖、浏览帖子等),给管理类一个编码:01,使用类一个编码:02,我们就对PrivilegeID进行如下的编码:
300101:删除帖子
300201:发帖
300202:回帖
300203:浏览帖子

对于资源(比如某个板块1,板块的ID为:01),我们可以组合出如下的Privileges(当然这个组合你也可以不用逗号分隔,用其他的组合方式也可以,不过不要产生歧义):
300101,01:板块1删除帖子的功能
300201,01:板块1发帖的功能
……
    对于RoleID也是采用的编码方式,也能体现角色的父子关系,也可以实现角色功能的继承等(当然获取角色功能列表的SQL语句就不是现在这么简单了)。在我现在的应用里面没有实现角色的继承(虽然角色的编码体现出了角色的父子关系)。

一个非常实用的javascript读写Cookie函数


function GetCookieVal(offset)
//获得Cookie解码后的值
{
var endstr = document.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = document.cookie.length;
return unescape(document.cookie.substring(offset, endstr));
}
function SetCookie(name, value)
//设定Cookie值
{
var expdate = new Date();
var argv = SetCookie.arguments;
var argc = SetCookie.arguments.length;
var expires = (argc > 2) ? argv[2] : null;
var path = (argc > 3) ? argv[3] : null;
var domain = (argc > 4) ? argv[4] : null;
var secure = (argc > 5) ? argv[5] : false;
if(expires!=null) expdate.setTime(expdate.getTime() + ( expires * 1000 ));
document.cookie = name + "=" + escape (value) +((expires == null) ? "" : ("; expires="+ expdate.toGMTString()))
+((path == null) ? "" : ("; path=" + path)) +((domain == null) ? "" : ("; domain=" + domain))
+((secure == true) ? "; secure" : "");
}
function DelCookie(name)
//删除Cookie
{
var exp = new Date();
exp.setTime (exp.getTime() – 1);
var cval = GetCookie (name);
document.cookie = name + "=" + cval + "; expires="+ exp.toGMTString();
}
function GetCookie(name)
//获得Cookie的原始值
{
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen)
{
var j = i + alen;
if (document.cookie.substring(i, j) == arg)
return GetCookieVal (j);
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
}

JS的IE和Firefox兼容性汇编

以下以 IE 代替 Internet Explorer,以 MF 代替 Mozzila Firefox
1. document.form.item 问题
(1)现有问题:
现有代码中存在许多 document.formName.item("itemName") 这样的语句,不能在 MF 下运行
(2)解决方法:
改用 document.formName.elements["elementName"]
(3)其它
参见 2

2. 集合类对象问题
(1)现有问题:
现有代码中许多集合类对象取用时使用 (),IE 能接受,MF 不能。
(2)解决方法:
改用 [] 作为下标运算。如:document.forms("formName") 改为 document.forms["formName"]。
又如:document.getElementsByName("inputName")(1) 改为 document.getElementsByName("inputName")[1]
(3)其它

3. window.event
(1)现有问题:
使用 window.event 无法在 MF 上运行
(2)解决方法:
MF 的 event 只能在事件发生的现场使用,此问题暂无法解决。可以这样变通:
原代码(可在IE中运行):
<input type="button" name="someButton" value="提交" onclick="javascript:gotoSubmit()"/>

<script language="javascript">
function gotoSubmit() {

alert(window.event);    // use window.event

}
</script>
新代码(可在IE和MF中运行):
<input type="button" name="someButton" value="提交" onclick="javascript:gotoSubmit(event)"/>

<script language="javascript">
function gotoSubmit(evt) {
evt = evt ? evt : (window.event ? window.event : null);

alert(evt);             // use evt

}
</script>
此外,如果新代码中第一行不改,与老代码一样的话(即 gotoSubmit 调用没有给参数),则仍然只能在IE中运行,但不会出错。所以,这种方案 tpl 部分仍与老代码兼容。

4. HTML 对象的 id 作为对象名的问题
(1)现有问题
在 IE 中,HTML 对象的 ID 可以作为 document 的下属对象变量名直接使用。在 MF 中不能。
(2)解决方法
用 getElementById("idName") 代替 idName 作为对象变量使用。

5. 用idName字符串取得对象的问题
(1)现有问题
在IE中,利用 eval(idName) 可以取得 id 为 idName 的 HTML 对象,在MF 中不能。
(2)解决方法
用 getElementById(idName) 代替 eval(idName)。

6. 变量名与某 HTML 对象 id 相同的问题
(1)现有问题
在 MF 中,因为对象 id 不作为 HTML 对象的名称,所以可以使用与 HTML 对象 id 相同的变量名,IE 中不能。
(2)解决方法
在声明变量时,一律加上 var ,以避免歧义,这样在 IE 中亦可正常运行。
此外,最好不要取与 HTML 对象 id 相同的变量名,以减少错误。
(3)其它
参见 问题4

7. event.x 与 event.y 问题
(1)现有问题
在IE 中,event 对象有 x, y 属性,MF中没有。
(2)解决方法
在MF中,与event.x 等效的是 event.pageX。但event.pageX IE中没有。
故采用 event.clientX 代替 event.x。在IE 中也有这个变量。
event.clientX 与 event.pageX 有微妙的差别(当整个页面有滚动条的时候),不过大多数时候是等效的。

如果要完全一样,可以稍麻烦些:
mX = event.x ? event.x : event.pageX;
然后用 mX 代替 event.x
(3)其它
event.layerX 在 IE 与 MF 中都有,具体意义有无差别尚未试验。

8. 关于frame
(1)现有问题
在 IE中 可以用window.testFrame取得该frame,mf中不行
(2)解决方法
在frame的使用方面mf和ie的最主要的区别是:
如果在frame标签中书写了以下属性:
<frame src="xx.htm" id="frameId" name="frameName" />
那么ie可以通过id或者name访问这个frame对应的window对象
而mf只可以通过name来访问这个frame对应的window对象
例如如果上述frame标签写在最上层的window里面的htm里面,那么可以这样访问
ie: window.top.frameId或者window.top.frameName来访问这个window对象
mf: 只能这样window.top.frameName来访问这个window对象

另外,在mf和ie中都可以使用window.top.document.getElementById("frameId")来访问frame标签
并且可以通过window.top.document.getElementById("testFrame").src = ‘xx.htm’来切换frame的内容
也都可以通过window.top.frameName.location = ‘xx.htm’来切换frame的内容
关于frame和window的描述可以参见bbs的‘window与frame’文章
以及/test/js/test_frame/目录下面的测试
—-adun 2004.12.09修改

9. 在mf中,自己定义的属性必须getAttribute()取得
10.在mf中没有 parentElement parement.children 而用
parentNode parentNode.childNodes
childNodes的下标的含义在IE和MF中不同,MF使用DOM规范,childNodes中会插入空白文本节点。
一般可以通过node.getElementsByTagName()来回避这个问题。
当html中节点缺失时,IE和MF对parentNode的解释不同,例如
<form>
<table>
<input/>
</table>
</form>
MF中input.parentNode的值为form, 而IE中input.parentNode的值为空节点

MF中节点没有removeNode方法,必须使用如下方法 node.parentNode.removeChild(node)

11.const 问题
(1)现有问题:
在 IE 中不能使用 const 关键字。如 const constVar = 32; 在IE中这是语法错误。
(2)解决方法:
不使用 const ,以 var 代替。

12. body 对象
MF的body在body标签没有被浏览器完全读入之前就存在,而IE则必须在body完全被读入之后才存在

13. url encoding
在js中如果书写url就直接写&不要写&amp;例如var url = ‘xx.jsp?objectName=xx&amp;objectEvent=xxx’;
frm.action = url那么很有可能url不会被正常显示以至于参数没有正确的传到服务器
一般会服务器报错参数没有找到
当然如果是在tpl中例外,因为tpl中符合xml规范,要求&书写为&amp;
一般MF无法识别js中的&amp;

14. nodeName 和 tagName 问题
(1)现有问题:
在MF中,所有节点均有 nodeName 值,但 textNode 没有 tagName 值。在 IE 中,nodeName 的使用好象
有问题(具体情况没有测试,但我的IE已经死了好几次)。
(2)解决方法:
使用 tagName,但应检测其是否为空。

15. 元素属性
IE下 input.type属性为只读,但是MF下可以修改

16. document.getElementsByName() 和 document.all[name] 的问题
(1)现有问题:
在 IE 中,getElementsByName()、document.all[name] 均不能用来取得 div 元素(是否还有其它不能取的元素还不知道)。

xajax从0.2升级到0.5的改变

xajax目前已经升级到0.5版本,旧版本的XAJAX与新版本的方法有些不同,新版本增加了延迟事件(delay events)和插件,具体请看内容

  • 1 附加
    • 1.1 延迟事件(delay events)
    • 1.2 插件
  • 2 Changes
    • 2.1 请求类型(request type)
    • 2.2 响应命令(Response Commands)
    • 2.3 目录结构(Folder Structure)
    • 2.4 方法重命名(Method Renaming)
  • 3 快速参考

附加

延迟事件(delay events)

你现在可以指定自己的延迟事件,或调用独立的’读取中…’函数(附全局延迟事件/函数);使用

00000">
xajax.call(‘functioname’,{onRequestDelay:delayFunctionName});

插件

xajax现在已经拥有一套插件系统,因此你可以扩展它使其与其它框架如script.aculo.us协同工作。下面是一段插件调用的示例:

00000">
xajaxResponse->plugin(‘scriptaculous’)->fade(‘myDiv’);

Changes

请求类型(request type)

请求类型的设置选项已经被去掉,因为大多数情况下使用的是POST方法。另外,POST方法允许在请求过程中发送更多的数据。GET请求方法被用作POST请求失败后的备选方案。

响应命令(Response Commands)

xajaxResponse已经被重构,可以用以支持将来可能出现的其它数据传输方法。目前响应命令是以数组方式存储的;数组在响应发送前会被转换为XML。以前的XML是通过字符串连接方式构建为命令添加在响应之后。

目录结构(Folder Structure)

xajax目录结构已经更改,使PHP文件和Javascript文件相互独立。所有PHP文件放在xajax_core目录下,所有Javascript文件放在xajax_js目录下。

方法重命名(Method Renaming)

请注意:你可以通过new legacyXajax()实例化方法取代new xajax()实例化方法、new legacyXajaxResponse()实例化方法取代new xajaxResponse()实例化方法保留所有以前的方法。

xajax方法

xajax->processRequests()变为xajax->processRequest()

所有布尔值设置方法如xajax->debugOn();and xajax->outputEntitiesOn();变为xajax->setFlag(‘debug’,true)以及xajax- >setFlag(‘outputEntities’,true); xajax->setFlags()还可以设置数组值如xajax->setFlags(array(‘debug’=>true, ‘outputEntities’=>true));

xajax->registerExternalFunction()方法已经与xajax-> registerFunction()整合到一起,因此xajax->registerFunction()函数现在有一个可选的第二参数,如 xajax->registerFunction(‘functionName’, ‘file.php’)

xajaxResponse方法

许多xajaxResponse方法都发生了改变。以前容易混淆的’add’前缀从很多函数中移出;于是乎,xajaxResponse- >addScript()变成了 xajaxResponse->script(),xajaxResponse->addAssign()变为xajaxResponse- >assign()。将响应与PHP5合到一起就比较有意思了:
$response
->alert("Hi!")
->assign("myDiv", "innerHTML", $stuff)
->plugin(‘script.aculo.us’)->highlight("myDiv")
->scriptCall(‘finishEditing’, $newID);

xajaxResponse->getXML()不用了;只需返回xajaxResponse对象即可。

旧代码 新代码 require_once(‘xajax.inc.php’); require(‘xajax_core/xajax.inc.php’); xajax->debugOn(); xajax->setFlag(‘debug’,true); xajax->debugOff(); xajax->setFlag(‘debug’,false); xajax->statusMessagesOn(); xajax->setFlag(‘statusMessages’,true); xajax->statusMessagesOff(); xajax->setFlag(‘statusMessages’,false); xajax->decodeUTF8InputOn(); setFlag(‘decodeUTF8Input’,true) xajax->registerExternalFunction(‘function’,’file.php’); xajax->registerFunction(‘function’,’file.php’); xajax->processRequests(); xajax->processRequest(); xajaxResponse->loadXML($response); xajaxResponse->loadCommands($response); return xajaxResponse->getXML(); return xajaxResponse xajaxResponse->addAssign(); xajax->assign() xajaxResponse->addAlert(); xajax->alert() xajaxResponse->addClear(); xajax->clear() xajaxResponse->addCreateInput(); xajax->createInput() xajaxResponse->addCreate(); xajax->create() xajaxResponse->addRemove(); xajax->remove() xajaxResponse->addScript(); xajax->script() xajaxResponse->addScriptCall(); xajax->call() xajax.createInput() xajax.forms.createInput() xajax.create() xajax.dom.create() xajax.remove() xajax.dom.remove() xajax.loadingFunction = function(){}; xajax.callback.global.onRequest= function(){}; xajax.doneLoadingFunction = function(){}; xajax.callback.global.onComplete= function(){}; new function xajax.callback.global.onFailure = function(args)

{
alert("In global.onFailure…HTTP status code: " + args.request.status);
}

更新的xajax升级资料你可以参考这里

http://wiki.xajaxproject.org/Zh:Upgrading_from_xajax_0.2_to_xajax_0.5

xajax 0.5版本方法集[转]

现在最新的XAJAX版本已经0.5 Beta4了。可是网上能找到的资料都只是0.25版的。没办法只好自己看源代码了。xajax的核心其实是xajaxResponse类,这里整理了一下它的常用方法:

xajaxResponse类的常用方法合集

1. xajaxResponse->confirmCommands($iCmdNumber, $sMessage)
弹出询问对话框,询问内容为$sMessage,第一个参数$iCmdNumber为数字。如果用户选择了“是”,则此语句后的一句或多句语句都会执行;如果用户选择了“否”,那么,则跳过前$iCmdNumber句再执行,即只有自第$iCmdNumber句起之后的语句(不包括第$ iCmdNumber句)会执行。
例:$xResponse->confirmCommands(4,’请确认是否真的删除记录’);

2. xajaxResponse->assign($sTarget,$sAttribute,$sData)
给元素ID为$sTarget的属性赋值,把它的属性$sAttribute值赋为$sData.
例:$xResponse->assign(‘mydiv’,’innerHTML’,’Hello world! This is a example of xajax!’);
      $xResponse->assign(‘mydiv’,’style.color’,’blue’);
      $xResponse->assign(‘forminput’,’value’,’Bill’);

3. xajaxResponse->append($sTarget,$sAttribute,$sData)
给ID为$sTarget的元素属性以追加方式赋值。在它的属性$sAttribute的原有值的基础上追加赋值$sData。
例:$xResponse->append(‘mydiv’,’innerHTML’,’This is append comment’);

4. xajaxResponse->prepend($sTarget,$sAttribute,$sData)
同上,是预赋值。具体什么是预赋值,还没弄明白。

5. xajaxResponse->replace($sTarget,$sAttribute,$sSearch,$sData)
替换ID为$sTarget的元素的属性值。把属性$sAttribute的值中所有包含$sSearch的值替换为$sData。
例:$xResponse->replace(‘mydiv’,’innerHTML’,’xajax’,'<strong>xajax</strong>’);
[突然明白了GOOGLE,BAIDU等搜索引擎的搜索页面中的关键字高亮是怎么实现的了。]

6. xajaxResponse->clear($sTarget,$sAttribute)
清除ID为$sTarget的元素属性值。清除它的$sAttribute的属性的值。
例:$xResponse->clear(‘mydiv’,’innerHTML’);

7. xajaxResponse->alert($sMsg)
弹出对话框,内容为$sMsg。即JS中的window.alert()方法。
例:$xResponse->alert(‘How are you?’);

8. xajaxResponse->redirect($sURL, $iDelay=0)
重定向。让浏览器$iDelay秒后转向$sURL。$iDelay省略时默认为0。即JS中的window.location()方法。
例:$xResponse->redirect(‘http://www.sohu.com’ ,15);

9. xajaxResponse->script($sJS)
执行一段JS脚本。参数$sJS为JS代码。
例:$xResponse->script("alert("hello world")");

10. xajaxResponse->create($sParent, $sTag, $sId, $sType=null)
在当前已存在的元素$sParent下创建一个$sTag元素,并把它的ID设为$sId。
例:$xResponse->create(‘mydiv’,’span’,’myspan’);

11. xajaxResponse->remove($sTarget)
移除一个ID为$sTarget的元素
例:$xResponse->remove(‘mydiv’);

12. xajaxResponse->insert($sBefore, $sTag, $sId)
在当前元素$sBefore之前插入一个元素$sTag,并把$sTag元素的ID设置为$sId。
例:$xResponse->insert(‘myspan’,’p’,’myp’);

13. xajaxResponse->insertAfter($sAfter, $sTag, $sId)
同上,只不过不是在之前插入元素,是是在元素$sAfter之后插入。

14. xajaxResponse->createInput($sParent, $sType, $sName, $sId)
以$sParent为父元素,创建一个INPUT元素,并把它的类型设置为$sType[即:type="$sType"],把元素的NAME设置为$sName[即:name="$sName"],把元素ID设置为$sId[即:id="$sId"]。
例:$xResponse->createInput(‘mydiv’,’text’,’username’,’input1′);

15. xajaxResponse->insertInput($sBefore, $sType, $sName, $sId)
在元素$sBefore之前插入一个INPUT元素,并设置:type="$sType" name="$sName" id="$sId"。
例:$xResponse->insertInput(‘input1′,’password’,’userpass’,’input2′);

16. xajaxResponse->insertInputAfter($sAfter, $sType, $sName, $sId)
在元素$sAfter之后插入一个INPUT元素,并设置:type="$sType" name="$sName" id="$sId"。
例:$xResponse->insertInputAfter(‘input2′,’text’,’checkcode’,’input3′);

以上只是一些常用的方法,还有很多高级的方法,一时未能明了。希望高手补充啊。

本文转载自 http://www.phpchina.com/bbs/viewthread.php

javascript(JS)完全控制Select下拉框

[html]
<select id="mysel" name="mysel">
   <option value="1">1 xxxxxxxxxx</option>
   <option value="2">2 yyyyyyyyyy</option>
   <option value="3">3 zzzzzzzzzz</option>
   <option value="4">4 wwwwwwwwww</option>
</select>
<button onclick="setSel(3)">设置第3项为选中项</button>
<button onclick="clearSel()">清空选择框</button>
<button onclick="fillSel()">填充选择框</button>
<button onclick="removeSel()">移除第一项</button>
<button onclick="editSel()">修改第一项</button>

<script type="text/javascript">
     function setSel(str){
         with(document.all){    
             for(var i=0;i<mysel.options.length;i++){                
                 if (mysel.options[i].value==str){
                     mysel.selectedIndex=i;
                     break;
                 }
             }            
         }
     }

     function clearSel(){
         with(document.all){    
             mysel.options.length=0;
         }
     }

     function fillSel(){
         with(document.all){
             mysel.options.length=0;
             mysel.options[0] = new Option("1 xxxxxxxxxx","1");
             mysel.options[1] = new Option("2 yyyyyyyyyy","2");
             mysel.options[2] = new Option("3 zzzzzzzzzz","3");
             mysel.options[3] = new Option("4 wwwwwwwwww","4");
             mysel.options[4] = new Option("5 aaaaaaaaaa","5");

             mysel.selectedIndex = 4;
         }
     }

     function removeSel(){
         with(document.all){
             mysel.remove(0);
             if (mysel.options.length>0){
                 mysel.selectedIndex=0;
             }
         }
     }

     function editSel(){
         with(document.all){
             if (mysel.options.length>0){
                 mysel.options[0] = new Option("这是新的第一项","new Value")
                 mysel.selectedIndex=0;
             }
         }
     }
</script>

[/html]

PHP Extensions and Mappings

PHP Extensions and MappingsPHP Language Extensions and Type MappingsPHP Extensions

The bridge implementations add the following primitives to PHP. The type mappings are shown in table 1 below.

  • new Java("CLASSNAME"): References and instantiates the class CLASSNAME. After script execution the referenced classes may be garbage collected. Example:

    <?php
    $v = new Java("java.util.Vector");
    $v->add($buf=new Java("java.lang.StringBuffer"));
    $buf->append("100");
    echo (int)($v->elementAt(0)->toString()) + 2;
    ?>

  • new JavaClass("CLASSNAME"): References the class CLASSNAME without creating an instance. The returned object is the class object itself, not an object of the class. After script execution the referenced classes may be garbage collected. Example:

    $Object = new JavaClass("java.lang.Object");
    $obj = $Object->newInstance();

    $Thread = new JavaClass("java.lang.Thread");
    $Thread->sleep(10);

  • java_require("JAR1;JAR2"): Makes additional libraries available to the current script. JAR can either be a "http:", "ftp:", "file:" or a "jar:" or a default location. On "Security Enhanced Linux" (please see the README section on "Security Enhanced Linux"<– incorporate this info into other pages in site) the location must be tagged with a lib_t security context. Example:

    // load scheme interpreter
    // try to load it from /usr/share/java/ or from sourceforge.net
    try { java_require("kawa.jar"); } catch (JavaException $e) {/*ignore*/}
    java_require("http://php-java-bridge.sourceforge.net/kawa.jar");
    $n=100;
    $System = new JavaClass("java.lang.System");
    $t1 = $System->currentTimeMillis();
    $code="(letrec ((f (lambda(v) (if (= v 0) 1 (* (f (- v 1)) v))))) (f $n))";
    $scheme = new java("kawa.standard.Scheme");
    $res = (float)java_values($scheme->eval($code));
    echo "${n}! => $resn";
    $delta = $System->currentTimeMillis() - $t1;
    echo "Evaluated in $delta ms.n";

  • java_context(): Makes the javax.script.ScriptContext available to the current script. All implicit web objects (session, servlet context, etc.) are available from the context, if the back end is running in a servlet engine or application server. The following example uses the jdk1.6 jrunscript to eval PHP statements interactively:

    /opt/jdk1.6/bin/jrunscript -l php-intractive
    php-interactive> echo (string)(java_context()->getAttribute("javax.script.filename"));
    => <STDIN>

  • java_values(JAVA_OBJECT): Fetches the values for JAVA_OBJECT, if possible. Examples:

    $str = new java("java.lang.String", "hello"); echo $str;
    => [o(String):"hello"]

    // fetch the php string from the java string
    echo (java_values($str));
    => hello

    // fetch the values of the java char array
    print_r (java_values($str->toCharArray()));
    => array('h', 'e', 'l', 'l', 'o')

    // no php type exists for java.lang.Object
    print (java_values(new java("java.lang.Object")));
    => [o(Object):"java.lang.Object@4a85fc"]

  • java_cast(JAVA_VALUE, php_type): Converts a primitive JAVA_VALUE to a php value of type php_type. Unlike java_values, which return the "natural" php value for the JAVA_VALUE, the cast can convert the JAVA_VALUE into the desired php_type before it is returned. Allowed conversions are "string", "boolean", "integer" or "long", "double" or "float", "null", "array" and "object". The "object" conversion is the identiy function. Since PHP5 (php_type)JAVA_VALUE is identical to java_cast(JAVA_VALUE, php_type) (Zend Engine 2 and above only). Examples:

    $str = new java("java.lang.String", "12"); echo $str;
    => [o(String):"12"]

    // fetch the php string from the java string
    echo java_cast($str, "string");
    => "12"

    echo java_cast($str, "integer" );
    => 12

    var_dump (java_cast($str, "boolean"));
    => true

  • java_begin_document() and java_end_document(): Enables/disables XML stream mode. In XML stream mode the PHP/Java Bridge XML statements are sent in one XML stream. Compared with SOAP, which usually creates the entire XML document before sending it, this mode uses much less resources on the web-server side. Raised server-side exceptions are reported when java_end_document() is invoked. Example:

    // send the following XML statements in one stream
    java_begin_document();
    for ($x = 0; $x < $dx; $x++) {
       $row = $sheet->createRow($x);
       for ($y = 0; $y < $dy; $y++) {
         $cell = $row->createCell($y);
         $cell->setCellValue("$x . $y");
         $cell->setCellStyle($style);
       }
    }
    java_end_document(); // back to synchronous mode

  • java_closure(ENVIRONMENT, MAP, TYPE): Makes it possible to call PHP code from Java. It closes over the PHP environment, packages it up as a java class and returns an instance of the class. If the ENVIRONMENT is missing, the current environment is used. If MAP is missing, the PHP procedures must have the same name as the required procedures. If TYPE is missing, the generated class is "generic", i.e. the interface it implements is determined when the closure is applied. Example:

    <?php
    function toString() { return "hello" ; }
    echo (string)java_closure();
    ?>
    => hello

  • $session=java_session(): Creates or retrieves a session context. When the back end is running in a J2EE environment, the session is taken from the request object, otherwise it is taken from PHP. Please see the ISession interface documentation for details. The java_session() must be called before the response headers have been sent and it should be called as the first statement within a PHP script.

    $session = java_session();

  • $session=java_session(SESSIONNAME): Creates or retrieves the session SESSIONNAME. This primitive uses a session store with the name SESSIONNAME which is independent of the current PHP- or Java session. Please see the ISession interface documentation for details. For Java values $_SESSION['var']=val is syntactic sugar for java_session("internal-prefix@".session_id())->put('var', val).

    $session=java_session("testSession");
    if($session->isNew()) {
       echo "new sessionn";
       $session->put("a", 1);
       $session->put("b", 5);
    } else {
       echo "cont sessionn";
    }
    $session->put("a", $session->get("a")+1);
    $session->put("b", $session->get("b")-1);

    $val=$session->get("a");
    echo "session var: $valn";

    if($session->get("b")==0) $session->destroy();

    The java_session primitive is meant for values which must survive the current script. If you want to cache data which is expensive to create, bind the data to a class. Example:

    // Compile this class, create cache.jar and copy it to /usr/share/java
    public class Cache {
       private static final Cache instance = makeInstance();
       public static Cache getInstance() { return instance; }
    }

    <?php
    java_require("cache.jar");
    $Cache = new JavaClass("Cache");
    $instance=$Cache->getInstance(); //instance will stay in the VM until the VM runs short of memory
    ?>

  • JavaException: A java exception class. Available in PHP 5 and above only. Example:

    try {
       new java("java.lang.String", null);
    } catch(JavaException $ex) {
       $exStr = java_cast($ex, "string");
       echo "Exception occured; mixed trace: $exStrn";
       $trace = new java("java.io.ByteArrayOutputStream");
       $ex->printStackTrace(new java("java.io.PrintStream", $trace));
       print "java stack trace: $tracen";
    }

    The original exception can be retrieved with $ex->getCause(), for example:

    function rethrow($ex) {
       static $NullPointerException=new JavaClass("java.lang.NullPointerException");
       $ex=$ex->getCause();
       if(java_instanceof($ex, $NullPointerException)) {
         throw new NullPointerException($ex);
       }
       ...
       die("unexpected exception: $ex");
    } try {
       new java("java.lang.String", null);
    } catch(JavaException $ex) {
       rethrow($ex);
    }

  • foreach(COLLECTION): It is possible to iterate over values of java classes that implement java.util.Collection or java.util.Map. Available in PHP 5 and above only. Example:

    $conversion = new java("java.util.Properties");
    $conversion->put("long", "java.lang.Byte java.lang.Short java.lang.Integer");
    $conversion->put("boolean", "java.lang.Boolean");
    foreach ($conversion as $key=>$value)
       echo "$key => $valuen";

  • [index]: It is possible to access elements of java arrays or elements of java classes that implement the java.util.Map interface. Available in PHP 5 and above only. Example:

    $Array = new JavaClass("java.lang.reflect.Array");
    $String = new JavaClass("java.lang.String");
    $entries = $Array->newInstance($String, 3);
    $entries[0] ="Jakob der Lügner, Jurek Becker 1937--1997";
    $entries[1] ="Mutmassungen über Jakob, Uwe Johnson, 1934--1984";
    $entries[2] ="Die Blechtrommel, Günter Grass, 1927--";
    for ($i = 0; $i < $Array->getLength($entries); $i++) {
       echo "$i: " . $entries[$i] ."n";
    }

  • java_instanceof(JAVA_OBJ, JAVA_CLASS): Tests if JAVA_OBJ is an instance of JAVA_CLASS. Example:

    $Collection=new JavaClass("java.util.Collection");
    $list = new java("java.util.ArrayList");
    $list->add(0);
    $list->add(null);
    $list->add(new java("java.lang.Object"));
    $list->add(new java("java.util.ArrayList"));
    foreach ($list as $value) {
       if($value instanceof java && java_instanceof($value, $Collection))
         /* iterate through nested ArrayList */
       else
         echo "$valuen";
    }

  • java_last_exception_get(): Returns the last exception instance or null. Since PHP 5 you can use try/catch instead.
  • java_last_exception_clear(): Clears the error condition. Since PHP 5 you can use try/catch instead.

Table 1. Type Mappings PHP Java Description Example object java.lang.Object An opaque object handle. However, we guarantee that the first handle always starts with 1 and that the next handle is n+1 (useful if you work with the raw XML protocol, see the python and scheme examples). $buf=new java("java.io.ByteArrayOutputStream");
$outbuf=new java("java.io.PrintStream", $buf); null null NULL value $outbuf->println(null); exact number integer (default) or long. 64 bit data on protocol level, coerced to 32bit int/Integer or 64bit long/Long $outbuf->println(100); boolean boolean boolean value $outbuf->println(true); inexact number double IEEE floating point $outbuf->println(3.14); string byte[] binary data, unconverted $bytes=$buf->toByteArray(); string java.lang.String An UTF-8 encoded string. Since PHP does not support Unicode, all java.lang.String values are auto-converted into a byte[] (see above) using UTF-8 encoding. The encoding can be changed with the java_set_file_encoding() primitive. $string=$buf->toString(); array (as array) java.util.Collection or T[] PHP4 sends and receives arrays as values. PHP5 sends arrays as values and receives object handles which implement the new iterator and array interface. // pass a Collection to Vector
$ar=array(1, 2, 3);
$v=new java("java.util.Vector", $ar);
echo $v->capacity();

// pass T[] to asList()
$A=new JavaClass("java.util.Arrays");
$lst=$A->asList($ar);
echo $lst->size(); array (as hash) java.util.Map PHP4 sends and receives hash-tables as values. PHP5 sends hash-tables as values and receives object handles which implement the new iterator interface. $h=array("k"=>"v", "k2"=>"v2");
$m=new java("java.util.HashMap",$h);
echo $m->size(); JavaException java.lang.Exception A wrapped exception class. The original exception can be retrieved with $exception->getCause(); …
catch(JavaException $ex) {
    echo $ex->getCause();
}

There is one example provided: test.php. You can either invoke the test.php by typing ./test.php or copy the example into the document root of your web-server and evaluate the file using the browser.

Custom java libraries (.jar files) can be stored in the following locations:

  1. Somewhere on a HTTP or FTP server, see PHP function java_require. On Security Enhanced Linux .jar files can only be loaded from locations which are tagged with the lib_t security context.
  2. In the sub-directory "lib" of the PHP extension directory, if it exists and is accessible when the JVM starts the bridge. This is usually "`php-config –extension-dir`/lib". On Security Enhanced Linux this directory is tagged with the lib_t security context.
  3. In the /usr/share/java/ directory, if it exists and is accessible when the JVM starts the bridge. On Security Enhanced Linux this directory is tagged with the lib_t security context.