4. The Idea
• The idea spawned from a need
• Custom functionality in Symfony is
easy
• Standard CMS functionality is not
so easy
Sympal - The flexible Symfony CMS | Jonathan H. Wage
5. The Idea
• 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 - The flexible Symfony CMS | Jonathan H. Wage
6. The Idea
So the idea is to provide what something
like Drupal gives you with a powerful MVC
framework and ORM under the hood.
Sympal - The flexible Symfony CMS | Jonathan H. Wage
7. The Idea
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 - The flexible Symfony CMS | Jonathan H. Wage
8. The Idea
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 - The flexible Symfony CMS | Jonathan H. Wage
10. Highlights
• 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 - The flexible Symfony CMS | Jonathan H. Wage
11. Highlights
• 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 - The flexible Symfony CMS | Jonathan H. Wage
13. Installation
• Install from your browser
• Or from the command line
• Use in new or existing projects
Sympal - The flexible Symfony CMS | Jonathan H. Wage
15. Installation
• Install from the command line
$ php symfony sympal:install --interactive
• Interactive option prompts you for
the same information as the
browser installation
• Omit --interactive and default
values will be used
Sympal - The flexible Symfony CMS | Jonathan H. Wage
16. Installation
• Once installed you will see the
default Sympal website.
Sympal - The flexible Symfony CMS | Jonathan H. Wage
18. Menus
• 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 - The flexible Symfony CMS | Jonathan H. Wage
19. Menus
• YUI tree view for managing menus
Sympal - The flexible Symfony CMS | Jonathan H. Wage
20. Menus
• Drag and drop ordering
Sympal - The flexible Symfony CMS | Jonathan H. Wage
21. Menus
• Right click a menu leaf to manage
Sympal - The flexible Symfony CMS | Jonathan H. Wage
22. Menus
• 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 rendering
echo $menu;
Sympal - The flexible Symfony CMS | Jonathan H. Wage
23. Menus
• Use custom menu class
class myMenuClass extends sfSympalMenuSite
{
}
echo get_sympal_menu('footer', true, 'myMenuClass');
Sympal - The flexible Symfony CMS | Jonathan H. Wage
24. Menus
• Specify global custom menu class
in configuration
all:
sympal_config:
menu_class: myMenuClass
• Now all your menus use that class
Sympal - The flexible Symfony CMS | Jonathan H. Wage
25. Menus
• 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 - The flexible Symfony CMS | Jonathan H. Wage
26. Menus
• 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 - The flexible Symfony CMS | Jonathan H. Wage
27. Menus
• Serves multiple purposes
– Breadcrumbs
– Admin bar menu
– Floating editor panel
• Building hierarchical structure
through OO interface
• Rendering HTML for the hierarchy
Sympal - The flexible Symfony CMS | Jonathan H. Wage
28. Menus
• 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 - The flexible Symfony CMS | Jonathan H. Wage
29. Menus
• 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 - The flexible Symfony CMS | Jonathan H. Wage
30. Menus
• Admin bar rendering is customized
with sfSympalMenuAdminBar class
• Overrides renderChild() method so
that the proper HTML is generated
for YUI to work
Sympal - The flexible Symfony CMS | Jonathan H. Wage
32. Breadcrumbs
• 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 - The flexible Symfony CMS | Jonathan H. Wage
33. Breadcrumbs
• 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 - The flexible Symfony CMS | Jonathan H. Wage
35. Content Types
• 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 - The flexible Symfony CMS | Jonathan H. Wage
36. Content Types
• 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 - The flexible Symfony CMS | Jonathan H. Wage
37. Content Types
• 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 - The flexible Symfony CMS | Jonathan H. Wage
38. Content Types
• Inspect the generated plugin
• Have a look at the default
schema.yml created
---
Article:
actAs: [sfSympalContentType]
columns:
title: string(255)
body: clob
Sympal - The flexible Symfony CMS | Jonathan H. Wage
39. Content Types
• Now we can install the generated plugin
$ php symfony sympal:plugin-install Article
• 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
Sympal - The flexible Symfony CMS | Jonathan H. Wage
40. Content Types
• When we go to add new content we
can now add Articles
Sympal - The flexible Symfony CMS | Jonathan H. Wage
41. Content Types
• We can click the menu item added
to the primary menu to view the list
of articles.
Sympal - The flexible Symfony CMS | Jonathan H. Wage
42. Content Types
• Click the sample article to view it
Sympal - The flexible Symfony CMS | Jonathan H. Wage
43. Content Types
• 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 - The flexible Symfony CMS | Jonathan H. Wage
45. Inline Editing
• Sympal allows you to edit your
content inline when logged in as an
authorized content editor.
Sympal - The flexible Symfony CMS | Jonathan H. Wage
46. Inline Editing
• When you double click some
content to edit the inline editor will
come up
Sympal - The flexible Symfony CMS | Jonathan H. Wage
47. Inline Editing
• Edit model columns inline in
addition to content slots
Sympal - The flexible Symfony CMS | Jonathan H. Wage
49. Plugin Manager
• 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 - The flexible Symfony CMS | Jonathan H. Wage
50. Plugin Manager
• From the command line
Sympal - The flexible Symfony CMS | Jonathan H. Wage
51. Plugin Manager
• From the web browser
Sympal - The flexible Symfony CMS | Jonathan H. Wage
52. Plugin Manager
Sympal - The flexible Symfony CMS | Jonathan H. Wage
54. Configuration
• 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 - The flexible Symfony CMS | Jonathan H. Wage
55. Configuration
• Or YAML can be controlled via a
web form
• When configuration form is saved
the YAML file is written
Sympal - The flexible Symfony CMS | Jonathan H. Wage
56. Configuration
• Since the configuration uses the
symfony app.yml it can be controlled at
different levels of symfony
– Project
– Application
– Module
Sympal - The flexible Symfony CMS | Jonathan H. Wage
57. Configuration
• 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 - The flexible Symfony CMS | Jonathan H. Wage
59. Security
• sfSympalUserPlugin is forked version of
sfDoctrineGuardPlugin
– Users
– Groups
– Permissions
– Forgot Password
– Registration
• Menus, content records, etc. can all be locked down with
permissions.
Sympal - The flexible Symfony CMS | Jonathan H. Wage
67. Sympal Admin Generator Theme
• Sympal comes with custom admin
generator them
• Tabbed forms for fieldsets and
embedded forms
Sympal - The flexible Symfony CMS | Jonathan H. Wage
68. Sympal Admin Generator Theme
• Easily click Filters to popup the
filters form
Sympal - The flexible Symfony CMS | Jonathan H. Wage
70. Floating Editor Panel
• When logged in as editor and viewing a content
record a floating editor panel is displayed
Sympal - The flexible Symfony CMS | Jonathan H. Wage
72. Content Slot Types
• 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 - The flexible Symfony CMS | Jonathan H. Wage
73. Content Slot Types
• The default slot types offered by
Sympal are
– Markdown
– MultiLineText
– RichText
– Text
• Add your own custom slot types for
your projects
Sympal - The flexible Symfony CMS | Jonathan H. Wage
74. YUI Rich Text Editor
Sympal - The flexible Symfony CMS | Jonathan H. Wage
75. YUI Rich Text Editor
• The RichText slot type uses the YUI
rich text editor
Sympal - The flexible Symfony CMS | Jonathan H. Wage
76. YUI Rich Text Editor
• The YUI rich text editor also
implements the ability to upload
and embed images inline
Sympal - The flexible Symfony CMS | Jonathan H. Wage
78. Sending E-Mails
• 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 - The flexible Symfony CMS | Jonathan H. Wage
79. Sending E-Mails
• 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 - The flexible Symfony CMS | Jonathan H. Wage
80. Sending E-Mails
• 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 - The flexible Symfony CMS | Jonathan H. Wage
81. Sending E-Mails
• 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 - The flexible Symfony CMS | Jonathan H. Wage
82. Sending E-Mails
• The newEmail() method returns an
instance of sfSympalMail
• sfSympalMail is a wrapper around
your mail sending program which
defaults to Swift in Sympal
Sympal - The flexible Symfony CMS | Jonathan H. Wage
84. Multiple Sites
• 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 - The flexible Symfony CMS | Jonathan H. Wage
85. Multiple Sites
Sympal - The flexible Symfony CMS | Jonathan H. Wage
87. Search Engine Optimization
• 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 - The flexible Symfony CMS | Jonathan H. Wage
88. Search Engine Optimization
• 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 - The flexible Symfony CMS | Jonathan H. Wage
90. Dashboard
• 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 - The flexible Symfony CMS | Jonathan H. Wage
91. Dashboard
• 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 - The flexible Symfony CMS | Jonathan H. Wage
92. Dashboard
• 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 - The flexible Symfony CMS | Jonathan H. Wage
94. Multiple Themes
• 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 - The flexible Symfony CMS | Jonathan H. Wage
95. Multiple Themes
• 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 - The flexible Symfony CMS | Jonathan H. Wage
96. Multiple Themes
Doctrine Theme
Sympal Theme
Sympal - The flexible Symfony CMS | Jonathan H. Wage
98. Sympal CLI Tasks
• Sympal comes with some other
pretty useful tasks for improving
your productivity when working in
Symfony
Sympal - The flexible Symfony CMS | Jonathan H. Wage
99. Sympal CLI Tasks
• 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 - The flexible Symfony CMS | Jonathan H. Wage
100. Sympal CLI Tasks
• Show a list of all available events
for a URL
Sympal - The flexible Symfony CMS | Jonathan H. Wage
101. Sympal CLI Tasks
• Show only the events which have
been connected to
Sympal - The flexible Symfony CMS | Jonathan H. Wage
102. Sympal CLI Tasks
• Inspect an individual event to see
who has connected to it and more
importantly where!
Sympal - The flexible Symfony CMS | Jonathan H. Wage
103. More on Sympal Events
Sympal - The flexible Symfony CMS | Jonathan H. Wage
104. More on Sympal Events
• 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 - The flexible Symfony CMS | Jonathan H. Wage
105. More on Sympal Events
• 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 - The flexible Symfony CMS | Jonathan H. Wage
106. More on Sympal Events
• 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 - The flexible Symfony CMS | Jonathan H. Wage
107. More on Sympal Events
• 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 - The flexible Symfony CMS | Jonathan H. Wage
108. More on Sympal Events
• Now lets connect to the set table
definition event and add a new column
class 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 - The flexible Symfony CMS | Jonathan H. Wage
109. More on Sympal Events
• 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 - The flexible Symfony CMS | Jonathan H. Wage
110. More on Sympal Events
• 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 - The flexible Symfony CMS | Jonathan H. Wage
111. More on Sympal Events
• 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 - The flexible Symfony CMS | Jonathan H. Wage
112. More on Sympal Events
• 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 - The flexible Symfony CMS | Jonathan H. Wage
113. What does the future hold?
• Continued development of Sympal
• Work towards a 1.0 release
• Spread the word and try and get as
much feedback as possible
Sympal - The flexible Symfony CMS | Jonathan H. Wage
114. When can I expect a stable release?
• Difficult to say
• Depends on how much feedback I
get and how quickly I get it
• We will continue to tag versions of
Sympal as we develop
Sympal - The flexible Symfony CMS | Jonathan H. Wage
115. What do we need?
• Users, testers, feedback, etc.
• Development help, documentation
help
• For development, we need the
most help with the frontend
Sympal - The flexible Symfony CMS | Jonathan H. Wage
116. What do we need?
• 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 - The flexible Symfony CMS | Jonathan H. Wage
117. Questions
Jonathan H. Wage
jonathan.wage@sensio.com
+1 415 992 5468
sensiolabs.com | doctrine-project.org | sympalphp.org | jwage.com
You can contact Jonathan about Doctrine and Open-Source or
for training, consulting, application development, or business
related questions at jonathan.wage@sensio.com
Sympal - The flexible Symfony CMS | Jonathan H. Wage