juphyter

Guide

Getting started

This page assumes the php kernel is installed and juphyter doctor reports it as ready. Installation covers both. The examples were run in a Quarto document, and they behave the same way in a JupyterLab notebook.

To follow along in JupyterLab, run jupyter lab from an environment that has it, such as ~/.venvs/juphyter/bin/jupyter lab, and choose the PHP kernel in the launcher. To follow along in Quarto, create a file first.qmd:

---
title: "A first PHP document"
jupyter: php
---

```{php}
echo "sum: ", array_sum(range(1, 10)), "\n";
```

Then run quarto render first.qmd, which writes first.html.

A first cell

A cell holds PHP without an opening <?php tag. Whatever the cell prints with echo appears first, and the value of its last expression appears after it.

$primes = [2, 3, 5, 7, 11, 13];

echo count($primes), " primes, summing to ", array_sum($primes), "\n";

array_sum($primes) / count($primes);
6 primes, summing to 41
6.833333333333333

A cell whose last expression is a statement or a call that returns null shows only what it printed.

State between cells

Variables, objects, functions, and classes carry from one cell to the next.

$primes[] = 17;

$primes;
[2, 3, 5, 7, 11, 13, 17]

Restarting the kernel starts a new PHP session with nothing defined. In JupyterLab, use Kernel > Restart Kernel. Each quarto render starts a new session.

Imports

A use statement applies to its own cell and to every later cell. A notebook can put its imports in its first cell and use short names afterward. This example uses phibble, which the php kernel finds when the document sits inside a Composer project that requires it, or which the phpstats kernel from Installation provides.

use Phibble\DataFrame;
$orders = DataFrame::fromRows([
    ['channel' => 'web', 'region' => 'north', 'total' => 120.50],
    ['channel' => 'store', 'region' => 'north', 'total' => 80.00],
    ['channel' => 'web', 'region' => 'south', 'total' => 42.25],
]);

$orders;
A tibble: 3 × 3
channel <chr> region <chr> total <dbl>
1 web north 120.5
2 store north 80
3 web south 42.25

A cell cannot declare a namespace, and it cannot declare a class or a function that an earlier cell already declared. Limitations explains both.

Errors

A cell that throws shows the exception, its message, and a traceback whose lines name the cell and the line number.

$mean = fn (array $values) => array_sum($values) / count($values);

$mean([]);
DivisionByZeroError: Division by zero
DivisionByZeroError: Division by zero
  in a closure
  at Cell 5, line 3

The session survives the exception. Variables defined before it keep their values.

Warnings, notices, and deprecations appear in the cell’s error output, and the cell keeps running.

$widths = ['narrow' => 4, 'wide' => 12];

$widths['narrow'] + $widths['medium'];
Warning: Undefined array key "medium" in Cell 6, line 3
4

Rich output

The kernel sends each value in every format it can produce, and the front end picks the one it can draw. A phibble data frame comes as an HTML table and as the text phibble prints at a terminal. A phiz plot comes as a Vega-Lite specification, as HTML, as a static SVG when vl-convert is installed, and as a one-line text description.

Any class can provide its own output. A toHtml(): string method supplies HTML, and a toMimeBundle(): array method supplies every format at once.

final class Progress
{
    public function __construct(private readonly int $done, private readonly int $total) {}

    public function toHtml(): string
    {
        return sprintf(
            '<progress value="%d" max="%d"></progress> %d of %d',
            $this->done,
            $this->total,
            $this->done,
            $this->total,
        );
    }

    public function __toString(): string
    {
        return sprintf('%d of %d', $this->done, $this->total);
    }
}

new Progress(7, 9);
7 of 9

Juphyter\display() shows a value part way through a cell, so one cell can show several tables or plots.

Juphyter\display(new Progress(3, 9));
Juphyter\display(new Progress(9, 9));
3 of 9
9 of 9

From phpstats/juphyter@57dda5a.