phiz

Getting started

Get started

A complete first chart

Install phiz in a project with composer require phpstats/phiz, then save this script as chart.php beside the vendor directory:

<?php

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

use Phiz\Datasets;
use Phiz\Plot;

$plot = Plot::of(Datasets::mpg())
    ->aes(x: 'displ', y: 'hwy', color: 'drv')
    ->point()
    ->labs(x: 'Displacement (L)', y: 'Highway mpg', color: 'Drive');

$plot->save('chart.html');

php chart.php writes chart.html, a standalone page. Open it in a browser to see the chart. The page loads vega, vega-lite, and vega-embed from the jsDelivr CDN, so viewing it needs a network connection. save('chart.svg'), save('chart.png'), and save('chart.pdf') write static files instead and need the vl-convert binary (Rendering).

Data, mappings, and geoms

A plot starts with data and aesthetic mappings. Plot::of() takes the data, aes() maps fields to visual channels, and a geom such as point() adds a layer. The bundled Datasets class provides a few classic datasets for examples.

use Phiz\Datasets;
use Phiz\Plot;

$plot = Plot::of(Datasets::mpg())
    ->aes(x: 'displ', y: 'hwy')
    ->point();

Mapping another field to color gives each class its own color and adds a legend. Fixed properties, such as a point size or an opacity, are geom arguments.

use Phiz\Datasets;
use Phiz\Plot;

$plot = Plot::of(Datasets::mpg())
    ->aes(x: 'displ', y: 'hwy', color: 'class')
    ->point(size: 40, alpha: 0.7);

Layers

Each geom adds a layer, and layers inherit the plot’s mappings. This plot overlays a loess smoother on the points and labels the axes.

use Phiz\Datasets;
use Phiz\Plot;

$plot = Plot::of(Datasets::mpg())
    ->aes(x: 'displ', y: 'hwy')
    ->point(alpha: 0.4)
    ->smooth(span: 0.6)
    ->labs(x: 'Displacement (L)', y: 'Highway mpg');

Plots are immutable. Every method returns a new plot, so a base plot can be stored and extended in several directions.

$base = Plot::of($mpg)->aes(x: 'displ', y: 'hwy');

$scatter = $base->point();
$smooth = $base->point(alpha: 0.3)->smooth(method: 'lm');

Pipes

PHP 8.5’s pipe operator composes ggplot2-style functions. ggplot() starts a plot, and each geom_*(), scale_*(), labs(), or theme_*() function returns a closure that takes a plot and returns the next one. The method chain builds the same specification on every supported PHP version.

use Phiz\Datasets;

use function Phiz\{aes, geom_point, geom_smooth, ggplot, labs, theme_minimal};

$plot = ggplot(Datasets::mpg(), aes(x: 'displ', y: 'hwy', color: 'drv')) |>
    geom_point(alpha: 0.5) |>
    geom_smooth(method: 'lm', se: false) |>
    labs(x: 'Displacement (L)', y: 'Highway mpg', color: 'Drive') |>
    theme_minimal();
use Phiz\Datasets;
use Phiz\Plot;

use function Phiz\aes;

$plot = Plot::of(Datasets::mpg(), aes(x: 'displ', y: 'hwy', color: 'drv'))
    ->point(alpha: 0.5)
    ->smooth(method: 'lm', se: false)
    ->labs(x: 'Displacement (L)', y: 'Highway mpg', color: 'Drive')
    ->theme('minimal');

The functions and the methods accept the same arguments. On PHP 8.3 and 8.4, apply() also takes the functions: ggplot($mpg, aes(x: 'displ', y: 'hwy'))->apply(geom_point(), labs(x: 'Displacement (L)')). A plot can also apply reusable fragments with apply():

$house = fn (Plot $plot) => $plot->theme('minimal', baseSize: 12)->size(480, 300);

$plot = Plot::of($mpg)->aes(x: 'displ', y: 'hwy')->point()->apply($house);

Output

A plot compiles to a Vega-Lite specification on demand.

$plot->toArray();        // the specification as a PHP array
$plot->toJson();         // as JSON
$plot->embed();          // an HTML fragment with the container and script tags
$plot->html();           // a standalone HTML page
$plot->svg();            // SVG through vl-convert
$plot->save('plot.pdf'); // the file extension picks the format

Rendering covers the options for each output, and Laravel and Livewire covers the Blade component.

From phpstats/phiz@bc7ed3e.