Skip to content

async-php/async-php

Repository files navigation

Async-PHP

Version License PHP Rust

A high-performance async runtime for PHP, built with Rust and powered by Tokio. Brings true async/await capabilities to PHP using Fibers.

English | 简体中文

✨ Features

🚀 Async I/O

  • Non-blocking file and network operations
  • Lightweight coroutines using PHP 8.1+ Fibers
  • Built on Tokio async runtime for maximum performance

🌐 HTTP Client & Server

  • HTTP/1.1, HTTP/2, and HTTP/3 (QUIC) support
  • Zero-copy I/O optimization
  • Connection pooling
  • Streaming request/response bodies
  • PSR-15 middleware support

💾 Async Database (PDO)

  • Full PDO compatibility with async operations
  • MySQL and PostgreSQL support
  • Connection pooling
  • Prepared statements with parameter binding
  • Transaction support

🔌 Network Programming

  • TCP, UDP, Unix domain sockets
  • TLS/SSL support with custom certificates
  • QUIC protocol (for HTTP/3)
  • Non-blocking socket operations

Advanced Features

  • Channels for inter-coroutine communication
  • Timers and delays
  • Context API for coroutine-local storage
  • Concurrent task execution
  • Redis client with connection pooling and async operations

📦 Installation

Prerequisites

  • PHP 8.1 or higher with Fibers support
  • Rust 1.70 or higher
  • Cargo (Rust package manager)

Build from Source

# Clone the repository
git clone https://github.com/your-org/async-php.git
cd async-php

# Build the extension (release mode)
cargo build --release

# The compiled extension will be at:
# target/release/libasync_php.dylib (macOS)
# target/release/libasync_php.so (Linux)
# target/release/async_php.dll (Windows)

Load the Extension

# Run PHP with the extension loaded
php -d extension=target/release/libasync_php.dylib your_script.php

# Or add to php.ini
extension=path/to/libasync_php.dylib

🚀 Quick Start

Hello World

<?php
use Async\Kernel;
use Async\Time;

Kernel::run(function () {
    echo "Starting...\n";

    // Non-blocking sleep
    Time::sleep(1000); // 1 second

    echo "Done!\n";
});

Concurrent Tasks

<?php
use Async\Kernel;
use Async\Time;

Kernel::run(function () {
    // Spawn concurrent tasks
    go(function () {
        echo "Task 1 started\n";
        Time::sleep(500);
        echo "Task 1 completed\n";
    });

    go(function () {
        echo "Task 2 started\n";
        Time::sleep(300);
        echo "Task 2 completed\n";
    });

    // Wait for tasks to complete
    Time::sleep(1000);
});

HTTP Client

<?php
use Async\Kernel;
use Async\Network\Http\Client;

Kernel::run(function () {
    $client = Client::new();

    // Make async HTTP request
    $response = $client->get('https://api.github.com/users/github');

    echo "Status: " . $response->status() . "\n";
    echo "Body: " . $response->text() . "\n";
});

HTTP Server

<?php
use Async\Kernel;
use Async\Network\Http\Server;
use Async\Network\Tcp\Listener;
use Async\Kernel\Network\Http\HttpRequest;
use Async\Kernel\Network\Http\HttpResponse;

Kernel::run(function () {
    $server = new Server();
    $listener = Listener::bind('127.0.0.1:8080');

    echo "Server listening on http://127.0.0.1:8080\n";

    while (true) {
        $conn = $listener->accept();

        go(function() use ($server, $conn) {
            $server->serve($conn, function(HttpRequest $req): HttpResponse {
                $resp = new HttpResponse();
                $resp->setStatus(200);
                $resp->setHeader('Content-Type', 'text/plain');
                $resp->setBody('Hello, World!');
                return $resp;
            });
        });
    }
});

HTTP/3 Server (QUIC)

<?php
use Async\Kernel;
use Async\Kernel\Network\Quic\QuicListener;
use Async\Kernel\Network\Http\Http3Server;
use Async\Kernel\Network\Http\HttpRequest;
use Async\Kernel\Network\Http\HttpResponse;

Kernel::run(function () {
    // HTTP/3 requires TLS certificates
    $listener = QuicListener::bind('127.0.0.1:4433', 'cert.pem', 'key.pem');
    $server = new Http3Server();

    echo "HTTP/3 server listening on https://127.0.0.1:4433\n";

    while (true) {
        $conn = $listener->accept();

        go(function() use ($server, $conn) {
            $server->serve($conn, function(HttpRequest $req): HttpResponse {
                $resp = new HttpResponse();
                $resp->setStatus(200);
                $resp->setHeader('Content-Type', 'text/plain');
                $resp->setBody('Hello from HTTP/3!');
                return $resp;
            });
        });
    }
});

Async Database (PDO)

<?php
use Async\Kernel;

Kernel::run(function () {
    // Create async PDO connection
    $pdo = new \PDO\PDO(
        'mysql:host=localhost;dbname=test',
        'username',
        'password'
    );

    // Execute queries asynchronously
    $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
    $stmt->execute([1]);
    $user = $stmt->fetch();

    echo "User: {$user['name']}\n";
});

Async Redis

<?php
use Async\Kernel;
use Redis\Redis;

Kernel::run(function () {
    // Create Redis client
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);

    // String operations
    $redis->set('name', 'Alice');
    echo $redis->get('name') . "\n"; // Alice

    // Counter operations
    $redis->incr('counter');
    $redis->incrBy('counter', 5);

    // List operations
    $redis->rPush('tasks', 'Task 1', 'Task 2', 'Task 3');
    $tasks = $redis->lRange('tasks', 0, -1);

    // Hash operations
    $redis->hSet('user:1', 'name', 'Bob');
    $redis->hSet('user:1', 'email', '[email protected]');
    $user = $redis->hGetAll('user:1');

    // Set operations
    $redis->sAdd('tags', 'php', 'rust', 'async');
    $tags = $redis->sMembers('tags');

    $redis->close();
});

📚 Documentation

Comprehensive tutorials and guides are available in the tutorials/ directory:

Quick Links

🏗️ Architecture

┌─────────────────────────────────────┐
│        PHP User Code                │
│  (Fiber-based async/await)          │
├─────────────────────────────────────┤
│     PHP Wrapper Classes             │
│  (Async\Network\Http\Client, etc)   │
├─────────────────────────────────────┤
│      Rust Extension (ext-php-rs)    │
│  - Tokio async runtime              │
│  - SQLx for database                │
│  - Hyper for HTTP/1.1 & HTTP/2      │
│  - Quinn + h3 for HTTP/3            │
│  - Reqwest for HTTP client          │
│  - Redis for caching                │
└─────────────────────────────────────┘

⚡ Performance

Async-PHP is built with performance in mind:

  • High Throughput: Handle thousands of concurrent connections
  • Low Latency: Native Rust performance for I/O operations
  • Memory Efficient: Lightweight coroutines using PHP Fibers
  • Zero-Copy: Efficient data transfer without unnecessary copies
  • Connection Pooling: Reuse connections for databases and HTTP clients

🧪 Testing

Run the examples to test the functionality:

# HTTP client test
php -d extension=target/release/libasync_php.dylib examples/http_client_test.php

# HTTP server test
php -d extension=target/release/libasync_php.dylib examples/http_test_simple.php

# HTTP/3 server test (requires TLS certificates)
php -d extension=target/release/libasync_php.dylib examples/http3_server_test.php

# PDO test (requires database)
php -d extension=target/release/libasync_php.dylib examples/pdo_live_test.php

# Redis test (requires Redis server)
php -d extension=target/release/libasync_php.dylib examples/redis_test.php

🔧 Development

Project Structure

async-php/
├── src/                    # Rust source code
│   ├── http/              # HTTP client & server
│   ├── net/               # Network (TCP, UDP, TLS, QUIC)
│   ├── pdo/               # Async PDO implementation
│   ├── io/                # I/O abstractions
│   └── lib.rs             # Main entry point
├── src-php/               # PHP wrapper classes
│   ├── Async/             # Main namespace
│   ├── PDO/               # PDO namespace
│   └── autoload.php       # Autoloader
├── examples/              # Working examples
├── tutorials/             # Documentation
├── Cargo.toml             # Rust dependencies
└── README.md              # This file

Building

# Debug build (faster compilation, slower runtime)
cargo build

# Release build (slower compilation, optimized runtime)
cargo build --release

# Run tests
cargo test

# Check code without building
cargo check

🤝 Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

Guidelines

  1. Follow existing code style
  2. Add tests for new features
  3. Update documentation
  4. Ensure all tests pass

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

This project is built on top of excellent open-source libraries:

  • Tokio - Async runtime for Rust
  • ext-php-rs - PHP extension framework for Rust
  • Hyper - HTTP implementation
  • Quinn - QUIC protocol implementation
  • SQLx - Async SQL toolkit
  • Reqwest - HTTP client

📞 Support

🗺️ Roadmap

  • WebSocket support
  • gRPC support
  • Redis support (completed!)
  • More database drivers (SQLite)
  • Async file I/O improvements
  • Performance benchmarks
  • More comprehensive examples

Made with ❤️ using Rust and PHP

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors