PageTree demo by

Developers

Creating a block in PHP

Any plugin can provide its own blocks. A block is a PHP class, a YAML form and a Twig template.

Scaffold the block

The create:block command creates the files in an existing plugin:

php artisan create:block Acme.Blog Testimonial

It creates, inside the Acme.Blog plugin:

FilePurpose
blocks/Testimonial.phpBlock class
blocks/testimonial/config_fields.yamlBack-office form
blocks/testimonial/default.phpTwig template

The first argument uses the Author.Plugin format. The block name is converted to a class name (my-block gives MyBlock) and its folder is named after the class in lowercase (blocks/myblock). It can only contain letters, digits, - and _.

Register the block

Declare the block in the registerBlocks() method of your plugin's Plugin.php:

// plugins/acme/blog/Plugin.php
public function registerBlocks()
{
    return [
        'blog.testimonial' => \Acme\Blog\Blocks\Testimonial::class,
    ];
}

The block appears in the library, in the group named after your plugin.

The block class

<?php namespace Acme\Blog\Blocks;

use LucasPalomba\PageTree\Classes\ComponentBase;

class Testimonial extends ComponentBase
{
    public $config_fields = 'config_fields.yaml';

    public $uniqueKey = 'blog.testimonial';

    public function componentDetails()
    {
        return [
            'label' => 'Testimonial',
            'description' => 'Customer quote with author',
            'icon' => 'ph ph-quotes', // Phosphor icon
        ];
    }

    // Options of the "style" dropdown field
    public function getStyleOptions()
    {
        return ['light' => 'Light', 'dark' => 'Dark'];
    }

    // Extra variables for the template, $data contains the field values
    public function prepareVars($data = null)
    {
        $this->vars['authorUpper'] = strtoupper($data->author ?? '');
    }
}
MemberPurpose
$uniqueKeyBlock type, stored in pages. Do not change it once the block is in use.
$config_fieldsName of the form file, in the block folder.
componentDetails()Label, description and icon shown in the library.
get{Field}Options()Options of a dropdown field, as in an October form.
prepareVars($data)Prepares template variables in $this->vars.
$hiddenWhen true, the block is no longer offered in the library, but existing blocks are still displayed and editable.

The form (config_fields.yaml)

Standard October form fields are supported, including repeaters, media finders and rich editors.

fields:
    quote:
        label: Quote
        type: textarea
    author:
        label: Author
        type: text
        span: left
    style:
        label: Style
        type: dropdown
        span: right

The Displayed? checkbox (isActive field) is added automatically at the end of the form. Declare an isActive field yourself only to change its label or position.

The default values of the fields are applied to new blocks, and to fields missing from existing blocks. Values already saved, even false, are kept.

The file generated by create:block contains a sample title field, to replace with your own fields.

The template (default.php)

Despite its extension, the template is written in Twig. Field values are in data, variables from prepareVars() are available directly.

<blockquote class="testimonial testimonial--{{ data.style|default('light') }}">
    <p>{{ data.quote }}</p>
    <footer>{{ authorUpper }}</footer>
</blockquote>
  • Content typed by editors is never evaluated as Twig on the website.
  • To make a text field editable in place, in the preview and on the website, print it with the pagetreeEditable filter: {{ data.quote|pagetreeEditable('quote', 'multiline') }}. See Editing on the website.
  • For a link field (pagefinder), use pagetreeLink(data.link): the function only accepts relative, http(s), mailto: and tel: links.
  • For a media file, use the |media filter.

The default.php file is included as PHP before being compiled by Twig: it is trusted code shipped with your plugin. Never feed it with user-provided content.

Without writing a plugin

For a simple block, a superuser can also create a custom block from the back-office.