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 相关文章推荐
thinkPHP中create方法与令牌验证实例浅析
Dec 08 PHP
yii使用activeFileField控件实现上传文件与图片的方法
Dec 28 PHP
PHP使用Pear发送邮件(Windows环境)
Jan 05 PHP
php pdo oracle中文乱码的快速解决方法
May 16 PHP
PHP转换文本框内容为HTML格式的方法
Jul 20 PHP
深入理解PHP类的自动载入机制
Sep 16 PHP
CI框架无限级分类+递归的实现代码
Nov 01 PHP
php 三元运算符实例详细介绍
Dec 15 PHP
PHP解耦的三重境界(浅谈服务容器)
Mar 13 PHP
php动态读取数据清除最右边距的方法
Apr 12 PHP
Eclipse PHPEclipse 配置的具体步骤
Aug 08 PHP
php设计模式之观察者模式定义与用法经典示例
Sep 19 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/12/25 PHP
php二分查找二种实现示例
2014/03/12 PHP
ThinkPHP模板IF标签用法详解
2014/07/01 PHP
javascript 写类方式之九
2009/07/05 Javascript
javascript类继承机制的原理分析
2009/09/12 Javascript
JavaScript基础篇之变量作用域、传值、传址的简单介绍与实例
2013/06/29 Javascript
JavaScript Function函数类型介绍
2015/04/08 Javascript
理解javascript对象继承
2016/04/17 Javascript
BootStrap 轮播插件(carousel)支持左右手势滑动的方法(三种)
2016/07/07 Javascript
详解AngularJs中$resource和restfu服务端数据交互
2016/09/21 Javascript
浅析script标签中的defer与async属性
2016/11/30 Javascript
JS中定位 position 的使用实例代码
2017/08/06 Javascript
详解使用PM2管理nodejs进程
2017/10/24 NodeJs
浅析node应用的timing-attack安全漏洞
2018/02/28 Javascript
Vue.js图片预览插件使用详解
2018/08/27 Javascript
vue中的watch监听数据变化及watch中各属性的详解
2018/09/11 Javascript
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
2019/04/14 Javascript
使用JavaScript获取Django模板指定键值数据
2020/05/27 Javascript
Vue循环遍历选项赋值到对应控件的实现方法
2020/06/22 Javascript
在Python的Flask框架下收发电子邮件的教程
2015/04/21 Python
用Python的Django框架来制作一个RSS阅读器
2015/07/22 Python
用python写个自动SSH登录远程服务器的小工具(实例)
2017/06/17 Python
python中的文件打开与关闭操作命令介绍
2018/04/26 Python
python使用opencv驱动摄像头的方法
2018/08/03 Python
Python socket 套接字实现通信详解
2019/08/27 Python
pytest中文文档之编写断言
2019/09/12 Python
python SocketServer源码深入解读
2019/09/17 Python
Django 实现图片上传和下载功能
2020/12/31 Python
惠普香港官方商店:HP香港
2019/04/30 全球购物
Rhone官方网站:男士运动服装、健身服装和高级运动服
2019/05/01 全球购物
美国亚马逊旗下男装网站:East Dane(支持中文)
2019/09/25 全球购物
描述RIP和OSPF区别以及特点
2015/01/17 面试题
三方协议书
2015/01/27 职场文书
房屋质量投诉书
2015/07/02 职场文书
篮球赛新闻稿
2015/07/17 职场文书
关于践行三严三实的心得体会
2016/01/05 职场文书