{"id":26530062,"url":"https://github.com/davidroman0o/frango","last_synced_at":"2025-06-12T03:36:45.008Z","repository":{"id":283532567,"uuid":"951964336","full_name":"davidroman0O/frango","owner":"davidroman0O","description":"Golang + FrankenPHP = PHP runtime in Golang","archived":false,"fork":false,"pushed_at":"2025-04-29T22:49:37.000Z","size":31138,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-05T20:56:11.247Z","etag":null,"topics":["frankenphp","go","golang","php"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidroman0O.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-20T14:16:49.000Z","updated_at":"2025-04-02T20:58:13.000Z","dependencies_parsed_at":"2025-03-21T04:29:34.668Z","dependency_job_id":"380f90eb-7cfd-4073-b56c-ba3c5dfd97ca","html_url":"https://github.com/davidroman0O/frango","commit_stats":null,"previous_names":["davidroman0o/go-php","davidroman0o/gophp","davidroman0o/frango"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/davidroman0O/frango","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidroman0O%2Ffrango","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidroman0O%2Ffrango/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidroman0O%2Ffrango/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidroman0O%2Ffrango/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidroman0O","download_url":"https://codeload.github.com/davidroman0O/frango/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidroman0O%2Ffrango/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259390482,"owners_count":22850241,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["frankenphp","go","golang","php"],"created_at":"2025-03-21T17:29:20.923Z","updated_at":"2025-06-12T03:36:44.995Z","avatar_url":"https://github.com/davidroman0O.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Frango - PHP Middleware for Go\n\nFrango is a focused, framework-agnostic middleware that integrates PHP into any Go HTTP server using [FrankenPHP](https://github.com/dunglas/frankenphp).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/gopher.png\" width=\"400\" height=\"400\" alt=\"frango Logo\"\u003e\n\u003c/p\u003e\n\n\u003e IT IS STILL WORK IN PROGRESS\n\n## Design Philosophy\n\nFrango is built as a **pure middleware** with no server abstractions. This design:\n\n1. **Maximizes compatibility** - Works with any HTTP server or router\n2. **Minimizes dependencies** - No external dependencies beyond FrankenPHP\n3. **Simplifies integration** - Drop-in middleware pattern fits Go's standard idioms\n4. **Enables flexibility** - Stack PHP processing with other middleware in any order\n\n## Features\n\n- **Pure middleware implementation** - Implements http.Handler for maximum compatibility\n- **Framework adapters** - Specialized adapters for popular frameworks (Chi, Gin, Echo)\n- **Development mode** - Automatic PHP file change detection during development\n- **Path-based routing** - Map URLs to PHP files with fine-grained control\n- **Directory mounting** - Serve entire directories of PHP files with one call\n- **Embedded support** - Embed PHP files directly in your Go binary\n\n## ⚠️ IMPORTANT: Prerequisites\n\nBefore you begin, make sure you have all the prerequisites below. **The library will not work without properly built PHP.**\n\n- Go 1.21 or later\n- PHP 8.2 or later **built with specific flags** (see Building PHP section)\n- Required PHP extensions:\n  - Redis extension (`pecl install redis`)\n  - cURL extension\n- GCC and other build tools for compiling FrankenPHP\n\n### Building PHP for FrankenPHP on macOS\n\nFrankenPHP requires PHP to be built as a static library with ZTS (thread safety) enabled. The standard PHP installation from Homebrew won't work.\n\n1. Install required dependencies:\n```bash\nbrew install libiconv bison brotli re2c pkg-config\necho 'export PATH=\"/opt/homebrew/opt/bison/bin:$PATH\"' \u003e\u003e ~/.zshrc\nsource ~/.zshrc  # Reload shell configuration\n```\n\n2. Get PHP source and configure it:\n```bash\n# Get PHP source\ncd ~ \u0026\u0026 mkdir -p php-build \u0026\u0026 cd php-build\ncurl -LO https://www.php.net/distributions/php-8.2.20.tar.gz\ntar -xzf php-8.2.20.tar.gz\ncd php-8.2.20\n\n# Configure with the correct flags for macOS\n# Note: We're explicitly configuring with minimal extensions to avoid dependency issues\n./configure \\\n    --enable-embed=static \\\n    --enable-zts \\\n    --disable-zend-signals \\\n    --disable-opcache-jit \\\n    --enable-static \\\n    --enable-shared=no \\\n    --with-iconv=/opt/homebrew/opt/libiconv/ \\\n    --without-sqlite3 \\\n    --without-pdo-sqlite \\\n    --disable-dom \\\n    --disable-xml \\\n    --disable-simplexml \\\n    --disable-xmlreader \\\n    --disable-xmlwriter \\\n    --disable-libxml\n```\n\n3. Compile and install PHP:\n```bash\nmake -j\"$(getconf _NPROCESSORS_ONLN)\"\nsudo make install\n```\n\n4. Verify the PHP build:\n```bash\n# Check that the static library was created\nls -la /usr/local/lib/libphp.a\n\n# Check php-config output\nphp-config --includes\nphp-config --ldflags\nphp-config --libs\n\n# The output should include paths to the PHP header files and libraries\n```\n\n### Alternative: Building PHP with Official FrankenPHP Method\n\nIf the above method doesn't work, try using the exact method from the FrankenPHP repository:\n\n1. Clone the FrankenPHP repository and build PHP from there:\n```bash\n# Clone the repository\ngit clone https://github.com/dunglas/frankenphp.git\ncd frankenphp\n\n# Build PHP using the provided script (this will handle everything for you)\n./install.sh\n\n# The script will download, configure and compile PHP with the correct flags\n```\n\n### Running the Application\n\n1. Install Go dependencies:\n```bash\ngo mod tidy\n```\n\n2. Run the application with the correct CGO flags:\n```bash\n# Method 1: Using php-config\nCGO_CFLAGS=$(php-config --includes) CGO_LDFLAGS=\"$(php-config --ldflags) $(php-config --libs)\" go run -tags=nowatcher ./examples/basic\n\n# Method 2: Explicitly setting the paths (try this if Method 1 fails)\nCGO_CFLAGS=\"-I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/Zend -I/usr/local/include/php/TSRM -I/usr/local/include/php/ext\" CGO_LDFLAGS=\"-L/usr/local/lib -lphp\" go run -tags=nowatcher ./examples/basic\n```\n\n## Important Notes About FrankenPHP\n\nBefore using this library, be aware of these FrankenPHP characteristics:\n\n- It doesn't provide a built-in global memory store that persists across multiple PHP requests and workers.\n- It runs PHP scripts using Caddy and a worker pool model, which means:\n  - Each request is processed independently.\n  - PHP memory resets after each request (just like traditional FPM).\n  - There is no global memory space shared between requests by default.\n\n## Installation\n\n```bash\ngo get github.com/davidroman0O/frango\n```\n\n## Quick Start\n\n```go\npackage main\n\nimport (\n    \"log\"\n    \"net/http\"\n    \n    \"github.com/davidroman0O/frango\"\n)\n\nfunc main() {\n    // Create the PHP middleware\n    php, err := frango.New(\n        frango.WithSourceDir(\"./web\"),\n        frango.WithDevelopmentMode(true),\n    )\n    if err != nil {\n        log.Fatalf(\"Error creating PHP middleware: %v\", err)\n    }\n    defer php.Shutdown()\n    \n    // Register PHP endpoints\n    php.HandlePHP(\"/api/users\", \"api/users.php\")\n    php.HandleDir(\"/pages\", \"pages\")\n    \n    // Create standard HTTP mux\n    mux := http.NewServeMux()\n    \n    // Add Go handlers\n    mux.HandleFunc(\"/api/time\", timeHandler)\n    \n    // Use PHP middleware for /api paths\n    mux.Handle(\"/api/\", php.Wrap(http.NotFoundHandler()))\n    \n    // Mount PHP directly for a dedicated path\n    mux.Handle(\"/php/\", http.StripPrefix(\"/php\", php))\n    \n    // Start the server\n    log.Println(\"Server starting on :8080\")\n    http.ListenAndServe(\":8080\", mux)\n}\n```\n\n## Integration Patterns\n\n### Standard net/http\n\n```go\n// Basic usage as middleware\nmux := http.NewServeMux()\nmux.Handle(\"/api/\", php.Wrap(apiHandler))\n\n// Direct mounting\nmux.Handle(\"/php/\", http.StripPrefix(\"/php\", php))\n\nhttp.ListenAndServe(\":8080\", mux)\n```\n\n### Separate PHP and Go Routes\n\nFor complex applications, you may want to clearly separate PHP and Go routes:\n\n```go\n// Create a router for Go API endpoints\napiMux := http.NewServeMux()\napiMux.HandleFunc(\"GET /api/status\", statusHandler)\n\n// Create a router for PHP pages\nphpMux := http.NewServeMux()\nphpMux.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n    php.ServeHTTP(w, r)\n})\n\n// Register PHP files\nphp.HandlePHP(\"/\", \"index.php\")\nphp.HandlePHP(\"/users\", \"users.php\")\n\n// Create a parent router\nrootMux := http.NewServeMux()\nrootMux.Handle(\"/api/\", apiMux)\nrootMux.Handle(\"/\", phpMux)\n\nhttp.ListenAndServe(\":8080\", rootMux)\n```\n\n### Chi Router\n\n```go\nr := chi.NewRouter()\n\n// Mount at a specific path\nr.Mount(\"/php\", php)\n\n// As middleware in a group\nr.Group(func(r chi.Router) {\n    r.Use(php.ForChi())\n    r.Get(\"/api/*\", yourHandler)\n})\n\nhttp.ListenAndServe(\":8080\", r)\n```\n\n### Gin\n\n```go\ng := gin.New()\n\n// Use middleware on specific routes\napiGroup := g.Group(\"/api\")\napiGroup.Use(func(c *gin.Context) {\n    req := c.Request\n    if php.ShouldHandlePHP(req) {\n        php.ServeHTTP(c.Writer, req)\n        c.Abort()\n        return\n    }\n    c.Next()\n})\n\ng.Run(\":8080\")\n```\n\n### Echo\n\n```go\ne := echo.New()\n\n// Use the built-in adapter\ne.Use(php.ForEcho())\n\ne.Start(\":8080\")\n```\n\n## Key Methods\n\n- `New(options...)` - Create a new middleware instance\n- `HandlePHP(pattern, phpFile)` - Register a PHP file at a URL path\n- `HandleDir(prefix, dirPath)` - Register all PHP files in a directory\n- `AddFromEmbed(urlPath, fs, fsPath)` - Add a PHP file from embed.FS\n- `Wrap(next http.Handler)` - Wrap another handler (middleware pattern)\n- `ServeHTTP(w, r)` - Implements http.Handler interface\n- `ShouldHandlePHP(r *http.Request)` - Checks if a request should be handled by PHP\n\n## Configuration Options\n\n```go\nphp, err := frango.New(\n    frango.WithSourceDir(\"./web\"),       // Source directory for PHP files\n    frango.WithDevelopmentMode(true),    // Enable development mode\n    frango.WithLogger(customLogger),     // Custom logger\n)\n```\n\n## Data Injection\n\nYou can inject Go variables into PHP templates:\n\n```go\n// Register a PHP file with dynamic data\nphp.HandleRender(\"/dashboard\", \"dashboard.php\", func(w http.ResponseWriter, r *http.Request) map[string]interface{} {\n    return map[string]interface{}{\n        \"title\": \"Dashboard\",\n        \"user\": map[string]interface{}{\n            \"name\": \"John Doe\",\n            \"role\": \"Admin\",\n        },\n    }\n})\n```\n\nIn PHP, access these variables:\n\n```php\n\u003c?php\n$title = go_var('title', 'Default Title');\n$user = go_var('user', []);\n\necho \"\u003ch1\u003e$title\u003c/h1\u003e\";\necho \"\u003cp\u003eWelcome, {$user['name']}!\u003c/p\u003e\";\n?\u003e\n```\n\n## License\n\nMIT\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidroman0o%2Ffrango","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidroman0o%2Ffrango","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidroman0o%2Ffrango/lists"}