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函数解决SQL injection
Oct 09 PHP
关于查看MSSQL 数据库 用户每个表 占用的空间大小
Jun 21 PHP
PHP文件缓存内容保存格式实例分析
Aug 20 PHP
PHP文件上传判断file是否己选择上传文件的方法
Nov 10 PHP
php中strtotime函数用法详解
Nov 15 PHP
Session 失效的原因汇总及解决丢失办法
Sep 30 PHP
学习php设计模式 php实现备忘录模式(Memento)
Dec 09 PHP
yii实现model添加默认值的方法(2种方法)
Jan 06 PHP
php判断邮箱地址是否存在的方法
Feb 13 PHP
PHP多种序列化/反序列化的方法详解
Jun 23 PHP
Thinkphp开发--集成极光推送
Sep 15 PHP
YII2框架中查询生成器Query()的使用方法示例
Mar 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中autoload的用法总结
2013/11/08 PHP
php打包压缩文件之ZipArchive方法用法分析
2016/04/30 PHP
简单理解PHP的面向对象编程方式
2016/05/17 PHP
javascript中通过arguments参数伪装方法重载
2014/10/08 Javascript
JS实现图片产生波纹一样flash效果的方法
2015/02/27 Javascript
AngularJs动态加载模块和依赖注入详解
2016/01/11 Javascript
JavaScript实现弹出DIV层同时页面背景渐变成半透明效果
2016/03/25 Javascript
非常棒的jQuery图片轮播效果
2016/04/17 Javascript
js倒计时简单实现代码
2016/08/11 Javascript
Javarscript中模块(module)、加载(load)与捆绑(bundle)详解
2017/05/28 Javascript
vue 打包后的文件部署到express服务器上的方法
2017/08/09 Javascript
Vue 中文本内容超出规定行数后展开收起的处理的实现方法
2019/04/28 Javascript
layui实现三级联动效果
2019/07/26 Javascript
使用layui 的layedit定义自己的toolbar方法
2019/09/18 Javascript
基于layui table返回的值的多级嵌套的解决方法
2019/09/19 Javascript
用js实现放大镜效果
2020/10/28 Javascript
python单链表实现代码实例
2013/11/21 Python
Python随机生成一个6位的验证码代码分享
2015/03/24 Python
python 调用win32pai 操作cmd的方法
2017/05/28 Python
Python实现的自定义多线程多进程类示例
2018/03/23 Python
Anaconda 离线安装 python 包的操作方法
2018/06/11 Python
详解numpy矩阵的创建与数据类型
2019/10/18 Python
python 两个一样的字符串用==结果为false问题的解决
2020/03/12 Python
白兰氏健康Mall:BRAND’S
2017/11/13 全球购物
豪华床上用品 :Jennifer Adams
2019/09/15 全球购物
JENNIFER BEHR官网:各种耳环和发饰
2020/06/07 全球购物
监理资料员岗位职责
2014/01/03 职场文书
大专生自我评价
2014/01/28 职场文书
日语专业毕业生自荐书
2014/06/18 职场文书
教师党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
公司表扬信格式
2015/05/04 职场文书
创业计划书之情侣餐厅
2019/09/29 职场文书
python基于tkinter制作m3u8视频下载工具
2021/04/24 Python
python实现三次密码验证的示例
2021/04/29 Python
使用python向MongoDB插入时间字段的操作
2021/05/18 Python
如何使用SQL Server语句创建表
2022/04/12 SQL Server