Skip to content

Instantly share code, notes, and snippets.

Last active August 20, 2016 14:11
What would you like to do?
A modular approach for Symphony.



The everyday developer will clone the workspace to create their project. This repository accepts Issues, Wiki and Pull Requests. All resources in here are custom to the specific project, all the dependencies will be resolved into /vendor. There are a few boilerplate files such conductor and index.php.

Favour convention approach, commands, datasources, events and sections are autodiscovered where possible, however some configuration may be required for the service container (if the items have dependencies). Needs fleshing out.

It will include:

- workspace/ (may even be flattened?)
-- commands/ 
-- data-sources/
-- events/
-- sections/
-- views/
- manifest/ (optional?)
-- tmp/
-- cache/
-- logs/
-- config (needs better environment support. consider YAML/XML/.env alternatives)
- public/ (exposed as the 'root' for Apache/nginx, very similar to Laravel)
-- .htaccess
-- index.php
- conductor (CLI)
- server.php
- composer.json


This is the rollup of all components that makes up a version of Symphony (eg. 2.6.7). This repository will accepts issues and pull requests. There may need to be some sort of orchestration component here, or moved up into symphony/workspace that ties all of this together in terms dependency injection, registering services etc.

- build/
-- misc. scripts for distributing symphony etc.
- src/
-- components/
--- templating/
---- src/
---- tests/
---- composer.json
--- etc.
- tests/ (Orchestration tests PHPUnit/Behat)
- specs/ (PHPSpec tests)


Component repositories are read only, and have issues and pull requests disabled. Issues are managed via symphony/symphony-cms with labels for each component. The project structure here is largely up to the developer, but as a 'core' component our best practice could be:

- src/ (source code)
- resources/ (documentation, assets etc.)
- tests/ (PHPUnit/Behat)
- specs/ (PHPSpec)
- composer.json


All extensions would ideally be installed as composer dependencies. The composer.json file is almost significant enough to replace the extension.meta.xml file, but it's likely both could coexist.

conductor extension add symphonycms/members (utilise to retrieve files) composer require symphonycms/members (requires extension have composer.json and be listed on

Extensions should mirror the component structure, but it'd be rather flexible (as long as there's an autoloader, things are a-ok)

Likely move away from 'convention' in favour of 'configuration', eg. A new Field isn't 'autodiscovered' by a /fields folder, rather the extension informs Symphony that it has a Field available to register in the service container. Needs fleshing out...


Something that is regularly raised is why isn't Symphony built on Symphony? It's a fair point, and some of the issues that exist today might of been avoided if this was the case. For example, the delegate system is fantastic, but often Extensions are able to do things the 'core' cannot!

I think Admin should be developed as if it was based on symphony/workspace, but it's pulled into that project as symphony/admin. This opens up an opportunity where the UI is 'optional' and could be custom built or interchanged depending on the project requirements.

The Admin is largely a visual representation for the objects in symphony/workspace (DS/Events) etc. In theory, all that could be removed to just leave a UI for Authors to manage and create content.

Copy link

nilshoerrmann commented Jul 1, 2016

A few random thoughts open for discussion:

Symphony as an API

Ten years ago, Symphony – as one of the very first systems – made it easy to manage content input and output. But with the rise of JavaScript frameworks, Symphony started falling behind: the system doesn’t offer an easy way to serve a content API to the front-end, especially if this requires JSON output.

When I think about the modularisation of Symphony, I think of it from an enduser’s perspective where the enduser is someone just using the system without hacking it. Maybe this slightly different view can refine the proposed new project structure. For me, a modularised Symphony should be a series of consecutive blocks I can choose to use. These blocks are:

  1. data management
  2. output management
  3. administration

1. Data management

The data block is everything from the core related to data management. In old words, there are fields, sections, entries, data sources and events. But there is no routing (pages) and no templating (XSLT). This block has no GUI but there is an API to manage data input and output (GET, PUT, POST, DELETE and such).

This data block can be used to build an API server without anything else. You’d administer it using a CLI.

If I’d like to use Symphony alongside front-end frameworks like Angular, React or Ember this is all I need.

Rethinking data sources and events

In this context, data sources and events would be advanced to API endpoint definitions. These files would describe

  • which API endpoints exist,
  • which authentication to use (none, Symphony, Members, oAuth, …)
  • which output to return at an endpoint (data source like)
  • which input to accept at an endpoint (event like)
  • the content flavour (XML, JSON, …)

2. Output management

The output block integrates routing, filtering and templating and is only needed when relying on „traditional“ server-side templating like the XSL we are all used to. Similar to block 1, it doesn’t offer a GUI, all configuration is file-based and stored in the workspace.

Now that data sources and events have transformed into endpoints, you’d no longer attach those to your pages. You’d add API calls to your pages instead:

  • /symphony/api/sections/entries/?flavor=xml&sort=desc&limit=20&filter=…
  • /symphony/api/sections/comments/?flavor=xml&sort=asc&limit=10

The output block will retrieve this data based on a route and will call a transformer (e. g. XSL, Twig, Handlebars) to create the output. The pages store all this in a configuration file that also defines which template to use.

If I’m a developer, blocks 1 and 2 might be sufficient for me to build any site or app I need

3. Administration

This is what we called the backend up to now. It’s the GUI to access and manage Symphony's data input and output. It should offer everything you need as a designer to create a website or app and should offer everything you need as an author. Although it might look completely different, the purpose of this block is exactly the same as the one of the current backend.

This block is only needed, if I'd like to use a graphical user interface.

Admin as a workspace

This is made for front-end users and therefore it should be built using technology the Symphony front-end folks are used to:

  • XML
  • XSLT
  • HTML
  • CSS
  • JavaScript

This will help developing the admin interface continuously because extending and improving the backend works exactly as building a front-end site. There is no need to program.

The backend is just one additional workspace. A front-end app to access the Symphony API. Which means in reverse conclusion that anything that can be done in the backend can also be done in a custom front-end.

Multiple Workspaces

If you think this further, it would be logical to not have one workspace but multiple. This would simplify different use cases:

  • different iterations of the same site could live side-by-side
  • one install could server different sites


The composer.json file is almost significant enough to replace the extension.meta.xml file, but it's likely both could coexist.

As we are talking about a major version release there is no need to be nostalgic: decide in favour of one, go with the common composer.json.

Likely move away from 'convention' in favour of 'configuration', eg. A new Field isn't 'autodiscovered' by a /fields folder, rather the extension informs Symphony that it has a Field available to register in the service container.

Looking at things from the front-end perspective, I’d favour Symphony’s current opinionated approach of using convention over configuration. It’s one of the great strengths of the system in my eyes. Things just look and work similar across all extensions which helps a lot when you are not a backend developer but have to dive into the world of the core and its extensions.

John O’Nolan, the creator of Ghost, has written about their choice of Ember for the Ghost backend that accentuates the benefits of this approach:

One of the most important reasons that we ultimately chose Ember was precisely because it is so opinionated and, at times, inflexible. Because in a fully open source team, that’s a huge advantage. There is a definitive right or wrong way to do things in our client-side app, and it is exactly the same as every other Ember app. We never need to have any debates or discussions about implementation. The framework puts us on the same page. […]
As an Ember developer, when you jump between Ghost, Discourse and your own Ember projects - you are immediately at home. Everything is the same right down to the directory structure. This dramatically lowers the barrier to entry for new developers.


I’d suggest to not use the plain word symphony for naming components but to keep up using symphony-cms in order to minimise confusion with Symfony.

Copy link

@nilshoerrman: Thanks a lot! Great.

Copy link

Sounds a lot like the “ideal architecture” I had in mind for quite a while now. Even started building something similar on my own, but didn’t get very far so far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment