golang 调用 php7详解及实例


Posted in PHP onJanuary 04, 2017

执行php文件

func Test_exec(t *testing.T) {
  engine.Initialize()
  ctx := &engine.Context{
    Output: os.Stdout,
  }
  err := engine.RequestStartup(ctx)
  if err != nil {
    fmt.Println(err)
  }
  defer engine.RequestShutdown(ctx)
  err = ctx.Exec("/tmp/index.php")
  if err != nil {
    fmt.Println(err)
  }
}

其中 /tmp/index.php 的内容为

<?php
echo("hello\n");

Eval,返回值

func Test_eval(t *testing.T) {
  engine.Initialize()
  ctx := &engine.Context{}
  err := engine.RequestStartup(ctx)
  if err != nil {
    fmt.Println(err)
  }
  defer engine.RequestShutdown(ctx)
  val, err := ctx.Eval("return 'hello';")
  if err != nil {
    fmt.Println(err)
  }
  defer engine.DestroyValue(val)
  if engine.ToString(val) != "hello" {
    t.FailNow()
  }
}

返回的value的生命周期所有权是golang程序,所以我们要负责DestroyValue

设置全局变量来传参

func Test_argument(t *testing.T) {
  engine.Initialize()
  ctx := &engine.Context{}
  err := engine.RequestStartup(ctx)
  if err != nil {
    fmt.Println(err)
  }
  defer engine.RequestShutdown(ctx)
  err = ctx.Bind("greeting", "hello")
  if err != nil {
    fmt.Println(err)
  }
  val, err := ctx.Eval("return $greeting;")
  if err != nil {
    fmt.Println(err)
  }
  defer engine.DestroyValue(val)
  if engine.ToString(val) != "hello" {
    t.FailNow()
  }
}

传递进去的参数的生命周期是php控制的,在request shutdown的时候内存会被释放。

PHP 回调 Golang

type greetingProvider struct {
  greeting string
}

func (provider *greetingProvider) GetGreeting() string {
  return provider.greeting
}

func newGreetingProvider(args []interface{}) interface{} {
  return &greetingProvider{
    greeting: args[0].(string),
  }
}

func Test_callback(t *testing.T) {
  engine.Initialize()
  ctx := &engine.Context{}
  err := engine.RequestStartup(ctx)
  if err != nil {
    fmt.Println(err)
  }
  defer engine.RequestShutdown(ctx)
  err = engine.Define("GreetingProvider", newGreetingProvider)
  if err != nil {
    fmt.Println(err)
  }
  val, err := ctx.Eval(`
  $greetingProvider = new GreetingProvider('hello');
  return $greetingProvider->GetGreeting();`)
  if err != nil {
    fmt.Println(err)
  }
  defer engine.DestroyValue(val)
  if engine.ToString(val) != "hello" {
    t.FailNow()
  }
}

PHP 错误日志

func Test_log(t *testing.T) {
  engine.PHP_INI_PATH_OVERRIDE = "/tmp/php.ini"
  engine.Initialize()
  ctx := &engine.Context{
    Log: os.Stderr,
  }
  err := engine.RequestStartup(ctx)
  if err != nil {
    fmt.Println(err)
  }
  defer engine.RequestShutdown(ctx)
  _, err = ctx.Eval("error_log('hello', 4); trigger_error('sent from golang', E_USER_ERROR);")
  if err != nil {
    fmt.Println(err)
  }
}

其中 /tmp/php.ini 的内容为

error_reporting = E_ALL
error_log = "/tmp/php-error.log"

错误会被输出到 /tmp/php-error.log。直接调用error_log会同时再输出一份到stderr

HTTP 输入输出

func Test_http(t *testing.T) {
  engine.Initialize()
  recorder := httptest.NewRecorder()
  ctx := &engine.Context{
    Request: httptest.NewRequest("GET", "/hello", nil),
    ResponseWriter: recorder,
  }
  err := engine.RequestStartup(ctx)
  if err != nil {
    fmt.Println(err)
  }
  defer engine.RequestShutdown(ctx)
  _, err = ctx.Eval("echo($_SERVER['REQUEST_URI']);")
  if err != nil {
    fmt.Println(err)
  }
  body, err := ioutil.ReadAll(recorder.Result().Body)
  if err != nil {
    fmt.Println(err)
  }
  if string(body) != "/hello" {
    t.FailNow()
  }
}

所有的PHP超级全局变量都会被初始化为传递进去的Request的值,包括

$_SERVER
$_GET
$_POST
$_FILE
$_COOKIE
$_ENV

echo的内容,http code和http header会被写回到传入的ResponseWriter

fastcgi_finish_request

PHP-FPM 很常用的一个功能是 fastcgi_finish_request ,用于在php里做一些异步完成的事情。这个特殊的全局函数必须支持

func Test_fastcgi_finish_reqeust(t *testing.T) {
  engine.Initialize()
  buffer := &bytes.Buffer{}
  ctx := &engine.Context{
    Output: buffer,
  }
  err := engine.RequestStartup(ctx)
  if err != nil {
    fmt.Println(err)
  }
  defer engine.RequestShutdown(ctx)
  ctx.Eval("ob_start(); echo ('hello');")
  if buffer.String() != "" {
    t.FailNow()
  }
  ctx.Eval("fastcgi_finish_request();")
  if buffer.String() != "hello" {
    t.FailNow()
  }
}

实际的作用就是把output提前输出到 ResposneWriter 里去,让调用方知道结果。对于当前进程的执行其实是没有影响的,只是影响了output。

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

PHP 相关文章推荐
PHP小教程之实现链表
Jun 09 PHP
Codeigniter实现智能裁剪图片的方法
Jun 12 PHP
PHPAnalysis中文分词类详解
Jun 13 PHP
PHP中构造函数和析构函数解析
Oct 10 PHP
thinkphp实现上一篇与下一篇的方法
Dec 08 PHP
PHP函数import_request_variables()用法分析
Apr 02 PHP
浅谈PHP的反射机制
Dec 15 PHP
PHP读取Excel类文件
May 15 PHP
PHP实现mysqli批量执行多条语句的方法示例
Jul 22 PHP
PHP基于面向对象实现的留言本功能实例
Apr 04 PHP
PHP7 mongoDB扩展使用的方法分享
May 02 PHP
Thinkphp 框架扩展之Widget扩展实现方法分析
Apr 23 PHP
PHP 与 UTF-8 的最佳实践详细介绍
Jan 04 #PHP
详解Yii2 定制表单输入字段的标签和样式
Jan 04 #PHP
PHPExcel导出2003和2007的excel文档功能示例
Jan 04 #PHP
CI框架实现优化文件上传及多文件上传的方法
Jan 04 #PHP
PHP搭建大文件切割分块上传功能示例
Jan 04 #PHP
php实现的简单中文验证码功能示例
Jan 03 #PHP
php与c 实现按行读取文件实例代码
Jan 03 #PHP
You might like
PHP简单判断字符串是否包含另一个字符串的方法
2016/03/25 PHP
php常用数组函数实例小结
2016/12/29 PHP
PHP实现移除数组中为空或为某值元素的方法
2017/01/07 PHP
基于Jquery的标签智能验证实现代码
2010/12/27 Javascript
基于jquery的图片轮播 tab切换组件
2012/07/19 Javascript
基于jQuery实现的百度导航li拖放排列效果,即时更新数据库
2012/07/31 Javascript
setTimeout()与setInterval()方法区别介绍
2013/12/24 Javascript
基于jQuery实现网页进度显示插件
2015/03/04 Javascript
vue loadmore组件上拉加载更多功能示例代码
2017/07/19 Javascript
vue教程之toast弹框全局调用示例详解
2020/08/24 Javascript
vue.js语法及常用指令
2017/10/29 Javascript
谈谈JS中的!!
2017/12/07 Javascript
详解使用webpack构建多页面应用
2017/12/21 Javascript
浏览器调试动态js脚本的方法(图解)
2018/01/19 Javascript
vue获取时间戳转换为日期格式代码实例
2019/04/17 Javascript
JS实现的贪吃蛇游戏案例详解
2019/05/01 Javascript
python实现读Excel写入.txt的方法
2018/04/29 Python
python 对给定可迭代集合统计出现频率,并排序的方法
2018/10/18 Python
Python PIL读取的图像发生自动旋转的实现方法
2019/07/05 Python
python飞机大战 pygame游戏创建快速入门详解
2019/12/17 Python
Python获取excel内容及相关操作代码实例
2020/08/10 Python
Python字符串查找基本操作代码案例
2020/10/27 Python
python多线程爬取西刺代理的示例代码
2021/01/30 Python
CSS3中文字镂空、透明值、阴影效果设置示例小结
2016/03/07 HTML / CSS
HTML5拖放API实现拖放排序的实例代码
2017/05/11 HTML / CSS
HTML5如何使用SVG的方法示例
2019/01/11 HTML / CSS
科沃斯机器人官网商城:Ecovacs
2016/08/29 全球购物
简述进程的启动、终止的方式以及如何进行进程的查看
2014/02/20 面试题
仓库管理员岗位职责
2014/03/19 职场文书
小学生环保演讲稿
2014/04/25 职场文书
五水共治一句话承诺
2014/05/30 职场文书
医学生求职自荐书
2014/06/12 职场文书
地球一小时宣传标语
2014/06/24 职场文书
校园元旦活动总结
2014/07/09 职场文书
践行三严三实心得体会
2014/10/13 职场文书
2016三八妇女节校园广播稿
2015/12/17 职场文书