Heim  >  Artikel  >  Backend-Entwicklung  >  Lassen Sie uns darüber sprechen, wie Golang PHP7 aufruft

Lassen Sie uns darüber sprechen, wie Golang PHP7 aufruft

藏色散人
藏色散人nach vorne
2021-09-20 16:30:172330Durchsuche

Dieser Artikel wurde von der Go-SpracheTutorial-Kolumne geschrieben, um vorzustellen, wie man PHP7 in Golang aufruft. Ich hoffe, dass er Freunden in Not hilfreich sein wird!

mit https://github.com/taowen/go-php7 https://github.com/taowen/go-php7
基于 https://github.com/deuill/go-php 修改而来,fork缘由(https://github.com/deuill/go-php/issues/32)

执行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 &#39;hello&#39;;")
    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(&#39;hello&#39;);
    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_requestModifiziert basierend auf https://github.com/deuill/go-php, Reason für fork (https://github.com/deuill/go-php/issues/32)

PHP-Datei ausführen

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()
    }
}

Der Inhalt von /tmp/index.php Für

rrreee

Eval, Rückgabewert

rrreee
Der Lebenszyklusbesitz des zurückgegebenen Werts liegt beim Golang-Programm, daher sind wir für DestroyValue verantwortlich

Legen Sie globale Variablen fest, um Parameter zu übergeben

rrreee weitergeben Der Lebenszyklus der Parameter wird von PHP gesteuert und der Speicher wird freigegeben, wenn die Anforderung beendet wird.

PHP-Callback Golang

rrreee

PHP-Fehlerprotokoll

rrreee
Der Inhalt von /tmp/php.ini ist rrreee🎜Der Fehler wird ausgegeben /tmp/php-error.log. Durch den direkten Aufruf von error_log wird gleichzeitig eine weitere Kopie an stderr ausgegeben echo, http Der Code und der http-Header werden an den eingehenden ResponseWriter zurückgeschrieben🎜

fastcgi_finish_request

🎜PHP-FPM Eine sehr häufig verwendete Funktion ist fastcgi_finish_request, die für einige Zwecke verwendet wird asynchrone Vervollständigung in PHP-Dingen. Diese spezielle globale Funktion muss 🎜rrreee🎜 unterstützen. Die eigentliche Funktion besteht darin, die Ausgabe vorab an ResposneWriter auszugeben, damit der Aufrufer das Ergebnis kennt. Es hat eigentlich keinen Einfluss auf die Ausführung des aktuellen Prozesses, sondern nur auf die Ausgabe. 🎜🎜🎜Empfohlenes Lernen: „🎜Golang-Tutorial🎜“🎜🎜

Das obige ist der detaillierte Inhalt vonLassen Sie uns darüber sprechen, wie Golang PHP7 aufruft. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen