文件系统

概述

The 文件系统API,已在中添加WordPress 2.6版,最初是为WordPress自己的自动更新功能创建的。

文件系统API抽象出在各种主机类型上安全地将本地文件读写到文件系统所需的功能。

它通过WP_文件系统_基础类和几个子类,这些子类实现了连接到本地文件系统的不同方式,具体取决于单个主机的支持。

任何需要在本地写入文件的主题或插件都应该使用WP_文件系统班级家庭。

目的

不同的托管系统在配置Web服务器的方式上有不同的限制。

特别是,许多主机系统都将Web服务器作为不同于WordPress文件所有者的用户运行。在这种情况下,从Web服务器用户写入文件的进程将拥有Web服务器用户帐户而不是实际用户帐户所拥有的结果文件。这可能会导致共享托管情况下的安全问题,即多个用户为不同的站点共享同一个Web服务器。

WP_文件系统能够检测写入文件的用户何时不匹配,并切换到使用FTP或类似方法。根据可用的PHP库,WP_文件系统支持使用FTP的三种不同方法(通过扩展、套接字或通过SSH),并将自动选择正确的方法。

在这种情况下,实现此代码的插件或主题需要向用户请求FTP凭据。添加了一些功能,使其易于实现,并使凭证输入表单的外观标准化。

文件系统API类参考

获取凭据

使用WP_Filesystem的第一步是向用户请求凭据。通常情况下,这是在保存表单输入的结果时完成的,或者在确定需要写入文件时完成的。

可以使用以下代码将凭据表单显示在管理页面上:

$url=wp_nonce_url('themes.php?page=example','example-theme-options');if(false===($creds=request_filesystem_credentials($url,“”,false,false,null)){返回;//在此处停止处理}

这个请求文件系统凭据()调用需要五个参数。

  • 表单应提交到的URL(在上面的示例中使用了主题页的非编码URL)
  • 方法重写(通常应将其保留为空字符串:“”)
  • 错误标志(除非检测到错误,否则通常为假,见下文)
  • 上下文目录(false,或要测试访问的特定目录路径)
  • 表单字段(来自上一个表单的表单字段名称数组,您希望“传递”结果凭据表单,如果没有,则为null)

这个请求文件系统凭据调用将测试它是否能够在没有凭据的情况下直接写入本地文件系统。如果是这种情况,那么它将返回true,并且不执行任何操作。然后,您的代码可以继续使用WP_文件系统类。

这个请求文件系统凭据调用还考虑硬编码信息,如主机名或用户名或密码,这些信息已插入wp-config.php文件使用定义。如果这些是在该文件中预定义的,则此调用将返回该信息,而不是显示表单,从而为用户绕过该表单。

如果它确实需要来自用户的凭据,那么它将输出FTP信息表单并返回false。在这种情况下,您应该停止进一步处理,以便允许用户输入凭据。您指定的任何表单字段名称都将作为隐藏输入包含在结果表单中,并在用户重新提交表单时返回,这一次是使用FTP凭据。

注意:不要使用的保留名称主机名用户名密码公钥,或私钥用于您自己的输入。这些由凭证表单本身使用。或者,如果您确实使用了它们请求文件系统凭据函数将假定它们是传入的FTP凭据。

提交凭据表单时,它将在传入的POST数据中查找这些字段,如果找到,它将以适合传递给WP_Filesystem的数组返回这些字段,这是下一步。

初始化WP_Filesystem_Base

在可以使用WP_Filesystem之前,必须使用正确的凭据对其进行初始化。可以这样做:

if(!WP_Filesystem($creds)){request_filesystem_credentials($url,“”,true,false,null);回报;}

首先你打电话给WP_文件系统函数,将以前的凭据传递给它。然后,它将尝试验证凭据。如果它们是好的,那么它就会变成真的。如果不是,则返回false。

在凭据不正确的情况下,上面的代码会再次调用请求文件系统凭据(),但这次错误标志设置为true。这将强制函数再次显示表单,这一次会向用户显示一条错误消息,指出其信息不正确。然后,用户可以重新输入其信息并重试。

使用WP_Filesystem_Base类

一旦类被初始化,那么全局$wp_filesystem变量被定义并可供您使用。这个WP_文件系统_基础类定义了几个可用于读取和写入本地文件的方法。例如,要编写文件,可以执行以下操作:

全局$wp_filesystem;$wp_filesystem->put_contents($wp_filesystem->put_contents)('/tmp/example.txt','文件内容示例',FS_CHMOD_FILE//WP文件的预定义模式设置);

其他可用方法包括获取内容()获取内容数组()读取文件;wp_content_dir()wp_plugins_dir(),以及wp_themes_dir()将文件系统路径返回到这些目录;mkdir()rmdir()创建和删除目录;以及其他一些方便的文件系统相关功能。

提示和技巧

你什么时候可以打电话请求文件系统凭据()?
对于使用WP文件系统API的开发人员来说,最初的挑战之一是您无法在任何地方对其进行初始化。The 请求文件系统凭据()函数在wp_已加载action hook,并且只包含在admin区域中。您可以使用的最早的钩子之一是admin_init。

WP文件系统API方法
呼叫的另一个问题请求文件系统凭据()直接是您无法确定您是否有权直接访问文件系统,或者是否会提示用户输入凭据。从用户体验的角度来看,如果你想在插件被激活时对文件进行更改,那么这就成了一个问题。想象一下,一个用户通过他们的管理区安装你的插件,输入他们的FTP详细信息,完成安装并激活你的插件。但一旦他们这样做了,就会被提示再次输入FTP详细信息,并让他们挠头思考原因。

更好的解决方案是添加一个通知(例如使用admin_notice),向用户解释插件需要写入文件系统才能完成安装。除了该通知,您还需要添加一个按钮或链接,以触发对请求文件系统凭据().

但是让我们进一步扩展这个场景,并说这个插件每次更新时都需要访问文件系统。如果你定期发布更新和错误修复,那么用户每次升级时都很难点击你的可操作按钮。最好是在调用之前确定我们是否具有直接写访问权限请求文件系统凭据()并且静默地进行安装。这就是获取文件系统方法()功能开始发挥作用。

$access_type=获取文件系统方法();if($access_type===“直接”){/*您可以安全地运行request_filesystem_credentials()而无需担心传入URL*/$creds=request_filesystem_credentials(site_url())。'/wp-admin/','',false,false());/*初始化API*/if(!WP_Filesystem($creds)){/*任何问题我们都会退出*/返回false;}	全局$wp_filesystem;/*进行下面的文件操作*/}	其他的{/*没有直接写入权限。用我们的通知提示用户*/add_action('admin_notices','you_admin_notie_function');	}

这种方法适用于所有相关人员。没有直接写入权限的用户会被提示对文件系统进行更改,而在可以直接写入文件系统的站点上,插件不会被注意到(这是一种好方法)。

使用路径
值得称职的WordPress开发人员应该熟悉设置常量或变量来访问插件路径。通常看起来是这样的:

define('MY_PLUGIN_DIR',PLUGIN_DIR_path(__FILE__));

使用Filesystem API时需要考虑的是,文件的路径并不总是相同的。使用直接方法时,您可以安全地使用MY_PLUGIN_DIR公司常数,但如果在使用FTP或SSH方法时尝试执行相同的操作,则可能会遇到问题。这是因为FTP和SSH通常以绝对路径上的某个目录为根。现在,Filesystem API为我们提供了使用以下方法克服此问题的方法$wp_filesystem->wp_content_dir()$wp_filesystem->wp_plugins_dir(),但两次定义插件的路径是不实际的。

/*用文件系统API路径替换“直接”绝对路径*/$plugin_path=str_replace(ABSPATH,$wp_filesystem->ABSPATH(),MY_plugin_DIR);/*现在,我们可以在所有文件系统API方法调用中使用$plugin_path*/if(!$wp_filesystem->is_dir($plugin_path.'/config/')){/*目录不存在,所以让我们创建它*/$wp_filesystem->mkdir($plugin_path.'/config/');}

解压缩文件($file,$to);

虽然此函数要求初始化Filesystem API,但它不是$wp_filesystem对象,这可能是其参数相互矛盾的原因。第一个参数$文件,需要是文件的绝对“直接”路径,而$t参数需要指向文件系统的绝对路径。

定义(“MY_PLUGIN_DIR”,插件DIR_path(__FILE_));全局$wp_filesystem;//之前已经初始化了文件系统API$plugin_path=str_replace(ABSPATH,$wp_filesystem->ABSPATH(),MY_plugin_DIR);//获取远程系统绝对路径/*使用该功能的可接受方式*/$文件=MY_PLUGIN_DIR。'/插件文件.zip’;$to=$plugin_path;$result=解压缩文件($file,$to);if($result!==true){//解压缩失败。句柄错误}/*不可接受*/$文件=MY_PLUGIN_DIR。'/插件文件.zip’;$到=MY_PLUGIN_DIR;//$to不能是文件夹的“直接”绝对路径,否则FTP和SSH方法将被搁置解压缩文件($file,$to);$file=$plugin_path。”/plugin-file.zip';//如果$file不是“直接”绝对路径,那么不使用FTP和SSH方法的用户将被冷落$to=$plugin_path;解压缩文件($file,$to);

外部参考