Getting started

Overview

What ++PHP is, how a project uses it, and where to go next.

++PHP is a typed superset of PHP. A .ppphp file is a PHP file with a few additions the compiler checks before anything runs: generics, typed arrays, typed locals, when expressions, and checked errors. The compiler turns those files into ordinary PHP that your existing runtime, packages, servers, and tools run unchanged.

Nothing changes in production. There is no extension, no bootstrap, and no ++PHP dependency at runtime; the compiler is a development dependency and its output is plain PHP with conventional PHPDoc.

How a project uses it

  1. Install the compiler with Composer and run ppphp init to create ppphp.json.
  2. Rename a file from .php to .ppphp and add the types that make its intent clear. The rest of the project can stay as it is.
  3. Run ppphp check while you work. It reports problems against your .ppphp source with a stable code, the exact location, and what to do about it.
  4. Run ppphp build to write the complete PHP tree. Test, run, and deploy that tree with the tools you already use.

A small class shows the shape of the language:

<?php

final class BasketTotal
{
    public function calculate(array<LineItem> $items): int
    {
        int $total = 0;

        foreach ($items as LineItem $item) {
            $total += $item->priceInCents;
        }

        return $total;
    }
}

The parameter is a list of LineItem values, the local $total has one type for its whole life, and the loop binding carries the element type into the body. Rename a member or change a return type anywhere in the project and ppphp check reports every place that no longer agrees.

What the compiler emits

The same class after ppphp build:

<?php
declare(strict_types=1);

final class BasketTotal
{
    /**
     * @param list<LineItem> $items
     */
    public function calculate(array $items): int
    {
        /** @var int $total */ $total = 0;

        /** @var LineItem $item */
        foreach ($items as $item) {
            $total += $item->priceInCents;
        }

        return $total;
    }
}

Generated files keep their namespaces and source-relative paths, declare strict_types=1, and pass php -l. Plain .php files in the same project are copied byte for byte, so the output directory is always a complete application.

What a .ppphp file requires

Parameters, properties, return values, and locals are explicitly typed. Nullability is written, not implied. Assignment cannot create a variable; a typed declaration does. Missing returns, wrong arguments, unknown members, and incompatible assignments are reported across the whole project, not just the file being edited.

Where a boundary is genuinely dynamic, write mixed, bare array, object, callable, or iterable. The broad type is the signal that validation belongs there.

Where to go next

  • Installation adds the compiler to a project and builds one file.
  • The CLI covers checking, building, focusing on one path, and reading diagnostics.
  • Project configuration documents every ppphp.json field and the Composer mapping.
  • Editors sets up VS Code or PhpStorm.
  • Migrating from PHP is the file-by-file adoption plan for an existing application.
  • The Language section describes each feature with examples.
  • Diagnostics lists every code the compiler can report.