PHPackages                             lekoala/silverstripe-blocks - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. lekoala/silverstripe-blocks

ActiveSilverstripe-vendormodule[Utility &amp; Helpers](/categories/utility)

lekoala/silverstripe-blocks
===========================

Build pages with blocks in SilverStripe

12PHP

Since Sep 12Pushed 1y ago1 watchersCompare

[ Source](https://github.com/lekoala/silverstripe-blocks)[ Packagist](https://packagist.org/packages/lekoala/silverstripe-blocks)[ RSS](/packages/lekoala-silverstripe-blocks/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

SilverStripe Blocks module
==========================

[](#silverstripe-blocks-module)

[![Build Status](https://camo.githubusercontent.com/1152a7ec26ac513ec49cce60dbcd1172c7dd33df1c55e0b318894dc28acbd810/68747470733a2f2f7472617669732d63692e636f6d2f6c656b6f616c612f73696c7665727374726970652d626c6f636b732e7376673f6272616e63683d6d6173746572)](https://travis-ci.com/lekoala/silverstripe-blocks/)[![scrutinizer](https://camo.githubusercontent.com/c6885e6bef662f362f229919b303e09bc39488307afa25c44310e220e15e2153/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6c656b6f616c612f73696c7665727374726970652d626c6f636b732f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/lekoala/silverstripe-blocks/)[![Code coverage](https://camo.githubusercontent.com/19f80b6ed2799b94bcac09984df1ea5def32ac3aa4b17dbbb0b5807d22decd72/68747470733a2f2f636f6465636f762e696f2f67682f6c656b6f616c612f73696c7665727374726970652d626c6f636b732f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/lekoala/silverstripe-blocks)

Intro
-----

[](#intro)

### Block pages

[](#block-pages)

Allows to modularize pages with "blocks" content. This aims to be a simple alternative to elemental module.

All the content is saved into the Content field and therefore can be used with no performance penality.

Working with blocks
-------------------

[](#working-with-blocks)

We have a blocks page that allows managing content by block instead of the big "content thing"

We have a default block, the "Content Block" that allow setting a title, a content and an image

Blocks are all the same DataOBject : the Block.php Content is stored as json, so there is no need to create extension of this class. Instead, we simply create new Types of block that use different templates for rendering.

Creating new block types
------------------------

[](#creating-new-block-types)

Typically, you want to integrate some new block based on a given html content

Start to create a new block (it can be in your app or your theme) in:

```
/app/templates/Blocks/MyNewBlock.ss

```

Then you can call the task

```
/dev/tasks/BlocksCreateTask

```

It will create the php class if missing and scss styles in your theme provided you have a scss directory

Use the fluent field builder
----------------------------

[](#use-the-fluent-field-builder)

Given the data is stored in json blocks, adding field is not very convient

You can do it manually with this

```
 $fields->push(new TextField('BlockData[Title]', 'Title'));

```

But it's really ugly to have to call this BlockData\[Title\] thing

Instead, you can have a much nicer

```
 $fields->addText('Title');

```

Please refer to BlockFieldList for all available methods it should cover most common cases For advanced usage, you might need to extend it in your your project to deal with your custom field types

By default, the Image field is visible (inherited from the BaseBlock). If you find this not convenient, feel free to remove it

```
$fields->removeByName('Image');

```

WARNING : as a safety measure, avoid naming conflicts with existing Block.php fields like Content. This is why the default value is "Description" in addEditor().

Data and settings
-----------------

[](#data-and-settings)

There are two tabs : the Main tab and the Settings tab. Basically, anything inside the main tab should be localizable and anything in the setting tab should be fixed.

In order to add a setting, you can add fields to the setting tab like this

```
    $fields->addSettings(function (BlockFieldList $fields) {
        $fields->addCheckbox('MySetting');
    });

```

Basically, what this helper does is setting the fluent builder key to Settings and set the current tab to Settings and reset everything after.

Dealing with basic collections (aka Items)
------------------------------------------

[](#dealing-with-basic-collections-aka-items)

For basic collections, we can still store everything inside our json blob

In this example, I add 3 items with Name, Email, Description and Image

```
foreach (range(1, 3) as $i) {
    $fields->addHeader("Item $i");
    $fields->addText([$i, 'Name']);
    $fields->addText([$i, 'Email']);
    $fields->addEditor([$i,'Description']);
    $fields->addUpload([$i, 'ImageID'], "Image"); // don't forget the ID suffix
}

```

Please note the \[\] array notation we use. Instead of passing the name as a string, we pass and array with the index and the name as the second argument. Our BlockFieldList knows how to deal with this.

And you can freely loop over them thanks to our special $Items (defined as a const ITEM\_KEYS in Blocks.php) Assets (files and images) are automatically published if used in the block

```

$Name
$Description

```

It includes default iterator values (FirstLast, Pos) but also specials one (Total, Counter and Columns).

- Total : the total number of items in the set
- Counter : the total number of items in the page
- Columns : a 12 columns based number (ideal for Bootstrap like usages)

Nice!

Dealing with Files &amp; Images
-------------------------------

[](#dealing-with-files--images)

By default, you have a many\_many Files and Images on each blocks. You can easily add these fields with

```
$fields->addImages();

```

or

```
$fields->addFiles();

```

Useful for sliders, attached documents...

These are sortable by default thanks to bummzack/sortablefile and can be used in the templates with

```

```

Dealing with relations
----------------------

[](#dealing-with-relations)

You might wonder what are doing these

```
public function Collection()
{
    return false;
}

public function SharedCollection()
{
    return false;
}

```

They return false by default to avoid any issue in the templates. But they can return any DataList or ArrayList that might be relevant depending on what your block does.

Like a Block for displaying latest blog posts, it could be

```
public function SharedCollection()
{
    return BlogPost::get()->limit(3);
}

```

Please note of the difference between Collections and SharedCollections

- Collection : data is filtered for the given block. It's specific and require a has\_one relation from the DataObject to the Block
- SharedCollection : data is the same for all blocks of this type

Other templating stuff
----------------------

[](#other-templating-stuff)

### Menus

[](#menus)

you can generated anchored base menus with the following snippet. Each block can have it's own id (Settings tab, based on MenuTitle if empty)

```

$Title

```

### Overriding the default Content block

[](#overriding-the-default-content-block)

You can easily override the default template by adding your own template in /app/templates/Blocks/ContentBlock.ss

Default template is:

```
$Description.RAW

$Image

```

### Buttons

[](#buttons)

TODO

### Pages

[](#pages)

All block content is rendered into the Content field of the page. This is needed in order to keep search working without adjustement.

Each block represent a section, something like this

```

Here is the block content based on your template

```

You can disable to prevent this automatic "section" stuff if you have a more custom need by disabling the wrap block config

```
LeKoala\Blocks\BlocksPage:
  wrap_blocks: false

```

### Extra data

[](#extra-data)

Since block types are not DataObjects, their methods are not exposed to the template, only their data

Basically, we take all the data fields, all the settings and merge them together before calling "renderWith" function

You can expose additionnal data to the template by using ExtraData

```
function ExtraData() {
    return [
        'Hello' => 'World
    ];
}

```

And then call

```
Hello $Hello

```

in your templates

### Casting

[](#casting)

If you store html in your blocks, it's not going to be casted properly. So ensure to use .RAW in your templates

```
$Description.RAW

```

### Previewing blocks

[](#previewing-blocks)

It can be a bit tedious to save and publish each time you change a block in order to refresh the $Content variable of the page This is why in Dev mode you can pass ?live=1 as a url parameter in order to fully refresh all blocks content when displaying the page

### Context

[](#context)

Keep in mind that html for the blocks are generated on save, in the admin. That means that some context stuff (Sessions, Controller::curr) may not work as you may think. Try to be as stateless as possible to avoid surprises!

Use Query
---------

[](#use-query)

The blocks give you a powerful accessor: the $Query method. In your template you can loop over ANY DATAOBJECT. Please be very cautious with this.

```

$Name

```

TODO
----

[](#todo)

- Finalize extract of specific form fields components
- Remove coupling with base module

Compatibility
-------------

[](#compatibility)

Tested with 4.6 but should work on any ^4 projects

Maintainer
----------

[](#maintainer)

LeKoala -

###  Health Score

15

—

LowBetter than 3% of packages

Maintenance29

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity17

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/250762?v=4)[Thomas Portelange](/maintainers/lekoala)[@lekoala](https://github.com/lekoala)

---

Top Contributors

[![lekoala](https://avatars.githubusercontent.com/u/250762?v=4)](https://github.com/lekoala "lekoala (18 commits)")

---

Tags

silverstripe

### Embed Badge

![Health badge](/badges/lekoala-silverstripe-blocks/health.svg)

```
[![Health](https://phpackages.com/badges/lekoala-silverstripe-blocks/health.svg)](https://phpackages.com/packages/lekoala-silverstripe-blocks)
```

###  Alternatives

[jclg/php-slack-bot

Slack bot user written in PHP

16825.5k1](/packages/jclg-php-slack-bot)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
