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 相关文章推荐
做一个有下拉功能的留言版
Oct 09 PHP
Google Voice 短信发送接口PHP开源版(2010.5更新)
Jul 22 PHP
PHP开发的一些注意点总结
Oct 12 PHP
php文件上传的简单实例
Oct 19 PHP
PHP统计nginx访问日志中的搜索引擎抓取404链接页面路径
Jun 30 PHP
ThinkPHP实现将SESSION存入MYSQL的方法
Jul 22 PHP
跟我学Laravel之请求与输入
Oct 15 PHP
详解PHP中websocket的使用方法
Sep 15 PHP
浅谈PHP表单提交(POST&amp;GET&amp;URL编/解码)
Apr 03 PHP
PHP+ajax实现获取新闻数据简单示例
May 08 PHP
php实现将数据做成json的格式给前端使用
Aug 21 PHP
PHP-FPM 设置多pool及配置文件重写操作示例
Oct 02 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
关于Yii中模型场景的一些简单介绍
2019/09/22 PHP
JavaScript关于select的相关操作说明
2010/01/13 Javascript
心扬JS分页函数代码
2010/09/10 Javascript
jquery 圆形旋转图片滚动切换效果
2011/01/19 Javascript
JS图片根据鼠标滚动延时加载的实例代码
2013/07/13 Javascript
利用javascript数组长度循环数组内所有元素
2013/12/27 Javascript
JS延迟加载加快页面打开速度示例代码
2013/12/30 Javascript
js实现checkbox全选和反选示例
2014/05/01 Javascript
jQuery取消ajax请求的方法
2015/06/09 Javascript
JQuery实现鼠标移动图片显示描述层的方法
2015/06/25 Javascript
jQuery实现点击按钮弹出可关闭层的浮动层插件
2015/09/19 Javascript
javascript实现对表格元素进行排序操作
2015/11/18 Javascript
基于Javascript实现二级联动菜单效果
2016/03/04 Javascript
Javascript数组Array基础介绍
2016/03/13 Javascript
jQuery实现的无限级下拉菜单功能示例
2016/09/12 Javascript
JQuery遍历元素的父辈和祖先的方法
2016/09/18 Javascript
通过sails和阿里大于实现短信验证
2017/01/04 Javascript
基于JavaScript实现淘宝商品广告效果
2017/08/10 Javascript
深入理解 webpack 文件打包机制(小结)
2018/01/08 Javascript
vue路由懒加载的实现方法
2018/03/12 Javascript
Vue.js项目中管理每个页面的头部标签的两种方法
2018/06/25 Javascript
koa2+vue实现登陆及登录状态判断
2019/08/15 Javascript
Vue如何循环提取对象数组中的值
2020/11/18 Vue.js
将图片文件嵌入到wxpython代码中的实现方法
2014/08/11 Python
Python实现抓取城市的PM2.5浓度和排名
2015/03/19 Python
使用Python操作Elasticsearch数据索引的教程
2015/04/08 Python
基于Python os模块常用命令介绍
2017/11/03 Python
Python如何定义接口和抽象类
2020/07/28 Python
描述JSP和Servlet的区别、共同点、各自应用的范围
2012/10/02 面试题
物业管理应届生求职信
2013/10/28 职场文书
《厄运打不垮的信念》教学反思
2014/04/13 职场文书
2014年师德师风自我剖析材料
2014/09/27 职场文书
2015年社会实践个人总结
2015/03/06 职场文书
iPhone13 Pro外观确定,升级4800万镜头,4月20日发新品
2021/04/15 数码科技
oracle重置序列从0开始递增1
2022/02/28 Oracle
Python实现日志实时监测的示例详解
2022/04/06 Python