PHP 怎么Go调PHP

wen PHP项目 1

本文目录导读:

PHP 怎么Go调PHP

  1. 通过命令行调用 PHP(最直接)
  2. 通过 HTTP 调用 PHP 服务(推荐)
  3. 使用 PHP-FPM (FastCGI) 协议
  4. 使用消息队列(异步调用)
  5. 使用 PHP 内置服务器(开发环境)
  6. 最佳实践建议

PHP 和 Go 是两种不同的编程语言,Go 调用 PHP 通常有两种场景:Go 代码中调用 PHP 脚本,或者 Go 程序通过 HTTP 请求调用 PHP 服务,以下是几种常见的方法:

通过命令行调用 PHP(最直接)

PHP 已安装且可执行文件在 PATH 中,可以使用 execos/exec 调用:

package main
import (
    "fmt"
    "os/exec"
    "strings"
)
func main() {
    // 简单调用 PHP 脚本
    cmd := exec.Command("php", "-r", `echo "Hello from PHP!";`)
    output, err := cmd.Output()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(output))
    // 调用 PHP 文件
    cmd = exec.Command("php", "/path/to/your/script.php")
    output, err = cmd.Output()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(output))
    // 带参数调用
    cmd = exec.Command("php", "/path/to/your/script.php", "arg1", "arg2")
    output, err = cmd.Output()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(output))
}

PHP 脚本示例 (script.php):

<?php
// 接收命令行参数
$arg1 = $argv[1] ?? 'default1';
$arg2 = $argv[2] ?? 'default2';
echo "Argument 1: $arg1, Argument 2: $arg2\n";
// 输出 JSON 结果
$result = ['name' => 'John', 'age' => 30];
echo json_encode($result);
?>
// Go 中解析 JSON 结果
var data map[string]interface{}
if err := json.Unmarshal(output, &data); err != nil {
    fmt.Println("JSON parse error:", err)
    return
}
fmt.Printf("Name: %s, Age: %v\n", data["name"], data["age"])

通过 HTTP 调用 PHP 服务(推荐)

最常见的做法是通过 HTTP/REST API 调用 PHP Web 服务:

package main
import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)
func main() {
    // GET 请求
    resp, err := http.Get("http://localhost:8080/api/users?name=John")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println("GET Response:", string(body))
    // POST 请求
    postData := map[string]interface{}{
        "name":  "John",
        "email": "john@example.com",
    }
    jsonData, _ := json.Marshal(postData)
    resp, err = http.Post("http://localhost:8080/api/users", 
                         "application/json", 
                         bytes.NewBuffer(jsonData))
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()
    body, _ = ioutil.ReadAll(resp.Body)
    fmt.Println("POST Response:", string(body))
}

PHP REST API 示例 (api.php):

<?php
header('Content-Type: application/json');
switch ($_SERVER['REQUEST_METHOD']) {
    case 'GET':
        // 处理 GET 请求
        $name = $_GET['name'] ?? 'Guest';
        echo json_encode(['message' => "Hello, $name!"]);
        break;
    case 'POST':
        // 处理 POST 请求
        $input = json_decode(file_get_contents('php://input'), true);
        echo json_encode(['received' => $input, 'status' => 'success']);
        break;
    default:
        http_response_code(405);
        echo json_encode(['error' => 'Method not allowed']);
}
?>

使用 PHP-FPM (FastCGI) 协议

对于更高效的调用,可以使用 FastCGI 协议:

package main
import (
    "fmt"
    "github.com/yookoala/gofast"
    "net"
)
func main() {
    // 连接到 PHP-FPM
    conn, err := net.Dial("tcp", "127.0.0.1:9000")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer conn.Close()
    // 创建 FastCGI 客户端
    client := gofast.NewClient(conn)
    // 调用 PHP 脚本
    response, err := client.Request(
        gofast.NewRequest(),
        "127.0.0.1:9000",
        "/path/to/script.php",
        nil, // 请求参数
    )
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(response))
}

使用消息队列(异步调用)

适合异步处理场景:

package main
import (
    "fmt"
    "github.com/streadway/amqp"
)
func main() {
    // 连接到 RabbitMQ
    conn, _ := amqp.Dial("amqp://guest:guest@localhost:5672/")
    defer conn.Close()
    ch, _ := conn.Channel()
    defer ch.Close()
    q, _ := ch.QueueDeclare("php_tasks", false, false, false, false, nil)
    // 发送消息给 PHP 消费者
    body := `{"action": "process_data", "data": "some data"}`
    err := ch.Publish("", q.Name, false, false, amqp.Publishing{
        ContentType: "application/json",
        Body:        []byte(body),
    })
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Message sent to PHP worker")
}

使用 PHP 内置服务器(开发环境)

package main
import (
    "fmt"
    "net/http"
    "os/exec"
    "time"
)
func main() {
    // 启动 PHP 内置服务器
    cmd := exec.Command("php", "-S", "127.0.0.1:8080", "-t", "/path/to/php/directory")
    cmd.Start()
    defer cmd.Process.Kill()
    // 等待服务器启动
    time.Sleep(2 * time.Second)
    // 调用 PHP 服务
    resp, err := http.Get("http://127.0.0.1:8080/index.php")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()
    fmt.Println("PHP server response:", resp.Status)
}

最佳实践建议

  1. HTTP API 方式:推荐用于生产环境,解耦性好,分布式支持
  2. 命令行方式:适合简单的数据处理或脚本执行
  3. 异步消息:适合耗时任务或批处理
  4. 性能考虑:如果是高性能要求,建议用 Go 重写 PHP 逻辑,或使用 gRPC

选择哪种方式取决于你的具体需求、性能要求和部署环境,大多数情况下,HTTP REST API 是最通用和可维护的方案

抱歉,评论功能暂时关闭!