Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Xphp Laravel Package

xphp-lang/xphp

XPHP extends PHP with static typing and modern language features, compiling back to plain PHP for seamless interoperability with existing code, Composer packages, and Laravel projects.

View on GitHub
Deep Wiki
Context7

Getting Started

XPHP is a young, single-purpose package (14 stars, no dependents at the time of writing), so the first hour should be spent confirming what it actually is before you design around it.

  1. Install and pin.

    composer require xphp-lang/xphp --dev
    

    Install it as a dev dependency first. Nothing in a 0-dependent package should land in require until you've proven it works on your PHP version.

  2. Read the repo before the README. With a package this small, the source is the documentation. Look in this order:

    • composer.json → require.php, autoload, bin, extra.laravel
    • bin/ or src/Console/ → the actual entry points you'll be calling
    • examples/ and tests/ → the only reliable source of working, current API usage
    • CHANGELOG.md / tags → the 2026-07-20 release is recent; check how much churn preceded it
  3. Verify it runs at all. The fastest smoke test is a throwaway script that exercises the package's primary public class:

    // smoke.php
    require 'vendor/autoload.php';
    // instantiate the main compiler/parser/transpiler class from src/ and dump output
    

    If there's a binary, run vendor/bin/xphp --help (or whatever bin declares) and confirm the version matches the tag you installed.

  4. First real use case: pick one small, boring, leaf-node piece of your app — a single value object, a formatter, a config loader — and run it through XPHP end to end. Do not start with a controller or a model. You want a target where a wrong output is obvious and cheap to debug.

  5. Decide the integration surface early. Because XPHP is not Laravel-aware, you're choosing between three shapes: a CLI/build step (safest), a dev-only service provider (convenient), or runtime library calls in production (highest risk). Pick the build step unless you have a strong reason not to.

Implementation Patterns

Compile in a Composer script, commit the output. The pattern that ages best with a low-adoption tool is to treat it as a build artifact generator and never let it run in production:

{
  "scripts": {
    "xphp:build": "xphp build src/X/ --out=generated/",
    "post-autoload-dump": ["@xphp:build"]
  }
}

Generated files go in generated/ and are either committed (reviewable diffs, no CI dependency) or .gitignored and rebuilt in CI. Committed output means a broken XPHP release can't take down a deploy — you just don't upgrade.

Wrap the library in a thin adapter. Don't sprinkle XPHP\... calls through your app. Give it one seam:

// app/Support/Xphp.php
final class Xphp
{
    public static function compile(string $source): string
    {
        // single place that touches the package API
    }
}

When the package inevitably renames or reshapes a method, you change one file. This also makes it trivially mockable in tests.

Expose it as an Artisan command in local only. A dev-only command is the right ergonomic layer for a Laravel team:

// app/Console/Commands/XphpCompile.php — registered only when $this->app->environment('local')
protected $signature = 'xphp:compile {path?} {--watch}';

Guard registration with $this->app->environment('local', 'testing') so it never becomes an accidental production entry point.

Golden-file tests are non-negotiable. Snapshot the generated output for every input you care about:

public function test_compiles_value_object(): void
{
    $this->assertSame(
        file_get_contents(base_path('tests/fixtures/vo.expected.php')),
        Xphp::compile(file_get_contents(base_path('tests/fixtures/vo.xphp')))
    );
}

With no dependents upstream, you are the compatibility test suite. These fixtures are also your upgrade safety net — a bump that changes output shows up as a red test, not a runtime bug.

CI: install pinned, build, diff, fail on drift. Run the build in CI and fail if git diff --exit-code generated/ is non-empty. That catches both "someone forgot to rebuild" and "a dependency update silently changed codegen."

Pipeline shape if you go the CLI route. xphp build in a Makefile/Composer target → linter and static analysis over the generated PHP (not the source) → PHPUnit → deploy. The generated code is what runs, so it's what must pass phpstan and Pint.

Gotchas and Tips

  • Zero dependents is the headline risk. Nobody else is running this in production. Budget for reading the source when something breaks, and pin to an exact version ("xphp-lang/xphp": "1.2.3", not ^1.2) so a minor release can't change your codegen overnight.
  • Check whether you need an extension. If XPHP requires a PECL extension or a patched PHP build, your CI image, your local Docker, and your deploy target all need it. Verify this on day one — it's the single most common reason a package like this dies on arrival.
  • Lockstep the PHP version. Confirm the require.php constraint matches every environment you deploy to. A package releasing in 2026 may target syntax your production PHP doesn't have.
  • Compare generated output to hand-written PHP. When something behaves oddly, read the emitted PHP before you read the XPHP source. Nine times out of ten the bug is visible in the output, and it's far faster than tracing the compiler.
  • Dump the AST/intermediate representation. If the package exposes a parse or debug mode, use it. "My input is valid" and "the compiler understood my input" are different claims.
  • Watch the autoloader. Generated classes need composer dump-autoload after a build, or they need an explicit require. A stale classmap will produce "class not found" errors that look like XPHP bugs and aren't.
  • Don't let it reach hot paths unchecked. Anything that parses or transforms at request time adds latency and a failure mode. If you must call it at runtime, wrap it in try/catch and cache the result by input hash.
  • Extension points are likely undocumented. If the package exposes visitors, node handlers, or a config array, treat each as unstable API. Subclass rather than monkey-patch, and keep customizations in one directory so an upstream refactor is a contained fix.
  • Have an exit ramp. Concretely: how many hours to replace XPHP with hand-written PHP? If the answer is "a day," fine. If it's "a quarter," you need a maintained fork or a second maintainer on the team before you scale usage.
  • Fork it if you depend on it. MIT license means forking is cheap and legitimate. For a 14-star package, "vendor fork + patch" is a reasonable steady state — just document the patch set so it's reproducible.

Overall: use it in a build step, behind an adapter, with golden-file tests and an exact version pin. That posture gets you the productivity upside while capping the downside at "we wrote some PHP by hand again."

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core