Post on 12-Apr-2017
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 1
SympalContent Management System Based on Symfony
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 2
Sympal is a Content Management System built on top of Symfony and Doctrine.
It is an evolution of many smaller CMS systems used in projects over the years.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 3
• Collection of Symfony plugins– sfSympalPlugin
• sfFeed2Plugin• sfFormExtraPlugin• sfSuperCachePlugin• sfSympalMenuPlugin• sfSympalPagesPlugin• sfSympalPluginManagerPlugin• sfSympalUserPlugin• sfTaskExtraPlugin• sfWebBrowserPlugin
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 5
• The idea spawned from a need• Custom functionality in Symfony is
easy• Standard CMS functionality is not
so easy
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 6
• A project with 75% custom functionality and 25% CMS functionality.
• The 75% custom is no problem• But what about that 25%?• It sometimes ends up taking more time
than the 75% custom!• We repeat ourselves a lot when it
comes to CMS functionality
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 7
So the idea is to provide what something like Drupal gives you with a powerful MVC
framework and ORM under the hood.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 8
The name Sympal was coined by my friend and ex co-worker Josh Reynolds a few
years ago while brainstorming. Sympal was born that day and I began recording notes
and collecting code from old projects.
Symfony + Drupal = Sympal
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 9
The code has existed in my own private repositories for a long time but not until the last few months have I started to formalize
it in to a working product and made it available to the public
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 11
• CLI or web installation• Menus• Breadcrumbs• Content types• Inline or backend content editing• Content slots• Plugin manager - Download/Install/Uninstall Sympal
plugins from the CLI or web browser.• Configuration controlled via YAML or a web form• Security - users, groups and permissions
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 12
• Events• Sending E-Mail• Multiple Sites• Multiple Themes/Layouts• Internationalized URLs• Map menus to content• Change url of content without breaking old urls• SEO• Logged in user Dashboard• Uses YUI for JS framework
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 14
• Install from your browser• Or from the command line• Use in new or existing projects
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 15
Install from your browser
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 16
• Install from the command line
• Interactive option prompts you for the same information as the browser installation
• Omit --interactive and default values will be used
$ php symfony sympal:install --interactive
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 17
Once installed you will see the default Sympal website.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 19
• Only requires one query• Multiple menus• Sub-menus• No matter how large or how
complex they only ever require one query.
• Menus can optionally be cached for 0 queries.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 20
YUI tree view for managing menus
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 21
Drag and drop ordering
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 22
Right click a menu leaf to manage
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 23
Rendering menus is done with a Symfony helper
// returns instance of sfSympalMenuSite which extends sfSympalMenu$menu = get_sympal_menu('footer');
// sfSympalMenu implements __toString() which invokes renderingecho $menu;
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 24
Use custom menu class
class myMenuClass extends sfSympalMenuSite{ }
echo get_sympal_menu('footer', true, 'myMenuClass');
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 25
• Specify global custom menu class in configuration
• Now all your menus use that class
all: sympal_config: menu_class: myMenuClass
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 26
• Core of menu system is database agnostic
• sfSympalMenu implements the basic menu functionality
• sfSympalMenuSite extends sfSympalMenu and implements the binding to the Doctrine MenuItem model
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 27
Using sfSympalMenu standalone$menu = new sfSympalMenu('My Test Menu');
$menu->addChild('Google', 'http://www.google.com');
$sensio = $menu->addChild('Sensio', 'http://www.sensio.com');$sensio->addChild('Sensio Labs', 'http://www.sensiolabs.com');$sensio->addChild('The Symfony MVC Framework', 'http://www.symfony-project.com');$sensio->addChild('The Symfony Components', 'http://components.symfony-project.org');$sensio->addChild('The Doctrine ORM', 'http://www.doctrine-project.org');
$menu->addChild('Yahoo', 'http://www.yahoo.com');
echo $menu;
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 28
• Serves multiple purposes– Breadcrumbs– Admin bar menu– Floating editor panel
• Building hierarchical structure through OO interface
• Rendering HTML for the hierarchy
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 29
• Connect to events to alter these objects before they are rendered
• Sympal plugins can add items to the admin bar, menus, floating editor panel, etc.
• Install a Sympal plugin and the functionality appears in your site and is instantly available.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 30
• The rendering of menus are done through these functions which can be overridden and customized.– render()– renderChild()– renderChildBody()– renderLink()– renderLabel()
• Rendering is split in to multiple methods to allow you to override only the pieces you need to change.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 31
• Admin bar rendering is customized with sfSympalMenuAdminBar class
• Overrides renderChild() method so that the proper HTML is generated for YUI to work
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 33
• Breadcrumbs don’t require any additional queries
• Generated from the same information used for menus
• Also generated with special child class of sfSympalMenuSite named sfSympalMenuBreadcrumbs
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 34
Rendering breadcrumbs are done with a Symfony helper, similar to the menus
// Get the current menu item to render breadcrumbs for// Or render breadcrumbs for any Doctrine MenuItem instance$menuItem = sfSympalToolkit::getCurrentMenuItem();
// Returns instance of sfSympalMenuBreadcrumbs$breadcrumbs = get_sympal_breadcrumbs($menuItem);
echo $breadcrumbs;
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 36
• Sympal comes bundled with two content types– Page - Simple title and body– ContentList - Content type which allows you to specify
information to render a list of another type of content.• Specify the query• Sorting• Limit• Conditions of list, etc.• What template to render the list with
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 37
• Easily add new content types through Sympal plugins
• Generate a new Sympal plugin that contains the skeleton for a new content type which can be installed
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 38
Generate the new Sympal plugin$ php symfony sympal:plugin-generate Article --content-type=Article
sfSympalArticlePlugin/ config/ doctrine/ schema.yml routing.yml sfSympalArticlePluginConfiguration.class.php data/ fixtures/ install.yml lib/ LICENSE package.xml.tmpl README
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 39
• Inspect the generated plugin• Have a look at the default
schema.yml created---Article: actAs: [sfSympalContentType] columns: title: string(255) body: clob
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 40
• Now we can install the generated plugin
• Installation does the following– Generates models, forms, etc. for schema– Creates tables in the database– Adds a sample content list for content type– Adds a sample content record for content type– Adds a menu item to the primary menu which is
mapped to the content list for the new content type
$ php symfony sympal:plugin-install Article
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 41
When we go to add new content we can now add Articles
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 42
We can click the menu item added to the primary menu to view the list of articles.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 43
Click the sample article to view it
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 44
• Rendering of content types utilizes Content Templates
• Use different templates to render different content types
• Use different templates to render individual content records
• By default it just uses some basic templates
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 46
Sympal allows you to edit your content inline when logged in as an authorized content editor.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 47
When you double click some content to edit the inline editor will come up
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 48
Edit model columns inline in addition to content slots
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 50
• Download, install and uninstall plugins• Works from the CLI or web browser• Sympal plugin manager tries to get a
plugin through the symfony plugin:install task first then tries to find the plugin in SVN and check it out
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 51
From the command line
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 52
From the web browser
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 55
Controlled via YAML
all: sympal_config: menu_class: sfSympalMenuSite yui_path: http://yui.yahooapis.com/2.7.0/build super_admin_signin_url: @sympal_dashboard enable_all_modules: true admin_module_web_dir: /sfSympalPlugin load_default_css: true
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 56
• Or YAML can be controlled via a web form
• When configuration form is saved the YAML file is written
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 57
• Since the configuration uses the symfony app.yml it can be controlled at different levels of symfony– Project– Application– Module
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 58
• Other items related to content records can be configured at different levels. For example the layout can be controlled– Globally– Per site– Per content type– Per content record
• This means you can customize the layout an individual content record uses.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 60
• sfSympalUserPlugin is forked version of sfDoctrineGuardPlugin– Users– Groups– Permissions– Forgot Password– Registration
• Menus, content records, etc. can all be locked down with permissions.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 67
Sympal Admin Generator Theme
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 68
• Sympal comes with custom admin generator them
• Tabbed forms for fieldsets and embedded forms
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 69
Easily click Filters to popup the filters form
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 70
Floating Editor Panel
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 71
When logged in as editor and viewing a content record a floating editor panel is displayed
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 72
Content Slot Types
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 73
• A content slot in Sympal is an arbitrary piece of content and has a type.
• Sympal comes bundled with a few content slot types
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 74
• The default slot types offered by Sympal are– Markdown– MultiLineText– RichText– Text
• Add your own custom slot types for your projects
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 75
YUI Rich Text Editor
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 76
The RichText slot type uses the YUI rich text editor
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 77
The YUI rich text editor also implements the ability to upload and embed images inline
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 79
• A reoccurring need• Re-implementing the functionality
over and over wasting time• We need a standard way to send
and manage our e-mail templates• Sympal offers a solution
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 80
In your actions you can easily create new e-mails and send them
class my_moduleActions extends sfActions{ public function executeSome_action(sfWebRequest $request) { $variables = array( 'name' => 'Jonathan H. Wage' ); $email = $this->newEmail('email_module/test', $variables); $email->send('jonwage@gmail.com'); }}
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 81
• The templates used for a Sympal e-mail are just a partial or component
• In the previous example we use a partial named _test.php
Hello <?php echo $name ?>,This is a test e-mail that we are sending to <?php echo $name ?>
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 82
• The first line of the template is the subject
• The second line and after is the body of the e-mail
• This way the contents of the e-mail(subject and body) are managed in one place
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 83
• The newEmail() method returns an instance of sfSympalMail
• sfSympalMail is a wrapper around your mail sending program which defaults to Swift in Sympal
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 85
• Sympal can handle multiple sites
• A sympal site is directly bound to a symfony application
• This is how Sympal knows which site you are in and can limit the data to only that site
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 87
Search Engine Optimization
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 88
• SEO capabilities are built in• You can specify global title,
keywords and description for your project.
• They can also be overridden by each site or even by individual content records
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 89
• sfSympalAutoSEOPlugin– Who is going to write it? :)– Automatically generate SEO for content
records from the final rendered HTML• Parse the first <h1> tag value for the meta title• Build a list of top words used in the content
record for the meta keywords• Parse the first <p> tag value for the meta
description– Write good content and you’ll have SEO
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 91
When a user logs in and has some credentials he’ll be forwarded to his dashboard. A super administrator would see everything. Something like the below...
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 92
• Dashboard is generated using the sfSympalMenu classes
• The menu instance used to generate the dashboard is passed through an event so you can easily add to it by connecting to an event
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 93
Connect to dashboard event and add to the menu object
class sfSympalTestPluginConfiguration extends sfPluginConfiguration{ public function initialize() { $this->dispatcher->connect('sympal.load_dashboard_boxes', array($this, 'loadDashboardBoxes') ); }
public function loadDashboardBoxes(sfEvent $event) { $menu = $event['menu']; $menu->addChild('My New Box', '@route_name'); }}
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 95
• Sympal offers the ability to have themes and you can configure in multiple places what them to use– Globally– Per site– Per content type– Or per content record
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 96
• We can now easily have Sympal theme plugins that you can download and instantly have a new theme to change to
• We already have three themes available that you can download and use– sfSympalPlugin - The default theme included with
Sympal– sfSympalJwageThemePlugin - The theme used on my
personal website, jwage.com– sfSympalDoctrineThemePlugin - The theme which
powers the Doctrine website
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 97
Doctrine Theme
Sympal Theme
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 99
Sympal comes with some other pretty useful tasks for improving your productivity when working in Symfony
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 100
• Most notable CLI tasks– sympal:delete-model - Delete a model from your
project. Finds and deletes model, form and filter files all in one command
– sympal:report-statistics - This task will report back to the Symfony Plugins API what all plugins you’re using in your project and will add them to your stack.
– sympal:event-list - Report a list of events that are available for a URL in your application• See who has connected to an event
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 101
Show a list of all available events for a URL
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 102
Show only the events which have been connected to
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 103
Inspect an individual event to see who has connected to it and more importantly where!
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 104
More on Sympal Events
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 105
• Some might say I have overused the Symfony events system in Sympal
• But, I really like it and I find it very useful in the CMS context. It allows for things to be very flexible and “changeable” by use of events.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 106
• A re-occurring question– How can I add to a model of another plugin,
or a model in my project from a plugin.
– Before Sympal this was not possible but now if you models simply actAs sfSympalRecord or sfSympalContentType you can connect to an event which is notified during the setup of a Doctrine model
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 107
• Add a new column to the Sympal User model
• The schema for the model looks like this User:
tableName: users actAs: [Timestampable, sfSympalRecord] columns: first_name: string(255) last_name: string(255)# ...
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 108
• The actAs: [sfSympalRecord] allows us to connect to two events– sympal.user.set_table_definition– sympal.user.set_up
• The set table definition allows us to add new columns, indexes, etc.
• The set up allows us to add relationships, add behaviors, etc.
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 109
Now lets connect to the set table definition event and add a new columnclass sfSympalTestPluginConfiguration extends sfPluginConfiguration{ public function initialize() { $this->dispatcher->connect('sympal.user.set_table_definition', array($this, 'setUserTableDefinition') ); }
public function setUserTableDefinition(sfEvent $event) { $model = $event->getSubject(); $model->hasColumn('my_new_column', 'string', 255); }}
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 110
• We have a lot more events and I can’t talk about them all• But I will try and list some of the other notable events
– sympal.user.pre_signin– sympal.user.post_signin– sympal.load_breadcrumbs– sympal.<model_name>.method_not_found– sympal.post_render_page_content– sympal.load_tools
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 111
With the Symfony events and the PHP __call() magic function we can fake “extending” a class by invoking a method_not_found event and letting users connect to it
class sfSympalTestPluginConfiguration extends sfPluginConfiguration{ public function initialize() { $this->dispatcher->connect('sympal.user.method_not_found', array(new myUserExtension(), 'extend') ); }}
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 112
Now lets define the myUserExtension class and add some new functionality
class myUserExtension extends sfSympalExtendClass{ public function getFullName() { return trim($this->getFirstName().' '.$this->getLastName()); }}
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 113
Now when I work with a User model instance I will be able to access my getFullName() method
$user = new User();$user->first_name = 'Jonathan';$user->last_name = 'Wage'; echo $user->getFullName(); // Jonathan Wage
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 115
• Continued development of Sympal
• Work towards a 1.0 release
• Spread the word and try and get as much feedback as possible
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 116
What do we need?
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 117
• Users, testers, feedback, etc.
• Development help, documentation help
• For development, we need the most help with the frontend
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 118
• Frontend development– YUI/JS/CSS guru– Usability guru
• Backend development– Familiarity with Symfony and Doctrine
obviously– Familiarity with other popular CMS in any
other languages to help with functionality and implementation
Sympal - a CMS based on Symfony
Jonathan H. Wage: Sympal a CMS Based on Symfony 119
You can contact Jonathan about Doctrine and Open-Source or for training, consulting, application development, or business
related questions at jonathan.wage@sensio.com
Jonathan H. Wagejonathan.wage@sensio.com+1 415 992 5468
sensiolabs.com | doctrine-project.org | sympalphp.org | jwage.com
Questions?