Maison  >  Article  >  développement back-end  >  Parlons de la façon dont Golang appelle php7

Parlons de la façon dont Golang appelle php7

藏色散人
藏色散人avant
2021-09-20 16:30:172330parcourir

Cet article est écrit par la colonne tutoriel go language pour présenter comment appeler php7 en golang. J'espère qu'il sera utile aux amis dans le besoin !

en utilisant 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_requestModifié basé sur https://github.com/deuill/go-php, Reason pour fork (https://github.com/deuill/go-php/issues/32)

Exécuter le fichier 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()
    }
}

Le contenu de /tmp/index.php Pour

rrreee

Eval, valeur de retour

rrreee
La propriété du cycle de vie de la valeur renvoyée est le programme Golang, nous sommes donc responsables de DestroyValue

Définir les variables globales pour transmettre les paramètres

rrreee passez-le Le cycle de vie des paramètres est contrôlé par PHP, et la mémoire sera libérée à l'arrêt de la requête.

Rappel PHP Golang

rrreee

Journal des erreurs PHP

rrreee
Le contenu de /tmp/php.ini est rrreee🎜L'erreur sera affichée vers /tmp/php-error.log. L'appel direct de error_log affichera simultanément une autre copie vers stderr🎜

Entrée et sortie HTTP

rrreee🎜Toutes les variables super globales PHP seront initialisées à la valeur de la requête transmise, y compris le contenu de 🎜rrreee🎜echo, http Le code et l'en-tête http seront réécrits dans le ResponseWriter entrant🎜

fastcgi_finish_request

🎜PHP-FPM Une fonction très couramment utilisée est fastcgi_finish_request, qui est utilisée pour effectuer une complétion asynchrone dans Des choses PHP. Cette fonction globale spéciale doit prendre en charge 🎜rrreee🎜La fonction réelle consiste à envoyer la sortie à ResposneWriter à l'avance afin que l'appelant connaisse le résultat. Cela n’a en réalité aucun impact sur l’exécution du processus en cours, mais affecte uniquement le résultat. 🎜🎜🎜Apprentissage recommandé : "🎜tutoriel golang🎜"🎜🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer