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 相关文章推荐
IIS6.0+PHP5.x+MySQL5.x+Zend3.0x+GD+phpMyAdmin2.8x通用安装实例(已经完成)
Dec 06 PHP
php xml文件操作实现代码(二)
Mar 20 PHP
探讨fckeditor在Php中的配置详解
Jun 08 PHP
php获取301跳转URL简单实例
Dec 16 PHP
PHP6 中可能会出现的新特性预览
Apr 04 PHP
PHP 正则表达式小结
Feb 12 PHP
PHP截取IE浏览器并缩小原图的方法
Mar 04 PHP
PHP创建多级目录的两种方法
Oct 28 PHP
一个实用的php验证码类
Jul 06 PHP
php 使用expat方式解析xml文件操作示例
Nov 26 PHP
如何重写Laravel异常处理类详解
Dec 20 PHP
PHP时间类完整代码实例
Feb 26 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/09/28 PHP
Laravel Memcached缓存驱动的配置与应用方法分析
2016/10/08 PHP
tp5修改(实现即点即改)
2019/10/18 PHP
Ajax局部更新导致JS事件重复触发问题的解决方法
2014/10/14 Javascript
js实现右下角提示框的方法
2015/02/03 Javascript
jQuery中实现prop()函数控制多选框(全选,反选)
2016/08/19 Javascript
jQuery动态创建元素以及追加节点的实现方法
2016/10/20 Javascript
JavaScript 深层克隆对象详解及实例
2016/11/03 Javascript
正则表达式,替换所有HTML标签的简单实例
2016/11/28 Javascript
JavaScript正则表达式exec/g实现多次循环用法示例
2017/01/17 Javascript
js控制按钮,防止频繁点击响应的实例
2017/02/15 Javascript
利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层
2017/03/15 Javascript
Vue.js学习笔记之常用模板语法详解
2017/07/25 Javascript
Node.js微信 access_token ( jsapi_ticket ) 存取与刷新的示例
2017/09/30 Javascript
layui的table单击行勾选checkbox功能方法
2018/08/14 Javascript
微信小程序在其他页面监听globalData中值的变化
2019/07/15 Javascript
jQuery实现简单三级联动效果
2020/09/05 jQuery
Python 正则表达式(转义问题)
2014/12/15 Python
python使用xlsxwriter实现有向无环图到Excel的转换
2018/12/12 Python
Python IDLE或shell中切换路径的操作
2020/03/09 Python
Python新手如何理解循环加载模块
2020/05/29 Python
弄清Pytorch显存的分配机制
2020/12/10 Python
python绘图pyecharts+pandas的使用详解
2020/12/13 Python
html5本地存储_动力节点Java学院整理
2017/07/12 HTML / CSS
雅诗兰黛澳大利亚官网:Estée Lauder澳大利亚
2019/05/31 全球购物
环境科学专业大学生自荐信格式
2013/09/21 职场文书
体育系毕业生求职自荐信
2014/04/16 职场文书
党员先锋岗事迹材料
2014/05/08 职场文书
小学运动会班级口号
2014/06/09 职场文书
法学求职信
2014/06/22 职场文书
法院答辩状格式
2015/05/22 职场文书
党支部综合考察意见
2015/06/01 职场文书
网络研修随笔感言
2015/11/18 职场文书
Python函数中的不定长参数相关知识总结
2021/06/24 Python
Go语言基础知识点介绍
2021/07/04 Golang
python全面解析接口返回数据
2022/02/12 Python