Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

betterde/voyager-php

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Voyager PHP Wrapper

Voyager PHP Wrapper is a Composer package for the voyager PHP extension. It adds auto-loadable PHP stubs and a small object-oriented facade around the native runtime function and method redefinition APIs.

The underlying extension lives in /Users/George/Develop/C/voyager and provides the native functions:

  • voyager_function_redefine()
  • voyager_method_redefine()

This package exposes those functions to Composer projects and provides Betterde\Voyager\Debug for a cleaner call style.

How It Works

How Voyager replaces code with Zend HashTables

Features

  • Redefine existing user-defined functions at runtime.
  • Redefine existing methods on user-defined classes at runtime.
  • Use closures directly for replacement implementations.
  • Use string argument/body mode for dynamic code generation.
  • Preserve a Composer-friendly developer experience with stubs and PSR-4 autoloading.
  • Provide readable flag constants for method visibility/static/reference behavior.

Requirements

  • PHP 8.1 or higher
  • Composer
  • The voyager PHP extension installed and enabled

The Composer package requires ext-voyager, so composer install will fail if the extension is not available to the PHP binary Composer is using.

Installing the Native Extension

Build and install the C extension first:

git clone https://github.com/betterde/voyager
cd voyager
phpize
./configure --enable-voyager
make
make install

Then enable it in your php.ini:

extension=voyager

You can also load it temporarily for a single command:

php -d extension=voyager.so your-script.php

Verify that PHP can see the extension:

php -m | grep voyager

Installing This Package

Install the wrapper with Composer:

composer require betterde/voyager

For local development from this repository:

composer install

Usage

Redefine a Function

<?php

use Betterde\Voyager\Debug;

require __DIR__ . '/vendor/autoload.php';

function greet(string $name): string
{
    return "Hello, {$name}!";
}

echo greet('World'); // Hello, World!

Debug::functionRedefine('greet', function (string $name): string {
    return "Hi, {$name}! This function was redefined.";
});

echo greet('World'); // Hi, World! This function was redefined.

Redefine a Method

<?php

use Betterde\Voyager\Debug;

require __DIR__ . '/vendor/autoload.php';

class UserService
{
    public function findUser(int $id): array
    {
        return ['id' => $id, 'name' => 'database user'];
    }
}

$service = new UserService();

Debug::methodRedefine(UserService::class, 'findUser', function (int $id): array {
    return ['id' => $id, 'name' => 'debug user'];
});

var_dump($service->findUser(1));

Use $this in a Redefined Method

<?php

use Betterde\Voyager\Debug;

class Counter
{
    public int $value = 0;

    public function increment(): int
    {
        return ++$this->value;
    }
}

$counter = new Counter();

Debug::methodRedefine(Counter::class, 'increment', function (): int {
    $this->value += 10;

    return $this->value;
});

echo $counter->increment(); // 10
echo $counter->increment(); // 20

String Body Mode

The native extension also supports defining the replacement with an argument list string and a code body string. The Debug facade keeps that mode available.

<?php

use Betterde\Voyager\Debug;

function normalize_name(string $name): string
{
    return trim($name);
}

Debug::functionRedefine(
    'normalize_name',
    '$name',
    'return strtoupper(trim($name));',
);

echo normalize_name(' voyager '); // VOYAGER

For methods, pass optional flags as the fifth argument:

Debug::methodRedefine(
    UserService::class,
    'findUser',
    '$id',
    'return ["id" => $id, "name" => "generated user"];',
    Debug::FLAG_PUBLIC,
);

API

Betterde\Voyager\Debug::functionRedefine()

public static function functionRedefine(
    string $functionName,
    Closure|string $closureOrArgs,
    ?string $code = null,
    ?bool $returnByReference = null,
    ?string $docComment = null,
): bool

Redefines an existing function.

  • Closure mode: pass a Closure as the second argument.
  • String mode: pass an argument list string as the second argument and a PHP code body string as the third argument.

Betterde\Voyager\Debug::methodRedefine()

public static function methodRedefine(
    string $className,
    string $methodName,
    Closure|string $closureOrArgs,
    ?string $code = null,
    int $flags = 0,
    ?string $docComment = null,
): bool

Redefines an existing class method.

Available facade flags:

Constant Value Meaning
Debug::FLAG_PUBLIC 0x0100 Public method
Debug::FLAG_PROTECTED 0x0200 Protected method
Debug::FLAG_PRIVATE 0x0400 Private method
Debug::FLAG_STATIC 0x0001 Static method
Debug::FLAG_RETURN_REFERENCE 0x0800 Return by reference

Flags may be combined with bitwise OR:

Debug::FLAG_PUBLIC | Debug::FLAG_STATIC

Native Functions

This package also autoloads stubs for the native functions, so IDEs and static analysis tools can understand them:

voyager_function_redefine(
    string $function_name,
    Closure|string $closure_or_args,
    ?string $code_or_doc_comment = null,
    ?bool $return_by_reference = null,
    ?string $doc_comment = null
): bool
voyager_method_redefine(
    string $class_name,
    string $method_name,
    Closure|string $closure_or_args,
    int|string|null $code_or_flags = null,
    int|string|null $flags_or_doc_comment = null,
    ?string $doc_comment = null
): bool

Important Notes

Voyager changes PHP runtime behavior at the Zend engine level. Treat it as a debugging, diagnostics, instrumentation, and emergency hot-fix tool.

  • Redefine only functions and methods you own and understand.
  • Avoid redefining code that is currently on the call stack.
  • Be careful with long-running workers, preloaded code, opcache, and production traffic.
  • Prefer narrow, reversible changes and add logging around live diagnostics.
  • Do not use runtime redefinition as a substitute for a normal deployment flow.

Project Structure

.
├── composer.json
├── src/
│   └── Debug.php
└── stubs/
    └── voyager_functions.php

About

A Composer package wrapper for the Voyager PHP extension, providing runtime function and method redefinition APIs for debugging, hot-fixing, instrumentation, and live system diagnostics.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.