I spent the last three months or more working around the edges of a new Content Management Framework.

I wanted to do this because I have always wanted to create my own CMS rather than using whatever CMS happens to be out there, and all CMSes seem to have issues and are opinionated. And most CMSes seems to reinvent fundamental concepts, sometimes rather badly.


I wanted to create a framework which would enable you, by providing the missing packages, to pipe-together your own CMS. I developed a POC CMS which served as an integration platform for the components I was developing.

I created a Content Type component which maps content (aka. field) types to properties in your model, enabling the generation of backend forms, configuring storage metadata and (default) frontend views.

Then there was the Description component which enables any object to be "described" by aggregating metadata from various providers and returning them as standard descriptors (f.e. edit URLs, thumbnail URLs, title, etc).

And because components should be agnostic to the storage layer, there is the Object Agent which provides an object manager abstraction (including support for queries).

The project is still lacking a unified architecture, but it has laid some good groundwork for future development (and indeed the experimental CMS was already quite capable).


As work progressed it became apparent that I required a data grid (the POC CMS was using a hierarchical tree browser). So I started this project, later a freelance project required a data grid in Bolt CMS, and I had real use case.

There already existed the Sylius Grid component, but that was coupled to the Sylius Resource component. Sylius is made for E-Commerce, and I understand that creating a CMS was not their aim, so trying to push CMS features into Sylius would be an inappropriate uphill struggle.

In summary, the grid:

  • Supports Doctrine ORM, PHPCR-ODM and Collections. (via. the above mentioned object agent component).
  • Maps grids to objects via. Metadata drivers. This means support for annotations and Arrays (and so, YAML), and eventually XML.
  • Has no templates! The grid creates a view object-graph which can be easily traversed with any templating engine, and avoids coupling to a CSS framework or making false assumptions about what you want.
  • Supports queries with select - you are not restricted to the properties of your objects and can use functions native to the object management system (e.g. concat, month, etc).
  • Supports joins.
  • Supports multiple grids per class.
  • Supports filters: Restrict the result set, forms built and rendered by the Symfony Form Framework.
  • Supports pagination and sorting.
  • Supports actions: Perform bulk actions on selected records on the current page.
  • It is extendable.
  • It can be used easily as a standalone component (single point of entry).

An example from the docs


use Psi\Component\Grid\Metadata\Annotations as Grid;

 * @Grid\Query(
 *     name="details",
 *     selects={
 *         "a.id": "id",
 *         "a.active": "active",
 *         "a.name": "name",
 *         "a.email": "email",
 *         "p.title": "productTitle"
 *     },
 *     joins={
 *         { "join": "a.product", "alias": "p" }
 *     },
 * )
 * @Grid\Grid(
 *     query="details",
 *     columns={
 *         @Grid\Column(name="active", type="boolean"),
 *         @Grid\Column(name="email", type="text", options={"sort_field": "a.email"}),
 *         @Grid\Column(name="name", type="text", options={"sort_field": "a.name"}),
 *     },
 *     filters={
 *         @Grid\Filter(name="email", type="string", options={"comparators": {"contains"}}),
 *         @Grid\Filter(name="active", type="boolean", options={"label": "Membre active"}),
 *         @Grid\Filter(name="name", type="string", options={"comparators": {"contains"}}),
 *     },
 * )
class User
    private $active;
    private $name;
    private $email;

    // ...

Be there Dragons here

This is a very early release, probably too early, but I am starting a new job on the 3rd of January and probably won't get much more time to work on it. So I am just putting out there (also it is used in my last freelance project, so it needs a release). Another reason is to have at least something to show for my last 3 months work!

I hope to carry on all of these projects in the future, but for now this is as far as it has got.

See it on github

Posted on: 2017-01-01 00:00:00


Recent Posts

Psi Grid Component (a data grid)

I spent the last three months or more working arou...

Bundles: Service Providers, Definition Factories and Tags.

In this post I will talk about how we have employe...

PHPBench 0.11

PHPBench 0.11 (Dornbirn) has been released, and it...