加入收藏 | 设为首页 | 会员中心 | 我要投稿 威海站长网 (https://www.0631zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux feof函数 PHP Wrapper是什么,SAE为什么需要PHP Wrapper

发布时间:2022-12-03 08:03:15 所属栏目:Linux 来源:未知
导读:
这篇关于PHP Wrapper在SAE上的应用方法的文章,觉得挺不错的,感兴趣的php开发者可以参考下,希望对大家在学习php的成长路上有所帮助!
一、PHP Wrapper是什么
自PHP 4.3开始,PHP开始允许

PHP Wrapper是什么,SAE为什么需要PHP Wrapper

这篇关于PHP Wrapper在SAE上的应用方法的文章,觉得挺不错的,感兴趣的php开发者可以参考下,希望对大家在学习php的成长路上有所帮助!

一、PHP Wrapper是什么

自PHP 4.3开始,PHP开始允许用户通过stream_wrapper_register()自定义URL风格的协议。用户使用fopen(), copy()等文件系统函数对封装协议进行操作时,PHP会调用注册协议时所提供的类中相应的函数。

PHP手册中给了一个例子,它将VariableStream类注册为var://协议,通过这个协议,用户可以使用文件系统函数直接读写全局变量。例如,用户可以通过 “var://foo” 读写 $GLOBALS['foo'] 。

二、SAE为什么需要PHP Wrapper

出于性能和安全方面的考虑,SAE平台上禁用了本地文件读写和对外的数据抓取。相应的,我们提供了对应的服务来做同样的事情。

由于新服务的接口和PHP本身的接口不太一样,专门为我们平台开发的程序当然不会存在问题,但是大量已有的程序和开源项目,就面临着繁杂的迁移工作。而使用PHP Wrapper对我们的服务的接口进行封装之后,用户就可以更方便地将程序迁移到SAE平台。

三、如何写PHP Wrapper

要通过PHP Wrapper封装一个协议,首先,我们需要写一个 streamWrapper 类,类名可自定义,类的格式为:

streamWrapper?{
public?resource?$context?;
__construct?(?void?)
public?bool?dir_closedir?(?void?)
public?bool?dir_opendir?(?string?$path?,?int?$options?)
public?string?dir_readdir?(?void?)
public?bool?dir_rewinddir?(?void?)
public?bool?mkdir?(?string?$path?,?int?$mode?,?int?$options?)
public?bool?rename?(?string?$path_from?,?string?$path_to?)
public?bool?rmdir?(?string?$path?,?int?$options?)
public?resource?stream_cast?(?int?$cast_as?)
public?void?stream_close?(?void?)
public?bool?stream_eof?(?void?)
public?bool?stream_flush?(?void?)
public?bool?stream_lock?(?mode?$operation?)
public?bool?stream_open?(?string?$path?,?string?$mode?,?int?$options?,?string?&$opened_path?)
public?string?stream_read?(?int?$count?)
public?bool?stream_seek?(?int?$offset?,?int?$whence?=?SEEK_SET?)
public?bool?stream_set_option?(?int?$option?,?int?$arg1?,?int?$arg2?)
public?array?stream_stat?(?void?)
public?int?stream_tell?(?void?)
public?int?stream_write?(?string?$data?)
public?bool?unlink?(?string?$path?)
public?array?url_stat?(?string?$path?,?int?$flags?)
}

类中各方法说明:

streamWrapper::__construct — 构造函数,仅在stream_open前被调用

streamWrapper::dir_closedir — 关闭目录句柄,响应closedir()函数

streamWrapper::dir_opendir — 打开目录句柄,响应opendir()函数

streamWrapper::dir_readdir — 从目录句柄读取条目,响应readdir()函数

streamWrapper::dir_rewinddir — 倒回目录句柄,响应rewinddir()函数

streamWrapper::mkdir — 创建目录,响应mkdir()函数

streamWrapper::rename — 目录或文件重命名,响应rename()函数

streamWrapper::rmdir — 删除目录,响应rmdir()函数

streamWrapper::stream_cast — 检索基础资源,响应stream_select()函数

streamWrapper::stream_close — 关闭资源,响应fclose()函数

streamWrapper::stream_eof — 检查文件指针是否已经在文件末尾,响应feof()函数

streamWrapper::stream_flush — 清除输出缓存,响应fflush()函数

streamWrapper::stream_lock — 咨询文件锁定,响应flock()函数

streamWrapper::stream_open — 打开文件或URL为流,响应fopen()函数

streamWrapper::stream_read — 从流中读取内容,响应fread(), fgets()函数

streamWrapper::stream_seek — 在流中定位指针,响应fseek()函数

streamWrapper::stream_set_option — 改变流设置

streamWrapper::stream_stat — 检索文件资源的信息,响应fstat()函数

streamWrapper::stream_tell — 检索流中指针的位置,响应ftell()函数

streamWrapper::stream_write — 向流中写入内容,响应fwrite(), fputs()函数

streamWrapper::unlink — 删除文件,响应unlink()函数

streamWrapper::url_stat — 检索文件的信息,响应所有stat()相关的函数,例如file_exists(), is_dir(), is_file(), filesize(), fileinode()等等

详细说明请参考PHP手册:

写好streamWrapper类之后,使用 stream_wrapper_register () 将这个类注册到Wrapper中,就可以开始使用了。函数使用方法为:

bool stream_wrapper_register ( string $protocol , string $classname [, int $flags = 0 ] )

例如:

stream_wrapper_register("saemc",?"SaeMemcacheWrapper");

由于SAE平台不支持对本地文件的写操作,因此Smarty之类的一些需要在本地写文件的开源项目就没办法直接在SAE平台上使用,而有了saemc Wrapper,用户就可以将Smarty编译的模板保存在MC中,很方便的将Smarty迁移到SAE平台上来。

在附件中我们为大家提供了SAE上Memcache Wrapper的实现代码,大家可以下载此附件进行测试。

在测试之前,需要先在本地启动一个端口为22222的Memcached服务:

memcached?-m?10?-p?22222?-u?nobody?-l?127.0.0.1

然后使用下面代码就可以测试了:

//包含附件代码,注册saemc?Wrapper
include_once('wrapper.php');
//测试?saemc?Wrapper
$fp?=?fopen(?"saemc://test.txt",?"w+"?)?or?die("fopen?faild!");
fwrite(?$fp,?"line1\n"?)?or?die("fwrite?line1?faild!");
fwrite(?$fp,?"line2\n"?)?or?die("fwrite?line2?faild!");
fwrite(?$fp,?"line3\n"?)?or?die("fwrite?line3?faild!");
var_dump(ftell($fp));
fseek(?$fp,?0?);
while?(?!feof(?$fp?)?)?{
????$c?=?fgets(?$fp?)?or?die("fgets?faild!");
??????var_dump($c);
}
fclose(?$fp?);
var_dump(file_get_contents("saemc://test.txt"));
var_dump(file_put_contents("saemc://path/test.txt",?"hello?world!\n"));
var_dump(file_put_contents("saemc://path/test.txt",?"hello?world!\n",?FILE_APPEND));
var_dump(file_get_contents("saemc://path/test.txt"));
var_dump(copy("saemc://path/test.txt",?"saemc://path/test_new.txt"));
var_dump(file_get_contents("saemc://path/test_new.txt"));
var_dump(unlink("saemc://path/test.txt"));
var_dump(file_get_contents("saemc://path/test.txt"));
var_dump(rename("saemc://path/test_new.txt",?"saemc://path/test.txt"));
var_dump(file_get_contents("saemc://path/test.txt"));
echo?"====test?include====\n";
include_once("saemc://path/test.txt");

测试页面的输出结果:

int(18)
string(6)?"line1
"
string(6)?"line2
"
string(6)?"line3
"
string(18)?"line1
line2
line3
"
int(13)
int(13)
string(26)?"hello?world!
hello?world!
"
bool(true)
string(26)?"hello?world!
hello?world!
"
bool(true)
bool(false)
bool(true)
string(26)?"hello?world!
hello?world!
"
====test?include====
hello?world!
hello?world!

我们提供的 Memcache Wrapper并没有实现目录操作的一些方法和Memcache的Timeout,大家可以参考PHP手册,尝试实现目录操作,或者通过context使这个Wrapper支持Memcache的Timeout。

另外,大家可以到下面这个地址查看SAE Stdlib中sae_include的源码,在其中还有我们为Storage服务封装的saestor Wrapper和为Fetchurl服务重新封装的http Wrapper的实现:

四、写Wrapper时的一些注意事项

1. 构造函数

streamWrapper 类很特别,它的构造函数并不是每次都调用的。只有在你的操作触发了stream_open相关的操作时才会调用,比如你用file_get_contents()了。而当你的操作触发和stream无关的函数时,比如file_exists会触发url_stat方法,这个时候构造函数是不会被调用的。

2. 读实现

Wrapper里边有Position和Seek等概念,但是很多服务其实是一次性就读取全部数据的,这个可以在stream_open的时候一次性读回,放到一个属性中,以后seek和tell的时候直接操作属性里边存放的数据就可以了。

3. 追加写实现

有很多服务是一次性写入所有数据,不支持追加写的功能(比如Memcache),这就需要我们自己在Wrapper中来实现追加写。可以将整个value一次性读取出来,将需要追加写的数据追加在读取出来的内容后面之后,再一次性写回。

但是这种追加写的实现方式性能会比较差,尤其是内容体积较大之后,一次性读取所有内容会非常消耗资源,因此在某些服务中我们不得不舍弃对追加写的支持。

4. url_stat的实现

在streamWrapper类的实现中linux feof函数,url_stat的实现是个难点。必须正确的实现url_stat才能使is_writable和is_readable等查询文件元信息的函数正常工作。

而我们需要为我们的虚设备伪造这些值。以mc为例,我们给大家一些参考数据:

url_stat应该返回一个数组,分13个项,内容如下:

dev 设备号 - 写0即可;

ino inode号 - 写0即可;

mode 文件mode - 这个是文件的权限控制符号,稍后详细说明;

nlink link - 写0即可;

uid uid - Linux上用posix_get_uid可以取到,windows上为0;

gid gid - Linux上用posix_get_gid可以取到,windows上为0;

rdev 设备类型 - 当为inode设备时有值;

size - 文件大小;

atime - 最后读时间 格式为unix时间戳;

mtime - 最后写时间;

ctime - 创建时间;

blksize - blocksize of filesystem IO 写零即可;

blocks - number of 512-byte blocks allocated 写零即可;

其中mode的值必须写对:

如果是文件,其值为:

0100000 + 文件权限,如 0100000 + 0777。

如果是目录,其值为:

040000 + 目录权限,如 0400000 + 0777。

5. 关于stat的缓存

PHP会在同一个页面的执行过程中对文件的元信息进行缓存。

根据PHP文档对 clearstatcache() 这个方法的说明得知:在使用 stat(), lstat(), file_exists(), is_writable(), is_readable(), is_executable(), is_file(), is_dir(), is_link(), filectime(), fileatime(), filemtime(), fileinode(), filegroup(), fileowner(), filesize(), filetype(), 或 fileperms() 方法查询文件信息时,PHP会将文件的stat的缓存以提高性能。 clearstatcache()方法可以用来清除这个缓存,当unlink()会自动清除stat缓存。

而实际上,PHP只有在对本地文件进行unlink, rename和rmdir操作时会清除stat缓存,而在通过其他的wrapper进行unlink, rename和rmdir操作时,并不会清除stat缓存。因此在写wrapper时我们要自己在unlink等方法中通过clearstatcache()来清除stat缓存。

总结

以上就是关于PHP Wrapper在SAE上的应用方法全部内容,希望这篇文章能够帮你解决如相关的PHP问题,更多请关注PHP栏目的其它相关文章!

编程学习分享?PHP Wrapper是什么,SAE为什么需要PHP Wrapper

(编辑:威海站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!