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面试题附答案
Jan 07 PHP
php curl获取网页内容(IPV6下超时)的解决办法
Jul 16 PHP
php实现把数组按指定的个数分隔
Feb 17 PHP
php中调用其他系统http接口的方法说明
Feb 28 PHP
ThinkPHP的L方法使用简介
Jun 18 PHP
浅析iis7.5安装配置php环境
May 10 PHP
php实现贪吃蛇小游戏
Jul 26 PHP
利用php-cli和任务计划实现刷新token功能的方法
May 03 PHP
PHP+Ajax实现的无刷新分页功能详解【附demo源码下载】
Jul 03 PHP
thinkphp分页集成实例
Jul 24 PHP
php使用curl模拟多线程实现批处理功能示例
Jul 25 PHP
php pdo连接数据库操作示例
Nov 18 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网上商城购物车设计代码分享
2012/02/15 PHP
浅析php变量修饰符static的使用
2013/06/28 PHP
PHP SPL标准库之SplFixedArray使用实例
2015/05/12 PHP
PHP生成随机字符串实例代码(字母+数字)
2019/09/11 PHP
php的instanceof和判断闭包Closure操作示例
2020/01/26 PHP
php实现统计IP数及在线人数的示例代码
2020/07/22 PHP
javascript 24小时弹出一次的代码(利用cookies)
2009/09/03 Javascript
javascript 跨浏览器开发经验总结(五) js 事件
2010/05/19 Javascript
JavaScript中的property和attribute介绍
2011/12/26 Javascript
JSON 数据格式介绍
2012/01/13 Javascript
javascript调试过程中找不到哪里出错的可能原因
2013/12/16 Javascript
Javascript技术栈中的四种依赖注入详解
2016/02/23 Javascript
js enter键激发事件实例代码
2016/08/17 Javascript
使用JS实现图片展示瀑布流效果(简单实例)
2016/09/06 Javascript
JavaScript 是什么意思
2016/09/22 Javascript
概述javascript在Google IE中的调试技巧
2016/11/24 Javascript
使用jQuery实现一个类似GridView的编辑,更新,取消和删除的功能
2017/03/15 Javascript
vue-router实现嵌套路由的讲解
2019/01/19 Javascript
浅探express路由和中间件的实现
2019/09/30 Javascript
通过实例了解Render Props回调地狱解决方案
2020/11/04 Javascript
Vue2.x和Vue3.x的双向绑定原理详解
2020/11/05 Javascript
[04:44]DOTA2西游记战队视频彩蛋流出 师徒开黑巧遇林书豪
2016/08/03 DOTA
学习python (2)
2006/10/31 Python
python程序封装为win32服务的方法
2021/03/07 Python
解决Pycharm 包已经下载,但是运行代码提示找不到模块的问题
2019/08/31 Python
装上这 14 个插件后,PyCharm 真的是无敌的存在
2021/01/11 Python
总结30个CSS3选择器
2017/04/13 HTML / CSS
新加坡网上化妆品店:Best Buy World
2018/05/18 全球购物
最新远光软件笔试题面试题内容
2013/11/08 面试题
.NET概念性的面试题
2012/02/29 面试题
村级个人对照检查材料
2014/08/22 职场文书
大学感恩节活动策划方案
2014/10/11 职场文书
整改报告怎么写
2014/11/06 职场文书
运动会新闻报道稿
2015/07/22 职场文书
婚宴致辞
2015/07/28 职场文书
小学生安全教育心得体会
2016/01/15 职场文书