golang 调用 php7详解及实例
执行php文件
funcTest_exec(t*testing.T){ engine.Initialize() ctx:=&engine.Context{ Output:os.Stdout, } err:=engine.RequestStartup(ctx) iferr!=nil{ fmt.Println(err) } deferengine.RequestShutdown(ctx) err=ctx.Exec("/tmp/index.php") iferr!=nil{ fmt.Println(err) } }
其中/tmp/index.php的内容为
<?php echo("hello\n");
Eval,返回值
funcTest_eval(t*testing.T){ engine.Initialize() ctx:=&engine.Context{} err:=engine.RequestStartup(ctx) iferr!=nil{ fmt.Println(err) } deferengine.RequestShutdown(ctx) val,err:=ctx.Eval("return'hello';") iferr!=nil{ fmt.Println(err) } deferengine.DestroyValue(val) ifengine.ToString(val)!="hello"{ t.FailNow() } }
返回的value的生命周期所有权是golang程序,所以我们要负责DestroyValue
设置全局变量来传参
funcTest_argument(t*testing.T){ engine.Initialize() ctx:=&engine.Context{} err:=engine.RequestStartup(ctx) iferr!=nil{ fmt.Println(err) } deferengine.RequestShutdown(ctx) err=ctx.Bind("greeting","hello") iferr!=nil{ fmt.Println(err) } val,err:=ctx.Eval("return$greeting;") iferr!=nil{ fmt.Println(err) } deferengine.DestroyValue(val) ifengine.ToString(val)!="hello"{ t.FailNow() } }
传递进去的参数的生命周期是php控制的,在requestshutdown的时候内存会被释放。
PHP回调Golang
typegreetingProviderstruct{ greetingstring } func(provider*greetingProvider)GetGreeting()string{ returnprovider.greeting } funcnewGreetingProvider(args[]interface{})interface{}{ return&greetingProvider{ greeting:args[0].(string), } } funcTest_callback(t*testing.T){ engine.Initialize() ctx:=&engine.Context{} err:=engine.RequestStartup(ctx) iferr!=nil{ fmt.Println(err) } deferengine.RequestShutdown(ctx) err=engine.Define("GreetingProvider",newGreetingProvider) iferr!=nil{ fmt.Println(err) } val,err:=ctx.Eval(` $greetingProvider=newGreetingProvider('hello'); return$greetingProvider->GetGreeting();`) iferr!=nil{ fmt.Println(err) } deferengine.DestroyValue(val) ifengine.ToString(val)!="hello"{ t.FailNow() } }
PHP错误日志
funcTest_log(t*testing.T){ engine.PHP_INI_PATH_OVERRIDE="/tmp/php.ini" engine.Initialize() ctx:=&engine.Context{ Log:os.Stderr, } err:=engine.RequestStartup(ctx) iferr!=nil{ fmt.Println(err) } deferengine.RequestShutdown(ctx) _,err=ctx.Eval("error_log('hello',4);trigger_error('sentfromgolang',E_USER_ERROR);") iferr!=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输入输出
funcTest_http(t*testing.T){ engine.Initialize() recorder:=httptest.NewRecorder() ctx:=&engine.Context{ Request:httptest.NewRequest("GET","/hello",nil), ResponseWriter:recorder, } err:=engine.RequestStartup(ctx) iferr!=nil{ fmt.Println(err) } deferengine.RequestShutdown(ctx) _,err=ctx.Eval("echo($_SERVER['REQUEST_URI']);") iferr!=nil{ fmt.Println(err) } body,err:=ioutil.ReadAll(recorder.Result().Body) iferr!=nil{ fmt.Println(err) } ifstring(body)!="/hello"{ t.FailNow() } }
所有的PHP超级全局变量都会被初始化为传递进去的Request的值,包括
$_SERVER $_GET $_POST $_FILE $_COOKIE $_ENV
echo的内容,httpcode和httpheader会被写回到传入的ResponseWriter
fastcgi_finish_request
PHP-FPM很常用的一个功能是fastcgi_finish_request,用于在php里做一些异步完成的事情。这个特殊的全局函数必须支持
funcTest_fastcgi_finish_reqeust(t*testing.T){ engine.Initialize() buffer:=&bytes.Buffer{} ctx:=&engine.Context{ Output:buffer, } err:=engine.RequestStartup(ctx) iferr!=nil{ fmt.Println(err) } deferengine.RequestShutdown(ctx) ctx.Eval("ob_start();echo('hello');") ifbuffer.String()!=""{ t.FailNow() } ctx.Eval("fastcgi_finish_request();") ifbuffer.String()!="hello"{ t.FailNow() } }
实际的作用就是把output提前输出到ResposneWriter里去,让调用方知道结果。对于当前进程的执行其实是没有影响的,只是影响了output。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!