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
我的论坛源代码(一)
Oct 09 PHP
建站常用13种PHP开源CMS比较
Aug 23 PHP
php实现的遍历文件夹下所有文件,编辑删除
Jan 05 PHP
php递归实现无限分类生成下拉列表的函数
Aug 08 PHP
PHP数组的交集array_intersect(),array_intersect_assoc(),array_inter_key()函数的小问题
May 29 PHP
PHP利用func_get_args和func_num_args函数实现函数重载实例
Nov 12 PHP
php实现的操作excel类详解
Jan 15 PHP
thinkPHP3.2.2框架行为扩展及demo示例
Jun 19 PHP
PHP安装memcache扩展的步骤讲解
Feb 14 PHP
PHP实现的权重算法示例【可用于游戏根据权限来随机物品】
Feb 15 PHP
PHP中str_split()函数的用法讲解
Apr 11 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创建基本身份认证站点的方法详解
2013/06/08 PHP
php实现Mongodb自定义方式生成自增ID的方法
2015/03/23 PHP
基于php实现随机合并数组并排序(原排序)
2015/11/26 PHP
CakePHP框架Model函数定义方法示例
2017/08/04 PHP
PHP实现websocket通信的方法示例
2018/08/28 PHP
ExtJS 2.0 实用简明教程之布局概述
2009/04/29 Javascript
javascript 写类方式之十
2009/07/05 Javascript
setTimeout和setInterval的区别你真的了解吗?
2011/03/31 Javascript
基于jquery库的tab新形式使用
2012/11/16 Javascript
jquery1.9 下检测浏览器类型和版本的方法
2013/12/26 Javascript
玩转方法:call和apply
2014/05/08 Javascript
node.js中的fs.fstat方法使用说明
2014/12/15 Javascript
JavaScript基础函数整理汇总
2015/01/30 Javascript
剖析Node.js异步编程中的回调与代码设计模式
2016/02/16 Javascript
网页中JS函数自动执行常用三种方法
2016/03/30 Javascript
jQuery Ztree行政地区树状展示(点击加载)
2016/11/09 Javascript
ionic2打包android时gradle无法下载的解决方法
2017/04/05 Javascript
微信小程序仿淘宝热搜词在搜索框中轮播功能
2020/01/21 Javascript
JavaScript大数相加相乘的实现方法实例
2020/10/18 Javascript
[02:05]2014DOTA2西雅图邀请赛 老队长全明星大猜想谁不服就按进显示器
2014/07/08 DOTA
[00:56]跨越时空加入战场 全新祈求者身心“失落奇艺侍祭”展示
2019/07/20 DOTA
将Python的Django框架与认证系统整合的方法
2015/07/24 Python
Python画图学习入门教程
2016/07/01 Python
TensorFlow神经网络优化策略学习
2018/03/09 Python
django的model操作汇整详解
2019/07/26 Python
解决django-xadmin列表页filter关联对象搜索问题
2019/11/15 Python
TensorFlow命名空间和TensorBoard图节点实例
2020/01/23 Python
Python爬虫实战案例之爬取喜马拉雅音频数据详解
2020/12/07 Python
termux中matplotlib无法显示中文问题的解决方法
2021/01/11 Python
Omio俄罗斯:一次搜索公共汽车、火车和飞机的机票
2018/11/17 全球购物
区域销售经理岗位职责
2013/12/10 职场文书
财务总监管理职责范文
2014/03/09 职场文书
政治学求职信
2014/06/03 职场文书
学前班语言教学计划
2015/01/20 职场文书
我们的节日中秋节活动总结
2015/03/23 职场文书
学校捐书活动总结
2015/05/08 职场文书