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 相关文章推荐
用PHP4访问Oracle815
Oct 09 PHP
PHP 杂谈《重构-改善既有代码的设计》之五 简化函数调用
May 07 PHP
PHP Global变量定义当前页面的全局变量实现探讨
Jun 05 PHP
深入理解PHP中的Session和Cookie
Jun 21 PHP
Thinkphp多文件上传实现方法
Oct 31 PHP
php从数据库查询结果生成树形列表的方法
Apr 17 PHP
将PHP程序中返回的JSON格式数据用gzip压缩输出的方法
Mar 03 PHP
php结合mysql与mysqli扩展处理事务的方法
Jun 29 PHP
php使用正则表达式获取字符串中的URL
Dec 29 PHP
php获取ip及网址的简单方法(必看)
Apr 01 PHP
PHP implode()函数用法讲解
Mar 08 PHP
在Laravel的Model层做数据缓存的实现
Sep 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 获取客户端真实IP地址多种方法小结
2010/05/15 PHP
php使用标签替换的方式生成静态页面
2015/05/21 PHP
实例讲解如何在PHP的Yii框架中进行错误和异常处理
2016/03/17 PHP
php远程下载类分享
2016/04/13 PHP
joomla实现注册用户添加新字段的方法
2016/05/05 PHP
用jquery模仿的a的title属性(兼容ie6/7)
2013/01/21 Javascript
用表格输出1-1000之间的数字实现代码(附特效)
2013/04/21 Javascript
jquery ajax属性async(同步异步)示例
2013/11/05 Javascript
节点的插入之append()和appendTo()的用法介绍
2014/01/13 Javascript
js 显示base64编码的二进制流网页图片
2014/04/04 Javascript
javascript中拼接HTML字符串的最快、最好的方法
2014/06/07 Javascript
JS使用插件cryptojs进行加密解密数据实例
2017/05/11 Javascript
js中null与空字符串&quot;&quot;的区别讲解
2019/01/17 Javascript
vue操作动画的记录animate.css实例代码
2019/04/26 Javascript
layui中select,radio设置不生效的解决方法
2019/09/05 Javascript
jQuery操作元素追加内容示例
2020/01/10 jQuery
[07:48]DOTA2上海特级锦标赛主赛事首日RECAP
2016/03/04 DOTA
[00:32]2018DOTA2亚洲邀请赛EG出场
2018/04/03 DOTA
让代码变得更易维护的7个Python库
2018/10/09 Python
Pandas库之DataFrame使用的学习笔记
2019/06/21 Python
Python3简单爬虫抓取网页图片代码实例
2019/08/26 Python
np.newaxis 实现为 numpy.ndarray(多维数组)增加一个轴
2019/11/30 Python
Ubuntu中配置TensorFlow使用环境的方法
2020/04/21 Python
Python Request类源码实现方法及原理解析
2020/08/17 Python
python如何绘制疫情图
2020/09/16 Python
Flask处理Web表单的实现方法
2021/01/31 Python
HTML5中indexedDB 数据库的使用实例
2017/05/11 HTML / CSS
Canvas获取视频第一帧缩略图的实现
2020/11/11 HTML / CSS
美国在线鞋类零售商:LifeStride
2019/06/09 全球购物
荷兰家电销售网站:Welhof
2020/12/08 全球购物
最新大学毕业求职简历的自我评价
2013/10/18 职场文书
预备党员入党自我评价范文
2014/03/10 职场文书
授权委托书格式
2014/07/31 职场文书
班组拓展活动方案
2014/08/14 职场文书
2016年优秀团员事迹材料
2016/02/25 职场文书
浅谈mysql增加索引不生效的几种情况
2021/06/23 MySQL