net-tools / simple_framework
用于简单应用框架的Composer库
Requires
- php: >= 8.0
- net-tools/core: ^1.0.0
Requires (Dev)
- phpunit/phpunit: ^8.0.0
- dev-master
- 1.1.31
- 1.1.30
- 1.1.29
- 1.1.28
- 1.1.27
- 1.1.26
- 1.1.25
- 1.1.24
- 1.1.23
- 1.1.22
- 1.1.21
- 1.1.20
- 1.1.19
- 1.1.18
- 1.1.17
- 1.1.16
- 1.1.15
- 1.1.14
- 1.1.13
- 1.1.12
- 1.1.11
- 1.1.10
- 1.1.9
- 1.1.8
- 1.1.7
- 1.1.6
- 1.1.5
- 1.1.4
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.21
- 1.0.20
- 1.0.19
- 1.0.18
- 1.0.17
- 1.0.16
- 1.0.15
- 1.0.14
- 1.0.13
- 1.0.12
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
This package is auto-updated.
Last update: 2024-08-29 19:43:37 UTC
README
用于创建简单Web应用的Composer库
此包定义了一个可用于创建简单Web应用的框架。最终用户可以专注于“业务”代码部分,而无需关注清理用户提交的数据、响应XMLHttpRequest等问题。
安装说明
要安装net-tools/simple_framework包,只需通过composer要求: require net-tools/simple_framework:^1.0.0
。
示例文件
在包中有一个名为samples
的子目录,其中包含一个非常简单的应用。请首先阅读本README,然后您可以参考此示例文件。
如何使用?
框架预览
该框架专注于命令,即PHP代码“响应”发送到应用的请求。请求可以是GET/POST请求(可能包含文件上传)或XMLHttpRequest。命令“响应”请求,返回一个可选值
- PHP值(任何数据类型): 当命令仅执行一些后台操作,如计算并返回计算结果时使用
- JSON字符串:用于响应XMLHttpRequest
- 文件下载:用户可以从您的应用中下载一些数据(可以是文件内容或即时生成的字符串)
- HTML内容:用于以格式化方式响应,稍后输出到屏幕(例如,命令生成产品列表)
这是一个简单的框架,您可能会说生成视图内容不应与计算混合。您是对的,但目标是创建一个包含基本功能的简单框架。
创建命令类
常见情况
要响应命令(如GET/POST请求),只需创建一个以命令名称命名的类,并从Command
类继承即可
namespace Myapp\Commands; use \Nettools\Simple_Framework\Command; use \Nettools\Simple_Framework\Request; use \Nettools\Simple_Framework\Application; class Test extends Command { public function execute(Request $req, Application $app) { return $this->returnHTML("Command <b>'test'</b> is called with parameter '{$req->param}' !"); } }
如您所猜,此命令返回HTML内容。此内容尚未输出到屏幕。这是在页面模板中稍后完成的。
返回的字符串将包含查询字符串的'param'值,可通过Request $req
对象访问。此对象填充了所有GET/POST参数,作为PHP属性。数据在设置到Request
对象之前被清理。
如果您想响应XMLHttpRequest,返回以下任一线的JSON值。Command
类的returnJson()
方法足够智能,允许不同数据类型,并在内部将它们转换为JSON格式的字符串。
return $this->returnJson('{"value":"'. $req->param . '"}'); // string return $this->returnJson(array('value' => $req->param)); // associative array return $this->returnJson((object)array('value' => $req->param)); // object litteral
要使用下载响应命令,使用returnFileDownload()
或returnStringDownload()
,具体取决于数据是否包含在文件中或即时生成的字符串
// downloading a file with Mimetype 'text/plain', the browser will suggest the name 'test.txt' as filename with 'my file content' as data downloaded. return $this->returnStringDownload("my file content", 'test.txt', 'text/plain'); // downloading a file from path '/tmp/compute.bin', with Mimetype 'application/octet-stream' ; when saved, the browser will suggest 'data.bin' as filename return $this->returnFileDownload('/tmp/compute.bin', 'data.bin', 'application/octet-stream');
处理文件上传
如果您想处理用户上传的文件,请使用Request
类的getFileUpload()
方法获取描述已上传文件的特定FileUploadRequest
对象
namespace Myapp\Commands; use \Nettools\Simple_Framework\Command; use \Nettools\Simple_Framework\Request; use \Nettools\Simple_Framework\Application; class Upload extends Command { public function execute(Request $req, Application $app) { // the input named 'upload' should always be in the request, even if no file has been submitted. // $f will contain a FileUploadRequest object. if ( $f = $req->getFileUpload('upload') ) // if a file has been submitted if ( $f->uploaded() ) { // we erase the temp file, this is just a test unlink($f->tmp_name); return $this->returnString('File was sent'); } // if no file has been submitted else if ( $f->no_file() ) return $this->returnString('The user has not uploaded a file'); // unknown other error else return $this->returnString('Upload error'); else return $this->returnString('Field upload does not exist'); } }
发送命令
要执行之前定义的命令,您必须向应用的URI发送HTTP请求。如果'index.php'是应用文件
index.php?cmd=test¶m=hello+world
如你所见,命令的名称应设置在cmd
URI查询字符串参数中。其他参数旨在在命令执行期间使用(如$req->param
用于param
查询字符串值)。
请求也可以通过POST动词或JavaScript中的XMLHttpRequest发送。
本页上的前两个示例(HTML响应和XMLHttpResponse)将输出:
命令 <b>'test'</b> 使用参数 'hello world' 被调用!
并且
{"value":"hello world"}
启动应用程序以处理请求
当使用HTTP请求(如 index.php?cmd=test¶m=hello+world
)向应用程序发送命令时,您需要启动应用程序框架,以便它可以处理请求并从命令执行返回输出。
<?php namespace Myapp; use \Nettools\Simple_Framework\WebApplication; use \Nettools\Simple_Framework\Registry; // créer l'application $app = new WebApplication( // user namespace for commands '\\Myapp\\Commands', // registry for config data new Registry() ); // launch app and get the returned result in $output $output = $app->run(); ?> <html> <body> Command output as HTML or php value : <?php echo $output; ?>. </body> </html>
创建了一个 WebApplication
对象,以便应用程序可以运行。其第一个参数是要查找命令类的命名空间(请参阅此处的前几个示例,命令的命名空间为 Myapp\Commands
),第二个参数是用于存储配置数据的 Registry
对象(为了简化示例,该注册表为空;对于此测试,我们不需要任何配置数据)。如果需要处理敏感的配置数据,创建您的注册表(使用 Config\ConfigObject
、JsonFile
或 Json
),然后将其封装在顶级 Config\PrivateConfig
注册表中(请参阅具体示例文件)。
然后,在 Application $app
对象上调用 run()
方法:在 Myapp\Commands
命名空间中搜索由 cmd
查询字符串参数引用的命令,调用它,并将结果设置到 $output
中。
对于Web应用程序(这可能是情况),一些返回值应该立即发送到浏览器(Json
、Download
、FileDownload
或 StringDownload
);是否输出或处理该输出(根据返回值类型)的过程由 ReturnedValuesOutput
子命名空间中的类处理。如果找到了名为 WebController_xxxx
的类(其中 xxxx 表示返回值类(Download
、Json
等),则此类负责输出。如果没有找到特定返回值的类,则不会向浏览器输出,并且值将通过 $app->run()
返回。
请参阅 Nettools\Simple_Framework
的 ReturnedValues
子命名空间中的类,以获取可接受的返回值完整列表(所有继承自 ReturnedValues\Value
)。
在其他情况下,命令返回一个值,该值从 $app->run()
执行中获取。在大多数情况下,这将是一些HTML内容或原始PHP类型(字符串、整数等),您可以在稍后的页面模板中包含或使用它:`echo $output
` 将 ReturnedValues\Value
对象转换为字符串。
处理错误情况和异常
当发生异常或您故意使命令失败时,框架将执行一些特定操作。
异常:框架将处理它们
在代码执行期间抛出(并且未被您的代码捕获)的异常在 Controller
对象的 run()
方法中被捕获,并显示一个包含所有必要调试数据的特定屏幕(并且脚本停止)。为了您的信息,这些调试数据是由 Nettools\Core\ExceptionHandlers\SimpleExceptionHandler
格式的(您可以通过参考 Nettools\Core 包来读取更多文档:http://net-tools.ovh/api-reference/net-tools/Nettools/Core/ExceptionHandlers.html)。
您可以为异常设置另一个异常处理器(例如,您不想在屏幕上显示调试数据,而是希望通过电子邮件将调试数据发送给网络管理员);要这样做,当创建 $app
对象时,创建一个名为 appcfg
的 Registry
,并将其 application->exceptionHandler
的值设置为您的选择(但是,它必须继承自 Nettools\Core\ExceptionHandlers\ExceptionHandler
,例如 Nettools\Core\ExceptionHandlers\PublicExceptionHandler
,它将在屏幕上显示有关异常的简短消息,而没有调试数据;调试数据将作为电子邮件正文和堆栈跟踪的附件发送到 postmaster@yourdomain.com)。
错误情况:失败
有时,您想表示一个命令执行未成功。为此,在您的命令 execute
调用期间,请使用适当的错误消息调用 $this
上的 fail()
。
class Failed extends Command { public function execute(Request $req, Application $app) { $this->fail('Something went wrong'); } }
然后应用程序控制器将处理错误。
-
如果请求是通过 GET/POST 发送的,则
Application
的run()
方法将返回一个具有不成功状态的 ReturnedValues\StringValue 对象。您需要通过调用返回值的isSuccessful()
方法来检测不成功的答案并进行适当的处理:$output = $app->run(); if (!$output->isSuccessful()) echo "error : " . $output;
-
如果请求是通过 XMLHttpRequest 发送的,则
Application
的run()
方法(实际上,它是Controller
对象的run()
方法)将自动在 stdout 输出一个 Json 字符串并停止脚本:{"statut":false,"message":"出了点问题"}
如果您想用非字符串的错误反馈来回答,您不能使用 fail 机制。然而,您可以用一个具有不成功状态的反回值来回应命令;Command
类的所有 returnXXX 方法都有一个第二个参数来设置执行状态(默认为成功/true)。
class ErrorOccured extends Command { public function execute(Request $req, Application $app) { return $this->returnPHP(array('msg'=>'Error message', 'line'=>134, 'severity'=>4), false); } }
安全功能
该框架可以完全不带安全功能使用(除了请求被净化之外),或者配置为发送包含特殊计算令牌的请求以识别用户(从而阻止未经授权的请求代表其他用户进行)。
令牌是通过一个秘密(需要在 appcfg
注册表中配置,在 controller->userSecurityHandlers
安全处理程序数组中)和请求中的当前用户 ID(可以是任何请求参数;默认情况下,是 i
参数)创建的。它作为 h
参数(默认情况下,但也可以命名为其他任何名称)与其他参数一起传递。请参阅相应的示例以了解用例。
基于令牌的安全功能 仅 防止黑客在不被授权(登录)的情况下发布其他用户 ID 的请求,因为他们不知道如何计算令牌值(不知道秘密或哈希过程)。
然而,它 不能 防止请求被多次发布(令牌不是一个一次性值),也不能防止请求容易受到 CSRF 攻击。
在未来的版本中,可能会实现 CSRF 安全功能和一次性令牌。
PHPUnit
要使用 PHPUnit 进行测试,请将 -c 配置选项指向 /phpunit.xml 配置文件。